Flex佈局-子項

致于数据科学家的小陈發表於2024-05-18

彈性盒子是一種用於 按行 或 按列的一維佈局方法.

元素可以膨脹以填充額外的空間, 也可以 收縮 以適應更小的空間.

flex 容器項重點

只是用表格進行排版而已, 橫向內容無關聯哈, 只是簡要回憶一些前置知識.

重點 常用佈局
flex-direction 內聯和塊的 水平垂直居中佈局
flex-wrap / flex-flow 不定項居中佈局
justify-content 均分列布局
align-items 子項分組佈局

flex 子項重點

也是用表格來進行排版, 橫向內容無關聯哈.

重點 常用佈局
flex-grow: 擴充套件比例 粘性頁尾佈局
flex-shrink 收縮比例 溢位項佈局
flex-basis 及flex縮寫 兩列與三列布局
order 與 align-self 等高佈局

子項-擴充比例

flex-row 預設值是 0, 表示布佔用剩餘空白間隙, 以擴充套件自己的寬度, 應用於當子項空間小於容器時.

  • flex-grow: 0 預設不佔剩餘空間
  • flex-grow: 1 佔滿剩餘空間
  • flex-grow: 0.5 佔滿剩餘空間的一半
  • flex-grow: 2 和 1 等價, 佔滿剩餘空間

當為一個盒子的時候, 進行一波檢視:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>子項: flex-grow</title>
  <style>
    .main {
      height: 300px;
      width: 500px;
      background-color: pink;
      display: flex;
    }

    .main div {
      width: 100px;
      height: 100px;
      background-color: skyblue;

      /* flex-grow: 0; 是預設值, 預設不佔剩餘空間 */

      /* 為 1 的時候, 就會佔滿全部剩餘空間 */
      /* flex-grow: 1; */

      /* 為 0.5 時, 佔滿剩餘空間的一半 */
      /* flex-grow: 0.5; */

      /* 當大於 1 時, 都會佔滿整個剩餘空間 */
      flex-grow: 2;
    }

  </style>
</head>
<body>
  <div class="main">
   <div>1</div>
  </div>
</body>
</html>

當為多個子項的時候, 還是可以以 1 作為參考分割比, 其實就是對剩餘空間的分配百分比計算.

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>子項: flex-grow</title>
  <style>
    .main {
      height: 300px;
      width: 500px;
      background-color: pink;
      display: flex;
    }

    /* 第一個盒子佔 200px 寬 */
    .main div:nth-of-type(1) {
      width: 200px;
      height: 100px;
      background-color: skyblue;

      /* 將剩下的 200px 都給它, 或者均分 */
      /* flex-grow: 1; */

      /* 分成 3份, 它佔 2分, 則 200 * 2/3 = 166.7 */
      /* flex-grow: 2; */

      /* 不滿足1的時候, 類似將剩餘分成10份, 它佔2, 另外一個佔1, 剩餘空間是7  */
      flex-grow: 0.2;
    }

    /* 第二個盒子佔 100px 寬 */
    .main div:nth-of-type(2) {
      width: 100px;
      height: 100px;
      background: gold;

      /* 將剩下的 200px 都給它, 或者均分 200 */
      /* flex-grow: 1; */

      flex-grow: 0.1;
    }

    /* 剩下空間為:  500 - 100 - 200 = 200px */

  </style>
</head>
<body>
  <div class="main">
   <div>1</div>
   <div>2</div>
  </div>
</body>
</html>

子項-收縮比例

flex-shrink 預設值是 1, 表示當 flex 容器空間不足時, 元素的收縮比例, 應用於當子項空間大於容器時.

  • flex-shring: 1 預設收縮, 和容器一樣, 子項不會溢位
  • flex-shrink: 0 不收縮, 子項正常溢位容器
  • flex-shrink: 2 大於1和等於1的效果是一致的, 子項不溢位

