flex:0 flex:1 flex:none flex:auto應該在什麼場景下使用?
一、推薦使用flex縮寫語法
CSS官方文件明確推薦flex屬性使用縮寫語法,描述如下所示:
Authors are encouraged to control flexibility using the flex shorthand rather than with its longhand properties directly, as the shorthand correctly resets any unspecified components to accommodate common uses.
大致意思是,建議使用單值縮寫,而不是完整的3個屬性值,因為單值屬性所對應的flex計算值根據開發者日常最常用的使用進行了優化。
這句話很多人並不知道什麼意思,這個說來話長,想想還是講一下吧。
flex
屬性是flex-grow
,flex-shrink
和flex-basis
這3個CSS屬性的縮寫,如果不清楚,可以參見我之前這篇口碑熱文“CSS flex屬性深入理解”。
按照以往的經驗,flex
屬性只有一個值的時候,另外預設的值應該使用預設值才對,但是flex
屬性並不是這樣的。
我們可以對比CSS border
屬性。
CSS border
屬性是border-width
,border-style
和border-color
這3個CSS屬性的縮寫,當border
屬性設定了1個值或2個值的時候,剩下的屬性值一定是預設值,例如:
border:2px
等同於border:2px none currentColor
,也就是此時border-style
是預設值none
,border-color
的計算值是當前的色值;border:#fff
等同於border:medium none #fff
,也就是此時border-width
是預設值medium
;border:solid
等同於border:medium solid currentColor
。
使用下面的程式碼可以得到flex-basis
預設值是auto
,flex-grow
預設值是0
,flex-shrink
預設值是1
。
console.log(getComputedStyle(document.body).flexGrow); console.log(getComputedStyle(document.body).flexShrink); console.log(getComputedStyle(document.body).flexBasis);
實際執行效果如下:
然後再看下flex
縮寫屬性的計算值,就會發現不一樣的事情:
flex:1
等同於flex:1 1 0%
,flex:1 2
等同於flex:1 2 0%
,即flex-basis
使用的不是預設值auto
,而是使用的0%
;flex:100px
等同於flex:1 1 100px
,即flex-grow
使用的不是預設值0
,而是使用的1
;
這就是上面提到的flex
屬性站在實用主義的角度對縮寫屬性的計算值進行了優化。
然後,還有一個重要原因,flex屬性的長語法需要理解深刻,反覆使用才能駕馭,門檻比較好,因此,實際開發,如果可以,建議使用flex縮寫。
常見的flex縮寫有下面這幾個,flex:0
、flex:1
、flex:none
、flex:auto
,那各個CSS宣告應該在什麼場景下使用才正確呢?
二、使用flex縮寫語法場景
下表展示了常見的flex
屬性單值語法對應的flex
計算值,涵蓋了絕大多數的flex
屬性的使用場景。
單值語法 | 等同於 | 備註 |
---|---|---|
flex: initial | flex: 0 1 auto | 初始值,常用 |
flex: 0 | flex: 0 0 0% | 適用場景少 |
flex: none | flex: 0 0 auto | 推薦 |
flex: 1 | flex: 1 1 0% | 推薦 |
flex: auto | flex: 1 1 auto | 適用場景少 |
1. flex:initial基本表現和適用場景
flex:initial
等同於設定flex: 0 1 auto
,可以理解為flex屬性的預設值。
該預設值圖形示意如下圖所示。
其行為表現文字描述為:
flex容器有剩餘空間時尺寸不會增長(flex-grow:0),flex容器尺寸不足時尺寸會收縮變小(flex-shrink:1),尺寸自適應於內容(flex-basis:auto)(行為類似fit-content)。
舉個例子,我們給flex容器設定深紅色的虛線框,如果此時flex子項(設定深天藍色輪廓)的內容都比較少,就會有如下圖所示的效果,剩餘空間依然保留。
相關CSS程式碼和HTML程式碼如下所示:
.container { display: flex; border: 2px dashed crimson; } .container item { border: 2px solid deepskyblue; }
<div class="container"> <item>範張</item> <item>範鑫</item> <item>範旭</item> <item>範帥</item> <item>範哥</item> </div>
如果子項內容很多,由於flex-shrink:1
,因此,會縮小,表現效果就是文字換行,效果如下圖所示。
'initial'
是CSS中的一個全域性關鍵字,表示CSS屬性的初始值,通常用來還原已經設定的CSS屬性。因此日常開發不會專門設定flex:initial
宣告,但是不設定並不是說flex
預設屬性值用的不多。
flex:initial適用場景
flex:initial
宣告適用於下圖所示的佈局效果。
上圖所示的佈局效果常見於按鈕、標題、小圖示等小部件的排版佈局,因為這些小部件的寬度都不會很寬,水平位置的控制多使用justify-content
和margin-left:auto/margin-right:auto
實現。
除了上圖所示的佈局效果外,flex:initial
宣告還適用於一側內容寬度固定,另外一側內容寬度任意的兩欄自適應佈局場景,佈局輪廓如圖下圖所示(點點點表示文字內容)。
此時,無需任何其他Flex佈局相關的CSS設定,只需要容器元素設定display:flex
即可。
總結下就是那些希望元素尺寸收縮,同時元素內容萬一較多又能自動換行的場景可以不做任何flex
屬性設定。
2. flex:0和flex:none的區別和各自適用場景
flex:0
等同於設定flex: 0 0 0%
,flex:none
等同於設定flex: 0 0 auto
。
這兩個值的圖形示意如下圖所示。
從上可以看出flex:0
和flex:none
對應的flex-grow
和flex-shrink
屬性值均是0
,因此兩者都會有如下的行為描述:
元素尺寸不會彈性增大、也不會彈性變小,也就是元素不再具有彈性。
那flex-basis:0%
和flex-basis:auto
有什麼區別呢?
flex-basis:0%
表示固定尺寸是0,由於元素不具有彈性,因此,設定flex:0
的元素的最終尺寸表現為最小內容寬度;flex-basis:auto
表示固定尺寸由內容決定,由於元素不具有彈性,因此,元素內的內容不會換行。但是,注意,不會換行並不表示設定flex:none
的元素最終尺寸表現就是最大內容寬度,如果外部尺寸不足,flex:none
有可能實際的尺寸是最小內容尺寸;
舉個例子,設定每個flex子項有足夠多的內容,HTML程式碼如下所示:
<h4>flex:0</h4> <div class="container flex-0"> <item>範張範張範張</item> <item>範鑫範鑫範鑫</item> <item>範旭範旭範旭</item> <item>範帥範帥範帥</item> <item>範哥範哥範哥</item> </div> <h4>flex:none</h4> <div class="container flex-none"> <item>範張範張範張</item> <item>範鑫範鑫範鑫</item> <item>範旭範旭範旭</item> <item>範帥範帥範帥</item> <item>範哥範哥範哥</item> </div>
然後對flex子項分別設定flex:0
和flex:none
,CSS程式碼如下所示:
.container { display: flex; } .flex-0 item { flex: 0; } .flex-none item { flex: none; }
結果如圖下圖所示:
可以看到應用了flex:0
的元素全部高高聳起,一柱擎天,表現為最小內容寬度;而應用了flex:none
的元素則無視容器的尺寸限制,直接溢位容器,沒有換行,表現為最大內容寬度。
適合使用flex:0的場景
由於應用了flex:0
的元素表現為最小內容寬度,因此,適合使用flex:0
的場景並不多,除非元素內容的主體是替換元素,此時文字內容就會庇護在替換元素的寬度下從而不會出現“一柱擎天”的排版效果。
該適用場景的佈局示意如下圖所示。
其中上圖左側部分的矩形表示一個影像,影像下方會有文字內容不定的描述資訊,此時,左側內容就適合設定flex:0
,這樣,無論文字的內容如何設定,左側內容的寬度都是影像的寬度。
適合使用flex:none的場景
當flex子項的寬度就是內容的寬度,且內容永遠不會換行,則適合使用flex:none
,這個場景比flex:0
適用的場景要更常見。
例如列表右側經常會有一個操作按鈕,對於按鈕元素而言,裡面的文字內容一定是不能換行的,此時,就非常適合設定flex:none
,例如下面這個例子,示意了按鈕使用了flex:none
之後的佈局變化,HTML和CSS程式碼如下所示:
<div class="item"> <img src="1.jpg"> <p>右側按鈕沒有設定flex:none,表現為最小內容寬度。</p> <button>按鈕</button> </div> <div class="item"> <img src="1.jpg"> <p>右側按鈕設定了flex:none,按鈕正常顯示了。</p> <button class="none">按鈕</button> </div>
.container { display: flex; padding: .5rem; border: 1px solid lightgray; background-color: #fff; } img { width: 3rem; height: 3rem; margin-right: .5rem; } button { align-self: center; padding: 5px; margin-left: .5rem; } .none { flex: none; }
從程式碼可以看出兩段內容的唯一區別就是下面的佈局對按鈕元素設定了flex:none
,結果就有如下圖所示的不同的佈局效果。
不僅按鈕正常顯示了,整個佈局會自動適配按鈕的尺寸,也就是按鈕文字多了,中間的文字內容寬度就會自動減小,整個佈局依然是彈性的。
3. flex:1和flex:auto的區別和各自適用場景
flex:1
等同於設定flex: 1 1 0%
,flex:auto
等同於設定flex: 1 1 auto
。
這兩個值的圖形示意如下圖所示。
結合flex屬性值的描述,我們可以得出flex:1
和flex:auto
的行為表現:
元素尺寸可以彈性增大,也可以彈性變小,具有十足的彈性,但是
flex:1
在尺寸不足時會優先最小化內容尺寸,flex:auto
在尺寸不足時會優先最大化內容尺寸。
上面的描述可以通過一個例子明白是什麼意思,這一次是僅僅設定第1項的文字內容很多,HTML程式碼如下所示:
<h4>flex:1</h4> <div class="container flex-1"> <item>範張範張範張範張範張範張範張範張範張</item> <item>範鑫</item> <item>範旭</item> <item>範帥</item> <item>範哥</item> </div> <h4>flex:auto</h4> <div class="container flex-auto"> <item>範張範張範張範張範張範張範張範張範張</item> <item>範鑫</item> <item>範旭</item> <item>範帥</item> <item>範哥</item> </div>
可以看出兩段HTML結構和內容都是一樣的,現在,對上下兩端HTML設定不同的CSS樣式,程式碼如下所示:
.flex-1 item { flex: 1; } .flex-auto item { flex: auto; }
結果就會看到如下圖所示的佈局效果。
上圖鮮明地體現了flex:1
和flex:auto
的區別,雖然都是充分分配容器的尺寸,但是flex:1
的尺寸表現更為內斂(優先犧牲自己的尺寸),flex:auto
的尺寸表現則更為霸道(優先擴充套件自己的尺寸)。
從某種程度上講,flex:1
的表現神似table-layout:fixed
,flex:auto
的表現神似table-layout:auto
。
適合使用flex:1的場景
當希望元素充分利用剩餘空間,同時不會侵佔其他元素應有的寬度的時候,適合使用flex:1
,這樣的場景在Flex佈局中非常的多。
例如所有的等分列表,或者等比例列表都適合使用flex:1
或者其他flex數值,適合的佈局效果輪廓如下圖所示。
以及適用於無規律佈局中動態內容元素,我們不妨繼續使用flex:none
那裡演示的例子進行說明。
下面這段HTML和CSS程式碼下的按鈕元素是換行顯示的(就是前面出現過的按鈕不換行的例子的HTML程式碼)。
<div class="item"> <img src="1.jpg"> <p>右側按鈕沒有設定flex:none,表現為最小內容寬度。</p> <button>按鈕</button> </div>
.container { display: flex; padding: .5rem; border: 1px solid lightgray; background-color: #fff; } img { width: 3rem; height: 3rem; margin-right: .5rem; } button { align-self: center; padding: 5px; margin-left: .5rem; }
除了設定<button>
元素flex:none
以外,在這個例子中,我們還可以設定<p>
元素flex:1
實現類似的效果。
p { flex: 1; }
結果就有如下圖所示,<p>
元素設定了flex:1
之後,按鈕元素正常顯示了。
適合使用flex:auto的場景
當希望元素充分利用剩餘空間,但是各自的尺寸按照各自內容進行分配的時候,適合使用flex:auto
。
flex:auto
多用於內容固定,或者內容可控的佈局場景,例如導航數量不固定,每個導航文字數量也不固定的導航效果就適合使用flex:auto
效果來實現,我做了個很簡單的示意,程式碼如下所示:
<nav class="flex"> <span>首頁</span> <span>排行榜</span> <span>我的訂單</span> <span>個人中心</span> </nav>
nav span { flex: auto; line-height: 3rem; background: #444; color: #fff; text-align:center; } span + span { border-left: 1px solid #eee; }
此時大家就可以看到一個基於內容自動分配寬度的自適應導航效果了,效果如下圖所示,文字越多的導航佔據的寬度越大,這完全是瀏覽器自動分配的。
三、最後總結一下
最後總結一下:
flex:initial
表示預設的flex狀態,無需專門設定,適合小控制元件元素的分佈佈局,或者某一項內容動態變化的佈局;flex:0
適用場景較少,適合設定在替換元素的父元素上;flex:none
適用於不換行的內容固定或者較少的小控制元件元素上,如按鈕。flex:1
適合等分佈局;flex:auto
適合基於內容動態適配的佈局;
以上就是本文內容,寫於2020年國慶,部分內容節選自明年會出版的新書《CSS新世界》。
感謝您的閱讀,如果您覺得本文內容還不錯,歡迎分享。
相關文章
- display:inline-flex 和 display:flex有什麼區別inlineFlex
- 深入理解 flex-grow、flex-shrink、flex-basisFlex
- flexFlex
- display:flex與inline-flex 區別Flexinline
- CSS flexCSSFlex
- flex相容Flex
- flex bisonFlex
- css flex佈局中妙用margin: autoCSSFlex
- 重新總結flex佈局(flex,flex-direction,justify-content,align-items,flex-wrap,align-self)Flex
- 重新認識flex縮寫屬性—[flex]Flex
- Flex佈局應用Flex
- flex入門—瞭解這些flex屬性Flex
- flex已知bugFlex
- flex 佈局Flex
- flex總結Flex
- ANTLR flex/bisonFlex
- flex實戰Flex
- Flex佈局Flex
- Flex腦圖Flex
- 在Flex控制元件中使用XMLListCollectionFlex控制元件XML
- flex:1學習筆記Flex筆記
- CSS Flex 佈局的 flex-direction 屬性講解CSSFlex
- flex佈局父項常見屬性flex-flowFlex
- flexbox佈局下flex:auto的元素沒有平均分佈Flex
- CSS flex-basisCSSFlex
- Flex Box 概念梳理Flex
- flex 彈性盒子Flex
- CSS flex-shrinkCSSFlex
- CSS flex-flowCSSFlex
- CSS flex-wrapCSSFlex
- CSS flex-directionCSSFlex
- css flex佈局CSSFlex
- flex快速學習Flex
- Flex & Bison 開始Flex
- flex佈局原理Flex
- 彈性盒子flexFlex
- 彈性盒模型中flex-grow 和flex的區別模型Flex
- 從前端小白到大佬 flex下前端Flex