【CSS趣味】flex 缺省的 auto 跟 0 到底有何區別

疑問

最近遇到個問題:flex:1;flex:1 1 0;是否等價。按照我以前對W3C屬性值語法的理解,flex:1;應該是flex:1 1 auto;的缺省寫法,剩下的兩個flex-shrinkflex-basis的坑應該分別對應1auto。嗯,若是我沒記錯的話,簡寫屬性(shorthand)有個特性:對於缺省值會重置爲對應的單個屬性的初始值(詳情請參看《CSS權威指南第三版》P130)。這裏的flex-shrinkflex-basis就是缺省的單個屬性。但是常規測試(彈性子項未填充內容)都不能讓人明顯感知到flex:1;flex:1 1 0;的區別。那麼問題來了:How Can We Feel The Difference?css

Try It

首先,肯定咱們要作什麼?經過實驗瞭解flex的缺省auto跟0有何區別。html

而後,給出代碼(能夠去個人Github上找到名爲shorthand_flex_test的兩個文件查看源代碼):git

.contain {
    background: #aec;
    height: 100px;
    display: flex;
    justify-content: space-around;/*設置主軸方向均分對齊*/
    flex-flow: row wrap;/*設置正常水平排列*/
    align-items: stretch;/*設置全部彈性子項拉伸到彈性容器高度*/
}
.item {
    border: 3px solid rgba(0,0,0,.2);
    padding: 10px;
    background: #eac;
    color: #fff;
    font-size: 2em;
    font-weight: bold;
    text-align: center;
}

效果圖:github

clipboard.png

接下來,看實驗。web

第一步:flex:1;flex:1 1 auto; 根據官方定義,缺省值就是初始值,兩個實現出來的效果就應該相同。chrome

給.item設置flex:1;,效果圖以下:app

clipboard.png

給.item設置flex:1 1 auto;,效果圖:編輯器

clipboard.png

WTF?不對!工具

先別急,F12看下設置flex:1;時devtool窗口裏的計算值測試

clipboard.png

再看看設置flex:1 1 auto;時的計算值(這句是廢話,請自動省略)

clipboard.png

小結:原來缺省的時候不是取的單項的初始值啊(flex-shrink:1flex-basis:auto)。那麼這個0%是否是就等價於0呢?

第二步,此次改成設置flex:1 1 0;

clipboard.png

圖仍是這樣的,但是計算值不同啊,以下

clipboard.png

小結:其實百分比的計算值是以父類容器的寬度爲基數計算的,而長度值0直接取值不用再計算,可是0%0的最終計算值都是0px

解答結果

因此說開始的疑問獲得解答了:flex:1;flex:1 1 0;的視覺效果和最終計算值是同樣的,只不過是計算過程不一樣。

擴展實驗

Part 1. 既然都作實驗了,那麼能夠「順便」研究一下,flex的幾個經常使用值的幾種寫法,這裏是drafts.csswg.org的連接。

第一種:flex:initial;等價於flex:0 1 auto;,也等價於flex:0 auto;

給.item設置flex:initial;

clipboard.png

計算值

clipboard.png

小結:這裏是auto自適應獲得的10%。這個屬性聲明獲得的效果就是使得彈性子項在有多餘空間的時候不拉伸,在空間不足時收縮到最小的寬度/高度(由主軸方向決定具體的計算基數)。這裏的寬度/高度可能涉及到彈性子項內部的文本內容,內容的有無使得auto跟另外一個flex-basis的屬性content有差別,後面講。另外,當設置爲這個屬性值的時候,彈性容器上設置的主軸方向對齊效果和margin:auto;居中效果才能生效。

第二種:flex:auto;等價於flex:1 1 auto;

給.item設置flex:auto;

clipboard.png

計算值

clipboard.png

小結:這使得彈性子項在有多餘空間時拉伸,在空間不足時收縮。這時候彈性子項纔有完整的彈性效果,而當多個彈性子項設置不一樣的flex屬性聲明時,任何多餘空間都將被設置了auto屬性值的彈性子項「吸取」掉。

第三種,flex:none等價於flex:0 0 auto;

給.item設置flex:none

clipboard.png

計算值

clipboard.png

小結:這使得彈性子項徹底失去彈性效果。效果跟設置auto屬性值差很少,可是一旦內容溢出彈性容器,這裏的彈性子項是不會收縮的。

Part 2. 繼續,看看以前提到的content是怎麼回事。

第一步,咱們來跟initial的等價值作個對照。initial的就不貼了,Part1的第一種裏有。直接看flex:0 1 content;

clipboard.png

計算值

clipboard.png

分析:什麼狀況?!flex的計算值呢?前面的none都會有計算值的,這裏居然不見了!稍等,可不能夠這樣理解,在設置content的時候,前面兩個值能夠忽略?

