iT邦幫忙

第 11 屆 iT 邦幫忙鐵人賽

DAY 26
1


今天將介紹 flex 屬性,在這之前先來了解一下 positive free space 與 negative free space 這兩個名詞。

positive free space

flex items主軸(main axis)方向上的尺寸總和小於 flex container 的尺寸,此時會出現 flex container 的空間沒有被填滿,這些剩餘空間就稱為 positive free space

例如,在主軸(main axis)為 row 下,若 flex container 的寬度為 500px,而 a、b、c 三個 flex items 寬度各為 100px,此時 flex container 還有 200px 的 positive free space。


圖片來源 MDN


negative free space

flex items主軸(main axis)方向上的尺寸總和大於 flex container 的尺寸,此時 flex container 的空間不夠用,而 flex items 的尺寸總和與 flex container 尺寸的差額就稱為 negative free space

例如,在主軸(main axis)為 row 下,若 flex container 的寬度為 500px,而 a、b、c 三個 flex items 寬度各為 200px,此時 flex container 的寬度 500px 小於 flex items 的寬度總和 600px,negative free space 為 600px 減 500px,等於 100px。


圖片來源 MDN


flex 屬性

摘自 W3C

  • flex-growflex-shrinkflex-basis 的縮寫。

    • flex-grow: 決定 flex item得到多少比例positive free space
    • flex-shrink: 決定 flex item得到多少比例negative free space
    • flex-basis: 決定 flex item 在尚未 grow 與 shrink 前的原始尺寸
  • 預設值為 flex: 0 1 auto


以下先單獨介紹 flex-grow、flex-shrink 與 flex-basis,暫時先不考慮混合狀況。


flex-grow

  • flex-basis 為基礎,決定 positive free space分配比例,所以有 positive free space 才有作用。
    • 必須為 ≥ 0 的值。
    • 若為 0 (預設值),則不會延伸

例如

在 flex-direction: row 下,有一個寬度為 500px 的 flex container,與三個寬度各為 100px、80px、70px 的 flex items,則在預設下會有 500px - 250px = 250px 的 positive free space 。


<div class="container">
  <div class="item1">item1</div>
  <div class="item2">item2</div>
  <div class="item3">item3</div>
</div>
.container {
  display: flex;
  outline: 3px solid #444;
  width: 500px;
  height: 120px;
  }  

.item1 {
  width: 100px;
  flex: 0 1 auto;    /* 此為預設值 */
}

.item2 {
  width: 80px;
  flex: 0 1 auto;    /* 此為預設值 */
}

.item3 {
  width: 70px;
  flex: 0 1 auto;    /* 此為預設值 */
}

現在將三個 flex items 的 flex-grow 分別設定為 122

  • item1 將分配到 1/(1+2+2) = 1/5 的 positive free space。最終寬度為 150px。
  • item2 將分配到 2/(1+2+2) = 2/5 的 positive free space。最終寬度為 180px。
  • item3 將分配到 2/(1+2+2) = 2/5 的 positive free space。最終寬度為 170px。
.item1 {
  width: 100px;
  flex: 1 1 auto; /* 將 flex-grow 改為 1,將佔 1/5 等分 */
}

.item2 {
  width: 80px;
  flex: 2 1 auto; /* 將 flex-grow 改為 2,將佔 2/5 等分 */
}

  
.item3 {
  width: 70px;
  flex: 2 1 auto;  /* 將 flex-grow 改為 2,將佔 2/5 等分 */
}


flex-shrink

  • flex-basis 為基礎,決定 negative free space分配比例,所以有 negative free space 才有作用。

    • 必須為 ≥ 0 的值。
    • 若為 0,則不會收縮,此時若 container 空間不夠,會發生 overflow
    • 預設值1
  • flex items 不會縮短至小於 min-content 的尺寸,除非設定 min-width 或 min-height 屬性。

例如

flex container 寬度為 500px,其三個 flex items 寬度各為 200px,故此時有 100px 的 negative free space,若將所有 flex items 的 flex-shrink 皆設定為 0,則將發生 overflow。

<div class="container">
  <div class="item1">item1</div>
  <div class="item2">item2</div>
  <div class="item3">item3</div>
</div>
.container { 
    display: flex;
    width: 500px;
    height: 120px;
    outline: 3px solid #333;
}

.container > * {      
  width: 200px;       /* 所有 flex items 寬度皆為 200px */ 
  flex: 0 0 auto;     /* 將所有的 flex-shrink 設定為 0 */
}

現在將第一個與第二個 flex item 的 flex-shrink 分別設定為 14,第三個 flex item 的 flex-shrink 依然為 0

注意,shrink 與 grow 的計算方法並不相同,公式可參考 前端新手村 flex grow & shrink 演算法