當為一個盒子的時候, 進行一波檢視:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>子項: flex-shrink</title>
  <style>
    .main {
      height: 200px;
      width: 500px;
      background-color: pink;
      display: flex;
    }

    /* 讓尺寸溢位父容器 */
    .main div {
      width: 600px;
      height: 100px;
      background-color: skyblue;

      /* flex-shring: 1; 自動收縮, 讓子項和容器大小相同 */

      /* 為 0 時, 不收縮, 則就溢位父容器啦 */
      /* flex-shrink: 0; */

      /* 為 0.5 時, 收縮, 超出部分 100px 的一半. 還是會溢位  */
      /* flex-shrink: 0.5; */

      /*為 2 時, 即只要大於 1, 就和容器一樣大小啦 */
      flex-shrink: 22;
    }

  </style>
</head>
<body>
  <div class="main">
   <div>1</div>
  </div>
</body>
</html>

多個盒子也是一樣的, 同擴充一行, 也是對溢位空間結合子項權重進行收縮分配而已啦.

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>子項: flex-shrink</title>
  <style>
    .main {
      height: 200px;
      width: 500px;
      background-color: pink;
      display: flex;
    }

    .main :nth-of-type(1) {
      width: 300px;
      height: 100px;
      background-color: skyblue;

      flex-shrink: 3;
    }

    .main :nth-of-type(2) {
      width: 400px;
      height: 100px;
      background-color: gold;

      flex-shrink: 2;
    }

    /* 
    總寬: 500; box1: 300; box2: 400
    總溢位: 300 + 400 - 500 = 200

    當 box1, box2 的 shrink = 1 時: 

    收縮值: 
    box1: 200 * (300 / (300 + 400)) = 200 * 3/7 = 85.7
    box2: 200 * 4/7 = 114.3
    
    當 box1-shrink = 3;  box2-shrink = 2時: 

    此時 box1: 300 * 3 = 900; box2: 400 * 2 = 800, 那一共就是 17 份
    收縮值: 
    box1: 200 * 9/17 = 105.9 
    box2: 200 * 8/17 = 94.1

    */

  </style>
</head>
<body>
  <div class="main">
   <div>1</div>
   <div>2</div>
  </div>
</body>
</html>

子項-初始尺寸

flex-basis 預設值是 auto, 指定了子項在主軸方向的初始大小.

比如, 當前為水平佈局,  子項的 width: 200px;  height: 100px;   

然後, 當改為垂直佈局,  子項的 width: 100px;  height: 200px

