注意:假如你想設(shè)置行內(nèi)元素為 flexible box,也可以置 display 屬性的值為 inline-flex。
flex 模型說明
當(dāng)元素表現(xiàn)為 flex 框時(shí),它們沿著兩個(gè)軸來布局:

- 主軸(main axis)是沿著 flex 元素放置的方向延伸的軸(比如頁面上的橫向的行、縱向的列)。該軸的開始和結(jié)束被稱為** main start** 和** main end**。
- 交叉軸(cross axis)是垂直于 flex 元素放置方向的軸。該軸的開始和結(jié)束被稱為 cross start 和** cross end**。
- 設(shè)置了
display: flex的父元素(在本例中是<section>)被稱之為 flex 容器(flex container)。 - 在 flex 容器中表現(xiàn)為柔性的盒子的元素被稱之為 flex 項(xiàng)(flex item)(本例中是
<article>元素。
列還是行?
彈性盒子提供了 flex-direction 這樣一個(gè)屬性,它可以指定主軸的方向(彈性盒子子類放置的地方)— 它默認(rèn)值是 row,這使得它們在按你瀏覽器的默認(rèn)語言方向排成一排(在英語/中文瀏覽器中是從左到右)。
嘗試將以下聲明添加到 section 元素的 css 規(guī)則里:
flex-direction: column
換行
當(dāng)你在布局中使用定寬或者定高的時(shí)候,可能會有一個(gè)問題出來即處于容器中的 彈性盒子子元素會溢出,破壞了布局。解決此問題的一種方法是將以下聲明添加到 section css 規(guī)則中:
flex-wrap: wrap
現(xiàn)在我們有了多行 彈性盒子— 任何溢出的元素將被移到下一行。在 article 元素上設(shè)置的 flex: 200px 規(guī)則,意味著每個(gè)元素的寬度至少是200px;我們將在后面更詳細(xì)地討論這個(gè)屬性。你可能還注意到,最后一行上的最后幾個(gè)項(xiàng)每個(gè)都變得更寬,以便把整個(gè)行填滿。
但是這里我們可以做得更多。首先,改變 flex-direction 屬性值為 row-reverse — 你會看到仍然有多行布局,但是每一行元素排列的方向和原來是相反的了。
flex-flow 縮寫
到這里,應(yīng)當(dāng)注意到存在著 flex-direction 和 flex-wrap — 的縮寫 flex-flow。比如,你可以將
flex-direction: row;
flex-wrap: wrap;
替換為
flex-flow: row wrap;
flex 項(xiàng)的動態(tài)尺寸
現(xiàn)在讓我們回到第一個(gè)例子,看看是如何控制 flex 項(xiàng)占用空間的比例的。打開你本地的 彈性盒子0.html,或者拷貝 彈性盒子1.html 作為新的開始(查看線上)。
第一步,將以下規(guī)則添加到 CSS 的底部:
article {
flex: 1;
}
這是一個(gè)無單位的比例值,表示每個(gè) flex 項(xiàng)沿主軸的可用空間大小。本例中,我們設(shè)置 <article> 元素的 flex 值為 1,這表示每個(gè)元素占用空間都是相等的,占用的空間是在設(shè)置 padding 和 margin 之后剩余的空間。因?yàn)樗且粋€(gè)比例,這意味著將每個(gè) flex 項(xiàng)的設(shè)置為 400000 的效果和 1 的時(shí)候是完全一樣的。
現(xiàn)在在上一個(gè)規(guī)則下添加:
article:nth-of-type(3) {
flex: 2;
}
現(xiàn)在當(dāng)你刷新,你會看到第三個(gè) <article> 元素占用了兩倍的可用寬度和剩下的一樣 — 現(xiàn)在總共有四個(gè)比例單位可用。 前兩個(gè) flex 項(xiàng)各有一個(gè),因此它們占用每個(gè)可用空間的1/4。 第三個(gè)有兩個(gè)單位,所以它占用2/4或這說是1/2的可用空間。
您還可以指定 flex 的最小值。 嘗試修改現(xiàn)有的 article 規(guī)則:
article {
flex: 1 200px;
}
article:nth-of-type(3) {
flex: 2 200px;
}
這表示“每個(gè)flex 項(xiàng)將首先給出200px的可用空間,然后,剩余的可用空間將根據(jù)分配的比例共享“。 嘗試刷新,你會看到分配空間的差別。
彈性盒子的真正價(jià)值可以體現(xiàn)在它的靈活性/響應(yīng)性,如果你調(diào)整瀏覽器窗口的大小,或者增加一個(gè) <article> 元素,這時(shí)的布局仍舊是好的。
flex: 縮寫與全寫
flex 是一個(gè)可以指定最多三個(gè)不同值的縮寫屬性:
- 第一個(gè)就是上面所討論過的無單位比例??梢詥为?dú)指定全寫
flex-grow屬性的值。 - 第二個(gè)無單位比例 —
flex-shrink— 一般用于溢出容器的 flex 項(xiàng)。這指定了從每個(gè) flex 項(xiàng)中取出多少溢出量,以阻止它們溢出它們的容器。 這是一個(gè)相當(dāng)高級的彈性盒子功能,我們不會在本文中進(jìn)一步說明。 - 第三個(gè)是上面討論的最小值??梢詥为?dú)指定全寫
flex-basis屬性的值。
我們建議不要使用全寫屬性,除非你真的需要(比如要去覆蓋之前寫的)。使用全寫會多些很多的代碼,它們也可能有點(diǎn)讓人困惑。
水平和垂直對齊
還可以使用 彈性盒子的功能讓 flex 項(xiàng)沿主軸或交叉軸對齊。讓我們一起看一下新例子 — flex-align0.html(在線瀏覽)— 我們將會有一個(gè)整潔,靈活的按鈕/工具欄。 此時(shí),你看到了一個(gè)水平菜單欄,其中一些按鈕卡在左上角,就像下面這樣:

