淺析 flex-grow、flex-shrink、flex-basis

Flexbox 支持對元素大小的靈活控制。本文重點說說 flex-basisflex-shrinkflex-grow 的算法。css

flex-basis

指定了 flex 元素在主軸方向上的初始大小。默認值是 auto,關於 auto 這個屬性值 MDN 上還有一段簡史,能夠了解下。直接上:chestnut:html

<div class="container">
  <div class="item one">200px</div>
  <div class="item two">500px</div>
</div>
複製代碼
.container {
  display: flex;
  width: 1000px;
  height: 50px;
  background-color: green;
}
.item {
  flex-basis: auto;
  height: 100%;
  text-align: center;
  line-height: 50px;
}
.one {
  width: 200px;
  background-color: red;
}
.two {
  width: 500px;
  background-color: orange;
}
複製代碼
WX20190424-201645@2x

關鍵字 auto 的意思好像是把 widthheight 設置爲自動,實際上並非這麼一回事。auto 的意思是這個項目能夠從對應的屬性(widthheight)那裏得到主尺寸,若是沒有設置主尺寸,根據內容肯定大小——相似於行內塊或者浮動元素!git

flex-basis 還能設置成 content 值,意思是根據項目內容肯定大小——跟 auto 的區別在於忽略 widthheight 設置的主尺寸。瀏覽器對 content 關鍵字支持度不一致!!github

flex: 0 會是什麼效果呢?算法

WX20190424-202456@2x

能夠看到,子元素的 width 都失效了。其實它是子元素的最小寬度(隱形最小寬度——即使你經過屬性指定可伸縮項要收縮,但它們可能也不會收縮到可容納內容的大小之下。)。將 500px 替換成一個 DOM:瀏覽器

<div class="item two">
  <div class="two-child">400px</div>
</div>
複製代碼
.two-child {
  width: 400px;
}
複製代碼

結果以下圖所示:flex

WX20190424-204007@2x

flex-grow

屬性表示剩餘空間的一個比值,默認值是0。回到最初 200px500px 的例子,200 + 500 = 700 並無徹底撐滿整個父元素 .container 的寬度,剩餘的寬度是如何處理的呢?spa

.one {
  flex-grow: 1;
}
.two {
  flex-grow: 1;
}
複製代碼

經過上述樣式,就能夠將剩餘的 300px 平均分給.one .two元素。3d

WX20190424-205440@2x

若是結合下面樣式會是怎樣的呢?code

.item {
  flex-basis: 0%;
}
複製代碼

答案是 .one .two 平分1000px,即各 500px。不受子元素的影響。

WX20190424-210237@2x

flex-shrink

父元素寬度不夠時就要壓縮子元素的寬度,經過 flex-shrink 配置。縮小不比擴大那麼簡單,縮小的計算方法會複雜一些。複雜的根源在於,再大的子元素也不能致使小元素壓縮得不見了。仍是用最前面的例子:

.one {
  width: 600px;
  flex-shrink: 1;
}
.two {
  width: 800px;
  flex-shrink: 1;
}
複製代碼

按照自動放大的方式,應該是 (600+800-1000)/2, .one 應該是 400px.two 應該是600px

WX20190424-211401@2x

結果 .one428.58px,這是如何計算過來的呢?

.one = (600 * 1/(600*1 + 800*1))*1000428.58
.two = (800 * 1/(600*1 + 800*1))*1000571.42
複製代碼

咱們換一個比例來驗證一下想法:

.one {
  width: 600px;
  flex-shrink: 2;
}
.two {
  width: 800px;
  flex-shrink: 3;
}
複製代碼

經過計算咱們獲得:

.one = (600*2/(600*2 + 800*3))*400133.33
.two = (800*3/(600*2 + 800*3))*400266.67
複製代碼

因此 .one 的寬度是 600 - 133.33 px, .two 的寬度是 800 - 266.67 px。下面驗證一下結果:

屏幕快照 2019-04-25 22 24 18 屏幕快照 2019-04-25 22 25 27

Bingo!正如咱們的猜測那樣。這裏用 A 表示第一個子元素,B 表示第二個子元素。計算公式以下:

A 壓縮的大小 = (A.flex-shrink * A.flex-basis) / (A.flex-shrink * A.flex-basis + B.flex-shrink * B.flex-basis) * 整體超出的寬度
B 壓縮的大小 = (B.flex-shrink * B.flex-basis) / (A.flex-shrink * A.flex-basis + B.flex-shrink * B.flex-basis) * 整體超出的寬度
複製代碼

flex

flexflex-growflex-shrinkflex-basis 的縮寫,當 flex-basis 是 0 的時候必定/必須/務必要帶上單位,0px 或 0% 任君選擇。

留一道思考題,上述最後一個例子,若是給 .one 一個 min-width: 500px; 計算會有什麼不一樣嗎?

歡迎指點缺陷,更多好文前往博客

相關文章
相關標籤/搜索