這樣的轉置的話, 就可以設定 `flex-basis: 200px 進行作用的.
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>子項: flex-basis</title>
  <style>
    .main {
      width: 500px;
      height: 500px;
      background-color: pink;
      display: flex;

      /* flex-direction: column; */
    }
    
    .main div {
      width: 100px;
      height: 100px;
      background-color: skyblue;

      /* row 佈局時, 覆蓋 width;  column 時, 覆蓋 height */
      flex-basis: 200px;
    }
  </style>
</head>
<body>
  <div class="main">
    <div></div>
  </div>
</body>
</html>

但在實踐中, 似乎用得也不多.

子項-flex

flex 屬性是 flex-grow, flex-shrink, flex-basis 的縮寫, 咱最長用的一個寫法就是 flex:1.

/* flex: 1 等同於: */

flex-grow: 1;    佔滿剩餘空間
flex-shrink: 1;  預設收縮
flex-basis: 0%; 


/* flex: auto 等同於: */ 

flex-grow: 1;    佔滿剩餘空間
flex-shrink: 1;  預設收縮
flex-basis: auto; 

/* 感覺還是直接寫減少記憶點 */
flex: 1 1 auto;

就其實 flex: 1 基本就搞定啦!

剩下的兩個屬性 orderalign-self 也基本很少用.

order 可以用來指定某個子項的排序優先順序; align-self 就跟 容器的 align-items 的對齊方式類似的.

用到的時候查一下就差不多啦, 不講了.

應用-等高佈局

當有多列排列時, 如果其中一列的內容比其他列的內容多時, 這些列依舊保持相同的高度.

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>等高佈局</title>
  <style>
    .main {
      width: 500px;
      background-color: pink;

      /* flex 佈局, 子項兩端對齊 */
      display: flex;
      justify-content: space-between;
    }

    .main div{
      width: 100px;
      background-color: skyblue;
    }

  </style>
</head>
<body>
  <div class="main">
    <div>
      <p>哈哈哈哈哈</p>
      <p>哈哈哈哈哈</p>
      <p>哈哈哈哈哈</p>
      <p>哈哈哈哈哈</p>
      <p>哈哈哈哈哈</p>
    </div>
    <div>
      <p>吃肉肉</p>
      <p>吃肉肉</p>
      <p>吃肉肉</p>
      <p>吃肉肉</p>
      <p>吃肉肉</p>
      <p>吃肉肉</p>
      <p>吃肉肉</p>
    </div>
  </div>
</body>
</html>

可以看到彈性佈局, 子項預設就是等高的, 啥也不用做就實現啦!

但是如果要用 float 來進行佈局, 那就需要先左浮動, 再右浮動, 再清除浮動, 然後再用一個撐開的技巧:

相互抵消, 撐出來.
margin-bottom: -2000px;
padding-bottom: 2000px;

算了吧, 還是 flex 一把梭.

應用-兩列與三列布局

最常見於網站後臺佈局, 左側是側邊欄選單, 右側是內容區, 或者最右側還有輔助欄的三列布局.

其特點就是: 其中一列或兩列是固定寬度, 中間的內容區域是根據螢幕自適應.

  • 需要固定的列給固定寬度
  • 內容區 flex-grow : 1; 佔滿剩餘空間即可, 還自適應.
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>兩列布局</title>
  <style>
    body {
      margin: 0;
    }
    .main {
      height: 100vh;
      /* background-color: pink; */
      display: flex;
    }
    
    /* 左側邊欄固定 */
    .col1 {
      width: 250px;
      background: skyblue;
    }

    /* 第二列的內容區, 佔滿剩餘空間即可 */
    .col2 {
      flex-grow: 1;
      background-color: #ccc;
    }

    /* 如需第三列, 則直接固定寬度就行啦 */
    .col3 {
      width: 250px;
      background-color: pink;
    }
  </style>
</head>
<body>
  <div class="main">
    <div class="col1">第一列</div>
    <div class="col2">第二列</div>
    <div class="col3">第三列</div>
  </div>
</body>
</html>

牛呀, 這個 flex 有點東西!

粘性頁尾佈局

主要是移動端用得比較多些, 關鍵是內容區用 flex-grow: 1 佔滿剩餘空間;

  • 當內容區是不滿一屏時, 頁尾預設出現在可視區最底端;

  • 當內容過多超出時, 頁尾會被內容區域擠壓到最後去; (捲軸);

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>粘性頁尾佈局</title>
  <style>
    body {
      margin: 0;
    }

    .main {
      /* 可視區 100vh */
      min-height: 100vh;
      display: flex;
      flex-direction: column;
    }

     .main .header {
      height: 100px;
      background-color: pink;
     } 

     .main .content {
      /* 讓內容區佔滿剩餘空間, 即撐開內容區域 */
      flex-grow: 1;
     }

     .main .footer {
      height: 100px;
      background-color: skyblue;
     }

  </style>
</head>
<body>
  <div class="main">
    <div class="header"></div>
    <div class="content">
      <p>哈哈哈哈哈</p>
      <p>哈哈哈哈哈</p>
      <p>哈哈哈哈哈</p>
      <p>哈哈哈哈哈</p>
      <p>當內容超級多時, 頁尾會自動被往下推</p>
    </div>
    <div class="footer"></div>
  </div>
</body>
</html>

溢位項佈局

應用場景主要在移動端頂部選單項, 當內容板塊很多, 而可視區有限時, 透過滑動讓溢位的項進入可視區.

直接用 flex + 子項 shrink: 0; 一步就做到位了.

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>溢位項佈局</title>
  <style>
    .main {
      height: 100px;
      background-color: pink;
      display: flex;
      align-items: center;
    }
    .main div {
      width: 200px;
      height: 100px;
      background-color: skyblue;
      margin-right: 10px;

      /* 讓它可以溢位 */
      flex-shrink: 0;
    }
  </style>
</head>
<body>
  <div class="main">
    <div>1</div>
    <div>2</div>
    <div>3</div>
    <div>4</div>
    <div>5</div>
    <div>6</div>
    <div>7</div>
    <div>8</div>
  </div>
</body>
</html>

關於 flex 子項重點的東西也差不多到這裡了.