一篇全面的CSS布局學(xué)習(xí)指南 [譯]

引言

無論你是剛接觸CSS被因,還是其它技術(shù)棧經(jīng)驗(yàn)豐富的開發(fā)人員偿凭,想要了解最新的布局技術(shù)婶熬。這篇文章覆蓋了你需要知道的最新的CSS技術(shù)杠巡。

在過去的幾年間量窘,CSS布局已經(jīng)顯著的改變了我們開發(fā)前端網(wǎng)站的方式。我們現(xiàn)在可以用CSS中各種布局方法來開發(fā)我們的網(wǎng)站氢拥,這就意味著我們需要經(jīng)常選擇哪種方式進(jìn)行布局蚌铜。在這篇文章中,我會(huì)介紹各種布局的基本使用方式和方法嫩海。

無論你是CSS新手困惑如何選擇最恰當(dāng)?shù)牟季址椒ǘ辏蛘吣闶鞘褂闷渌夹g(shù)棧經(jīng)驗(yàn)豐富的開發(fā)者想要了解最新的CSS布局,這篇文章都不容錯(cuò)過叁怪。當(dāng)然审葬,我不會(huì)將各種布局的細(xì)枝末節(jié)都放在這里,那樣的話就是一本書而不是一篇文章奕谭。我會(huì)對(duì)各種布局做一個(gè)基本概述涣觉,同時(shí)也會(huì)給大家提供一個(gè)鏈接進(jìn)行進(jìn)一步學(xué)習(xí)。

1 正常文檔流(Normal Flow)

如果你打開一個(gè)沒有用任何CSS來改變頁(yè)面布局的網(wǎng)頁(yè)血柳,那么網(wǎng)頁(yè)元素就會(huì)排列在一個(gè)正常流(normal flow)之中果元。在正常流中批什,元素盒子(boxes)會(huì)基于文檔的寫作模式(writing mode)一個(gè)接一個(gè)地排列叭喜。這就意味著跨晴,如果你的寫作模式是水平方向的(句子是從左到右或從右到左書寫),正常流會(huì)垂直地一個(gè)接一個(gè)排列頁(yè)面的塊級(jí)元素员淫。

當(dāng)然映皆,如果你是在一個(gè)垂直方向的寫作模式下步淹,句子是垂直方向書寫的澈驼,那么塊級(jí)元素會(huì)水平方法排列榴都。

Block and Inline Directions change with Writing Mode.

正常流是一種最基礎(chǔ)的布局:當(dāng)你為文檔應(yīng)用了CSS、創(chuàng)建了某些CSS布局抹竹,你其實(shí)是讓這些塊做了一個(gè)正常文檔流之外的“事”宛琅。

1.1 通過頁(yè)面結(jié)構(gòu)來發(fā)揮正常文檔流的優(yōu)勢(shì)

通過確保你書寫的頁(yè)面具有良好的頁(yè)面結(jié)構(gòu)(well-structured manner)英古,你可以最大程度利用正常流所帶來的優(yōu)勢(shì)。試想一下澳厢,如果瀏覽器中沒有正常流,那么你創(chuàng)建的元素都會(huì)堆積在瀏覽器的角上。這就意味著你必須指定所有的元素的布局方式需曾。而不是瀏覽器以一種可讀的方式顯示我們的內(nèi)容。

有了正常流以政,即使CSS加載失敗了殊轴,用戶仍然能閱讀你的頁(yè)面內(nèi)容芋哭;同時(shí),一些不使用CSS的工具(例如一些閱讀器)會(huì)按照元素在文檔中的位置來讀取頁(yè)面內(nèi)容。從可用性(accessibility)角度來看,這無疑是非常有幫助的,同時(shí)也讓開發(fā)者輕松了一些皆怕。如果你的內(nèi)容順序和用戶預(yù)期的閱讀順序一致,你就不需要為了將元素調(diào)整到正確的位置而進(jìn)行大量的布局調(diào)整端逼。當(dāng)你繼續(xù)讀下去會(huì)發(fā)現(xiàn)朗兵,使用新的布局方式是如何讓頁(yè)面布局事半功倍的。

因此顶滩,在思考如何布局之前余掖,你需要思考下文檔結(jié)構(gòu),以及你希望用戶以何種順序來閱讀文檔中的內(nèi)容礁鲁。

1.2 脫離正常文檔流

一旦你有了一個(gè)結(jié)構(gòu)良好的頁(yè)面盐欺,你就需要去決定如何利用它并將它變?yōu)槲覀冃枰牟季纸Y(jié)構(gòu)。這會(huì)涉及到脫離正常文檔流(moving away from normal flow)仅醇,即本文后續(xù)的部分內(nèi)容冗美。我們有許多布局“利器”可以使用,其中第一個(gè)就是float析二,它是一個(gè)描述什么是脫離正常文檔流的非常好的例子粉洼。

2 浮動(dòng)(Floats)

浮動(dòng)可以將盒子(box)移動(dòng)到左側(cè)或右側(cè)节预,同時(shí)讓內(nèi)容環(huán)繞其展示。

要讓一個(gè)元素進(jìn)行浮動(dòng)属韧,需要為該元素設(shè)置一個(gè)值為leftrightfloat屬性安拟,默認(rèn)值為none

.item {
    float: left;
}

值得強(qiáng)調(diào)的是宵喂,當(dāng)你使某個(gè)元素浮動(dòng)并讓文字環(huán)繞它時(shí)糠赦,內(nèi)容的line box被截?cái)嗔恕H绻阕屢粋€(gè)元素浮動(dòng)锅棕,同時(shí)為緊跟著的包含文本的元素設(shè)置一個(gè)背景色拙泽,你會(huì)發(fā)現(xiàn)背景色會(huì)出現(xiàn)在浮動(dòng)元素下方。

The background color on the content runs under the float

如果你想要在浮動(dòng)元素和環(huán)繞的文本之間創(chuàng)建邊距裸燎,你需要給浮動(dòng)元素設(shè)置外邊距顾瞻。在文本元素上設(shè)置外邊距只會(huì)讓其相對(duì)于容器縮進(jìn)。例如在下面這個(gè)例子中顺少,你就需要為左側(cè)浮動(dòng)的圖片設(shè)置右邊距和下邊距朋其。

<div class="container">
  <div class="item"></div>
  <p>Pea horseradish azuki bean lettuce avocado asparagus okra. Kohlrabi radish okra azuki bean corn fava bean mustard tigernut jícama green bean celtuce. </p>
  <p>Grape silver beet  collard greens avocado quandong fennel gumbo black-eyed pea watercress potato tigernut corn groundnut. Chickweed okra pea winter purslane coriander yarrow sweet pepper radish garlic brussels sprout groundnut summer purslane earthnut pea tomato spring onion azuki bean gourd. Gumbo kakadu plum komatsuna black-eyed pea green bean zucchini gourd winter purslane silver beet rock melon radish asparagus spinach.</p>
</div>
body {
  padding: 20px;
  font: 1em Helvetica Neue, Helvetica, Arial, sans-serif;
}

p {
  margin: 0 0 1em 0;
}

.container {
  width: 500px;
  border: 5px solid rgb(111,41,97);
  border-radius: .5em;
  padding: 10px;
}

.item {
  width: 100px;
  height: 100px;
  float: left;
  margin: 0 20px 20px 0;
  background-color: rgba(111,41,97,.3);
}

2.1 清除浮動(dòng)

一旦你對(duì)一個(gè)元素應(yīng)用了浮動(dòng),所有接下來的元素都會(huì)環(huán)繞它直到內(nèi)容處于它下方且開始應(yīng)用正常文檔流脆炎。如果你想要避免這種情況梅猿,可以手動(dòng)去清除浮動(dòng)。

當(dāng)你不想要某個(gè)元素受到其之前的浮動(dòng)元素影響時(shí)秒裕,為其添加clear屬性即可袱蚓。使用left值可以清除左浮動(dòng)效果,right值為右浮動(dòng)几蜻,both則會(huì)清除左右浮動(dòng)喇潘。

.clear {
    clear: both;
}

但是,當(dāng)你發(fā)現(xiàn)在容器內(nèi)有了一個(gè)浮動(dòng)元素梭稚,同時(shí)容器文本內(nèi)容過短時(shí)就會(huì)出現(xiàn)問題颖低。文本盒子會(huì)被繪制在浮動(dòng)元素下,然后接下來的部分會(huì)以正常流繪制在其后弧烤。

The box around the text does not clear the float