negative free space = 500px - 200 *3 = -100px

  • item 1 將分配到 1/5 的 negative free space,所以最後寬度為 180px。

算法: 1 * 200/(1 * 200 + 4 * 200 + 0 * 200)= 1/5

  • item 2 將分配到 4/5 的 negative free space,所以最後寬度為 120px。

算法: 4 * 200/(1 * 200 + 4 * 200 + 0 * 200)= 4/5

  • item 3 將分配到 0/5 的 negative free space,所以最後寬度為 200px。

算法: 0 * 200/(1 * 200 + 4 * 200 + 0 * 200)= 0

.item1 {
  flex: 0 1 auto;      /* 佔 1*200/(1*200+4*200+0*200)= 1/5 等份 */
}

.item2 {
  flex: 0 4 auto;     /* 佔 4*200/(1*200+4*200+0*200)= 4/5 等份 */
}

.item3 {
  flex: 0 0 auto;     /* 佔 0*200/(1*200+4*200+0*200)= 0 等份 */
}


flex-basis

  • 決定 flex item 在尚未 grow 或 shrink 前的原始尺寸

  • 預設值auto

    • 指定尺寸 width、height (視主軸 main axis 而定),則依照所指定的尺寸
    • 指定尺寸 width、height (視主軸 main axis 而定),則由其內容大小決定。
  • 若為 0,則 flex item 不被納入空間計算。例如有一個 container 寬度 400px,裡面有 item1 與 item2,寬度各為 200px,此時 flex-basis 為預設的 auto,故沒有剩餘空間。但若將 item2 的 flex-basis 設為 0,則會有 200px 的剩餘空間,原因是 flex-basis 優先級高於 width 與 height。

  • 除了 auto 之外,尚有 content、max-content、min-content 等屬性值,不過多數瀏覽器不支援。

  • 可給定有單位數值,例如 100px 或 10%,若同時設定 flex-basis (非 auto)尺寸(width 或 height,視主軸 main axis 而定),則以 flex-basis優先

例如:

有三個 flex items,指定第一個 flex item 的 width 為 200px,
在 flex-direction: row 且 flex-grow 與 flex-shrink 皆為 0 的前提下,設定 flex-basis 值為 auto,此時

  • 第一個 flex item 的寬度為 200px。
  • 第二與第三個 flex item 的寬度為其內容尺寸。

<div class="container">
  <div>flex item 1</div>
  <div>flex item 2</div>
  <div>flex item 3</div>
</div>
div {
  outline: 1px solid #333;
}

.container {
  display: flex;
}

.container :first-child {
  width: 200px;    /* 第一個子元素給定寬度 200px */
}

.container > * {
  flex: 0 0 auto;  /* 所有子元素的 flex basis 為 auto*/
}



就先介紹到這拉
明天見~




參考資源

W3C-CSS Flexible Box Layout Module Level 1
MDN-Controlling Ratios of Flex Items Along the Main Axis
前端新手村 flex grow & shrink 演算法


上一篇
flex 3
下一篇
flex 5
系列文
前端新手進化史30

1 則留言

0
Chris
iT邦新手 5 級 ‧ 2019-10-12 14:51:04

grow 和 shink 兩者的算法不同哦

shink × basis 再累計,才是分母。你的例子用 auto, 所以要看寬度
item 1
壓縮比例 = 1001 / (1001 + 801 + 701) = 0.4
壓縮後的寬度 = 0.4 * free space
https://ithelp.ithome.com.tw/articles/10194694

看更多先前的回應...收起先前的回應...
yachen iT邦新手 5 級‧ 2019-10-12 16:41:39 檢舉

咦,shrink 範例結果我開開發者工具看是沒錯的,還是只是湊巧XD
https://codepen.io/yachen/pen/KKKVKPg?editors=1100
但我的確沒考慮到混合 basis 的狀況~
晚點來研究,先寫今天的鐵人QQ
感恩 seafood!!

Chris iT邦新手 5 級‧ 2019-10-12 21:07:38 檢舉

明天來寫一篇證明,證明我是錯的!XDDD
驗證一下較為複雜的例子。
flex 的三個屬性都亂調都要符合證明結果,才算正確。

yachen iT邦新手 5 級‧ 2019-10-13 00:59:02 檢舉

咦,我好像真的是湊巧XDD
然後我發現你看錯題目拉~
100 80 70 是 grow 範例的XD

shrink 範例是 3 個 items 寬度各 200px,容器 500px。
代入你的公式是行得通的~

yachen iT邦新手 5 級‧ 2019-10-13 11:56:42 檢舉

shrink 計算方式修正完畢!/images/emoticon/emoticon12.gif

我要留言

立即登入留言