簡介
我們經常聽說一種布局:Flexbox或者是彈性布局,它的全稱叫做彈性盒子布局(Flexible Box Layout),那么它到底該如何實現呢?從我們熟悉的 display 屬性開始,給元素添加 display: flex,該元素變成了一個彈性容器(flex container),它的直接子元素變成了彈性子元素(flex item),那么最簡單的彈性盒子布局就完成了,它具有以下的效果:
1、彈性容器像塊元素一樣填滿可用寬度(注意,這里只是彈性容器,即添加了display: flex的元素),高度由自身內容決定,但是彈性子元素不一定填滿其彈性容器的寬度。
2、彈性子元素默認是在同一行按照從左到右的順序并排排列。
3、彈性子元素高度相等,該高度由它們的內容決定。
當然,我們可以手動的設置它們的寬高,但是在Flexbox布局中,彈性是其最突出的屬性,所有一般我們不建議這樣做。在大致了解了它最顯著的作用之后,下面我們來進行細致深入的學習。
基礎概念
Flexbox布局中,有兩根重要的軸線——主軸&副軸,其屬性幾乎都是圍繞著這兩根軸線來描述的。默認情況下,主軸是水平的,它的起點為最左側,終點為最右側,對應的,有一根與之垂直相交的副軸,它的起點是最上側,終點是最下側。當然,這些方向可以改變,我們稍后介紹。
相關屬性
1、flex-direction 作用:決定主軸的方向(彈性子元素的排列方向)
row(默認值):水平,起始在左端
row-reverse:水平,起始在右端
column:豎直,起始在上沿
column-reverse:豎直,起始在下沿
2、flex-wrap 作用:決定直接子元素是否換行以及如何換行
nowrap(默認):不換行
wrap:換行,第一行在上方
wrap-reverse:換行,第一行在下方
3、flex-flow
作用:前面兩個屬性的簡寫,默認值為 row nowrap
4、justify-content 作用:決定彈性子元素在主軸上的對齊方式
flex-start(默認值):左對齊
flex-end:右對齊
center:居中
space-between:兩端對齊,彈性子元素之間的間隔相等
space-around:彈性子元素兩側的間隔相等,相鄰之間的間隔會疊加
5、align-content 作用:決定多行/列彈性子元素在交叉軸上的的對齊方式 (前提是要開啟flex-wrap)
stretch(默認值):每行元素將會被拉伸,直至撐滿整個交叉軸,每行/列之間的間隔相等
flex-start:與交叉軸起點對齊
flex-end:與交叉軸終點對齊
center:在交叉軸上居中對齊
space-between:與交叉軸兩端對齊,彈性子元素之間的間距相等
space-around:彈性子元素兩側的間隔相等,相鄰之間的間隔會疊加
6、flex-items 作用:決定單行/列彈性子元素在交叉軸上的對齊方式
stretch(默認值):如果沒有設置高度/高度設置為auto,那么將撐滿整個盒子
flex-start、flex-end、center屬性值的效果同上
baseline:項目的第一行文字的基線對齊(效果如下,紫色是盒子)
7、flex-basis 作用:指定子元素未受flex-grow或flex-shrink影響時的初始大小
取值:<length>或<percent>,初始值是auto(此時會檢查元素是否設置了width屬性。如果有,則使用 width 的值作為 flex-basis 的值;如果沒有,則用元素內容自身的大小。如果 flex-basis 的值不是 auto,width 屬性會被忽略)
8、flex-grow 作用:每個彈性子元素的 flex-basis 值計算出來后,它們(加上子元素之間的外邊距)加起來會占據一定的寬度。加起來的寬度不一定正好填滿彈性容器的寬度,可能會有留白。多出來的留白(或剩余寬度)會按照 flex-grow(增長因子)的值分配給每個彈性子元素。
取值:非負,初始值是0(此時元素的寬度不會超過flex-basis的寬度,不參與分配)
示例:flex-grow 的值越大,元素的“權重”越高,也就會占據更大的剩余寬度。一個 flex-grow: 2 的子元素增長的寬度為 flex-grow: 1 的子元素的兩倍,如下圖
9、lex-shrink 作用: flex-shrink 屬性與 flex-grow 遵循相似的原則。計算出彈性子元素的初始主尺寸后,它們的累加值可能會超出彈性容器的可用寬度。如果不用 flex-shrink,就會導致溢出,每個子元素的 flex-shrink 值代表了它是否應該收縮以及相應的收縮比例以防止溢出。(在開啟了flex-wrap之后會忽略此屬性)
取值:非負,初始值為1(為 0 時,不會縮小)
效果:
如果元素A的flex-shrink為0,而其他的元素都為0,那么A不會縮小
如果元素A的flex-shrink為2,元素B的flex-shrink為1,那么A的縮小的部分的長度是B的縮小部分的長度的2倍
示例:如下圖:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>flex-shrink縮放</title>
<style>
* {
padding: 0;
margin: 0;
box-sizing: border-box;
}
body {
padding: 1em;
}
#content {
display: flex;
width: 500px;
}
#content div {
flex-basis: 120px;
border: 3px solid rgba(0, 0, 0, 0.2);
}
.box {
flex-shrink: 2;
}
.box1 {
flex-shrink: 1;
}
.result {
margin-top: 20px;
}
p {
line-height: 1.5em;
}
</style>
</head>
<body>
<p>容器寬度為 500px, 彈性子元素的flex-basic 是120px</p>
<p>A, B, C 設置 flex-shrink:2, D 和 E 設置 flex-shrink:1</p>
<p>根據js打印輸出可知,A、B、C縮小的長度是D、E縮小長度的2倍</p>
<div id="content">
<div class="box" id="A" style="background-color:red;">A</div>
<div class="box" style="background-color:lightblue;">B</div>
<div class="box" style="background-color:yellow;">C</div>
<div class="box1" id="D" style="background-color:brown;">D</div>
<div class="box1" style="background-color:lightgreen;">E</div>
</div>
<div class="result"></div>
<script>
const A = document.getElementById("A");
const A_width = getComputedStyle(A).width;
const D = document.getElementById("D");
const D_width = getComputedStyle(D).width;
const content = document.getElementById("content");
const content_width = getComputedStyle(content).width;
const result = document.querySelector(".result");
result.innerHTML = `A, B, C 縮放之后的長度是${A_width},<br />
E縮放之后的長度是${D_width}, <br />
容器寬度是${content_width}`
</script>
</body>
</html>
10、flex 作用:flex-grow、flex-shrink、flex-basis三個屬性的簡寫
取值:
單值語法:值必須是以下之一:
一個 <flex-grow> 的有效值:此時簡寫會擴展為 flex: <flex-grow> 1 0。
一個<flex-basis>的有效值:此時簡寫會擴展為 flex: 1 1 <flex-basis>。
關鍵字 none 或者全局關鍵字(見后面)之一。
雙值語法:
第一個值必須是一個 flex-grow 的有效值。
第二個值必須是以下之一:
一個 flex-shrink的有效值:此時簡寫會擴展為 flex: <flex-grow> <flex-shrink> 0。
一個 flex-basis 的有效值:此時簡寫會擴展為 flex: <flex-grow> 1 <flex-basis>。
三值語法:值必須按照以下順序指定:
一個 flex-grow 的有效值。
一個 flex-shrink 的有效值。
一個 flex-basis 的有效值。
全局關鍵字
全局關鍵字:
initial
元素會根據自身寬高設置尺寸。它會縮短自身以適應 flex 容器,但不會伸長并吸收 flex 容器中的額外自由空間來適應 flex 容器。相當于將屬性設置為"flex: 0 1 auto"。
auto
元素會根據自身的寬度與高度來確定尺寸,但是會伸長并吸收 flex 容器中額外的自由空間,也會縮短自身來適應 flex 容器。這相當于將屬性設置為 “flex: 1 1 auto”.
none
元素會根據自身寬高來設置尺寸。它是完全非彈性的:既不會縮短,也不會伸長來適應 flex 容器。相當于將屬性設置為"flex: 0 0 auto"。
flex屬性與以往的簡寫屬性不同,推薦使用簡寫形式,因為這樣可以盡可能避免多次分開書寫導致的布局不一致,并且可以提高對瀏覽器的兼容性。
<'flex-grow'>
定義 flex 項目的 flex-grow 。負值無效。省略時默認值為 1。 (初始值為 0)
<'flex-shrink'>
定義 flex 元素的 flex-shrink 。負值無效。省略時默認值為1。 (初始值為 1)
<'flex-basis'>
定義 flex 元素的 flex-basis 屬性。若值為0,則必須加上單位,以免被視作伸縮性。省略時默認值為 0。(初始值為 auto)
采用邏輯推斷的方法,初始值肯定會從安全性的角度考慮,所以,元素盡量不要隨意放大,所以flex-grow屬性初始為0;容器會盡量容納下所有的元素,所以flex-shrink屬性初始值為1;為了以元素自身為主導,flex-basis初始值為auto。而所謂的默認值,是在flex簡寫的寫法中被省略時補充的值,以上規則能夠體現出來。
11、order 作用:將彈性子元素從兄弟節點中移動到指定位置,覆蓋源碼順序,值越小,位置越靠前
取值:整數,初始值是0
注意:慎重使用,因為視覺布局與源碼順序差別太大會影響網站的可訪問性。在大多數瀏覽器里使用 Tab 鍵瀏覽元素的順序與源碼保持一致,如果視覺上差別太大就會令人困惑。視力受損的用戶使用的大部分屏幕閱讀器也是根據源碼的順序來的。
12、align-self 作用:跟彈性容器的 align-items 屬性效果相同,但是它能單獨給彈性子元素設定不同的對齊方式。
取值與效果:auto 為初始值,會以容器的 align-items 值為準。其他值會覆蓋容器的設置。align-self屬性支持的關鍵字與 align-items 一樣:flex-start、flex-end、center、stretch 以及 baseline。