為了避免這種情況忱屑,我們需要為容器中某個(gè)元素應(yīng)用clear屬性。我們可以在容器最后添加一個(gè)空元素并設(shè)置clear屬性暇昂。但是在某些情況下可能無法使用這種方式(例如一些CMS系統(tǒng)生成的頁(yè)面)莺戒。因此,最常見的清除浮動(dòng)的hack方案是:在容器內(nèi)添加一個(gè)CSS偽元素急波,并將其clear屬性設(shè)置為both从铲。

<div class="container">
  <div class="item"></div>
  <p>Pea horseradish azuki bean lettuce avocado asparagus okra.</p>

</div>
body {
  padding: 20px;
  font: 1em Helvetica Neue, Helvetica, Arial, sans-serif;
}

p {
  margin: 0 0 1em 0;
}

.container {
  width: 500px;
  border: 5px solid rgb(111,41,97);
  border-radius: .5em;
  padding: 10px;
}

.item {
  width: 100px;
  height: 100px;
  float: left;
  margin: 0 20px 20px 0;
  background-color: rgba(111,41,97,.3);
}

.container::after {
  content: "";
  display: table;
  clear: both;
}

2.2 塊級(jí)格式化上下文(Block Formatting Context)

清除浮動(dòng)的另一個(gè)方法是在容器內(nèi)創(chuàng)建BFC。一個(gè)BFC元素完全包裹住了它內(nèi)部的所有元素澄暮,包括內(nèi)部的浮動(dòng)元素名段,保證浮動(dòng)元素不會(huì)超出其底部阱扬。創(chuàng)建BFC的方式有很多種,其中最常用的一種清除浮動(dòng)的方式是為元素設(shè)置除visible(默認(rèn))之外的overflow屬性值伸辟。

.container {
    overflow: auto;
}

像上面這樣使用overflow一般情況下是有效的价认。然而,在某些情況下自娩,這可能會(huì)帶來一些陰影的截?cái)嗷蚴欠穷A(yù)期的滾動(dòng)條。同時(shí)它也使你的CSS變得不那么直觀:設(shè)置overflow是因?yàn)槟阆胍故緷L動(dòng)條還是僅僅為了獲取清除浮動(dòng)的能力呢渠退?

為了使清除浮動(dòng)的意圖更加直觀忙迁,并且避免BFC的負(fù)面影響,你可以使用flow-root作為display屬性的值碎乃。display: flow-root做的唯一的一件事就是去創(chuàng)建一個(gè)BFC姊扔,因此可以避免其他創(chuàng)建BFC方法帶來的問題。

.container {
    display: flow-root;
}

2.3 浮動(dòng)的傳統(tǒng)用法

在新的布局方式出現(xiàn)以前梅誓,float經(jīng)常會(huì)被用來創(chuàng)建多欄布局恰梢。我們會(huì)給一系列元素設(shè)置寬度并且將它們一個(gè)接一個(gè)進(jìn)行浮動(dòng)。通過為浮動(dòng)元素設(shè)置一些精細(xì)的百分比大小可以創(chuàng)建類似網(wǎng)格的效果梗掰。

我不建議在當(dāng)下仍然過度地使用這種方法嵌言。但是,在現(xiàn)有的網(wǎng)站中及穗,這種方式仍然會(huì)存在許多年摧茴。因此,當(dāng)你碰到一個(gè)頁(yè)面里面到處是float的應(yīng)用埂陆,可以確定它就是用的這種技術(shù)苛白。

2.4 關(guān)于浮動(dòng)與清除浮動(dòng)的其他閱讀資料

3 定位(Positioning)

想要把一個(gè)元素從正常流中移除,或者改變其在正常文檔流中的位置焚虱,可以使用CSS中的position屬性购裙。當(dāng)處于正常文檔流時(shí),元素的position屬性為static鹃栽。在塊級(jí)維度上元素會(huì)一個(gè)接一個(gè)排列下去躏率,當(dāng)你滾動(dòng)頁(yè)面時(shí)元素也會(huì)隨著滾動(dòng)。

當(dāng)你改變?cè)氐膒osition屬性時(shí)谍咆,通常情況下你也會(huì)設(shè)置一些偏移量來使元素相對(duì)于參照點(diǎn)進(jìn)行一定的移動(dòng)禾锤。不同的position值會(huì)參照不同的參照點(diǎn)。

3.1 相對(duì)定位(relative postioning)

如果一個(gè)元素具有屬性position: relative摹察,那么它偏移的參照位是其原先在正常文檔流中的位置恩掷。你可以使用top、left供嚎、bottom和right屬性來相對(duì)其正常流位置進(jìn)行移動(dòng)黄娘。

.item {
    position: relative;
    bottom: 50px;
}

注意峭状,頁(yè)面上的其他元素并不會(huì)因該元素的位置變化而受到影響。該元素在正常流中的位置會(huì)被保留逼争,因此你需要自己去處理一些元素內(nèi)容覆蓋的情況优床。

<div class="container">
  
  <p>Pea horseradish azuki bean lettuce avocado asparagus okra. Kohlrabi radish okra azuki bean corn fava bean mustard tigernut jícama green bean celtuce. </p>
  
  <div class="item"></div>
  <p>Grape silver beet  collard greens avocado quandong fennel gumbo black-eyed pea watercress potato tigernut corn groundnut. Chickweed okra pea winter purslane coriander yarrow sweet pepper radish garlic brussels sprout groundnut summer purslane earthnut pea tomato spring onion azuki bean gourd. Gumbo kakadu plum komatsuna black-eyed pea green bean zucchini gourd winter purslane silver beet rock melon radish asparagus spinach.</p>
</div>
body {
  padding: 20px;
  font: 1em Helvetica Neue, Helvetica, Arial, sans-serif;
}

p {
  margin: 0 0 1em 0;
}

.container {
  width: 500px;
  border: 5px solid rgb(111,41,97);
  border-radius: .5em;
  padding: 10px;
}

.item {
  width: 100px;
  height: 100px;
  background-color: rgba(111,41,97,.3);
  position: relative;
  bottom: 50px;
}

3.2 絕對(duì)定位(absolute postioning)

給一個(gè)元素設(shè)置position: absolute屬性可以將其完全從正常流中移除。其原本占據(jù)的空間也會(huì)被移除誓焦。該元素會(huì)相對(duì)于其包裹元素進(jìn)行定位。

因此观话,當(dāng)你為某個(gè)元素設(shè)置position: absolute時(shí)晦溪,首先發(fā)生的變化是該元素會(huì)定位在視口的左上角嫌术。你可以通過設(shè)置top膨报、left、bottom和right偏移量屬性來將元素移動(dòng)到你想要的位置。

.item {
    position: absolute;
    top: 20px;
    right: 20px;
}

通常情況下你并不希望元素相對(duì)于視口進(jìn)行定位万俗,而是相對(duì)于容器元素库倘。在這種情況下,你需要為包裹容器元素設(shè)置一個(gè)除了默認(rèn)static之外的值寥袭。

由于給一個(gè)元素設(shè)置position: relative并不會(huì)將其從正常流中移除膘掰,所以通常這是一個(gè)不錯(cuò)的選擇零渐。如果你相對(duì)于父元素設(shè)置偏移量风宁,那么元素就會(huì)相對(duì)于這個(gè)絕對(duì)定位的元素進(jìn)行偏移固翰。

<div class="container">
  
  <p>Pea horseradish azuki bean lettuce avocado asparagus okra. Kohlrabi radish okra azuki bean corn fava bean mustard tigernut jícama green bean celtuce. </p>
  
  <div class="item"></div>
  <p>Grape silver beet  collard greens avocado quandong fennel gumbo black-eyed pea watercress potato tigernut corn groundnut. Chickweed okra pea winter purslane coriander yarrow sweet pepper radish garlic brussels sprout groundnut summer purslane earthnut pea tomato spring onion azuki bean gourd. Gumbo kakadu plum komatsuna black-eyed pea green bean zucchini gourd winter purslane silver beet rock melon radish asparagus spinach.</p>
</div>
body {
  padding: 20px;
  font: 1em Helvetica Neue, Helvetica, Arial, sans-serif;
}

p {
  margin: 0 0 1em 0;
}

.container {
  width: 500px;
  border: 5px solid rgb(111,41,97);
  border-radius: .5em;
  padding: 10px;
  position: relative;
}

.item {
  width: 100px;
  height: 100px;
  background-color: rgba(111,41,97,.3);
  position: absolute;
  top: 20px;
  left: 20px;
}

3.3 固定定位(fixed positioning)

