本文來自SmashingMagazine上一篇非常不錯的CSS佈局綜述類文章,彙總了各類CSS佈局技術,並提供了這些技術深度閱讀的連結。故而翻譯過來和大家分享,原文連結在文末,感謝作者Rachel Andrew。
引言
無論你是一個想要學習CSS佈局的新手,還是一個比較有經驗但想要進一步鞏固與瞭解最新CSS佈局知識的前端開發者,這篇指南都能幫你全面瞭解如今CSS佈局發展的現狀。
在過去的許多年中,正如翻天覆地的前端開發一般,CSS佈局也產生了巨大的變化。現在我們有需要可選的CSS佈局方式來開發我們的網站,這也就要求我們對這些方式作出選擇。在這片文章裡,我會介紹各種CSS佈局的基本使用方式以及使用的目的。
如果你還是CSS方面的新手並且想要了解什麼是最好的佈局方法,這篇文章正式你所需要的;當然,如果你是一位比較有經驗的開發者,想要了解一些關於CSS佈局的最新知識,這篇文章也不容錯過。當然,我不會將各類技術的細枝末節都放到這篇文章裡(否則可以寫一本書了),而是對各類技術做一個基本的概述,同時會給大家提供相關連結來進一步學習。
1. 正常文件流(Normal Flow)
如果你開啟一個沒有用任何CSS來改變頁面佈局的網頁,那麼網頁元素就會排列在一個正常流(normal flow)之中。在正常流中,元素盒子(boxes)會基於文件的寫作模式(writing mode)一個接一個地排列。這就意味著,如果你的寫作模式是水平方向的(句子是從左到右或從右到左書寫),正常流會垂直地一個接一個排列頁面的塊級元素。
當然,如果你是在一個垂直方向的寫作模式下,句子是垂直方向書寫的,所以塊級元素會水平方法排列。
正常流是一種最基礎的佈局:當你為文件應用了CSS、建立了某些CSS佈局,你其實是讓這些塊做了一個正常文件流之外的“事”。
1.1. 通過頁面結構來發揮正常文件流的優勢
通過確保你書寫的頁面具有良好的頁面結構(well-structured manner),你可以最大程度利用正常流所帶來的優勢。試想一下,如果瀏覽器中沒有正常流,那麼你建立的元素都會堆積在瀏覽器的右上角。這就意味著你必須指定所有的元素的佈局方式。
有了正常流,即使CSS載入失敗了,使用者仍然能閱讀你的頁面內容;同時,一些不使用CSS的工具(例如一些閱讀器)會按照元素在文件中的位置來讀取頁面內容。從 可用性(accessibility) 角度來看,這無疑是非常有幫助的,同時也讓開發者輕鬆了一些。如果你的內容順序和使用者預期的閱讀順序一致,你就不需要為了將元素調整到正確的位置而進行大量的佈局調整。當你繼續讀下去會發現,使用新的佈局方式是如何讓頁面佈局事半功倍的。
因此,在思考如何佈局之前,你需要認真思考你的文件結構,以及你希望使用者以何種順序來閱讀文件中的內容。
1.2. 脫離正常文件流
一旦你有了一個結構良好的頁面,你就需要去決定如何利用它並將它變為我們需要的佈局結構。這會涉及到 脫離正常文件流(moving away from normal flow),即本文後續的部分內容。我們有許多佈局“利器”可以使用,其中第一個就是float
,它是一個描述什麼是脫離正常文件流的非常好的例子。
2. 浮動(Float)
浮動被用來將盒子(box)置於左側或右側,同時讓內容環繞其展示。
要讓一個元素進行浮動,需要為該元素設定一個值為left
或right
的float
屬性。預設值為none
。
.item {
float: left
}複製程式碼
值得強調的是,當你使某個元素浮動並讓文字環繞它時,內容的line box被截斷了。如果你讓一個元素浮動,同時為緊跟著的包含文字的元素設定一個背景色,你會發現背景色會出現在浮動元素下方。
如果你想要在浮動元素和環繞的文字之間建立邊距,你需要給浮動元素設定外邊距。在文字元素上設定外邊距只會讓其相對於容器縮排。例如在下面這個例子中,你就需要為左側浮動的圖片設定右邊距和下邊距。
<
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. 清除浮動
一旦你對一個元素應用了浮動,所有接下來的元素都會環繞它直到內容處於它下方且開始應用正常文件流。如果你想要避免這種情況,可以手動去清除浮動。
當你不想要某個元素受到其之前的浮動元素影響時,為其新增clear
屬性即可。使用left
值可以清除左浮動效果,right
值為右浮動,both
則會清除左右浮動。
.clear {
clear: both;
}複製程式碼
但是,當你發現在容器內有了一個浮動元素,同時容器文字內容過短時就會出現問題。文字盒子會被繪製在浮動元素下,然後接下來的部分會以正常流繪製在其後。
為了避免這種情況,我們需要為容器中某個元素應用clear
屬性。我們可以在容器最後新增一個空元素並設定clear
屬性。但是在某些情況下可能無法使用這種方式(例如一些CMS系統生成的頁面)。因此,最常見的清除浮動的hack方案是:在容器內新增一個CSS偽元素,並將其clear
屬性設定為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;
}複製程式碼
example: Smashing Guide to Layout: clearfix on Codepen
2.2. 塊級格式化上下文(Block Formatting Context)
清除浮動的另一個方法是在容器內建立BFC。一個BFC元素完全包裹住了它內部的所有元素,包括內部的浮動元素,保證浮動元素不會超出其底部。建立BFC的方式有很多種,其中最常用的一種清除浮動的方式是為元素設定除visible(預設)之外的overflow
屬性值。
.container {
overflow: auto;
}複製程式碼
像上面這樣使用overflow
一般情況下是有效的。然而,在某些情況下,這可能會帶來一些陰影的截斷或是非預期的滾動條。同時它也使你的CSS變得不那麼直觀:設定overflow
是因為你想要展示滾動條還是僅僅為了獲取清除浮動的能力呢?
為了使清除浮動的意圖更加直觀,並且避免BFC的負面影響,你可以使用flow-root
作為display
屬性的值。display: flow-root
做的唯一的一件事就是去建立一個BFC,因此可以避免其他建立BFC方法帶來的問題。
.container {
display: flow-root;
}複製程式碼
2.3. 浮動的一些遺留用法
在新的佈局方式出現以前,float
經常會被用來建立多欄佈局。我們會給一系列元素設定寬度並且將它們一個接一個進行浮動。通過為浮動元素設定一些精細的百分比大小可以建立類似網格的效果。
我不建議在當下仍然過度地使用這種方法。但是,在現有的網站中,這種方式仍然會存在許多年。因此,當你碰到一個頁面裡面到處是float
的應用,可以確定它就是用的這種技術。
2.4. 關於浮動與清除浮動的其他閱讀資料
- “The Clearfix: Force an Element To Self-Clear its Children,” Chris Coyier, CSS-Tricks
- “float,” CSS: Cascading Style Sheets, MDN web docs
- “clear,” CSS: Cascading Style Sheets, MDN web docs
- “Understanding CSS Layout And The Block Formatting Context,” Rachel Andrew, Smashing Magazine
3. 定位(Positioning)
想要把一個元素從正常流中移除,或者改變其在正常文件流中的位置,可以使用CSS中的position
屬性。當處於正常文件流時,元素的position
屬性為static
。在塊級維度上元素會一個接一個排列下去,當你滾動頁面時元素也會隨著滾動。
當你改變元素的position屬性時,通常情況下你也會設定一些偏移量來使元素相對於參照點進行一定的移動。不同的position值會產生不同的參照點。
3.1. 相對定位(relative postioning)
如果一個元素具有屬性position: relative
,那麼它偏移的參照位是其原先在正常文件流中的位置。你可以使用top、left、bottom和right屬性來相對其正常流位置進行移動。
.item {
position: relative;
bottom: 50px;
}複製程式碼
注意,頁面上的其他元素並不會因該元素的位置變化而受到影響。該元素在正常流中的位置會被保留,因此你需要自己去處理一些元素內容覆蓋的情況。
<
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;
}複製程式碼
example: Smashing Guide to Layout: position: relative on Codepen
3.2. 絕對定位(absolute postioning)
給一個元素設定position: absolute
屬性可以將其完全從正常流中移除。其原本佔據的空間也會被移除。該元素會定位會相對於視口容器,除非其某個祖先元素也是定位元素(position值不為static)。
因此,當你為某個元素設定position: absolute
時,首先發生的變化是該元素會定位在視口的左上角。你可以通過設定top
、left
、bottom
和right
偏移量屬性來將元素移動到你想要的位置。
.item {
position: absolute;
top: 20px;
right: 20px;
}複製程式碼
通常情況下你並不希望元素相對於視口進行定位,而是相對於容器元素。在這種情況下,你需要為容器元素設定一個除了預設static
之外的值。
由於給一個元素設定position: relative
並不會將其從正常流中移除,所以通常這是一個不錯的選擇。給你想要相對的容器元素設定position : relative
,就可以讓絕對定位的元素相對其進行偏移。
<
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;
}複製程式碼
example: Smashing Guide to Layout: position: absolute on Codepen
3.3. 固定定位(fixed positioning)
大多數情況下,position: fixed
的元素會相對於視口定位,並且會從正常文件流中被移除,不會保留它所佔據的空間。當頁面滾動時,固定的元素會留在相對於視口的位置,而其他正常流中的內容則和通常一樣滾動。
.item {
position: fixed;
top: 20px;
left: 100px;
}複製程式碼
當你想要一個固定導航欄一直停留在螢幕上時這會非常有效。和其他的position值一樣,這也可能會造成一些元素被遮擋,需要小心保證頁面內容的可讀而不會被固定元素遮擋。
<
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;
}複製程式碼
example: Smashing Guide to Layout: position: fixed on Codepen
為了使一個固定定位的元素不相對於視口進行定位,你需要為容器元素設定transform
、perspective
、filter
三個屬性之一(不為預設值none)。這樣固定的元素就會相對於該塊級元素偏移,而非視口。
3.4. STICKY 定位
設定position: sticky
會讓元素在頁面滾動時如同在正常流中,但當其滾動到相對於視口的某個特定位置時就會固定在螢幕上,如同fixed一般。這個屬性值是一個較新的CSS屬性,在瀏覽器相容性上會差一些,但在不相容的瀏覽器中會被忽略並會退到正常的滾動情況。
.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%;
}複製程式碼
example: Smashing Guide to Layout: position: sticky on Codepen
3.5. 關於定位(positioning)的其他閱讀資料
- “Positioning,” MDN Learning Area, MDN web docs, Mozilla
- “position: sticky;
,” Chris Coyier, CSS-Tricks - “CSS position:sticky,” Browser support information for sticky positioning, caniuse
4. 彈性佈局(Flex Layout)
彈性盒子(Flexbox)佈局是一種為一維佈局而設計的佈局方法。一維的意思是你希望內容是按行或者列來佈局。你可以使用display: flex
來將元素變為彈性佈局。
.container {
display: flex;
}複製程式碼
該容器的直接子元素會變為彈性項(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);
}複製程式碼
example: Smashing Guide to Layout: flex on Codepen
4.1. 彈性盒子的軸(axes)
在上面的例子中,我們會稱彈性項在行內是從起始位置開始排列,而不是說它們是左對齊。這些元素會按行排列是因為預設的flex-direction
值為row
,row
代表了文字的行文方向。由於我們工作的環境是英文(中文也是如此),一種自左向右的語言,行的開始位置就是在左邊,因此我們的彈性項也是從左邊開始的。因此flex-direction
的值被定義為彈性盒子的主軸(main axis)。
交叉軸(cross axis)則是和主軸垂直的一條軸。如果你的flex-direction
是row
並且彈性項是按照行內方向排列的,那麼交叉軸就是塊級元素的排列方向。如果flex-direction
是column
那麼彈性項就會以塊級元素排列的方向排布,然後交叉軸就會變為row
。
如果你習慣於從主軸與交叉軸的角度來使用彈性盒子,那麼一切會變得非常簡單。
4.2. 方向和次序
彈性盒子模型讓我們可以通過為flex-direction
屬性設定row-reverse
或column-reverse
值來改變主軸上彈性項的方向。
<
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);
}複製程式碼
example: Smashing Guide to Layout: flex-direction on Codepen
當然,你也可以通過order
屬性來改變某一個彈性項的順序。但是要特別注意,這可能會給那些通過鍵盤(而非滑鼠或觸屏)訪問你的網站的使用者帶來一些麻煩,因為tab的順序是頁面內元素在原始碼中的順序而非顯示順序。你可以閱讀之後的“顯示和文件順序”部分來了解更多相關內容。
4.3. 一些Flex的屬性
這些flex的屬性是用來控制彈性項在主軸上空間大小的。這三個屬性是:
- flex-grow
- flex-shrink
- flex-basis
通常可以使用它們的簡寫形式:flex
。第一個值代表flex-grow
,第二個是flex-shrink
,而第三個則是flex-basis
。
.item {
flex: 1 1 200px;
}複製程式碼
flex-basis
會為彈性項設定未拉伸和壓縮時的初始大小。在上面的例子中,大小是200px,因此我們會給每個項200px的空間大小。但是大多數情況下容器元素大小不會正好被分為許多200px大小的項,而是可能有一些不足或剩餘空間。flex-grow
和flow-shrink
屬性允許我們在容器大小不足或有空餘時控制各個彈性項的大小。
如果flex-grow
的值是任意的正數,那麼彈性項會被允許拉伸來佔據更多的空間。因此,在上面的例子中,當各項被設為200px後,所有多餘的空間會被每個彈性項平分並填滿。
如果flex-shrink
的值為任意的正數,那麼當彈性項被設定了flex-basis
後,元素溢位容器時會進行收縮。在上面這個CSS的例子中,如果容器空間不足,每個彈性項會等比例縮放以適應容器的大小。
flex-grow
和flex-shrink
的值可以是任意的正數。一個具有較大flex-grow
值的彈性項會在容器有剩餘空間時拉伸更大的比例;而一個具有更大flex-shrink
值的項則會在容器空間不足時被壓縮的更多。
<
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;
}複製程式碼
example: Smashing Guide to Layout: flex properties on Codepen
理解這些屬性是理解如何使用彈性佈局的關鍵,下面列出的一些資源會幫助我們進一步學習其中的細節。當你需要在容器的一個維度上拉伸或者壓縮一些元素時,你可以考慮使用彈性盒子模型。如果你發現你正嘗試在行和列兩個維度上排列你的內容,你需要的是網格模型(grid),這時彈性盒子模型很可能不是最合適的工具了。
4.4. 關於彈性盒子佈局的其他閱讀資料
- “CSS Flexible Box Layout,” A complete guide to the specification, MDN web docs, Mozilla
- “A Complete Guide to Flexbox,” Chris Coyier, CSS-Tricks
- “Flexbox Froggy,” A game for learning Flexbox
- “Flexbugs,” A community curated list of browser bugs relating to Flexbox
- Learn Flexbox for free – 12 interactive screencasts to take you from beginner to advanced from scrimba(譯者薦)
5. 網格佈局(grid layout)
CSS網格佈局(grid layout)是一種用來進行二維佈局的技術。二維(two-dimesional)意味著你希望按照行和列來排布你的內容。和彈性盒子類似,網格佈局也需要設定一個display
值。你可以為容器元素設定display: grid
,並且使用grid-template-columns
和grid-template-rows
屬性來控制網格中的行與列。
.container {
display: grid;
grid-template-columns: 200px 200px 200px;
grid-template-rows: 200px 200px;
}複製程式碼
上面這段CSS會建立一個行列元素大小固定的網格。不過這也許並不是你希望的。預設值為auto
,你可以認為這代表了“讓格子儘可能的大”。如果你每沒有指定行(row track)的大小,所有新增進來的行內容大小都會被置為auto
。一種常用的模式是為網格制定列寬度,但是允許網格按需新增行。
你可以使用任意的長度單位或時百分比來設定行與列,同時你可以使用為網格系統所創造的新的單位——fr
。fr
是一種彈性單位,它可以指定網格容器內的空間被如何劃分。
網格會替你計算與分配空間,你不需要去計算元素的百分比去適應容器大小。在下面這個例子中,我們使用fr
來建立網格的列,這使得網格的列可以自適應。同時我們還使用了grid-gap
來保證元素間的間距(關於網格內元素與的間距會在“對齊”這一部分詳細介紹)。
<
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);
}複製程式碼
example: Smashing Guide to Layout: a simple grid on Codepen
5.1. 關於網格的一些術語
網格系統總是有兩個軸:inline axis表示頁面中文字的文字排列的方向,block axis表示頁面中塊級元素的排列方向。
一個被設定為display: grid
的元素就是所謂的網格容器。在網格容器中會有網格線(grid line),網格線就是你在指定grid-template-columns
和grid-template-rows
時網格中行列所生成的。網格中的最小單位(也就是被四條網格線擷取生成的區域)被成為網格單元格(grid cell),進一步的,由若干個單元格組成的矩形區域被成為網格區域(grid area)。
5.2. 網格的自動排列規則
一旦你建立了網格,那麼網格容器的直接子元素就會開始將它們自己一個一個地放置在網格的單元格中。子元素的放置是依據網格的自動排列規則(auto-placement rule)。這些規則確保了網格內元素是被安排在各個空的單元格中,而不會彼此遮蓋。
網格中任何沒有被進行定位的直接子元素都會根據自動排列規則進行放置。在下面這個列子中,我讓每三個元素中的第一個佔據兩行,但仍然從起始行開始去自動排列。
<
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);
}複製程式碼
example: Smashing Guide to Layout: auto-placement on Codepen
5.3. 基於行/列的基本定位方法
定位網格元素最簡單的方式是使用基於行/列(line)的定位方法,只需告訴瀏覽器從哪一排到哪一排來進行合併。例如,如果你需要一個2*2的網格區域,你可以將指定元素從第一行開始到第三行、從第一列開始到第三列,這樣就可以覆蓋到四個單元格。
.item {
grid-column-start: 1;
grid-column-end: 3;
grid-row-start: 1;
grid-row-end: 3;
}複製程式碼
這些屬性可以用縮寫來表示:grid-column
和grid-row
,其中起一個值代表起始值,第二個值代表結束值。
.item {
grid-column: 1 / 3;
grid-row: 1 / 3;
}複製程式碼
你也可以讓網格項(grid item)佔據同一個單元格。支援一些內容間會覆蓋的設計。網格項會像通常網頁中的元素那樣疊起來,在html原始碼中下面的網格項會疊在其他元素上面。你仍然可以用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);
}複製程式碼
example: Smashing Guide to Layout: line-based placement on Codepen
5.4. 通過命名區域來定位元素
你可以通過命名區域(named areas)來定位網格中的元素。要是用這種方式,你需要給每個元素一個名字,然後通過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";
}複製程式碼
使用這種方式有幾個需要注意的點。如果你想要合併一些單元格作為你的網格項,你需要重複元素的名字。網格區域需要能形成一個完整的矩形 —— 每個單元格都需要被填入一個值。如果你想要空出某些單元格,那就需要使用.
這個值。例如在下面的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;
}複製程式碼
example: Smashing Guide to Layout: grid-template-areas on Codepen
5.5. 關於網格佈局的其他閱讀資料
這片文章只包括了CSS網格佈局的一些初步內容,其中還有非常多的內容值得學習,下面的一些資料可以幫助你進一步學習。一些元件或整個頁面的佈局都可以使用網格。如果你需要在兩個維度進行佈局,網格佈局是一個不錯的選擇 —— 不論需要佈局的區域的大小。
- “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
- Learn CSS Grid for free – 14 interactive screencasts to take you from beginner to advanced from scrimba(譯者薦)
我(作者)在Smashing Magazine也寫一些文章來幫助你深入理解各種網格的概念:
- “Best Practices With CSS Grid Layout”
- “Styling Empty Cells With Generated Content And CSS Grid Layout”
- “Using CSS Grid: Supporting Browsers Without Grid”
- “CSS Grid Gotchas And Stumbling Blocks”
- “Naming Things In CSS Grid Layout”
6. 顯示順序和文件順序(visual and document order)
在文章的最開始,我建議你以從上到下的閱讀順序來組織你的文件順序,這樣會有助於可讀性和CSS的佈局方式。從我們關於彈性盒子和CSS網格的簡短介紹來看,你可以發現用這些佈局方法可能會極大地改變頁面展示的元素在文件中的順序。這可能會導致一個隱含的問題。
在一些非視覺化的應用場景中,瀏覽器會遵循文件原始碼來進行使用。因此,螢幕閱讀器會讀取文件的順序,此外使用鍵盤tab鍵來瀏覽的使用者訪問文件的順序是基於原始碼的順序,而不是元素展示的順序。許多螢幕閱讀器的使用者並非完全失明,他們可能在使用螢幕閱讀器的同時也能夠看到這些元素在文件的哪個部分。在這些情況下,當與原始碼進行對比時,這種混亂的頁面展現可能會令人充滿迷惑。
當你改變了元素在文件中原來的順序時,一定確保知道自己在做什麼。如果你發現你自己正在CSS中重新排序你的元素,你應該去回頭看看是否要重新組織你的頁面元素。你可以通過使用tab訪問來測試一下你的頁面。
6.1. 關於顯示順序和文件順序的其他閱讀資料
- “CSS Grid Layout and Accessibility,” Web technology for developers, MDN web docs, Mozilla
- “HTML Source Order vs CSS Display Order,” Adrian Roselli
- “Flexbox And The Keyboard Navigation Disconnect,” Code Things, Tink
- “The Responsive Order Conflict For Keyboard Focus,” Alastair Campbell
7. 盒模型的生成(box generation)
你寫在網頁裡的任何東西都會生成一個盒子(box),這篇文章討論的所有東西其實都是如何能夠使用CSS來按照你的設計佈局這些盒子。然而,在某些情況下,你可能根本不想建立一個盒子。有兩個display
的屬性值會幫你處理這種情況。
7.1. 不生成盒子或內容(display: none
)
如果你希望元素以及它所有的內容(包括所有子元素)都不會生成,你可以使用display: none
。這樣元素就不會被展示,並且不會保留其本該佔有的空間。
.item {
display: none;
}複製程式碼
7.2 不生成該元素,但是生成其所有子元素(display: contents
)
display: content
是display
的一個新的屬性值。為一個元素應用display: content
屬性會導致其自身的盒子不生成但所有的子元素都會照常生成。這有什麼用呢?試想一下,如果你希望一個彈性佈局或網格佈局中的非直接子元素能應用這些佈局,這就會非常有用。
在下面這個例子裡,第一個彈性項包含了兩個子元素,由於它被設為display: contents
,它的盒子不會生成並且它的兩個子元素會成為彈性項,並被當作彈性盒子容器的直接子元素來佈局。
<
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;
}複製程式碼
example: Smashing Guide to Layout: display: contents on Codepen
7.3. 關於box generation的其他閱讀資料
- “Vanishing Boxes With display: contents,” Rachel Andrew
- How display: contents;
Works,” Ire Aderinokun, - CSS display: contents,” Browser support information, caniuse
8. 對齊
在以前,要實現對齊往往會用到一些很”tricky”的方式,並且能夠使用的方法也非常有限。隨著CSS盒模型對齊(box alignment module)的出現,這一切都發生了變化。你將會使用它來控制網格容器與彈性盒子容器中的對齊。未來其他的各種佈局方法都會應用這些對齊屬性。盒模型對齊(box alignment specification)規範中的一系列詳細屬性如下:
justify-content
align-content
place-content
justify-items
align-items
place-items
justify-self
align-self
place-self
row-gap
column-gap
gap
由於不同的佈局模型有不同的特性,因此用於不同佈局模型的對齊屬性會有一些表現上的差異。讓我們來看看在一些簡單的網格與彈性佈局中對齊是如何工作的。
align-items
和justify-items
屬性相對是align-self
和justify-self
屬性的一種批量形式。這些屬性會控制與元素在其網格區域(grid area)中的對齊情況。
<
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);
}複製程式碼
example: Smashing Guide to Layout: Grid align-items, justify-items, align-self, justify-self on Codepen
align-content
和justify-content
屬性則會對網格中的行/列(tracks)進行對齊控制(網格容器中需要在排列完行/列元素後有多餘的空間)。
<
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);
}複製程式碼
example: Smashing Guide to Layout: Grid align-content, justify-content on Codepen
在彈性盒子中,align-items
和align-self
用來解決交叉軸上的對齊問題,而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);
}複製程式碼
example: Smashing Guide to Layout: Flex justify-content, align-items, align-self on Codepen
在交叉軸上,把彈性行(flex line)和額外空間包裹在彈性容器中之後,你就可以使用align-content
了。
<
div class="container">
<
div>
1<
/div>
<
div>
2<
/div>
<
div>
3<
/div>
<
div>
4<
/div>
<
div>
5<
/div>
<
/div>
複製程式碼
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);
}複製程式碼
example: Smashing Guide to Layout: Flex align-content on Codepen
下面的一些連結更細節地討論了各類佈局方法中的盒模型對齊。花些時間去理解對齊的工作原理是非常值得的,它對理解彈性盒子、網格佈局以及未來的一些佈局方法都會很有幫助。
8.1. 行/列的間隔
一個多欄佈局具有column-gap
屬性,到目前位置,網格佈局具有grid-column-gao
、grid-row-gap
和grid-grid
。這些現在都被從grid標準中刪除而被新增進盒模型對齊中了。與此同時,grid-
的字首屬性被重新命名為column-gap
、row-gap
和gap
。瀏覽器會將帶有字首的屬性換為新的重新命名屬性,所以如果你在目前的程式碼中使用相容性更好的老名字也不用擔心。
重新命名意味著這些屬性也能被應用於其他佈局方法,一個明顯的備選就是彈性盒子。雖然目前沒有瀏覽器支援盒子模型中的gap屬性,但是在未來我們應該可以使用column-gap
和row-gap
來建立彈性專案元素間的間距。
8.2. 關於box generation的其他閱讀資料
- “CSS Box Alignment,” CSS: Cascading Style Sheets, MDN web docs, Mozilla
- “Box Alignment in Flexbox,” CSS Flexible Box Layout, MDN web docs, Mozilla
- “Box Alignment in CSS Grid Layout,” CSS Grid Layout, MDN web docs, Mozilla
- “The New Layout Standard For The Web: CSS Grid, Flexbox And Box Alignment,” Rachel Andrew, Smashing Magazine
- “Box Alignment Cheatsheet,” Rachel Andrew
9. 多欄佈局(多列布局)
多欄佈局(multi-column layout)是一種支援建立多欄的佈局型別,如同報紙上那樣。每一塊都被分割成欄(column),你會按照塊方向在欄中往下讀然後會在回到下一欄的頂部。然而用這種方式閱讀在網頁內容中並不總是有效,因為人們並不想去讓滾動條滾動來、滾動去地去閱讀。當需要展示少部分內容、摺疊一組核取方塊或者其他一些小的UI元件時會非常有用。
當展示一組高度不同的卡片或產品時多欄佈局也非常有用。
9.1. 設定欄的寬度
要設定一個最有的欄寬,並通知瀏覽器依此寬度展示儘可能多的欄可以使用下面的CSS:
.container {
column-width: 300px;
}複製程式碼
這會建立儘可能多的300px的欄,所有剩下的空間會被所有欄共享。因此,除非空間被劃分為300px時沒有剩餘,否則你的欄會比300px稍多一些。
9.2. 設定欄的數目
除了設定寬度,你可以使用column-count
來設定欄的數目。在這種情況下,瀏覽器會將空間均分給你需要的數目的欄。
.container {
column-count: 3;
}複製程式碼
如果你同時新增了column-width
和column-count
,那麼column-count
屬性會作為一個最大值限制。在下面的程式碼裡,欄會被新增直到達到三個,此時任何額外的空間都會被分給三欄,即使空間足夠成為一個額外的新欄。
.container {
column-width: 300px;
column-count: 3;
}複製程式碼
9.3. 間距和欄規則
你無法為單個欄盒子新增外邊距和內邊距,需要用column-gap
屬性來設定間距。如果你不具體指定column-gap
的值,它會預設為1em來防止欄間碰撞。這和其他佈局方法中column-gap
的行為不一樣,其他佈局中預設為0。你可以在間距上使用任意的長度單元,包括0(如果你不希望有欄間距)。
column-rule
屬性讓你有能力向兩欄間新增規則。它是column-rule-width
、column-rule-color
和column-rule-style
的簡寫形式,可border行為類似。注意,一個規則自身不會佔用任何空間。它會佔據在間距的頂部,從而增加或減少那些你設定column-gap
的規則與內容間的空間。
<
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;
}複製程式碼
example: Smashing Guide to Layout: multicol on Codepen
9.4. 允許元素橫跨多欄
你可以使用column-span
屬性讓多欄容器內的元素橫跨多欄,類似通欄。
h3 {
column-span: all;
}複製程式碼
當column-span
出現時,多欄容器分欄會在這個元素上放停下,因此,容器裡的內容會在元素上方形成多欄樣式,然後在橫跨元素(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;
}複製程式碼
example: Smashing Guide to Layout: multicol span on Codepen
你只可以使用column-span: all
或column-span: none
,並不能讓元素橫跨某幾個欄(非通欄)。在文章寫作時,Firefox還不支援column-span
屬性。
9.5. 關於多欄佈局的其他閱讀資料
- “Using Multi-Column Layouts,” CSS Multi-column Layout, MDN web docs, Mozilla
10. 碎片化(Fragmentation)
多欄佈局是碎片化(fragmentation)的一個例子,頁面內容會被拆分成欄。這和列印時內容被分到不同頁非常類似。這個過程是碎片化規範(Fragmentation specification)處理的。這個規範包括了一些幫助控制內容切分的屬性。
例如,如果你有一組置於多欄中的卡片,並且你想確保卡片不會被截為兩半分到不同的欄,你可以使用break-inside
屬性的avoid
值。考慮瀏覽器相容性的因素,你也可能會想使用遺留的page-break-inside
屬性。
.card {
page-break-inside: avoid;
break-inside: avoid;
}複製程式碼
如果你想在heading元素後禁止斷行,你可以使用break-after
屬性。
.container h2 {
page-break-after: avoid;
break-after: avoid;
}複製程式碼
這些屬性可以被用在列印樣式或多欄樣式中。在下面的例子裡,在多欄容器中的三個段落被拆分到了三欄之中。我為p
元素設定了break-inside: avoid
,這意味著每個多欄會在自己的欄中結束(即使這會使各欄長度不同)。
<
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;
}複製程式碼
example: Smashing Guide to Layout: multicol fragmentation on Codepen
10.1. 關於碎片化的其他閱讀資料
- “A Guide To The State Of Print Stylesheets In 2018,” Rachel Andrew, Smashing Magazine
- “Column Breaks,” QuirksMode.org
11. 如何選擇佈局型別?
大多數的網頁會混合使用多種佈局型別。各佈局規範都準確定義了它們之間是如何相互作用的。例如,你可能會在網格佈局的網格項中使用彈性佈局。一些彈性容器可能具有定位屬性或浮動。這些規範根據最優的佈局方式已經包含了佈局模型的混合使用。在這篇指南中,我嘗試概述了這種佈局型別的基本使用方式,來幫助你瞭解實現一個效果可能的最好方法。
然而,別害怕去運用多種方式來實現佈局設計。擔心你的選擇會不會造成實際問題的情況比你想象中要少很多。所以請在開始就組織好你的文件結構,並且注意你文件內容的可視展示順序。剩下的大部分工作就是在瀏覽器中試試你的佈局方式是否符合預期。
原文:Getting Started With CSS Layout,感謝作者Rachel Andrew。