點燈坊

學而時習之,不亦悅乎

CSS Flexbox 之使用 flex-grow 與 flex-shrink 改變寬度

Sam Xiao's Avatar 2019-07-10

若 Item 總寬度 小於 Container,會依 flex-grow 決定如何瓜分剩餘 Container 寬度;若 Item 總寬度 大於 Container,會依 flex-shrink 決定如何縮減以配合 Container 寬度。

Version

macOS Mojave 10.14.5
WebStorm 2019.1.3
Chrome 75.0.3770.100
CSS 3

HTML

index.html

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Flexbox</title>
  <meta name="viewport" content="width=device-width,initial-scale=1.0">
  <link rel="stylesheet" href="style.css">
</head>
<body>
  <div class="box">
    <h1 class="item0">1</h1>
    <h1 class="item1">2</h1>
    <h1 class="item2">3</h1>
  </div>
</body>
</html>

<div> 下有 3 個 <h1>

CSS

style.css

.box {
  display: flex;
  background: #d3d3d3;
}

.item0 {
  background: #faa;
  flex-basis: 300px;
}

.item1 {
  background: #afa;
  flex-basis: 300px;
}

.item2 {
  background: #aff;
  flex-basis: 300px;
}

第 1 行

.box {
  display: flex;
  background: #d3d3d3;
}

displayflex,表示使用 flexbox。

第 6 行

.item0 {
  background: #faa;
  flex-basis: 300px;
}

.item1 {
  background: #afa;
  flex-basis: 300px;
}

.item2 {
  background: #aff;
  flex-basis: 300px;
}

每個 item 都使用 flex-basis 設定寬度,其寬度都相等。

Chrome

grow000

各 item 根據 flex-basis 設定寬度顯示,但明顯發現 container 還有不少寬度 尚未使用

flex-grow

grow001

1 佔滿了所有 container 剩餘寬度。

.item0 {
  background: #faa;
  flex-basis: 300px;
  flex-grow: 1;
}

flex-box 設定為 1,表示 item0 將以 比例 1 呈現,若沒設定 flex-grow 預設為 0,因此各 item 以 1 : 0 : 0 瓜分 container 剩餘寬度。

因為 flex-grow 預設為 0,所以 0 : 0 : 0 不瓜分 container 剩餘寬度

grow002

Container 剩餘寬度不再由 item0 獨佔,而由 item0item1item2 依比例瓜分。

.item0 {
  background: #faa;
  flex-basis: 300px;
  flex-grow: 1;
}

.item1 {
  background: #afa;
  flex-basis: 300px;
  flex-grow: 2;
}

.item2 {
  background: #aff;
  flex-basis: 300px;
  flex-grow: 3;
}

flex-grow 設定皆不同,因此依 1 : 2 : 3 比例瓜分。

flex-shrink

grow003

Container 寬度變小,各 item 看起來像均分 container。

.box {
  display: flex;
  background: #d3d3d3;
  width: 900px;
}

.item0 {
  background: #faa;
  flex-basis: 400px;
}

.item1 {
  background: #afa;
  flex-basis: 400px;
}

.item2 {
  background: #aff;
  flex-basis: 400px;
}

第 1 行

.box {
  display: flex;
  background: #d3d3d3;
  width: 900px;
}

Container 總寬度為 900px

第 7 行

.item0 {
  background: #faa;
  flex-basis: 400px;
}

.item1 {
  background: #afa;
  flex-basis: 400px;
}

.item2 {
  background: #aff;
  flex-basis: 400px;
}

各 item 的 flex-basis 總和為 1200px,已經大於 container 的 900px,因為 flex-shrink 預設為 1,所以各 item 以 1 : 1 : 1 等比例縮減以配合 container 寬度,因此看起來像等寬均分 container。

grow004

Container 寬度依然是 900px,但 item 0 縮減的程度明顯比 item 1item 2 大。

.item0 {
  background: #faa;
  flex-basis: 400px;
  flex-shrink: 3;
}

item 0flex-shrink 設定為 3,所以各 item 以 3 : 1 : 1 比例縮減,因此 item 0 明顯縮減較大。

grow005

Container 寬度依然是 900px,但縮減程度明顯 item2 > item1 > item0

.item0 {
  background: #faa;
  flex-basis: 400px;
  flex-shrink: 1;
}

.item1 {
  background: #afa;
  flex-basis: 400px;
  flex-shrink: 2;
}

.item2 {
  background: #aff;
  flex-basis: 400px;
  flex-shrink: 3;
}

flex-shrink 設定皆不同,因此依 1 : 2 : 3 比例縮減,也就是 item3 縮減程度最大,因此最短。

grow006

僅管各 item 寬度總和大於 container,但仍希望其 overflow 與 container。

.item0 {
  background: #faa;
  flex-basis: 400px;
  flex-shrink: 0;
}

.item1 {
  background: #afa;
  flex-basis: 400px;
  flex-shrink: 0;
}

.item2 {
  background: #aff;
  flex-basis: 400px;
  flex-shrink: 0;
}

若各 item 的 flex-shrink 皆設為 0,則表示都不 shrink,因此會 overflow 於 container。

Conclusion

  • flex-grow 用來設定瓜分 container 剩餘寬度比例;flex-shrink 用來設定縮減 item 寬度比例
  • flex-grow 預設為 0;而 flex-shrink 預設為 1
  • 若各 item 寬度總和小於 container,想要依相同比例瓜分 container 剩餘寬度,則各 item 的 flex-grow 都設定為 1
  • 若各 item 寬度總和大於 container,想要 overflow 與 container,則各 item 的 flex-shrink 都設定為 0

Reference

Garth Braithwaite, Using flex-shrink and flex-grow to make flexbox children resize correctly
MDN, flex-shrink
MDN, flex-grow