大多數(shù)情況下凑耻,position: fixed的元素會(huì)相對(duì)于瀏覽器窗口定位邻吭,并且會(huì)從正常文檔流中被移除畸写,不會(huì)保留它所占據(jù)的空間千所。當(dāng)頁(yè)面滾動(dòng)時(shí),固定的元素會(huì)留在相對(duì)于瀏覽器窗口的位置蒜埋,而其他正常流中的內(nèi)容則和通常一樣滾動(dòng)真慢。

.item {
    position: fixed;
    top: 20px;
    left: 100px;
}

當(dāng)你想要一個(gè)固定導(dǎo)航欄一直停留在屏幕上時(shí)這會(huì)非常有效。和其他的position值一樣理茎,這也可能會(huì)造成一些元素被遮擋烛占,需要小心保證頁(yè)面內(nèi)容的可讀而不會(huì)被固定元素遮擋姑原。

<div class="container">
  
  <p>Pea horseradish azuki bean lettuce avocado asparagus okra. Kohlrabi radish okra azuki bean corn fava bean mustard tigernut jícama green bean celtuce. </p>
  
  <div class="item"></div>
  <p>Grape silver beet  collard greens avocado quandong fennel gumbo black-eyed pea watercress potato tigernut corn groundnut. Chickweed okra pea winter purslane coriander yarrow sweet pepper radish garlic brussels sprout groundnut summer purslane earthnut pea tomato spring onion azuki bean gourd. Gumbo kakadu plum komatsuna black-eyed pea green bean zucchini gourd winter purslane silver beet rock melon radish asparagus spinach.</p>
  
   <p>Grape silver beet  collard greens avocado quandong fennel gumbo black-eyed pea watercress potato tigernut corn groundnut. Chickweed okra pea winter purslane coriander yarrow sweet pepper radish garlic brussels sprout groundnut summer purslane earthnut pea tomato spring onion azuki bean gourd. Gumbo kakadu plum komatsuna black-eyed pea green bean zucchini gourd winter purslane silver beet rock melon radish asparagus spinach.</p>
  
   <p>Grape silver beet  collard greens avocado quandong fennel gumbo black-eyed pea watercress potato tigernut corn groundnut. Chickweed okra pea winter purslane coriander yarrow sweet pepper radish garlic brussels sprout groundnut summer purslane earthnut pea tomato spring onion azuki bean gourd. Gumbo kakadu plum komatsuna black-eyed pea green bean zucchini gourd winter purslane silver beet rock melon radish asparagus spinach.</p>
</div>
body {
  padding: 20px;
  font: 1em Helvetica Neue, Helvetica, Arial, sans-serif;
}

p {
  margin: 0 0 1em 0;
}

.container {
  width: 500px;
  border: 5px solid rgb(111,41,97);
  border-radius: .5em;
  padding: 10px;
  position: relative;
}

.item {
  width: 100px;
  height: 100px;
  background-color: rgba(111,41,97,.3);
  position: fixed;
  top: 20px;
  left: 20px;
}

為了使一個(gè)固定定位的元素不相對(duì)于視口進(jìn)行定位,你需要為容器元素設(shè)置transform精钮、perspective、filter三個(gè)屬性之一(不為默認(rèn)值none)性雄。這樣固定的元素就會(huì)相對(duì)于該塊級(jí)元素偏移赋铝,而非視口盛卡。

3.4 STICKY 定位

設(shè)置position: sticky會(huì)讓元素在頁(yè)面滾動(dòng)時(shí)如同在正常流中,但當(dāng)其滾動(dòng)到相對(duì)于視口的某個(gè)特定位置時(shí)就會(huì)固定在屏幕上跃捣,如同fixed一般。這個(gè)屬性值是一個(gè)較新的CSS屬性夺蛇,在瀏覽器兼容性上會(huì)差一些疚漆,但在不兼容的瀏覽器中會(huì)被忽略并會(huì)退到正常的滾動(dòng)情況。

.item {
    position: sticky;
    top: 0;
}
<div class="container">
  
  <p>Pea horseradish azuki bean lettuce avocado asparagus okra. Kohlrabi radish okra azuki bean corn fava bean mustard tigernut jícama green bean celtuce. </p>
  
  <div class="item"></div>
  <p>Grape silver beet  collard greens avocado quandong fennel gumbo black-eyed pea watercress potato tigernut corn groundnut. Chickweed okra pea winter purslane coriander yarrow sweet pepper radish garlic brussels sprout groundnut summer purslane earthnut pea tomato spring onion azuki bean gourd. Gumbo kakadu plum komatsuna black-eyed pea green bean zucchini gourd winter purslane silver beet rock melon radish asparagus spinach.</p>
  
   <p>Grape silver beet  collard greens avocado quandong fennel gumbo black-eyed pea watercress potato tigernut corn groundnut. Chickweed okra pea winter purslane coriander yarrow sweet pepper radish garlic brussels sprout groundnut summer purslane earthnut pea tomato spring onion azuki bean gourd. Gumbo kakadu plum komatsuna black-eyed pea green bean zucchini gourd winter purslane silver beet rock melon radish asparagus spinach.</p>
  
   <p>Grape silver beet  collard greens avocado quandong fennel gumbo black-eyed pea watercress potato tigernut corn groundnut. Chickweed okra pea winter purslane coriander yarrow sweet pepper radish garlic brussels sprout groundnut summer purslane earthnut pea tomato spring onion azuki bean gourd. Gumbo kakadu plum komatsuna black-eyed pea green bean zucchini gourd winter purslane silver beet rock melon radish asparagus spinach.</p>
</div>
body {
  padding: 20px;
  font: 1em Helvetica Neue, Helvetica, Arial, sans-serif;
}

p {
  margin: 0 0 1em 0;
}

.container {
  width: 500px;
  border: 5px solid rgb(111,41,97);
  border-radius: .5em;
  padding: 10px;
  position: relative;
}

.item {
  width: 100px;
  height: 30px;
  background-color: rgba(111,41,97,.3);
  position: sticky;
  top: 0;
  width: 100%;
}

3.5 關(guān)于定位(positioning)的其他閱讀資料

4 彈性布局(Flex Layout)

彈性盒子(Flexbox)布局是一種為一維布局而設(shè)計(jì)的布局方法。一維的意思是你希望內(nèi)容是按行或者列來布局娶聘。你可以使用display: flex來將元素變?yōu)閺椥圆季帧?/p>

.container {
    display: flex;
}

該容器的直接子元素會(huì)變?yōu)閺椥皂?xiàng)(flex item)闻镶,并按行排列。

<div class="container">
  <div class="item">1</div>
  <div class="item">2</div>
  <div class="item">3</div>
</div>
body {
  padding: 20px;
  font: 1em Helvetica Neue, Helvetica, Arial, sans-serif;
}

* {box-sizing: border-box;}

p {
  margin: 0 0 1em 0;
}

.container {
  width: 500px;
  border: 5px solid rgb(111,41,97);
  border-radius: .5em;
  padding: 10px;
  display: flex;
}

.item {
  width: 100px;
  height: 100px;
  padding: 10px;
  background-color: rgba(111,41,97,.3);
  border: 2px solid rgba(111,41,97,.5);
}

4.1 彈性盒子的軸(axes)

在上面的例子中丸升,我們會(huì)稱彈性項(xiàng)在行內(nèi)是從起始位置開始排列铆农,而不是說它們是左對(duì)齊。這些元素會(huì)按行排列是因?yàn)槟J(rèn)的flex-direction值為row狡耻,row代表了文本的行文方向墩剖。由于我們工作的環(huán)境是英文(中文也是如此),一種自左向右的語言夷狰,行的開始位置就是在左邊胖缤,因此我們的彈性項(xiàng)也是從左邊開始的枝恋。因此flex-direction的值被定義為彈性盒子的主軸(main axis)。

交叉軸(cross axis)則是和主軸垂直的一條軸。如果你的flex-direction是row并且彈性項(xiàng)是按照行內(nèi)方向排列的帽氓,那么交叉軸就是塊級(jí)元素的排列方向。如果flex-direction是column那么彈性項(xiàng)就會(huì)以塊級(jí)元素排列的方向排布特恬,然后交叉軸就會(huì)變?yōu)閞ow舆逃。

如果你習(xí)慣于從主軸與交叉軸的角度來使用彈性盒子,那么一切會(huì)變得非常簡(jiǎn)單背捌。

4.2 方向和次序

彈性盒子模型讓我們可以通過為flex-direction屬性設(shè)置row-reverse或column-reverse值來改變主軸上彈性項(xiàng)的方向毙籽。

<div class="container">
  <div class="item">1</div>
  <div class="item">2</div>
  <div class="item">3</div>
