長久以來,唯一可用的且有穩定的跨瀏覽器兼容性的能用來構建 CSS 佈局的工具只有 floats 和 positioning。它們是既可行,表現也不錯的佈局方案,但是在某些佈局方面它們就有限制,並且難以實現。彈性盒子使得很多佈局任務變得更加容易。
首先,我們需要選擇將哪些元素將設置爲柔性的盒子。我們需要給這些 flexible 元素的父元素 display 設置一個特定值。
section {
display: flex;
}
就這樣一個簡單的聲明就給了我們所需要的一切。 我們的多列布局具有大小相等的列,並且列的高度都是一樣。 這是因爲這樣的 flex 項(flex容器的子項)的默認值是可以解決這些的常見問題的。
假如你想設置行內元素爲 flexible box,也可以置 display 屬性的值爲 inline-flex。
flex模型說明
- 主軸(main axis)是沿着 flex 元素放置的方向延伸的軸(比如頁面上的橫向的行、縱向的列)。該軸的開始和結束被稱爲 main start 和 main end。
- 交叉軸(cross axis)是垂直於 flex 元素放置方向的軸。該軸的開始和結束被稱爲 cross start 和 cross end。
- 設置了
display: flex
的父元素(在本例中是<section>
)被稱之爲 flex 容器(flex container)。 - 在 flex 容器中表現爲柔性的盒子的元素被稱之爲 flex 項(flex item)(本例中是
<article>
元素。
列與行排列
彈性盒子提供了 flex-direction 這樣一個屬性,它可以指定主軸的方向(彈性盒子子類放置的地方)— 它默認值是 row,這使得它們在按你瀏覽器的默認語言方向排成一排
按列排列:
flex-direction: column
你還可以使用flex-direction的 row-reverse 和 column-reverse 值反向排列 flex 項目。
換行問題
當你在佈局中使用定寬或者定高的時候,可能會有一個問題出來即處於容器中的 彈性盒子子元素會溢出,破壞了佈局。
解決此問題的一種方法是將以下聲明添加到 section css 規則中:
flex-wrap: wrap
flex-flow縮寫
存在着 flex-direction 和 flex-wrap — 的縮寫 flex-flow。比如,你可以將
flex-direction: row;
flex-wrap: wrap;
替換爲:
flex-flow: row wrap;
flex項的動態尺寸
控制 flex 項佔用空間的比例:
article {
flex: 1;
}
這是一個無單位的比例值,表示每個 flex 項沿主軸的可用空間大小。我們設置 <article> 元素的 flex 值爲 1,這表示每個元素佔用空間都是相等的,佔用的空間是在設置 padding 和 margin 之後剩餘的空間。因爲它是一個比例,這意味着將每個 flex 項的設置爲 400000 的效果和 1 的時候是完全一樣的。
在上一個規則下添加:
article:nth-of-type(3) {
flex: 2;
}
現在當你刷新,你會看到第三個 <article> 元素佔用了兩倍的可用寬度和剩下的一樣 — 現在總共有四個比例單位可用。 前兩個 flex 項各有一個,因此它們佔用每個可用空間的1/4。 第三個有兩個單位,所以它佔用2/4或這說是1/2的可用空間。
還可以指定 flex 的最小值:
article {
flex: 1 200px;
}
article:nth-of-type(3) {
flex: 2 200px;
}
這表示“每個flex 項將首先給出200px的可用空間,然後,剩餘的可用空間將根據分配的比例共享“。 flex的縮寫與全寫
flex
是一個可以指定最多三個不同值的縮寫屬性:
- 第一個就是上面所討論過的無單位比例。可以單獨指定全寫
flex-grow
屬性的值。 - 第二個無單位比例 —
flex-shrink
— 一般用於溢出容器的 flex 項。這指定了從每個 flex 項中取出多少溢出量,以阻止它們溢出它們的容器。 這是一個相當高級的彈性盒子功能,我們不會在本文中進一步說明。 - 第三個是上面討論的最小值。可以單獨指定全寫
flex-basis
屬性的值。
我們建議不要使用全寫屬性,除非你真的需要(比如要去覆蓋之前寫的)。
水平和垂直對齊
div {
display: flex;
align-items: center;
justify-content: space-around;
}
align-items
控制 flex 項在交叉軸上的位置。
- 默認的值是
stretch
,其會使所有 flex 項沿着交叉軸的方向拉伸以填充父容器。如果父容器在交叉軸方向上沒有固定寬度(即高度),則所有 flex 項將變得與最長的 flex 項一樣長(即高度保持一致)。我們的第一個例子在默認情況下得到相等的高度的列的原因。 - 在上面規則中我們使用的
center
值會使這些項保持其原有的高度,但是會在交叉軸居中。這就是那些按鈕垂直居中的原因。 - 你也可以設置諸如
flex-start
或flex-end
這樣使 flex 項在交叉軸的開始或結束處對齊所有的值。查看align-items
瞭解更多。
可以用 align-self
屬性覆蓋 align-items
的行爲。比如,你可以這樣:
button:first-child {
align-self: flex-end;
}
justify-content
控制 flex 項在主軸上的位置。
- 默認值是
flex-start
,這會使所有 flex 項都位於主軸的開始處。 - 你也可以用
flex-end
來讓 flex 項到結尾處。 center
在justify-content
裏也是可用的,可以讓 flex 項在主軸居中。- 而我們上面用到的值
space-around
是很有用的——它會使所有 flex 項沿着主軸均勻地分佈,在任意一端都會留有一點空間。 - 還有一個值是
space-between
,它和space-around
非常相似,只是它不會在兩端留下任何空間。
彈性盒子也有可以改變 flex 項的佈局位置的功能,而不會影響到源順序(即 dom 樹裏元素的順序)。
button:first-child {
order: 1;
}
- 所有 flex 項默認的
order
值是 0。 - order 值大的 flex 項比 order 值小的在顯示順序中更靠後。
- 相同 order 值的 flex 項按源順序顯示。所以假如你有四個元素,其 order 值分別是2,1,1和0,那麼它們的顯示順序就分別是第四,第二,第三,和第一。
- 第三個元素顯示在第二個後面是因爲它們的 order 值一樣,且第三個元素在源順序中排在第二個後面。
排在主軸的最前面:
button:last-child {
order: -1;
}
flex嵌套彈性盒子也能創建一些頗爲複雜的佈局。設置 flex 項爲 flex 容器也是沒有什麼問題的,它的孩子也就表現爲 flexible box 了。
這個例子的 HTML 是相當簡單的。我們用用一個 <section>
元素包含了三個 <article>
。第三個 <article>
元素包含了三個 <div>
:
section - article
article
article - div - button
div button
div button
button
button
首先,我們設置 <section>
的子代佈局爲 flexible box。
section {
display: flex;
}
下面我們給 <article>
元素設置一些 flex 值。特別注意這裏的第二條規則—我們設置第三個 <article>
元素裏的子元素同樣表現爲 flex 項,但是這次我們使它們放置爲列。
article {
flex: 1 200px;
}
article:nth-of-type(3) {
flex: 3 200px;
display: flex;
flex-flow: column;
}
接下來,我們選擇了第一個 <div>
。首先使用 flex: 1 100px;
簡單的給它一個最小的高度 100px,然後設置它的子代(<button>
元素)爲 flex 項。在這裏我們將它們放在一個包裝行中,使它們居中對齊,就像我們在前面看到的單個按鈕示例中所做的那樣。
article:nth-of-type(3) div:first-child {
flex: 1 100px;
display: flex;
flex-flow: row wrap;
align-items: center;
justify-content: space-around;
}
最後,我們給按鈕設置大小,有意思的是我們給它一個值爲1的 flex 屬性。如果你調整瀏覽器窗口寬度,你會看到這是一個非常有趣的效果。按鈕將佔用儘可能多的空間,儘可能多的坐在同一條線上,但是當它們不再適合在同一條線上,他們會到下一行去。
button {
flex: 1;
margin: 5px;
font-size: 18px;
line-height: 1.5;
}