flex 布局原理
flex 是 flexible box 的縮寫,即為 ‘ 彈性布局 ’ ,用來為盒子模型提供最大的靈活性,任何容器后可以指定為 flex 布局
無論是塊元素還是行內元素
1、當為父元素盒子設置為 flex 布局之后,子元素的 float、clear 和 vertical-align屬性將失效
2、伸縮布局 = 彈性布局 = 伸縮盒布局 = 彈性盒布局 = flex布局
采用 flex 布局的元素,稱為 flex 容器( flex container),簡稱為 “容器”。
所有的子元素自動成為容器成員,稱為 flex項目(flex item),簡稱“項目”。子元素可以橫向排列也可以縱向排列。
總結flex 布局原理:通過給父元素添加 flex 屬性,來控制子盒子的位置和排列方式。
相關概念:
主軸(main axis):
伸縮容器的主軸,伸縮項目主要沿着這條軸進行排列布局,主軸不一定是水平的(主要取決於justify-content屬性)
主軸起點(main start)和主軸終點(main-end)
伸縮項目放置在伸縮容器從主軸起點向主軸終點方向。
主軸尺寸(main size)
伸縮項目在主軸方向的高度和寬度主要取決於主軸的尺寸,伸縮項目主要的大小屬性要么是寬度要么是高毒屬性,由哪一個對着主軸方向決定。
側軸(cross axis)
垂直於主軸的稱為側軸,方向主要取決於主軸的方向。
側軸起點(cross-start)和側軸終點(cross-end)
伸縮行的配置從容器的側軸起點邊開始,往側軸終點邊結束。
側軸尺寸(main size)
伸縮項目的在側軸方向的寬度或高度就是項目的側軸長度,伸縮項目的側軸長度屬性是寬度或高度,由哪一個對着側軸方向決定。
那么什么是主軸和側軸呢?
默認的主軸方向就是 x 軸方向,水平向右
默認的側軸方向就是 y 軸方向,水平向下
彈性容器(display)
display:flex 屬性將元素設置為彈性盒子
將其 display屬性值定義為 flex 或是 inline-flex 將元素變為彈性盒子(彈性容器)
flex:將對象設置為彈性伸縮盒子顯示
inline-flex:將對象作為內聯(行內)塊級伸縮盒顯示
flex 和 inline-flex 的區別:
display: flex:設置父元素彈性盒子。設置元素橫向排列,子元素就不在是獨占一行,父元素也會隨着頁面大小變化而改變尺寸。
display: inline-flex:設置父元素行內彈性盒子。父元素的寬度完全由子元素撐開,並且不會隨着頁面大小變化改變尺寸。
實例:
1、display: flex:設置父元素彈性盒子
div{ display:flex; }
2、display:inline-flex:設置父元素行內彈性盒子
div{ display:inline-flex; }
flex 布局父級常見屬性
以下7個屬性是相對於父元素設置的
1、flex-direction:設置主軸的方向
2、justify-content:設置主軸上子元素排列的方式
3、flex-warp:設置子元素是否換行
4、align-content:設置側軸上子元素的排列方向(多行)
5、align-items:設置側軸上子元素排列方式(單行)
6、flex-flow:復合屬性,相當於同時設置了 flex-direction 和 flex-warp
7、display:將盒子設置為彈性盒子
設置在子元素上面的6個屬性:
1、flex-grow:彈性子元素拉伸因子
2、flex-shrink:彈性子元素的收縮比率
3、flex-basis: 指定flex元素在主軸方向上的初始大小
4、flex:規定了彈性元素如何伸長或縮短以適應 flex容器中的可用空間
5、order:設置或檢索彈性盒模型子元素出現的順序
6、align-self:子項自己在側軸上的排列方式
一、flex-direction 設置主軸的方向
flex-direction 屬性指定內部元素是如何在 flex容器中布局的,定義主軸方向(正方向 or 反方向)
設置伸縮盒主軸的起點和終點位置,子元素依然按照從主軸起點向終點方向排列
屬性值:
flex-direction 屬性決定主軸的方向
注意:主軸和側軸是會變化的,當經過 flex-direction 設置后,主軸變成了側軸,側軸也就變成了原來的主軸。
但是子元素是跟着主軸來排列的。
(column 柱、reverse的反轉)
屬性值 | 說明 |
row | 默認值,主軸橫向,起點左側終點右側(元素從左向右排列) |
row-reverse | 主軸橫向反轉,起點右側,終點左側(元素從左向右排列) |
column | 主軸縱向,起點上方,終點下方(元素從上向下排列) |
column-reverse | 主軸縱向反轉,起點下方,終點上方(元素從下向上排列) |
實例:
1、flex-driection:row;
默認值,子元素沿着主軸方向排列從左向右
2、flex-driection:row-reverse;
主軸橫向反轉,主軸起點在左側,終點變為右側,子元素從右向左排列
3、flex-driection:column;
主軸縱向,主軸起點在上方,終點在下方,子元素從上到下排列
4、flex-driection:column-reverse;
主軸縱向反轉,主軸起點在下方,終點在上方,子元素從下向上排列
二、justify-content 設置子元素在主軸上的對齊方式
justify-content 屬性定義了瀏覽器之間,如何分配沿着彈性容器的主軸的元素之間及周圍空間的分配
設置主軸上面的子元素
注意:使用 justify-content 元素之前一定要先確認主軸方向 flex-direction
屬性值:
屬性值 | 說明 |
flex-end | 彈性子元素向主軸終點位置對齊 |
center | 彈性子元素向行中間位置對齊 |
space-around | 平均分配剩余空間,兩端保留子元素與子元素之間間距大小的一半 |
space-between | 先在兩邊貼邊,再平分剩余空間(重要) |
flex-end | 彈性子元素向主軸起點位置對齊 |
實例:
1、justify-content: flex-start;
主軸的默認方向下row,子元素 first-start 向主軸的初始位置對齊【默認情況】
.flex-container{ /* 設置元素為彈性容器 */ display:flex; border:tomato 2px solid; /* 先確認主軸的方向默認主軸 x軸 row */ flex-direction:row; /* justify-content:設置主軸上子元素的排列方式 */ justify-content:flex-start; }
2、justify-content:flex-end;
行尾位置開始排列。每行最后一個彈性元素與行尾對齊(子元素向主軸終點位置對齊),其他元素將與后一個對齊。
.flex-container{ /* 設置元素為彈性容器 */ display:flex; border:tomato 2px solid; /* justify-content:設置主軸上子元素的排列方式 */ justify-content:flex-end; }
3、justify-content:center;
子元素向中間位置對齊
4、justify-center:space-around;
(平均分配盒子剩余的空間,每個盒子都有相等的margin-right 和 margin-left)
在每行上均勻分布彈性元素。相鄰元素之間距離相等。每行第一個元素到行首的距離 和每行最后一個元素到行尾的距離將會是相鄰元素之間距離的一半。
5、justify-content: space-between;
每行上均勻分布彈性元素。相鄰的彈性元素之間距離相同。每行第一個元素與行首對齊,每行最后一個元素與行尾對齊
四、flex-wrap 元素換行
在 flex 布局中,默認的子元素是不換行,如果容納不下,會縮小子元素的寬度,放到父元素里面。
flex-warp 設置或檢索伸縮盒對象的子元素超出父容器時是否換行
默認情況下,項目都排在一條線(又稱“軸線”)上,flex-warp 屬性定義,flex布局中默認是不換行的。
屬性值 | 說明 |
nowarp | 默認值,當子元素溢出父元素的時候不換行 |
warp | 換行,當子元素溢出父元素的時候自動換行 |
warp-reverse | 翻轉warp排列(換行默認的是從左向右從上到下,翻轉之后就是從下向上) |
實例:
flex布局中,默認的子元素是不換行的。當子元素的寬度超出父元素的寬度時,子元素不會換行,而是會被壓縮
1、flex-warp:nowrap;
默認值,設置子元素不換行。子元素寬度被壓縮。
.flex-container{ display:flex; border:tomato 2px solid; flex-wrap:nowrap; width:600px; }
2、flex-wrap:wrap; 子元素溢出父元素的時候自動換行
3、flex-wrap:wrap-reverse;反轉子元素wrap的排列
五、align-items 設置側軸上的子元素排列方式(單行)
該屬性是在控制子項在測軸(默認是y軸)上的排列方式 在子元素的為單項的時候使用。
將一整行沿着 y 軸上下軸來移動
屬性值:
屬性值 | 說明 |
flex-start | 元素向側軸起點對齊 |
flex-end | 元素向側軸終點對齊 |
center | 元素在側軸居中。如果元素在側軸上的高度高於其容器,在上下兩個方向上溢出距離相同 |
stretch | 默認值,彈性元素被在側軸方向拉伸到與容器相同的高度 |
baseline | 將文字對齊 |
實例:
1、align-items:flex-start;
默認值,單行整行的子元素向側軸起點對齊(表現為向上對齊),子元素不設置寬度的時候高度默認有內容撐開。
2、align-items:flex-end;
單行整行子元素向側軸終點對齊(向下對齊)
3、align-items:center;
單行子元素向側軸中間對齊(垂直居中對齊),子元素不設置高度默認由內容撐開
當子元素在側軸上高度超過父元素的。設置align-items:center;后子元素會在上下兩個方向上溢出相同距離。
實現將單行彈性子元素在彈性容器中水平垂直居中
.flex-container{ display:flex; border:tomato 2px solid; /* 設置主軸居中 */ justify-content:center; /* 選擇測軸居中 */ align-items:center; width:600px; height:200px; margin:100px auto;
4、align-items:stretch;
當子元素不設置高度的時候,設置stretch,彈性元素會被拉伸到和父元素相同的高度。
5、align-content:baseline,將文字基於基線對齊
六、align-content 設置側軸上子元素的排列方式(多行)
設置了瀏覽器如何沿着彈性盒子布局的側軸在內容項之間和周圍分配空間。
子元素在側軸上的排列方式並且只能用於子元素換行的情況(多行),在單行的情況下是沒有效果的。
注意:該屬性對單行彈性盒子無效。
使用 flex-wrap:wrap 設置彈性
屬性值 | 說明 |
flex-start | 在側軸的頭部開始排列 |
flex-end | 在側軸的尾部開始排列 |
center | 在側周中間顯示 |
space-around | 子元素在側軸平分剩余空間 |
space-between | 子元素在側軸先分布在兩側,在平分剩余空間 |
stretch | 設置子元素高度平分父元素高度 |
1、align-content:flex-start;
默認值,彈性子元素(多行)在側軸頭部開始排列。
默認情況下,彈性子元素不會換行,flex-wrap:wrap; 子元素換行
.flex-container{ display:flex; border:tomato 2px solid; /* 設置彈性子元素換行 */ flex-wrap:wrap; /*多行彈性子元素向側軸頭部排列 */ width:600px; height:300px; margin:100px auto; }
2、align-content:flex-end;多行子元素向側軸終點排列
3、align-content:center;所有行向側軸的中心填充。
4、ailgn-content:space-around
彈性子元素平分側軸的剩余空間,相當於給每行元素設置了相同距離的margin-top 和 margin-bottom
所有行在容器中平均分布,相鄰兩行間距相等。容器的垂直軸起點邊和終點邊分別與第一行和最后一行的距離是相鄰兩行間距的一半。
5、align-content:space-between;
所有行在彈性容器中平均分布,相鄰兩行間距相等。容器的垂直軸起點邊和終點邊分別與第一行和最后一行的邊對齊。
6、align-content:stretch;
拉伸所有航來填滿剩余空間,剩余空間平均分配給每一行
七、flex-flow 簡寫
flex-flow 是 flex-direction 和 flex-wrap 屬性的綜合屬性
.flex-container{ display:flex; border:tomato 2px solid; /* 設置彈性子元素換行 */ flex-wrap:wrap; /* 將主軸設置為側軸,主軸縱向 */ flex-direction:column; }
等價於,flex-flow簡寫屬性
.flex-container{ display:flex; border:tomato 2px solid; /* 設置彈性子元素換行 */ /* 主軸縱向*/ flex-flow: cloumn wrap; }
flex 布局子項常見的屬性
flex 子項目占的份數
flex-grow 彈性盒的擴展比率
flex-shrink 設置收縮比率
flex-basisalign-self 控制子項自己在側軸的排列方式
order 屬性定義子項的排列順序(前后順序)
flex-grow 定義彈性子元素的拉伸因子
設置或檢索彈性盒的擴展比率。根據彈性盒子元素所設置的擴展因子作為比例來分配剩余空間
屬性值:
<number> :數值定義擴展比率。不允許負值
0:默認值為0,如果沒有定義該屬性,不參與分配剩余空間
實例(分配原則如下):
1、flex-grow:0;默認值
子元素的實際寬度= 70 + (600-350)* 0 = 70px
2、flex-grow:<number>; 定義子元素擴展比率
子元素實際寬度
= 寬度 + 剩余空間 * 2/(2+2+2+2+2)
=70 +(600-350)* 2/10
=70+50=120px
section{ width:600px; display:flex; border:tomato 2px solid; } section div{ height:70px; width:70px; flex-grow:2; border:goldenrod 1px solid; background-color: gold; }
flex-shrink 屬性指定了flex子元素的收縮規則。
flex元素僅在默認寬度之和大於容器的時候才會發生收縮,其收縮的大小是依據 flex-shrink 的值。flex-shrink 屬性值能是一個只<number>
屬性值:
<number> :負值是不允許的
1:flex-shrink 的默認值為1,如果沒有顯示定義該屬性,將會自動按照默認值1所在因子相加之后計算比率來進行控件收縮。
實例:
1、flex-shrink:1;默認值
在默認情況下,子元素的寬度超過父元素,子元素寬度會被壓縮,不會溢出父元素
原則:子元素超出的空間 = 5*70 - 300 = 50px
父元素寬度300px,每個子元素寬度70px
加權總和:(70*1)* 5 = 350
每個子元素被移除的寬度:(70*1)/350 * 50 = 10px
每個子元素最終寬度:70 - 10 = 60px
所以設置 flex-shrink:1;可以使得子元素寬度被壓縮到,剛好適應父元素的寬度
2、flex-shrink:<number>; 指定子元素的收縮比例
子元素超出的空間為:160+80 - 200 = 40px
父元素 200px;子元素1為160px;子元素2為80px
加權總和:160 + 80*2 = 320
元素1被移除的空間:(160*1) /320 * 40 = 20px
子元素1的寬度:160 - 20 = 140px
子元素2移除的空間:(80*2) /320 * 40 = 20px
子元素2的寬度:80 - 20 = 60px
section{ width:200px; /* height: 100px; */ margin:100px auto; display:flex; border:tomato 2px solid; } section div:nth-child(1){ height:70px; width:160px; flex-shrink: 1; border:goldenrod 1px solid; background-color: gold; } section div:nth-child(2){ height: 70px; width:80px; flex-shrink: 2; border:goldenrod 1px solid; background-color:goldenrod; }
flex-basis :指定flex元素在主軸方向上的初始大小
設置活檢索彈性盒的伸縮基准值(最大作用就是更改寬度)
如果不使用box-sizing 改變盒模型,那么這個屬性就決定了 flex 元素的內容區(content-box)的大小
屬性值:
auto:默認值,無特定寬度(auto取決於原有的寬度)
<length>:用長度定義寬度,不能設置負值
<percentage>:百分比定義寬度,不能設置負值
一、flex 屬性
flex規定了彈性元素如何伸長或縮短以適應 flex容器中的可用空間。
這是一個簡寫屬性,可以用來設置 flex-grow、flex-shrink、flex-basis。設置或檢索伸縮盒對象的子元素如何分配空間。建議優先使用這個屬性,而不是單獨寫三個分離的屬性,因為瀏覽器會推算相關值。
flex用於合並指定 flex-grow 和 flex-grow 以及 flex-basis 屬性,默認值為 0 1 auto。
如果縮寫 flex:1,則其計算值為 :1 1 0,auto等價與1 1 auto,none等價於 0 0 auto;
語法:flex:none | [flex-grow] | [flex-shrink] | [flex-basis]
[ flex-grow ]:定義彈性盒子元素的擴展比率
[ flex-shrink ]:定義彈性盒子元素的收縮比率
[ flex-basis ]:定義彈性盒子元素的默認基准
flex屬性定義子元素分配剩余空間,用 flex 表示占了多少份數。
flex 屬性可以指定1個,2個或3個值。
單值語法:
一個無單位數(<number>)
一個有效的寬度值(width)
關鍵字none,auto,或是initial
flex:none | flex:0 1 auto 完全不伸縮,僵化 |
flex:initial | flex:0 1 auto 不能生長,但是缺乏空間時可以縮小 |
flex:auto | flex:1 1 auto 依照可用空間平均伸縮 |
flex:<position-number> | flex:<position-number> 1 0 能屈能伸,屬性值判定生長比例 |
雙值語法:
第一個值必須是一個無單位數,定義子元素的拉伸。第二個值必須是以下之一:
一個無單位數(<number>),
一個有效的寬度值(width)
三值語法:
第一個值必須是一個無單位的number,定義子元素的拉伸程度 flex-grow
第二個值必須是一個無單位的number,定義子元素的收縮規則 flex-shrink
第三個值必須為一個有效的寬度值,元素在主軸上的初始大小 flex-basis
HTML代碼:
<section> <div></div> <div></div> <div></div> </section>
實例:
1、三個彈性子元素平分頁面空間。
flex 屬性設置為單個數值的 計算規則:如果子元素沒有設置寬度 所有設置了 flex的子元素 數值之和為總共的份數
在這個例子中,共有三個元素都設置了flex:1 ;所以三個元素分別占據 彈性容器的 1/3
section{ width:60%; height: 100px; margin:100px auto; display:flex; border:tomato 2px solid; } section div:nth-child(1){ flex:1; background-color: burlywood; } section div:nth-child(2){ flex:1; background-color:goldenrod; } section div:nth-child(3){ flex:1; background-color: gold; }
3、聖杯布局
section{ width:60%; height: 100px; margin:100px auto; display:flex; border:tomato 2px solid; } section div:nth-child(1){ width: 100px; height:100px; background-color: burlywood; } section div:nth-child(2){ flex:1; background-color:goldenrod; } section div:nth-child(3){ width: 100px; height:100px; background-color: gold; }
3、flex:auto;
auto等價與 1 1 auto,flex-grow為1,flex-shrink為 1,flex-basis 為auto;
剩余的空間被自動平均分配
section{ width:600px; display:flex; border:tomato 2px solid; } section div{ width: 70px; height:70px; flex: auto; border:goldenrod 1px solid; background-color: gold; }
4、flex:none;
none等價於0 0 auto,flex-grow為0,flex-shrink為 0,flex-basis 為auto;
子元素寬度高度保持原有情況不拉伸,不縮放。
section{ width:600px; display:flex; border:tomato 2px solid; } section div{ width: 70px; height:70px; flex: none; background-color: gold; }
三、align-self 控制子 項自己在側軸上的排列方式
align-self 屬性允許單個項目有和其他項目不一樣的對齊方式,可以覆蓋 align-items 屬性
默認值為 auto,表示繼承父元素的align-items,如果沒有父元素,則等同於 stretch。
屬性值 | 說明 |
auto | 如果align-self值為 auto,則計算值為元素父元素的 align-items,如果其沒有父元素,則計算值為 stretch |
flex-start | 彈性盒子元素的側軸(縱軸)起始位置緊靠住該行的側軸起始位置 |
flex-end | 彈性盒子元素的側軸(縱軸)起始位置的邊界緊靠住該行的側軸結束邊界 |
center | 子元素在該行側軸上居中放置。(如果該行的尺寸小於彈性盒子元素的尺寸,則會向兩個方向溢出相同的長度) |
stretch | 如果指定側軸的大小的屬性值為 ‘auto’,則其值會使項目的邊距盒的尺寸盡可能接近所在行的尺寸,但同事會遵照 ‘min’/max-width/height' 屬性的限制 |
baseline | 如彈性盒子元素的行內軸與側軸為同一條,該值與 ‘flex-start’等效。其他情況下,該值將參與基線對齊 |
align-self:用於設置彈性元素自身在側軸方向上的對齊方式
語法:align-self:auto | flex-start | flex-end | center | baseline | stretch
實例:
div:nth-child(1){align-self: auto;} div:nth-child(2){align-self:flex-start;} div:nth-child(3){align-self:flex-end;} div:nth-child(4){align-self:stretch} div:nth-child(5){align-self:baseline} div:nth-child(6){align-self: center;}
四、order 子元素出現的順序
設置或檢索彈性盒模型子元素出現的順序
語法:order:<integer>
屬性值:<integer>:整數,使用整數來定義排列的順序,數值最小的排在最前面。可以為負值
先后順序為:……-2 、-1 、0 、1 、2 、3……。元素的默認值是 order:0
實例:
正常情況下的子元素排列順序:
div:nth-child(1){ order:1; } div:nth-child(4),
div:nth-child(5){ order:2; } div:nth-child(3){ order:-1; }
彈性布局的小妙用:
一、自動margin
在彈性容器內的子元素會被當做是彈性項目
為彈性子元素設置 margin:auto可以實現元素在彈性容器中的水平垂直居中
HTML
<div class="box"> <div class="child"></div> </div>
CSS
.box{ display:flex; } .child{ margin:auto; }