</div>
body {
  padding: 20px;
  font: 1em Helvetica Neue, Helvetica, Arial, sans-serif;
}

* {box-sizing: border-box;}

p {
  margin: 0 0 1em 0;
}

.container {
  width: 500px;
  border: 5px solid rgb(111,41,97);
  border-radius: .5em;
  padding: 10px;
  display: flex;
  flex-direction: row-reverse;
}

.item {
  width: 100px;
  height: 100px;
  padding: 10px;
  background-color: rgba(111,41,97,.3);
  border: 2px solid rgba(111,41,97,.5);
}

當(dāng)然,你也可以通過order屬性來改變某一個(gè)彈性項(xiàng)的順序毡庆。但是要特別注意坑赡,這可能會(huì)給那些通過鍵盤(而非鼠標(biāo)或觸屏)訪問你的網(wǎng)站的用戶帶來一些麻煩,因?yàn)榘磘ab按鈕選擇元素的順序是頁(yè)面內(nèi)元素在源碼中的順序而非顯示順序么抗。你可以閱讀之后的“顯示和文檔順序”部分來了解更多相關(guān)內(nèi)容毅否。

4.3 一些Flex的屬性

這些flex的屬性是用來控制彈性項(xiàng)在主軸上空間大小的。這三個(gè)屬性是:

  • flex-grow
  • flex-shrink
  • flex-basis

通秤叮可以使用它們的簡(jiǎn)寫形式:flex螟加。第一個(gè)值代表flex-grow,第二個(gè)是flex-shrink吞琐,而第三個(gè)則是flex-basis捆探。

.item {
    flex: 1 1 200px;
}

flex-basis會(huì)為彈性項(xiàng)設(shè)置未拉伸和壓縮時(shí)的初始大小。在上面的例子中站粟,大小是200px黍图,因此我們會(huì)給每個(gè)項(xiàng)200px的空間大小。但是大多數(shù)情況下容器元素大小不會(huì)正好被分為許多200px大小的項(xiàng)奴烙,而是可能有一些不足或剩余空間助被。flex-grow和flow-shrink屬性允許我們?cè)谌萜鬟^大或過小時(shí)控制各項(xiàng)的大小剖张。

如果flex-grow的值是任意的正數(shù),那么彈性項(xiàng)會(huì)被允許拉伸來占據(jù)更多的空間恰起。因此修械,在上面的例子中,當(dāng)各項(xiàng)被設(shè)為200px后检盼,所有多余的空間會(huì)被每個(gè)彈性項(xiàng)平分并填滿肯污。

如果flex-shrink的值為任意的正數(shù),那么當(dāng)彈性項(xiàng)被設(shè)置了flex-basis后吨枉,元素溢出容器時(shí)會(huì)進(jìn)行收縮蹦渣。在上面這個(gè)CSS的例子中,如果容器空間不足貌亭,每個(gè)彈性項(xiàng)會(huì)等比例縮放以適應(yīng)容器的大小柬唯。

flex-grow和flex-shrink的值可以是任意的正數(shù)。一個(gè)具有較大flex-grow值的彈性項(xiàng)會(huì)在容器有剩余空間時(shí)拉伸更大的比例圃庭;而一個(gè)具有更大flex-shrink值的項(xiàng)則會(huì)在容器空間不足時(shí)被壓縮的更多锄奢。

<div class="container">
  <div class="item">1</div>
  <div class="item">2</div>
  <div class="item">3</div>
</div>
body {
  padding: 20px;
  font: 1em Helvetica Neue, Helvetica, Arial, sans-serif;
}

* {box-sizing: border-box;}

p {
  margin: 0 0 1em 0;
}

.container {
  width: 500px;
  border: 5px solid rgb(111,41,97);
  border-radius: .5em;
  padding: 10px;
  display: flex;
}

.item {
  flex: 1 1 0;
  width: 100px;
  height: 100px;
  padding: 10px;
  background-color: rgba(111,41,97,.3);
  border: 2px solid rgba(111,41,97,.5);
}

.container :first-child {
  flex: 2 1 0; 
}

理解這些屬性是理解如何使用彈性布局的關(guān)鍵,下面列出的一些資源會(huì)幫助我們進(jìn)一步學(xué)習(xí)其中的細(xì)節(jié)剧腻。當(dāng)你需要在容器的一個(gè)維度上拉伸或者壓縮一些元素時(shí)拘央,你可以考慮使用彈性盒子模型。如果你發(fā)現(xiàn)你正嘗試在行和列兩個(gè)維度上排列你的內(nèi)容书在,你需要的是網(wǎng)格模型(grid)灰伟,這時(shí)彈性盒子模型很可能不是最合適的工具了。

4.4 關(guān)于彈性盒子布局的其他閱讀資料

5 網(wǎng)格布局(grid layout)

CSS網(wǎng)格布局(grid layout)是一種用來進(jìn)行二維布局的技術(shù)儒旬。二維(two-dimesional)意味著你希望按照行和列來排布你的內(nèi)容栏账。和彈性盒子類似,網(wǎng)格布局也需要設(shè)置一個(gè)display值栈源。你可以為容器元素設(shè)置display: grid挡爵,并且使用grid-template-columns和grid-template-rows屬性來控制網(wǎng)格中的行與列。

.container {
    display: grid;
    grid-template-columns: 200px 200px 200px;
    grid-template-rows: 200px 200px;
}

上面這段CSS會(huì)創(chuàng)建一個(gè)行列元素大小固定的網(wǎng)格甚垦。不過這也許并不是你希望的茶鹃。默認(rèn)值為auto,你可以認(rèn)為這代表了“對(duì)于內(nèi)容格子足夠大”制轰。如果你沒有指定行(row track)的大小前计,所有添加進(jìn)來的行內(nèi)容大小都會(huì)被置為auto胞谭。一種常用的模式是為網(wǎng)格制定列寬度垃杖,并允許網(wǎng)格按需添加行。

你可以使用任意的長(zhǎng)度單位或時(shí)百分比來設(shè)置行與列丈屹,同時(shí)你可以使用為網(wǎng)格系統(tǒng)所創(chuàng)造的新的單位——fr调俘。fr是一種彈性單位伶棒,它可以指定網(wǎng)格容器內(nèi)的空間被如何劃分。

網(wǎng)格會(huì)替你計(jì)算與分配空間彩库,你不需要去計(jì)算元素的百分比去適應(yīng)容器大小肤无。在下面這個(gè)例子中,我們使用fr來創(chuàng)建網(wǎng)格的列骇钦,這使得網(wǎng)格的列可以自適應(yīng)宛渐。同時(shí)我們還使用了grid-gap來保證元素間的間距(關(guān)于網(wǎng)格內(nèi)元素與的間距會(huì)在“對(duì)齊”這一部分詳細(xì)介紹)。

<div class="container">
  <div>1</div>
  <div>2</div>
  <div>3</div>
  <div>4</div>
  <div>5<br>has more content.</div>
</div>
body {
  padding: 20px;
  font: 1em Helvetica Neue, Helvetica, Arial, sans-serif;
}

* {box-sizing: border-box;}

p {
  margin: 0 0 1em 0;
}

.container {
  width: 500px;
  border: 5px solid rgb(111,41,97);
  border-radius: .5em;
  padding: 10px;
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  grid-gap: 20px;
}

.container > div {
  padding: 10px;
  background-color: rgba(111,41,97,.3);
  border: 2px solid rgba(111,41,97,.5);
}

和Flexbox布局中的flex-grow和flex-shrink一樣眯搭,fr單位也是用來處理可用空間的分配問題窥翩。fr的值越高意味著在行列中可以獲得更高比例的空間。你也可以即使用fr單位又使用絕對(duì)長(zhǎng)度單位鳞仙。在計(jì)算fr單位長(zhǎng)度之前寇蚊,將從可用空間中減去其他長(zhǎng)度單位所需的空間。

<div class="container">
  <div>1</div>
  <div>2</div>
  <div>3</div>
  <div>4</div>
  <div>5<br>has more content.</div>
</div>
body {
  padding: 20px;
  font: 1em Helvetica Neue, Helvetica, Arial, sans-serif;
}

* {box-sizing: border-box;}

p {
  margin: 0 0 1em 0;
}

.container {
  width: 500px;
  border: 5px solid rgb(111,41,97);
  border-radius: .5em;
  padding: 10px;
  display: grid;
  grid-template-columns: 1fr 2fr 100px;
  grid-gap: 20px;
}

.container > div {
  padding: 10px;
  background-color: rgba(111,41,97,.3);
  border: 2px solid rgba(111,41,97,.5);
}