首先,拷貝一份到本地。
然后,將下面的 CSS 添加到例子的底部:
div {
display: flex;
align-items: center;
justify-content: space-around;
}
刷新一下頁面,你就會看到這些按鈕很好的垂直水平居中了。我們是通過下面所說的兩個(gè)新的屬性做到的。
align-items控制 flex 項(xiàng)在交叉軸上的位置。
- 默認(rèn)的值是
stretch,其會使所有 flex 項(xiàng)沿著交叉軸的方向拉伸以填充父容器。如果父容器在交叉軸方向上沒有固定寬度(即高度),則所有 flex 項(xiàng)將變得與最長的 flex 項(xiàng)一樣長(即高度保持一致)。我們的第一個(gè)例子在默認(rèn)情況下得到相等的高度的列的原因。 - 在上面規(guī)則中我們使用的
center值會使這些項(xiàng)保持其原有的高度,但是會在交叉軸居中。這就是那些按鈕垂直居中的原因。 - 你也可以設(shè)置諸如
flex-start或flex-end這樣使 flex 項(xiàng)在交叉軸的開始或結(jié)束處對齊所有的值。查看align-items了解更多。
你可以用 align-self 屬性覆蓋 align-items 的行為。比如,你可以這樣:
button:first-child {
align-self: flex-end;
}
去看看它產(chǎn)生的效果,然后刪除它。
justify-content控制 flex 項(xiàng)在主軸上的位置。
- 默認(rèn)值是
flex-start,這會使所有 flex 項(xiàng)都位于主軸的開始處。 - 你也可以用
flex-end來讓 flex 項(xiàng)到結(jié)尾處。 -
center在justify-content里也是可用的,可以讓 flex 項(xiàng)在主軸居中。 - 而我們上面用到的值
space-around是很有用的——它會使所有 flex 項(xiàng)沿著主軸均勻地分布,在任意一端都會留有一點(diǎn)空間。 - 還有一個(gè)值是
space-between,它和space-around非常相似,只是它不會在兩端留下任何空間。
在繼續(xù)下面之前,多多使用提到過的屬性吧,看看它們的效果。
flex 項(xiàng)排序
彈性盒子也有可以改變 flex 項(xiàng)的布局位置的功能,而不會影響到源順序(即 dom 樹里元素的順序)。這也是傳統(tǒng)布局方式很難做到的一點(diǎn)。
代碼也很簡單,將下面的 CSS 添加到示例代碼下面。
button:first-child {
order: 1;
}
刷新下,然后你會看到 "Smile" 按鈕移動到了主軸的末尾。下面我們談下它實(shí)現(xiàn)的一些細(xì)節(jié):
- 所有 flex 項(xiàng)默認(rèn)的
order值是 0。 - order 值大的 flex 項(xiàng)比 order 值小的在顯示順序中更靠后。
- 相同 order 值的 flex 項(xiàng)按源順序顯示。所以假如你有四個(gè)元素,其 order 值分別是2,1,1和0,那么它們的顯示順序就分別是第四,第二,第三,和第一。
- 第三個(gè)元素顯示在第二個(gè)后面是因?yàn)樗鼈兊?order 值一樣,且第三個(gè)元素在源順序中排在第二個(gè)后面。
你也可以給 order 設(shè)置負(fù)值使它們比值為 0 的元素排得更前面。比如,你可以設(shè)置 "Blush" 按鈕排在主軸的最前面:
button:last-child {
order: -1;
}
flex 嵌套
彈性盒子也能創(chuàng)建一些頗為復(fù)雜的布局。設(shè)置一個(gè)元素為flex項(xiàng)目,那么他同樣成為一個(gè) flex 容器,它的孩子(直接子節(jié)點(diǎn))也表現(xiàn)為 flexible box ??匆幌?complex-彈性盒子.html(在線瀏覽)。

