背景
flex布局更有效的實現對齊,空間分配。最近又學習下flex子元素的尺寸計算規則,主要是flex-grow
, flex-shrink
的計算規則的學習。
一、基本概念
1.1 主軸(Main axis)
定義了flex元素布局起始點和方向,flex子元素在主軸上依次放置。
主軸有4個方向,通過flex-direction
指定:
水平方向,從左到右,默認的
水平方向,從右到左
垂直方向,從上到下
垂直方向,從下到上
1.2 主軸的尺寸(Main axis size)
就是flex容器content矩形(不包含padding, border, margin區域)在主軸方向的尺寸。
1.3 交叉軸(Cross axis)
交叉軸就是跟主軸錘子的方向,主要用于flex元素的對齊。
1.4 交叉軸的尺寸(Cross axis size)
就是flex容器content矩形(不包含padding, border, margin區域)在Cross軸方向的尺寸。
1.5 flex盒模型(flex box)
display為flex
,inline-flex
,的元素,也叫flex容器。
1. flex容器包含的不僅是flex元素,也包含空白空間。
2. 涉及的CSSflex-directionflex-wrapflex-flow
flex-direction和 flex-wrap的簡寫。
控制flex容器內容(flex元素和空白空間)在主軸方向對齊。注意區分align-items。
控制多行flex容器個行的對齊方式。
控制flex容器內容(flex元素和空白空間)在交叉軸方向對齊。
Tip:
1、這些CSS屬性都是有相關性的:
首頁先指定flex容器的主軸方向(flex-direction), 如果flex子元素超過在主軸 尺寸,那就涉及是否換行(flex-wrap)。如果沒有超過主軸尺寸,那就涉及行內對齊(justify-content), 如果存在多行每個行直接也要對齊(align-content)。
2、可能比較容易混淆 justify-content,align-content,align-items。
記住content是指flex元素和空白空間,items指的是flex元素。這樣就容易就是這三個屬性的用處了。
1.6 flex元素(flex items)
1. 語法
flex box的子元素,不包含流外子元素( absolute, fix元素),但是包含float元素。
flex子元素相鄰的margin不會發生合并。
float元素作為flex子元素時,float屬性無效(因為要參與flex布局,不是流式布局)。
2. 涉及CSS屬性
指定flex元素在主軸方向上占用flex容器的尺寸,默認為auto,即以flex元素的尺寸作為其占用的尺寸(主軸是row取值flex元素的寬度,主軸是column取值flex元素的高度),根據該屬性計算是否有空余空間。
注意:flex元素占用的尺寸跟flex-basis有關,跟元素的寬高沒直接關系。
指定各個flex元素彈性增長因數,即占用正空白空間(positive free space)的比例份額數量。0值(默認值)表示不占用空白空間
指定各個flex元素彈性收縮因數,即分配負空白空間(negative free space)的比例份額數量。但是元素不能無限收縮為0,也不能小于元素的最小尺寸(如min-width或者min-height)。
flex-grow flex-shrink flex-basis簡寫
調整自己在交叉軸的對齊方式,只有在不撐滿交叉軸時,這個屬性才有效。
指定順序
二、計算自由空間和flex-basis
flex子元素在主軸上的比例依賴這三個CSS屬性:
其中:
flex-basis + flex-grow組合控制著伸
flex-basis + flex-shrink組合控制著縮
所以要確定flex子元素在主軸上的比例,首先要確定使用哪種組合。
2.1 規則
flex-basis
屬性指定在任何空間分配發生之前初始化flex子元素的尺寸,更確切的說flex-basis
屬性指的flex子元素盒模型(box-sizing)的尺寸,所以跟flex子元素width(height)取值邏輯類似,如果box-sizing=content,則flex-basis也不包含padding和border區域。
2.2 剩余自由空間計算
自由空間計算
flex容器在主軸方向的content矩形的尺寸
期望自用空間
在計算flex容器的自由空間前要先統計flex子元素占用的尺寸,注意這里指的是flex子元素的margin區域的尺寸,并且相鄰的flex子元素margin是不會發生合并的。
剩余自由空間計算 = 自由空間計算 - 期望自用空間
正自由空間
正值的剩余自由空間,此時采用flex-basis + flex-grow組合。
負自由空間
負正值的剩余自由空間,此時采用flex-basis + flex-shrink組合。
三、深入了解flex-grow
3.1 規則
如果存在正自由空間(positive free space),則采用flex-basis + flex-grow
組合計算flex子元素在主軸上的比例。把正自由空間比作蛋糕的話,flex-grow
表示希望分得蛋糕的量:
flex-grow: 0.2
表示希望獲得20%的蛋糕;flex-grow: 1
表示希望獲得100%整個蛋糕(有點過分啊,不考慮其他兄弟);flex-grow: 2
表示希望獲得200%的蛋糕(這是明搶啊,態度很明確)。但畢竟蛋糕就一個,flex容器盡量滿足felx子元素的要求,采用一種簡單的按照比例分蛋糕方式:
flex-grow
得出總和,簡稱SUM_flex_grow;正自由空間尺寸 * flex_grow / Max(SUM_flex_grow, 1)
。3.2 Demo1:按照比例分蛋糕
function demo1() { return ( <> <div className="flex"> <div className="item" style={{flexBasis: 100, flexGrow: 1, marginRight: 10}}>One</div> <div className="item" style={{flexBasis: 150, flexGrow: 2, }}>Two</div> </div> <style jsx>{` .flex { display: flex; width: 600px; outline: 1px dashed red; } .item { padding: 10px; border: 10px solid #666666; } `}</style> </> )}
解析:
計算剩余自由空間
計算各個flex子元素增長尺寸
3.3 Demo2:SUM(flex-grow) < 1
function demo3() { return ( <> <div className="flex"> <div className="item" style={{flexBasis: 100, flexGrow: 0.2, marginRight: 10}}>One</div> <div className="item" style={{flexBasis: 150, flexGrow: 0.3, }}>Two</div> </div> <style jsx>{` .flex { display: flex; width: 600px; outline: 1px dashed red; } .item { padding: 10px; border: 10px solid #666666; } `}</style> </> )}
解析:
計算剩余自由空間
計算各個flex子元素增長尺寸
注意:
如果SUM(flex-grow)小于1,此時剩余空間沒有全部分配給各個flex子元素。
3.3 Demo3 跟max-width沖突
留意該栗子中:
box-sizing=border-box
max-width=150px
function demo4() { return ( <> <div className="flex"> <div className="item" style={{flexBasis: 100, flexGrow: 1, marginRight: 10, maxWidth: 150}}>One</div> <div className="item" style={{flexBasis: 150, flexGrow: 2 }}>Two</div> <div className="item" style={{flexBasis: 100, flexGrow: 3 }}>Three</div> </div> <style jsx>{` .flex { display: flex; width: 800px; outline: 1px dashed red; } .item { padding: 10px; border: 10px solid #666666; box-sizing: border-box; } `}</style> </> )}
解析:
計算剩余自由空間
flex容器主軸尺寸 = 800px
元素one的希望尺寸 = 100px(flex-basis) + 10px(margin-right) = 110px
box-sizing=border-box
元素two的希望尺寸 = 150px(flex-basis) = 150px
box-sizing=border-box
元素three的希望尺寸 = 150px(flex-basis) = 150px
box-sizing=border-box
剩余自由空間 = 800px - 110px - 150px - 150px = 390px,即存在正剩余空間。
計算各個flex子元素增長尺寸
1 + 2 + 3
= 6,即大于1 ,一個蛋糕不夠分,只能按照比例分了。。390px * 1 / Max(1, 6)
= 390px * 1/6
=65px這樣元素one的尺寸就是100px + 65px
= 165px,大于其max-width=150px
指定的最大值,所以最終元素one的尺寸是150px。即元素one吃不完分配的蛋糕,把吃不完的蛋糕還回去了,讓其他兄弟多分些(先拋個問題:這些吃不完的蛋糕如何分配呢?)。
元素two和元素three重新分配剩下是自由剩余空間,即回到步驟1重新計算。
3.4 小結:
max-
屬性沖突時,即元素one吃不完的蛋糕會放入總蛋糕中,由后面的flex子元素重新分配。四、深入了解flex-shrink
4.1 規則
如果存在負自由空間(negative free space),則采用flex-basis + flex-shrink
組合計算Flex子元素在主軸上的比例。flex-shrink
取值表達了個flex子元素貢獻的愿望:
flex-shrink: 0.2
表示希望分攤負自由空間的20%;flex-shrink: 1
表示希望分攤100%負自由空間(夠兄弟,其他兄弟不用分攤);flex-shrink: 2
表示希望分攤200%負自由空間(分攤的態度很明確)。flex容器都感動哭了,但為了照顧各個flex子元素的感受,采用了一個“更合理”的分攤規則:
negative_free_space * Min(1, SUM(flex-shrink))
valid_negative_free_space * A / SUM_A
。計算的規則比上面的要復雜一些,不是簡單的切分negative-free-space。收縮量不僅依賴flex-shrink,還依賴flex-basis。這樣做只是為了“更合理”,即相同的flex-shrink情況下,flex-basis越小的flex元素收縮的越慢(跟納稅一樣,收入越高交的越多)。
注意: 如果flex-shrink總和小于1,則表示部分負自由空間被分攤了(即有些尺寸沒有被收縮)。
4.2 Demo1:“減少貧富差距”
function demo5() { return ( <> <div className="flex"> <div className="item" style={{flexBasis: 100, flexGrow: 1, marginRight: 10}}>One</div> <div className="item" style={{flexBasis: 150, flexGrow: 2, flexShrink: 2 }}>Two</div> </div> <style jsx>{` .flex { display: flex; width: 300px; outline: 1px dashed red; } .item { padding: 10px; border: 10px solid #666666; } `}</style> </> )}
解析(過長跟flex-grow過程類似):
計算剩余自由空間
計算各個flex子元素收縮尺寸
4.2 Demo: SUM(flex-shrink) < 1
function demo8() { return ( <> <div className="flex"> <div className="item" style={{flexBasis: 100, flexShrink: 0.2, marginRight: 10}}>One</div> <div className="item" style={{flexBasis: 150, flexShrink: 0.3 }}>Two</div> </div> <style jsx>{` .flex { display: flex; width: 300px; outline: 1px dashed red; } .item { padding: 10px; border: 10px solid #666666; } `}</style> </> )}
flex子元素超出了flex容器。
解析:
計算剩余自由空間
計算各個flex子元素收縮尺寸
4.4 Demo3: box-sizing =border-box
留意:元素one, twobox-sizing= border-box
function demo6() { return ( <> <div className="flex"> <div className="item" style={{flexBasis: 100, flexGrow: 1, marginRight: 10}}>One</div> <div className="item" style={{flexBasis: 150, flexGrow: 2, flexShrink: 2 }}>Two</div> </div> <style jsx>{` .flex { display: flex; width: 200px; outline: 1px dashed red; } .item { padding: 10px; border: 10px solid #666666; box-sizing: border-box; } `}</style> </> )}
解析:
計算剩余自由空間
計算各個flex子元素收縮尺寸
4.5 Demo5 跟min-width沖突
留意該栗子中:
元素one的min-width=60px
function demo7() { return ( <> <div className="flex"> <div className="item" style={{flexBasis: 100, flexShrink: 2, marginRight: 10, minWidth: 60}}>One</div> <div className="item" style={{flexBasis: 150, flexShrink: 2 }}>Two</div> <div className="item" style={{flexBasis: 100, flexShrink: 1 }}>Three</div> </div> <style jsx>{` .flex { display: flex; width: 300px; outline: 1px dashed red; } .item { padding: 10px; border: 10px solid #666666; } `}</style> </> )}
解析:
計算剩余自由空間
計算各個flex子元素收縮尺寸
元素two和元素three重新分配剩下是自由剩余空間,即回到步驟1重新計算。
4.6 小結
參考
css-tricks: A Complete Guide to Flexbox
規范
Understanding flexbox
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持武林網。
新聞熱點
疑難解答