5.1 關(guān)于網(wǎng)格的一些術(shù)語

網(wǎng)格系統(tǒng)總是有兩個(gè)軸:inline axis表示頁(yè)面中文字的文字排列的方向棍好,block axis表示頁(yè)面中塊級(jí)元素的排列方向仗岸。

一個(gè)被設(shè)置為display: grid的元素就是所謂的網(wǎng)格容器。在網(wǎng)格容器中會(huì)有網(wǎng)格線(grid line)借笙,網(wǎng)格線就是你在指定grid-template-columns和grid-template-rows時(shí)網(wǎng)格中行列所生成的扒怖。網(wǎng)格中的最小單位(也就是被四條網(wǎng)格線截取生成的區(qū)域)被成為網(wǎng)格單元格(grid cell),進(jìn)一步的提澎,由若干個(gè)單元格組成的矩形區(qū)域被成為網(wǎng)格區(qū)域(grid area)姚垃。

網(wǎng)格線在行列之間
行列在網(wǎng)格線之間
網(wǎng)格單元是網(wǎng)格中最小的單位,網(wǎng)格區(qū)域是一個(gè)或多個(gè)網(wǎng)格單元組成的矩形區(qū)域

5.2 網(wǎng)格的自動(dòng)排列規(guī)則

一旦你創(chuàng)建了網(wǎng)格盼忌,那么網(wǎng)格容器的直接子元素就會(huì)開始將它們自己一個(gè)一個(gè)地放置在網(wǎng)格的單元格中积糯。子元素的放置是依據(jù)網(wǎng)格的自動(dòng)排列規(guī)則(auto-placement rule)。這些規(guī)則確保了網(wǎng)格內(nèi)元素是被安排在各個(gè)空的單元格中谦纱,而不會(huì)彼此遮蓋看成。

網(wǎng)格中任何沒有被進(jìn)行定位的直接子元素都會(huì)根據(jù)自動(dòng)排列規(guī)則進(jìn)行放置。在下面這個(gè)列子中跨嘉,我讓每三個(gè)元素中的第一個(gè)占據(jù)兩行川慌,但仍然從起始行開始去自動(dòng)排列。

<div class="container">
  <div>1</div>
  <div>2</div>
  <div>3</div>
  <div>4</div>
  <div>5</div>
  <div>6</div>
  <div>7</div>
  <div>8</div>
  <div>9</div>
</div>
body {
  padding: 20px;
  font: 1em Helvetica Neue, Helvetica, Arial, sans-serif;
}

* {box-sizing: border-box;}

p {
  margin: 0 0 1em 0;
}

.container {
  width: 500px;
  border: 5px solid rgb(111,41,97);
  border-radius: .5em;
  padding: 10px;
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  grid-gap: 20px;
}

.container > div {
  padding: 10px;
  background-color: rgba(111,41,97,.3);
  border: 2px solid rgba(111,41,97,.5);
}

.container > div:nth-child(3n+1) {
  grid-row-end: span 2;
  background-color: rgba(193,225,237,.3);
  border: 2px solid rgba(193,225,237,.5);
}

5.3 基于行/列的基本定位方法

最簡(jiǎn)單的布局元素的方法就是基于行列的布局方法祠乃,只要告訴瀏覽器從哪一行到哪一行進(jìn)行合并就可以了梦重。例如,現(xiàn)在又一個(gè)3行2列的表格亮瓷,我們可以從第一行到第三行琴拧,第一列到第三列放置一個(gè)元素,這樣他就總共覆蓋4個(gè)網(wǎng)格單元嘱支,占用2行2列蚓胸。

.item {
    grid-column-start: 1;
    grid-column-end: 3;
    grid-row-start: 1;
    grid-row-end: 3;
}

這些屬性可以用縮寫來表示:grid-column和grid-row挣饥,其中起一個(gè)值代表起始值,第二個(gè)值代表結(jié)束值沛膳。

.item {
    grid-column: 1 / 3;
    grid-row: 1 / 3;
}

你也可以讓網(wǎng)格項(xiàng)(grid item)占據(jù)同一個(gè)單元格扔枫。支持一些內(nèi)容間會(huì)覆蓋的設(shè)計(jì)。網(wǎng)格項(xiàng)會(huì)像通常網(wǎng)頁(yè)中的元素那樣疊起來锹安,在html源碼中下面的網(wǎng)格項(xiàng)會(huì)疊在其他元素上面短荐。你仍然可以用z-index來控制它的堆疊順序。

<div class="container">
  <div class="one">1</div>
  <div class="two">2</div>
  <div class="three">3</div>
  <div class="four">4</div>
  <div class="five">5</div>
</div>
body {
  padding: 20px;
  font: 1em Helvetica Neue, Helvetica, Arial, sans-serif;
}

* {box-sizing: border-box;}

p {
  margin: 0 0 1em 0;
}

.container {
  width: 500px;
  border: 5px solid rgb(111,41,97);
  border-radius: .5em;
  padding: 10px;
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  grid-gap: 20px;
}

.container > div {
  padding: 10px;
}

.one {
  grid-column: 1 / 4;
  grid-row: 1;
  background-color: rgba(111,41,97,.3);
  border: 2px solid rgba(111,41,97,.5);
}

.two {
  grid-column: 1 / 3;
  grid-row: 2;
  background-color: rgba(111,41,97,.3);
  border: 2px solid rgba(111,41,97,.5);
}

.three {
  grid-column: 2 / 4;
  grid-row: 2 / 5;
  background-color: rgba(193,225,237,.3);
  border: 2px solid rgba(193,225,237,.5);
}

.four {
  grid-column: 1;
  grid-row: 4 ;
  background-color: rgba(193,225,237,.3);
  border: 2px solid rgba(193,225,237,.5);
}

.five {
  grid-column: 3 ;
  grid-row: 4 / 5;
  background-color: rgba(111,41,97,.3);
  border: 2px solid rgba(111,41,97,.5);
}

5.4 通過命名區(qū)域來定位元素

你可以通過命名區(qū)域(named areas)來定位網(wǎng)格中的元素叹哭。要是用這種方式搓侄,你需要給每個(gè)元素一個(gè)名字,然后通過grid-template-areas屬性的值來描述布局方式话速。

.item1 {
    grid-area: a;
}

.item2 {
    grid-area: b;
}

.item3 {
    grid-area: c;
}

.container {
    display: grid;
    grid-template-columns: 1fr 1fr 1fr 1fr;
    grid-template-areas: 
     "a a b b"
     "a a c c";
}

使用這種方式有幾個(gè)需要注意的點(diǎn)讶踪。如果你想要合并一些單元格作為你的網(wǎng)格項(xiàng),你需要重復(fù)元素的名字泊交。網(wǎng)格區(qū)域需要能形成一個(gè)完整的矩形 —— 每個(gè)單元格都需要被填入一個(gè)值乳讥。如果你想要空出某些單元格,那就需要使用.這個(gè)值廓俭。例如在下面的CSS里我將最右下角的單元格留空云石。

.container {
    display: grid;
    grid-template-columns: 1fr 1fr 1fr 1fr;
    grid-template-areas: 
     "a a b b"
     "a a c .";
}

下面是demo示例

<div class="container">
  <div class="one">1</div>
  <div class="two">2</div>
  <div class="three">3</div>
  <div class="four">4</div>
  <div class="five">5</div>

</div>
body {
  padding: 20px;
  font: 1em Helvetica Neue, Helvetica, Arial, sans-serif;
}

* {box-sizing: border-box;}

p {
  margin: 0 0 1em 0;
}

.container {
  width: 500px;
  border: 5px solid rgb(111,41,97);
  border-radius: .5em;
  padding: 10px;
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  grid-auto-rows: minmax(50px, auto);
  grid-gap: 20px;
  grid-template-areas: 
    "a a a"
    "b c c"
    ". . d"
    "e e d"
}

.container > div {
  padding: 10px;
  background-color: rgba(111,41,97,.3);
  border: 2px solid rgba(111,41,97,.5);
}

.one {
  grid-area: a;
}

.two {
  grid-area: b;
}

.three {
  grid-area: c;
}

.four {
  grid-area: d;
}

.five {
  grid-area: e;
}

5.5 關(guān)于網(wǎng)格布局的其他閱讀資料