這個(gè)例子的 HTML 是相當(dāng)簡單的。我們用一個(gè) <section> 元素包含了三個(gè) <article>元素。第三個(gè) <article> 元素包含了三個(gè) <div>:
section - article
article
article - div - button
div button
div button
button
button
現(xiàn)在讓我們看一下布局用到的代碼。
首先,我們設(shè)置 <section> 的子節(jié)點(diǎn)布局為 flexible box。
section {
display: flex;
}
下面我們給 <article> 元素設(shè)置 flex 值。特別注意這里的第二條CSS規(guī)則—我們設(shè)置第三個(gè) <article> 元素的子節(jié)點(diǎn)的布局同樣為 flex ,但是屬性值為列布局。
article {
flex: 1 200px;
}
article:nth-of-type(3) {
flex: 3 200px;
display: flex;
flex-flow: column;
}
接下來,我們選擇了第一個(gè) <div>。首先使用 flex: 1 100px; 簡單的給它一個(gè)最小的高度 100px,然后設(shè)置它的子節(jié)點(diǎn)(<button> 元素)為 flex 項(xiàng)。在這里我們將它們放在一個(gè)包裝行(wrap raw)中,使它們居中對齊,就像我們在前面看到的單個(gè)按鈕示例中做的那樣。
article:nth-of-type(3) div:first-child {
flex: 1 100px;
display: flex;
flex-flow: row wrap;
align-items: center;
justify-content: space-around;
}
最后,我們給按鈕設(shè)置大小,有意思的是我們給它一個(gè)值為1的 flex 屬性。如果你調(diào)整瀏覽器窗口寬度,你會看到這是一個(gè)非常有趣的效果。按鈕將盡可能占用最多的空間,盡可能多的堆在同一條線上,但是當(dāng)它們不再適合在同一條線上,他們中的一些會到下一行去。
button {
flex: 1;
margin: 5px;
font-size: 18px;
line-height: 1.5;
}
跨瀏覽器兼容性
大多數(shù)瀏覽器都支持 彈性盒子,諸如 Firefox, Chrome, Opera, Microsoft Edge 和 IE 11,較新版本的 Android/iOS 等等。但是你應(yīng)該要意識到仍舊有被人使用的老瀏覽器不支持 彈性盒子(或者支持,但是只是支持非常非常老版本的 彈性盒子)。
雖然你只是在學(xué)習(xí)和實(shí)驗(yàn),這不太要緊; 然而,如果您正在考慮在真實(shí)網(wǎng)站中使用彈性盒子,則需要進(jìn)行測試,并確保在盡可能多的瀏覽器中您的用戶體驗(yàn)仍然可以接受。
彈性盒子相較其他一些 CSS 特性可能更為棘手。 例如,如果瀏覽器缺少 CSS 陰影,則該網(wǎng)站可能仍然可用。 但是假如不支持 彈性盒子功能就會完全打破布局,使其不可用。
我們將在未來的模塊中討論克服棘手的跨瀏覽器支持問題的策略。
Link to section總結(jié)
到這里,介紹彈性盒子的基礎(chǔ)知識就結(jié)束了。 我們希望你體會到樂趣,并且玩的開心,能隨著你的學(xué)習(xí)與你一起向前。 接下來,我們將看到CSS布局的另一個(gè)重要方面—網(wǎng)格系統(tǒng)。