第二步,設置flex:content;

clipboard.png

計算值

clipboard.png

分析:果真是一毛同樣的。BUT,WHY?content究竟是幹啥子的?

標準裏說這個屬性值設置會使得彈性子項的寬度/高度直接由其中的內容決定。哦~,難怪對照效果中明顯是上面那組的彈性子項「們」是被內容撐開了的。

でも、這豈不是跟不設置flex屬性沒兩樣了!書讀少勿欺我!保險起見,我只能開「大招」了:

-webkit-flex: content;
    -moz-flex: content;
    -ms-flex: content;
    -o-flex: content;
    flex: content;

clipboard.png

計算值裏仍是找不到flex的影子

clipboard.png

第三步,再在第二步的「大招」基礎上加個width:100px;

clipboard.png

計算值裏還只沒影兒

clipboard.png

分析:這裏給每一個彈性子項設置了固定寬度(由於這水平軸就是主軸),由於沒有flex屬性的伸展因子flex-grow和收縮因子flex-shrink的影響,每一個彈性子項都「老老實實的」按照justify-content: space-around的指令水平對齊了(嘴上說着不要「身體」仍是挺老實的嘛,嘖嘖)。

好吧,只能認可,content是個無效的屬性值。對!它並非屬性值。好大一個玩笑(輕點,別打臉)。它只是表示彈性子項的寬度/高度由內容決定,即被內容撐開。而這個撐開的寬度/高度則做爲伸展因子和收縮因子的基數進行相應彈性變化的計算。

Part 3. 憑什麼說被內容撐開的寬度/高度就是連體因子(舌頭打結了)的計算基數?不服來辯!

第一步,先看不設置flex屬性時上面對照實驗中上面一組的數據(記得「關了」width),從左至右:

clipboard.png

clipboard.png

clipboard.png

能夠看到第一個no1和第三個no3的寬度是相同的84.297,第二個是290.875。這裏要注意由於box-sizing初始值是content-box,因此內容區寬就是width的取值,邊距邊框都不用管。

第二步,設置一個伸展因子flex:1 1 auto;這裏必須設置flex-basis:auto;由於缺省後就是flex-basis:0%;了,至關於以撐開的寬度/高度做爲的基數置零了。效果圖就不上了,對應前面的flex:auto;,下面是計算值

clipboard.png

clipboard.png

clipboard.png

能夠看到此次的第一個no1和第三個no3的寬度是126.813,第二個是333.391。而後讓咱們搬出伸展因子的計算公式:

flex-basis + flow-grow / sum( flow-grow ) * remain

這裏的flow-grow指的就是flex-flow方向上的伸展因子的數值,而因爲設置了flex-basis:auto;主軸的基數flex-basis的計算值應該就是第一步的數據84.29七、290.875和84.297;remain則是容器總寬度減去第一步中的全部寬度總和的結果:

665 - ( 84.2969 + 290.875 + 84.2969) - (10 + 3) * 2 * 3 = 127.5312

這裏由於是算的彈性容器內的區域因此要把內邊距和邊框都加上,另外以前在盒模型裏顯示的84.297不是精確值,最下面的計算值清單裏的精確值是84.2969,以避免引發後面結果錯誤。

clipboard.png

最後套入公式:

第二部中第一個和第三個彈性子項的寬:

84.2969 + ( 1 / 3 ) * 127.5312 = 126.8073
(這裏跟126.813很接近,可是我找不出那裏算漏了的,有知道的朋友麻煩告知,謝謝)

第二個彈性子項的寬:

290.875 + (1 / 3 ) * 127.5312 = 333.3854(待查錯)

這一部分先到這裏吧。花了我很久時間,好晚了。

總結

flex的缺省值並不是是單一屬性的初始值,而且還有經常使用的簡寫屬性值initialautonone;當彈性子項沒有設置固定寬度(對於水平的狀況,也就是寬度自己是auto的)時,flex-basis若是也是auto,那麼flex-basis的使用值就是彈性子項的內容自己撐起來的寬度(對於水平的狀況)

工具與環境

  • 操做系統:window 7 ultimate 64bit

  • chrome內核版本:45.0.2454.101

  • 編輯器:Sublime Text 3

參考資料

嘮叨

在查找資料過程當中,發現一些不錯的東西,分享加收藏一下。

先這樣了,爲了發完這文章熬夜了。熊貓君思密達。
對了代碼能夠去個人Github上找,說完了。

再補一點信息,必定不要忘了標準的文檔開篇說的:

Publication as a Candidate Recommendation does not imply endorsement by the W3C Membership. This is a draft document and may be updated, replaced or obsoleted by other documents at any time. It is inappropriate to cite this document as other than work in progress.1

相關文章
相關標籤/搜索