這片文章只包括了CSS網(wǎng)格布局的一些初步內(nèi)容,其中還有非常多的內(nèi)容值得學(xué)習(xí)研乒,下面的一些資料可以幫助你進(jìn)一步學(xué)習(xí)汹忠。一些組件或整個(gè)頁(yè)面的布局都可以使用網(wǎng)格。如果你需要在兩個(gè)維度進(jìn)行布局雹熬,網(wǎng)格布局是一個(gè)不錯(cuò)的選擇 —— 不論需要布局的區(qū)域的大小宽菜。

  • CSS Grid Layout,” Web technology for developers, MDN web docs, Mozilla
  • Grid by Example,” Everything you need to learn CSS Grid Layout, Rachel Andrew
  • Grid Garden,” A fun interactive game to test and improve your CSS skills
  • Layout Land,” Jen Simmons, YouTube

我(作者)在Smashing Magazine也寫一些文章來幫助你深入理解各種網(wǎng)格的概念:

6 顯示順序和文檔順序(visual and document order)

在文章的最開始,我建議你以從上到下的閱讀順序來組織你的文檔順序竿报,這樣會(huì)有助于可讀性和CSS的布局方式铅乡。從我們關(guān)于彈性盒子和CSS網(wǎng)格的簡(jiǎn)短介紹來看,你可以發(fā)現(xiàn)用這些布局方法可能會(huì)極大地改變頁(yè)面展示的元素在文檔中的順序烈菌。這可能會(huì)導(dǎo)致一個(gè)隱含的問題阵幸。

在一些非可視化的應(yīng)用場(chǎng)景中,瀏覽器會(huì)遵循文檔源碼來進(jìn)行使用芽世。因此挚赊,屏幕閱讀器會(huì)讀取文檔的順序,此外使用鍵盤tab鍵來瀏覽的用戶訪問文檔的順序是基于源碼的順序济瓢,而不是元素展示的順序荠割。許多屏幕閱讀器的用戶并非完全失明,他們可能在使用屏幕閱讀器的同時(shí)也能夠看到這些元素在文檔的哪個(gè)部分葬荷。在這些情況下涨共,當(dāng)與源碼進(jìn)行對(duì)比時(shí),這種混亂的頁(yè)面展現(xiàn)可能會(huì)令人充滿迷惑宠漩。

當(dāng)你改變了元素在文檔中原來的順序時(shí)举反,一定確保知道自己在做什么。如果你發(fā)現(xiàn)你自己正在CSS中重新排序你的元素扒吁,你應(yīng)該去回頭看看是否要重新組織你的頁(yè)面元素火鼻。你可以通過使用tab訪問來測(cè)試一下你的頁(yè)面。

6.1 關(guān)于顯示順序和文檔順序的其他閱讀資料

7 盒模型的生成(box generation)

你寫在網(wǎng)頁(yè)里的任何東西都會(huì)生成一個(gè)盒子(box)雕崩,這篇文章討論的所有東西其實(shí)都是如何能夠使用CSS來按照你的設(shè)計(jì)布局這些盒子魁索。然而,在某些情況下盼铁,你可能根本不想創(chuàng)建一個(gè)盒子粗蔚。有兩個(gè)display的屬性值會(huì)幫你處理這種情況。

7.1 不生成盒子或內(nèi)容(display: none)

如果你希望元素以及它所有的內(nèi)容(包括所有子元素)都不會(huì)生成饶火,你可以使用display: none鹏控。這樣元素就不會(huì)被展示,并且不會(huì)保留其本該占有的空間肤寝。

.item {
    display: none;
}

7.2 不生成該元素当辐,但是生成其所有子元素(display: contents)

display: content是display的一個(gè)新的屬性值。為一個(gè)元素應(yīng)用display: content屬性會(huì)導(dǎo)致其自身的盒子不生成但所有的子元素都會(huì)照常生成鲤看。這有什么用呢缘揪?試想一下,如果你希望一個(gè)彈性布局或網(wǎng)格布局中的非直接子元素能應(yīng)用這些布局义桂,這就會(huì)非常有用找筝。

在下面這個(gè)例子里,第一個(gè)彈性項(xiàng)包含了兩個(gè)子元素慷吊,由于它被設(shè)為display: contents呻征,它的盒子不會(huì)生成并且它的兩個(gè)子元素會(huì)成為彈性項(xiàng),并被當(dāng)作彈性盒子容器的直接子元素來布局罢浇。

<div class="container">
  <div class="item">
    <div class="subitem">A</div>
    <div class="subitem">B</div>
  </div>
  <div class="item">2</div>
  <div class="item">3</div>
</div>
body {
  padding: 20px;
  font: 1em Helvetica Neue, Helvetica, Arial, sans-serif;
}

* {box-sizing: border-box;}

p {
  margin: 0 0 1em 0;
}

.container {
  width: 500px;
  border: 5px solid rgb(111,41,97);
  border-radius: .5em;
  padding: 10px;
  display: flex;
}

.item {
  flex: 1 1 200px;
  padding: 10px;
  background-color: rgba(111,41,97,.3);
  border: 2px solid rgba(111,41,97,.5);
}

.subitem {
  padding: 10px;
  background-color: rgba(193,225,237,.3);
  border: 2px solid rgba(193,225,237,.5);
}

.container .item:first-child {
  display: contents;
}

7.3 關(guān)于box generation的其他閱讀資料

8 對(duì)齊

在以前陆赋,要實(shí)現(xiàn)對(duì)齊往往會(huì)用到一些很"tricky"的方式,并且能夠使用的方法也非常有限嚷闭。隨著CSS盒模型對(duì)齊(box alignment module)的出現(xiàn)攒岛,這一切都發(fā)生了變化。你將會(huì)使用它來控制網(wǎng)格容器與彈性盒子容器中的對(duì)齊胞锰。未來其他的各種布局方法都會(huì)應(yīng)用這些對(duì)齊屬性灾锯。盒模型對(duì)齊(box alignment specification)規(guī)范中的一系列詳細(xì)屬性如下:

  • justify-content
  • align-content
  • place-content
  • justify-items
  • align-items
  • place-items
  • justify-self
  • align-self
  • place-self
  • row-gap
  • column-gap
  • gap

由于不同的布局模型有不同的特性,因此用于不同布局模型的對(duì)齊屬性會(huì)有一些表現(xiàn)上的差異嗅榕。讓我們來看看在一些簡(jiǎn)單的網(wǎng)格與彈性布局中對(duì)齊是如何工作的顺饮。

align-items和justify-items屬性相對(duì)是align-self和justify-self屬性的一種批量形式吵聪。這些屬性會(huì)控制與元素在其網(wǎng)格區(qū)域(grid area)中的對(duì)齊情況。

<div class="container">
  <div>1</div>
  <div>2</div>
  <div>3</div>
  <div>4</div>
  <div class="special">5</div>
</div>
body {
  padding: 20px;
  font: 1em Helvetica Neue, Helvetica, Arial, sans-serif;
}

* {box-sizing: border-box;}

p {
  margin: 0 0 1em 0;
}

.container {
  width: 500px;
  border: 5px solid rgb(111,41,97);
  border-radius: .5em;
  padding: 10px;
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  grid-auto-rows: minmax(100px, auto);
  grid-gap: 20px;
  align-items: center;
  justify-items: start;
}

.special {
  grid-column: 2 / 4;
  align-self: end;
  justify-self: end;
}

.container > div {
  padding: 10px;
  background-color: rgba(111,41,97,.3);
  border: 2px solid rgba(111,41,97,.5);
}

align-content和justify-content屬性則會(huì)對(duì)網(wǎng)格中的行/列(tracks)進(jìn)行對(duì)齊控制(網(wǎng)格容器中需要在排列完行/列元素后有多余的空間)兼雄。

<div class="container">
  <div>1</div>
  <div>2</div>
  <div>3</div>
  <div>4</div>
  <div>5</div>
</div>
body {
  padding: 20px;
  font: 1em Helvetica Neue, Helvetica, Arial, sans-serif;
}

* {box-sizing: border-box;}

p {
  margin: 0 0 1em 0;
}

.container {
  width: 500px;
  height: 300px;
  border: 5px solid rgb(111,41,97);
  border-radius: .5em;
  padding: 10px;
  display: grid;
  grid-template-columns: 100px 100px 100px;
  grid-auto-rows: minmax(100px, auto);
  grid-gap: 20px;
  align-content: space-between;
  justify-content: end;
}

.container > div {
  padding: 10px;
  background-color: rgba(111,41,97,.3);
  border: 2px solid rgba(111,41,97,.5);
}

在彈性盒子中吟逝,align-items和align-self用來解決交叉軸上的對(duì)齊問題,而justify-content則用于解決主軸上空間的分配赦肋。

<div class="container">
  <div>1</div>
  <div>2</div>
  <div class="special">3</div>
  <div>4</div>
