本站不支持 CodePen 的腳本插入,能夠到個人博客閱讀直接顯示示例代碼的版本。css
有不少談及 Flexbox 的文章,但依然有很多前端對此感到困惑。一方面,flex 相關的 CSS 屬性繁多,影響到的具體效果也包含多個方面;另外一方面,CSS 可使用 Shorthand properties 風格的寫法(例如最多見的 background: url(images/bg.gif) no-repeat left top;
),很容易讓新手弄不清具體含義。前端
這篇文章要講的 Flexbox 固然仍是 CSS3 規範中的彈性盒模型,不過寫出前面一段,是由於我但願這篇文章能夠解決那些問題——簡單說,就是 Flexbox 讓人困惑這樣的問題。解決的方法,就是理解它。css3
爲了理解彈性盒模型,先要從古龍的筆法開始。古龍是臺灣的武俠小說大師,成就僅次於金庸。古龍描寫的一些人物,很是深刻人心,其犀利以及使人難忘的程度,甚至超過金庸。好比,有一位中年男性,在整部小說裏,他的手很是重要,古龍對此有屢次描寫——「他的手指修長而有力」。而在不止一本書中,不止一兩個情節中,有幾位青年女性,她們的腿很是重要,古龍的描述是——「大腿結實而富有彈性」,或者「修長結實而富有彈性」。ide
輕呼一口氣,思考一下,爲何描寫手指的時候要說「修長而有力」,而描寫大腿倒是「結實而富有彈性」?這真是一個很是值得思考的問題。實際上,人的腿也能夠是「修長而有力」的;並且,人的手指也是有彈性的。但古大師的描寫絕非隨意爲之,其中的道理,能夠隨便找些包含大腿的人物畫看一看,或者只是想象一下——一幅人物畫中,手指的面積有多大?除非爲了強調手部而加了特技,不然手指所佔的面積是很小的;而大腿,在一幅正常的人物畫中,是充滿空間的。這裏說的充滿,固然並非指徹底佔滿空間,也不是上下左右必定沒有空隙。佈局
記住這種「充滿」,如今思考一下 Flexbox。何時,咱們會想到或者說須要彈性這件事情?答案是當咱們須要「充滿」一個容器的時候。帶着這種思考,再回到人物畫。手指只是在畫面的特定位置,解決這種問題,咱們能夠簡單地用 position: absolute;
或 float: left;
這些屬性搞定。而大腿是「充滿」畫面的,當咱們須要「充滿」容器的時候,彈性就很重要!要解決這類問題,咱們應該思考的就不是某個局部的空間,而是空間的分配。包括如何分配容器內的全部盒子,若是空間過大怎麼辦,若是空間太小怎麼辦;而在移動端,設備的屏幕尺寸有不少種,問題就變成了空間有時候大、有時候小怎麼辦。flex
讀者應該已經可以想到,彈性盒模型就是爲了更方便地解決這些問題而產生的。那麼先看一看非彈性的盒子遇到這些場景會有哪些不便。ui
See the Pen understanding-css-flexbox 1: percentage by Alpha Bao (@AlphaBao) on CodePen.flexbox
上面是用浮動和百分比的方式寫的橫向網格,因爲直接給其中一個設置了不一樣的高度,很明顯,能夠看出,四個格子的高度是不一樣的。若是格子的高度變化是由其中的內容引發,也會存在一樣的問題。url
另外,示例之中是四個格子,因此設置每一個格子爲 width: 25%;
就可讓它們橫向充滿父級容器,並且大小變化也沒有影響。但若是須要渲染的數據是動態的,寫成具體某個百分比顯然就不行了。即元素個數變化時每一個元素的百分比也須要變化,就須要修改 CSS。spa
這些問題都是由於這樣的盒模型是沒有「彈性」的,若是有彈性,就可讓佈局按照咱們但願的方式渲染。
.container {
display: flex;
}複製代碼
彈性盒模型帶來了 Flexbox 佈局,像上面這樣,給充當 container 的盒子設置 display: flex;
就可讓它的子元素彈性排列,默認是橫向的,由於 flex-direction: row;
是默認值,咱們先不關心它。先看一下最經常使用的屬性 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-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
屬性就開始起做用,使元素膨脹,直到充滿容器。
前面考慮的都是空間還有剩餘的狀況,接下來考慮一下空間不足的狀況。首先要弄清楚,具體怎樣會致使空間不足。
See the Pen understanding-css-flexbox 4: flex-shrink by Alpha Bao (@AlphaBao) on CodePen.
能夠看到,經過設置寬度或者由內容填充,此時可能致使空間不足。此時 flex-shrink
會起做用。首先計算初始大小,再考慮空間不足的狀況,這時候根據 flex-shrink
的值決定如何收縮各個元素,數值越大,相對其餘元素的收縮倍數就越大。flex-shrink
默認值是 1
,即不改變這個屬性值的狀況下,空間不足時每一個元素的收縮程度相同。若是改成 0
,則不收縮。
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 了。
如上所見,本文所談的,並非大腿這件事情,若是你想看「真正的」大腿,能夠讀一讀古龍的《多情劍客無情劍》、《午夜蘭花》、《長生劍》以及《蕭十一郎》。