想象一雙結實而富有彈性的大腿:理解 Flexbox 佈局
說明
本站不支援 CodePen 的指令碼插入,可以到我的部落格閱讀直接顯示示例程式碼的版本。
Flexbox 讓人困惑
有很多談及 Flexbox 的文章,但依然有不少前端對此感到困惑。一方面,flex 相關的 CSS 屬性繁多,影響到的具體效果也包含多個方面;另一方面,CSS 可以使用 Shorthand properties 風格的寫法(例如最常見的 background: url(images/bg.gif) no-repeat left top;
),很容易讓新手弄不清具體含義。
這篇文章要講的 Flexbox 當然還是 CSS3 規範中的彈性盒模型,不過寫出前面一段,是因為我希望這篇文章可以解決那些問題——簡單說,就是 Flexbox 讓人困惑這樣的問題。解決的方法,就是理解它。
什麼時候,我們會想到彈性
為了理解彈性盒模型,先要從古龍的筆法開始。古龍是臺灣的武俠小說大師,成就僅次於金庸。古龍描寫的一些人物,非常深入人心,其犀利以及令人難忘的程度,甚至超過金庸。比如,有一位中年男性,在整部小說裡,他的手非常重要,古龍對此有多次描寫——“他的手指修長而有力”。而在不止一本書中,不止一兩個情節中,有幾位青年女性,她們的腿非常重要,古龍的描述是——“大腿結實而富有彈性”,或者“修長結實而富有彈性”。
輕呼一口氣,思考一下,為什麼描寫手指的時候要說“修長而有力”,而描寫大腿卻是“結實而富有彈性”?這真是一個非常值得思考的問題。實際上,人的腿也可以是“修長而有力”的;而且,人的手指也是有彈性的。但古大師的描寫絕非隨意為之,其中的道理,可以隨便找些包含大腿的人物畫看一看,或者只是想象一下——一幅人物畫中,手指的面積有多大?除非為了強調手部而加了特技,否則手指所佔的面積是很小的;而大腿,在一幅正常的人物畫中,是充滿空間的。這裡說的充滿,當然並不是指完全佔滿空間,也不是上下左右一定沒有空隙。
記住這種“充滿”,現在思考一下 Flexbox。什麼時候,我們會想到或者說需要彈性這件事情?答案是當我們需要“充滿”一個容器的時候。帶著這種思考,再回到人物畫。手指只是在畫面的特定位置,解決這種問題,我們可以簡單地用 position: absolute;
或 float: left;
這些屬性搞定。而大腿是“充滿”畫面的,當我們需要“充滿”容器的時候,彈性就很重要!要解決這類問題,我們應該思考的就不是某個區域性的空間,而是空間的分配。包括如何分配容器內的所有盒子,如果空間過大怎麼辦,如果空間過小怎麼辦;而在移動端,裝置的螢幕尺寸有很多種,問題就變成了空間有時候大、有時候小怎麼辦。
讀者應該已經能夠想到,彈性盒模型就是為了更方便地解決這些問題而產生的。那麼先看一看非彈性的盒子遇到這些場景會有哪些不便。
百分比網格
See the Pen understanding-css-flexbox 1: percentage by Alpha Bao (@AlphaBao) on CodePen.
上面是用浮動和百分比的方式寫的橫向網格,由於直接給其中一個設定了不同的高度,很明顯,可以看出,四個格子的高度是不同的。如果格子的高度變化是由其中的內容引起,也會存在同樣的問題。
另外,示例之中是四個格子,所以設定每個格子為 width: 25%;
就可以讓它們橫向充滿父級容器,而且大小變化也沒有影響。但如果需要渲染的資料是動態的,寫成具體某個百分比顯然就不行了。即元素個數變化時每個元素的百分比也需要變化,就需要修改 CSS。
這些問題都是因為這樣的盒模型是沒有“彈性”的,如果有彈性,就可以讓佈局按照我們希望的方式渲染。
Flex 網格
.container {
display: flex;
}
彈性盒模型帶來了 Flexbox 佈局,像上面這樣,給充當 container 的盒子設定 display: flex;
就可以讓它的子元素彈性排列,預設是橫向的,因為 flex-direction: row;
是預設值,我們先不關心它。先看一下最常用的屬性 flex-grow
。
flex-grow
See the Pen understanding-css-flexbox 2: flex-grow by Alpha Bao (@AlphaBao) on CodePen.
可以看到其中一個是 flex-grow: 2;
,其他都是 1,意思是這些子元素將充滿容器,它們將容器分成了若干份,每個 flex-grow: 1;
元素佔據一份,flex-grow: 2;
的佔兩份,因為它的 flex-grow
值是其他元素的兩倍。也就是說,flex-grow
決定子元素如何膨脹。在 Flexbox 的充滿/填充策略中,flex-grow
影響的是元素膨脹到多大。注意這其實是如何分配父級容器空間的問題,而且是容器大小會改變的情形下,所以具體子元素的大小是取決於空間剩餘情況的,並不是 flex-grow
越大,元素就一定會越大。
flex-basis
再看 flex-basis
屬性,它是指元素的初始大小,上一個例子中,只設定了 flex-grow
,所以初始大小就是元素內容決定的,如果元素沒有內容,大小就是零。
See the Pen understanding-css-flexbox 3: flex-basis by Alpha Bao (@AlphaBao) on CodePen.
flex-basis
的預設值是 auto
,是指元素的大小(本文中指的是元素橫向的長度,因為 flex-direction
預設值是 row
,這決定了 main axis(主軸)是橫向的,即容器的子元素橫向排列)根據元素的長度屬性或者由內容決定。可以是具體長度值也可以是百分比。
.c3 {
width: 15em;
flex-basis: auto;
}
此時初始寬度是 15em
,也可以寫為下面這樣:
.c3 {
flex-basis: 15em;
}
兩種寫法效果相同。
計算完初始大小,再根據容器空間剩餘情況,繼續完成“充滿”容器這件事情。如果先只考慮空間還有剩餘的情況,前面提到的 flex-grow
屬性就開始起作用,使元素膨脹,直到充滿容器。
flex-shrink
前面考慮的都是空間還有剩餘的情況,接下來考慮一下空間不足的情況。首先要弄清楚,具體怎樣會導致空間不足。
See the Pen understanding-css-flexbox 4: flex-shrink by Alpha Bao (@AlphaBao) on CodePen.
可以看到,通過設定寬度或者由內容填充,此時可能導致空間不足。此時 flex-shrink
會起作用。首先計算初始大小,再考慮空間不足的情況,這時候根據 flex-shrink
的值決定如何收縮各個元素,數值越大,相對其他元素的收縮倍數就越大。flex-shrink
預設值是 1
,即不改變這個屬性值的情況下,空間不足時每個元素的收縮程度相同。如果改為 0
,則不收縮。
flex
flex 是上面三者的簡寫形式(這類寫法的屬性就是 Shorthand properties)。
.item {
flex: none | [ <'flex-grow'> <'flex-shrink'>? || <'flex-basis'> ]
}
See the Pen understanding-css-flexbox 5: flex by Alpha Bao (@AlphaBao) on CodePen.
上面的每個子元素都設定了 flex: 1 1 100px;
,即初始寬度值是 100px,如果空間剩餘,每個元素平均分配,如果空間不足,每個元素同等程度的收縮。flex: 0 1 auto;
是 flex
屬性的預設值,表示不膨脹(如果都不膨脹,那麼有剩餘空間也不會充滿),收縮因數是 1
,元素在主軸方向上的長度取決於長度值或者元素內容。
通過上面幾個例子,可以看得出在大小會動態變化的父級容器裡面,這種分配空間的策略優勢很明顯,這就是彈性帶來的便利。flex
是實際開發中常用的寫法,它的內容其實就是如何“充滿”容器空間的策略,是 Flexbox 中最重要的部分。
結束語
本文只談及了 flex-grow
flex-shrink
flex-basis
,關於 Flexbox,還有很多內容。比如決定纏繞方式的 flex-wrap
,它的效果類似 float
,還有 justify-content
,它決定元素在 main axis(主軸)方向的對齊方式,align-self
則決定 cross axis(垂直的交叉軸)方向(在例如主軸是水平方向,而各個元素具有不同的高度這類情況下起作用)。屬性名有點亂,不過它們都是圍繞充滿和彈性擴充套件開的。只要結合對“充滿”空間這件事情的想象,理解了彈性的含義,就弄清了目標與方法,應該能比較容易地學會並運用 Flexbox 了。
如上所見,本文所談的,並不是大腿這件事情,如果你想看“真正的”大腿,可以讀一讀古龍的《多情劍客無情劍》、《午夜蘭花》、《長生劍》以及《蕭十一郎》。
擴充套件閱讀
相關文章
- flexbox(彈性盒佈局模型),以及適用場景Flex模型
- flex佈局(彈性佈局)Flex
- 彈性佈局(伸縮佈局)
- flex彈性佈局 響應式佈局Flex
- Flex-彈性佈局Flex
- display:flex 彈性佈局Flex
- flex 彈性佈局的基本操作Flex
- React Native flexBox佈局(一)React NativeFlex
- flex彈性佈局 垂直居中Flex
- css之彈性佈局(flex)CSSFlex
- 彈性盒模型,flex佈局模型Flex
- CSS:彈性佈局(display:flex)CSSFlex
- flex彈性佈局的基本介紹Flex
- iOS 上的 FlexBox 佈局iOSFlex
- 深入理解聖盃佈局和雙飛翼佈局
- CSS3-彈性佈局篇CSSS3
- React Native——flex(彈性佈局)React NativeFlex
- Flexbox——快速佈局神器Flex
- Android上的Flexbox佈局AndroidFlex
- css彈性佈局程式碼例項CSS
- flex彈性佈局程式碼例項Flex
- 元素水平垂直居中【彈性佈局 || Translate】
- iOS Flexbox 佈局優化iOSFlex優化
- React Native佈局(flexbox)React NativeFlex
- 淘寶彈性佈局方案lib-flexible實踐Flex
- CSS-彈性佈局3-伸縮屬性CSS
- 佈局總結-水平居中佈局的實現
- Flex彈性佈局(附超Q小demo)Flex
- 前端面試3:flex彈性盒佈局前端面試Flex
- display: flex彈性佈局程式碼例項Flex
- CSS-彈性佈局2-交叉軸CSS
- CSS3佈局神器 - FlexboxCSSS3Flex
- React Native 之 flexbox佈局React NativeFlex
- CSS 3中彈性盒佈局的最新版CSS
- Flexbox 佈局的最簡單表單Flex
- Flexbox 佈局的正確使用姿勢Flex
- CSS佈局–聖盃佈局和雙飛翼佈局以及使用Flex實現聖盃佈局CSSFlex
- css--flex彈性佈局詳解和使用CSSFlex