</div>
body {
  padding: 20px;
  font: 1em Helvetica Neue, Helvetica, Arial, sans-serif;
}

* {box-sizing: border-box;}

p {
  margin: 0 0 1em 0;
}

.container {
  width: 500px;
  height: 300px;
  border: 5px solid rgb(111,41,97);
  border-radius: .5em;
  padding: 10px;
  display: flex;
  justify-content: space-between;
  align-items: flex-end;
}

.special {
  align-self: stretch;
}

.container > div {
  padding: 10px;
  background-color: rgba(111,41,97,.3);
  border: 2px solid rgba(111,41,97,.5);
}

在交叉軸上块攒,把彈性行(flex line)和額外空間包裹在彈性容器中之后,你就可以使用align-content了佃乘。

<div class="container">
  <div>1</div>
  <div>2</div>
  <div>3</div>
  <div>4</div>
  <div>5</div>
</div>
body {
  padding: 20px;
  font: 1em Helvetica Neue, Helvetica, Arial, sans-serif;
}

* {box-sizing: border-box;}

p {
  margin: 0 0 1em 0;
}

.container {
  width: 500px;
  height: 300px;
  border: 5px solid rgb(111,41,97);
  border-radius: .5em;
  padding: 10px;
  display: flex;
  flex-wrap: wrap;
  align-content: space-between;
}

.container > div {
  flex: 1 1 200px;
  padding: 10px;
  background-color: rgba(111,41,97,.3);
  border: 2px solid rgba(111,41,97,.5);
}

下面的一些鏈接更細(xì)節(jié)地討論了各類布局方法中的盒模型對(duì)齊囱井。花些時(shí)間去理解對(duì)齊的工作原理是非常值得的趣避,它對(duì)理解彈性盒子庞呕、網(wǎng)格布局以及未來的一些布局方法都會(huì)很有幫助。

8.1 行/列的間隔

一個(gè)多欄布局具有column-gap屬性程帕,到目前位置千扶,網(wǎng)格布局具有g(shù)rid-column-gap、grid-row-gap和grid-gap骆捧。這些現(xiàn)在都被從grid標(biāo)準(zhǔn)中刪除而被添加進(jìn)盒模型對(duì)齊中了枪汪。與此同時(shí)钞脂,grid-的前綴屬性被重命名為column-gap撒穷、row-gap和gap恋沃。瀏覽器會(huì)將帶有前綴的屬性換為新的重命名屬性,所以如果你在目前的代碼中使用兼容性更好的老名字也不用擔(dān)心枫攀。

重命名意味著這些屬性也能被應(yīng)用于其他布局方法括饶,一個(gè)明顯的備選就是彈性盒子。雖然目前沒有瀏覽器支持盒子模型中的gap屬性来涨,但是在未來我們應(yīng)該可以使用column-gap和row-gap來創(chuàng)建彈性項(xiàng)目元素間的間距图焰。

8.2 關(guān)于box generation的其他閱讀資料

9 多欄布局(多列布局)

多欄布局(multi-column layout)是一種支持創(chuàng)建多欄的布局類型,如同報(bào)紙上那樣蹦掐。每一塊都被分割成欄(column)技羔,你會(huì)按照塊方向在欄中往下讀然后會(huì)在回到下一欄的頂部。然而用這種方式閱讀在網(wǎng)頁(yè)內(nèi)容中并不總是有效卧抗,因?yàn)槿藗儾⒉幌肴プ対L動(dòng)條滾動(dòng)來藤滥、滾動(dòng)去地去閱讀。當(dāng)需要展示少部分內(nèi)容社裆、折疊一組復(fù)選框或者其他一些小的UI組件時(shí)會(huì)非常有用拙绊。

當(dāng)展示一組高度不同的卡片或產(chǎn)品時(shí)多欄布局也非常有用。

9.1 設(shè)置欄的寬度

要設(shè)置一個(gè)最佳的欄寬,并通知瀏覽器依此寬度展示盡可能多的欄可以使用下面的CSS:

.container {
    column-width: 300px;
}

這會(huì)創(chuàng)建盡可能多的300px的欄标沪,所有剩下的空間會(huì)被所有欄共享榄攀。因此,除非空間被劃分為300px時(shí)沒有剩余金句,否則你的欄會(huì)比300px稍多一些檩赢。

9.2 設(shè)置欄的數(shù)目

除了設(shè)置寬度,你可以使用column-count來設(shè)置欄的數(shù)目趴梢。在這種情況下,瀏覽器會(huì)將空間均分給你需要的數(shù)目的欄币他。

.container {
    column-count: 3;
}

如果你同時(shí)添加了column-width和column-count坞靶,那么column-count屬性會(huì)作為一個(gè)最大值限制。在下面的代碼里蝴悉,欄會(huì)被添加直到達(dá)到三個(gè)彰阴,此時(shí)任何額外的空間都會(huì)被分給三欄,即使空間足夠成為一個(gè)額外的新欄拍冠。

.container {
    column-width: 300px;
    column-count: 3;
}

9.3 間距和欄規(guī)則

你無法為單個(gè)欄盒子添加外邊距和內(nèi)邊距尿这,需要用column-gap屬性來設(shè)置間距。如果你不具體指定column-gap的值庆杜,它會(huì)默認(rèn)為1em來防止欄間碰撞射众。這和其他布局方法中column-gap的行為不一樣,其他布局中默認(rèn)為0晃财。你可以在間距上使用任意的長(zhǎng)度單元叨橱,包括0(如果你不希望有欄間距)。

column-rule屬性讓你有能力向兩欄間添加規(guī)則断盛。它是column-rule-width罗洗、column-rule-color和column-rule-style的簡(jiǎn)寫形式,可border行為類似钢猛。注意伙菜,一個(gè)規(guī)則自身不會(huì)占用任何空間。它會(huì)占據(jù)在間距的頂部命迈,從而增加或減少那些你設(shè)置column-gap的規(guī)則與內(nèi)容間的空間贩绕。

div class="container">
  <p>Pea horseradish azuki bean lettuce avocado asparagus okra. Kohlrabi radish okra azuki bean corn fava bean mustard tigernut jícama green bean celtuce. </p>
  <p>Grape silver beet  collard greens avocado quandong fennel gumbo black-eyed pea watercress potato tigernut corn groundnut. Chickweed okra pea winter purslane coriander yarrow sweet pepper radish garlic brussels sprout groundnut summer purslane earthnut pea tomato spring onion azuki bean gourd. Gumbo kakadu plum komatsuna black-eyed pea green bean zucchini gourd winter purslane silver beet rock melon radish asparagus spinach.</p>
</div>
body {
  padding: 20px;
  font: 1em Helvetica Neue, Helvetica, Arial, sans-serif;
}

* {box-sizing: border-box;}

p {
  margin: 0 0 1em 0;
}

.container {
  width: 500px;
  border: 5px solid rgb(111,41,97);
  border-radius: .5em;
  padding: 10px;
  column-width: 120px;
  column-gap: 20px;
  column-rule: 4px dotted #000;
}

9.4 允許元素橫跨多欄

你可以使用column-span屬性讓多欄容器內(nèi)的元素橫跨多欄,類似通欄壶愤。

h3 {
    column-span: all;
}

當(dāng)column-span出現(xiàn)時(shí)丧叽,多欄容器分欄會(huì)在這個(gè)元素上放停下,因此公你,容器里的內(nèi)容會(huì)在元素上方形成多欄樣式踊淳,然后在橫跨元素(spanning element)的下方形成一組新的欄盒子(column box)。

<div class="container">
  <p>Pea horseradish azuki bean lettuce avocado asparagus okra. Kohlrabi radish okra azuki bean corn fava bean mustard tigernut jícama green bean celtuce. </p>
  <h2>Veggies!</h2>
  <p>Grape silver beet  collard greens avocado quandong fennel gumbo black-eyed pea watercress potato tigernut corn groundnut. Chickweed okra pea winter purslane coriander yarrow sweet pepper radish garlic brussels sprout groundnut summer purslane earthnut pea tomato spring onion azuki bean gourd. </p>
</div>
body {
  padding: 20px;
  font: 1em Helvetica Neue, Helvetica, Arial, sans-serif;
}

* {box-sizing: border-box;}

p {
  margin: 0 0 1em 0;
}

.container {
  width: 500px;
  border: 5px solid rgb(111,41,97);
  border-radius: .5em;
  padding: 10px;
  column-width: 120px;
  column-gap: 20px;
  column-rule: 4px dotted #000;
}

.container h2 {
  column-span: all;
  background-color: rgba(193,225,237,.6);
  border:2px solid rgba(193,225,237,.6);
  margin: 1em 0;
  padding: .5em;
}

你只可以使用column-span: all或column-span: none,并不能讓元素橫跨某幾個(gè)欄(非通欄)迂尝。在文章寫作時(shí)脱茉,F(xiàn)irefox還不支持column-span屬性。

9.5 關(guān)于多欄布局的其他閱讀資料

10. 碎片化(Fragmentation)

多欄布局是碎片化(fragmentation)的一個(gè)例子垄开,頁(yè)面內(nèi)容會(huì)被拆分成欄琴许。這和打印時(shí)內(nèi)容被分到不同頁(yè)非常類似。這個(gè)過程是碎片化規(guī)范(Fragmentation specification)處理的溉躲。這個(gè)規(guī)范包括了一些幫助控制內(nèi)容切分的屬性榜田。

例如,如果你有一組置于多欄中的卡片锻梳,并且你想確奔卡片不會(huì)被截為兩半分到不同的欄,你可以使用break-inside屬性的avoid值疑枯”缈椋考慮瀏覽器兼容性的因素,你也可能會(huì)想使用遺留的page-break-inside屬性荆永。

.card {
    page-break-inside: avoid;
    break-inside: avoid;
}

如果你想在heading元素后禁止斷行废亭,你可以使用break-after屬性。

.container h2 {
    page-break-after: avoid;
    break-after: avoid;
}

這些屬性可以被用在打印樣式或多欄樣式中具钥。在下面的例子里豆村,在多欄容器中的三個(gè)段落被拆分到了三欄之中。我為p元素設(shè)置了break-inside: avoid骂删,這意味著每個(gè)多欄會(huì)在自己的欄中結(jié)束(即使這會(huì)使各欄長(zhǎng)度不同)你画。

<div class="container">
  <p>Pea horseradish azuki bean lettuce avocado asparagus okra. Kohlrabi radish okra azuki bean corn fava bean mustard tigernut jícama green bean celtuce. </p>
  <p>Grape silver beet  collard greens avocado quandong fennel gumbo black-eyed pea watercress potato tigernut corn groundnut. Chickweed okra pea winter purslane coriander yarrow sweet pepper radish garlic brussels sprout</p>
  
  <p>Groundnut summer purslane earthnut pea tomato spring onion azuki bean gourd. Gumbo kakadu plum komatsuna black-eyed pea green bean zucchini gourd winter purslane silver beet rock melon radish asparagus spinach.</p>
</div>
body {
  padding: 20px;
  font: 1em Helvetica Neue, Helvetica, Arial, sans-serif;
}

* {box-sizing: border-box;}

p {
  margin: 0 0 1em 0;
}

.container {
  width: 500px;
  border: 5px solid rgb(111,41,97);
  border-radius: .5em;
  padding: 10px;
  column-width: 120px;
  column-gap: 20px;
  column-rule: 4px dotted #000;
}

.container p {
  page-break-inside: avoid;
  break-inside: avoid;
}

10.1 關(guān)于碎片化的其他閱讀資料

11 如何選擇布局類型?

大多數(shù)的網(wǎng)頁(yè)會(huì)混合使用多種布局類型桃漾。各布局規(guī)范都準(zhǔn)確定義了它們之間是如何相互作用的坏匪。例如,你可能會(huì)在網(wǎng)格布局的網(wǎng)格項(xiàng)中使用彈性布局撬统。一些彈性容器可能具有定位屬性或浮動(dòng)适滓。這些規(guī)范根據(jù)最優(yōu)的布局方式已經(jīng)包含了布局模型的混合使用。在這篇指南中恋追,我嘗試概述了這種布局類型的基本使用方式凭迹,來幫助你了解實(shí)現(xiàn)一個(gè)效果可能的最好方法。

然而苦囱,別害怕去運(yùn)用多種方式來實(shí)現(xiàn)布局設(shè)計(jì)嗅绸。擔(dān)心你的選擇會(huì)不會(huì)造成實(shí)際問題的情況比你想象中要少很多。所以請(qǐng)?jiān)陂_始就組織好你的文檔結(jié)構(gòu)撕彤,并且注意你文檔內(nèi)容的可視展示順序鱼鸠。剩下的大部分工作就是在瀏覽器中試試你的布局方式是否符合預(yù)期猛拴。

原文:Getting Started With CSS Layout,感謝作者Rachel Andrew蚀狰。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末愉昆,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子麻蹋,更是在濱河造成了極大的恐慌跛溉,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,123評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件扮授,死亡現(xiàn)場(chǎng)離奇詭異芳室,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)刹勃,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,031評(píng)論 2 384
  • 文/潘曉璐 我一進(jìn)店門堪侯,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人深夯,你說我怎么就攤上這事抖格∨灯唬” “怎么了咕晋?”我有些...
    開封第一講書人閱讀 156,723評(píng)論 0 345
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)收奔。 經(jīng)常有香客問我掌呜,道長(zhǎng),這世上最難降的妖魔是什么坪哄? 我笑而不...
    開封第一講書人閱讀 56,357評(píng)論 1 283
  • 正文 為了忘掉前任质蕉,我火速辦了婚禮,結(jié)果婚禮上翩肌,老公的妹妹穿的比我還像新娘模暗。我一直安慰自己,他們只是感情好念祭,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,412評(píng)論 5 384
  • 文/花漫 我一把揭開白布兑宇。 她就那樣靜靜地躺著,像睡著了一般粱坤。 火紅的嫁衣襯著肌膚如雪隶糕。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,760評(píng)論 1 289
  • 那天站玄,我揣著相機(jī)與錄音枚驻,去河邊找鬼。 笑死株旷,一個(gè)胖子當(dāng)著我的面吹牛再登,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 38,904評(píng)論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼霎冯,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼铃拇!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起沈撞,我...
    開封第一講書人閱讀 37,672評(píng)論 0 266
  • 序言:老撾萬榮一對(duì)情侶失蹤慷荔,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后缠俺,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體显晶,經(jīng)...
    沈念sama閱讀 44,118評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,456評(píng)論 2 325
  • 正文 我和宋清朗相戀三年壹士,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了磷雇。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,599評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡躏救,死狀恐怖唯笙,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情盒使,我是刑警寧澤崩掘,帶...
    沈念sama閱讀 34,264評(píng)論 4 328
  • 正文 年R本政府宣布,位于F島的核電站少办,受9級(jí)特大地震影響苞慢,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜英妓,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,857評(píng)論 3 312
  • 文/蒙蒙 一挽放、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧蔓纠,春花似錦辑畦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,731評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至猴誊,卻和暖如春潦刃,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背懈叹。 一陣腳步聲響...
    開封第一講書人閱讀 31,956評(píng)論 1 264
  • 我被黑心中介騙來泰國(guó)打工乖杠, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人澄成。 一個(gè)月前我還...
    沈念sama閱讀 46,286評(píng)論 2 360
  • 正文 我出身青樓胧洒,卻偏偏與公主長(zhǎng)得像畏吓,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子卫漫,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,465評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容

  • 本文仍舊轉(zhuǎn)載于阮一峰老師 一菲饼、概述 網(wǎng)格布局(Grid)是最強(qiáng)大的 CSS 布局方案。 它將網(wǎng)頁(yè)劃分成一個(gè)個(gè)網(wǎng)格列赎,...
    blossom_綻放閱讀 490評(píng)論 0 0
  • 原文地址 注:此文是我翻譯的第一篇技術(shù)文章宏悦。適合有一定CSS原生網(wǎng)格布局使用經(jīng)驗(yàn)的開發(fā)者(讀前需要先去了解一下原生...
    我不叫沒耐性閱讀 744評(píng)論 0 2
  • 簡(jiǎn)介 CSS Grid布局 (又名"網(wǎng)格"),是一個(gè)基于二維網(wǎng)格布局的系統(tǒng)包吝,旨在改變我們基于網(wǎng)格設(shè)計(jì)的用戶界面方式...
    咕咚咚bells閱讀 2,488評(píng)論 0 4
  • 相信大部分前端小伙伴已經(jīng)有過使用 Grid 布局的體驗(yàn)饼煞,一定是美滋滋。Flex 布局和 Grid 布局作為 CSS...
    藍(lán)線閱讀 3,775評(píng)論 0 3
  • 朋友圈每天都會(huì)曬出各種各樣的美食,精美的蛋糕嚷狞,筋道的面皮块促,花樣繁多,讓你不由感慨床未,高手在民間竭翠。 當(dāng)然,我們也不例外...
    趙粉溫閱讀 540評(píng)論 1 3