CSS 列表項佈局技巧

lawler61發表於2018-11-20

css-item-layout

github 原文地址(實時更新):CSS 列表項佈局技巧

感謝 創宇前端 的推廣:juejin.im/post/5c171f…

一、現有情況

  1. 在開發中我們經常會遇到關於如何展示列表的問題,例如:
  • 圖片選擇器列表

圖一

  • 人員部門選擇列表

圖二

  • 工作狀態列表

圖三

二、通用方法

  1. 為了讓其看起來更加舒適美觀,通常我們會在每個列表項上新增 margin-rightmargin-bottom 屬性來隔開它們,然後一行超過容器長度後進行換行

  2. 那麼在各種情況下,如何處理列表項中margin-rightmargin-bottom,讓列表間隔和換行看起來更加自然美觀是本篇的重點

三、各種情況下的佈局

元素寬度已知,即知道每行最多多少個,且所有元素都在一個容器中

  1. 思路:item 在一個容器中,每第三個去掉 margin-right,最後三個取消 margin-bottom(如最後一行不滿 3 個也不影響)

  2. 關鍵程式碼

<div class='container'>
  <div class='item'>寬度已知,最多放三個</div>
  <div class='item'>寬度已知,最多放三個</div>
  <div class='item'>寬度已知,最多放三個</div>
  ...
</div>

<style>
  /* scss code */
  .container {
    .item {
      margin-right: 30px;
      margin-bottom: 20px;

      &:nth-child(3n) { margin-right: 0; } /* 一行最多幾個就填 幾n */
      &:nth-last-child(-n+3) { margin-bottom: 0; }
    }
  }
</style>
複製程式碼
  1. 執行截圖

元素寬度已知,即知道每行最多多少個,且所有元素都在一個容器中

  1. 完整程式碼

元素寬度已知 或 未知,且元素按照行數在相應容器中

  1. 思路:最後一個 container 去掉 margin-bottom,最後一個 item 去掉 margin-right

  2. 關鍵程式碼

<div class='container'>
  <div class='item'></div>
  <div class='item'></div>
</div>
<div class='container'>
  <div class='item'></div>
  <div class='item'></div>
  <div class='item'></div>
</div>
<div class='container'>
  <div class='item'></div>
</div>

<style>
  /* scss code */
  .container {
    margin-bottom: 20px;
    &:last-child { margin-bottom: 0; }

    .item {
      margin-right: 30px;
      &:last-child { margin-right: 0; }
    }
  }
</style>
複製程式碼
  1. 執行截圖

元素寬度已知 或 未知,且元素按照行數在相應容器中

  1. 完整程式碼

元素寬度未知,即不知道一行最多多少個,且所有元素都在一個容器中,常見於 flex 佈局

法1:Flex 佈局

  1. 思路:利用 flex 佈局的 justify-content 主軸屬性來控制元素的間距

  2. 缺點:flex 雖然強大,但是面對 長度不定的列表項佈局 還是不能很好滿足要求

  3. 關鍵程式碼

<div class='container'>
  <div class='item'>兩個可以成一行</div>
  <div class='item'>兩個可以成一行</div>
  <div class='item'>這三個字</div>
  <div class='item'>獨成一行呀獨成一行呀獨成一行呀獨成</div>
  <div class='item'>兩個才能成一行呀</div>
  <div class='item'>四個</div>
</div>

<style>
  /* scss code */
  .container {
    display: flex;
    flex-wrap: wrap;
    justify-content: space-between; /* 可以嘗試其他值,但效果仍不好 */

    .item {
      /* margin-right: 30px; 可以不用 m-r,由 flex 來控制左右間距 */
      margin-bottom: 20px;
    }
  }
</style>
複製程式碼
  1. 執行截圖

法1:元素寬度未知,且所有元素都在一個容器中

  1. 完整程式碼

法2:負margin

  1. 接下來介紹 負margin 方法,可以很好的解決 長度不定的列表項佈局 問題

  2. 思路:用一個 wrapper 包在最外層,container 設定 負的 margin 來抵消 item 的 外邊距

  1. 關鍵程式碼
<div class="wrapper">
  <div class='container'>
    <div class='item'>兩個才能成一行呀</div>
    <div class='item'>兩個才能成一行呀</div>
    <div class='item'>這三個字</div>
    <div class='item'>獨成一行呀獨成一行呀獨成一行呀獨</div>
    <div class='item'>四個</div>
  </div>
</div>

<style>
  /* scss code */
  .wrapper {
    .container {
      display: flex;
      flex-wrap: wrap;
      margin-right: -30px;
      margin-bottom: -20px;

      .item {
        margin-right: 30px;
        margin-bottom: 20px;
      }
    }
  }
</style>
複製程式碼
  1. 執行截圖

元素寬度未知,即不知道一行最多多少個,且所有元素都在一個容器中,常見於 flex 佈局

  1. 完整程式碼

flex 佈局中元素整體居左,最後幾個居右;整體居右,前幾個居左;某幾個居中

有多少人有過被 justify-self: flex-end; 支配的恐懼,其實沒有 justify-self 這個屬性啦!

MDN上flex的屬性

法1:flex: 1 + text-align

  1. 思路:給 flex 佈局中的元素設定了 flex: 1,可以類似看成 display: block 元素,所以設定 text-align 就搞定

  2. 關鍵程式碼

<div class='container'>
  <div class='item'>第一項</div>
  <div class='item'>第二項</div>
  <div class='item'>第三項</div>
  <div class='item'>最後一項</div>
</div>

<style>
  /* scss code 整體居左,某幾個元素居右 */
  .container {
    display: flex;
    justify-content: flex-start; /* 預設為 flex-start */

    .item {
      &:nth-last-child(2) { /* 想讓最後幾個元素居右就填幾 */
        flex: 1;
        text-align: right;
      }
    }
  }
</style>

<style>
  /* scss code 整體居右,某幾個元素居左 */
  .container {
    display: flex;
    justify-content: flex-end;

    .item {
      &:nth-child(2) { /* 想讓前幾個元素居左就填幾 */
        flex: 1;
        text-align: left;
      }
    }
  }
</style>

<style>
  /* scss code 整體居左,某幾個居中 */
  .container {
    display: flex;

    .item {
      &:nth-child(2) { /* 想從第前幾個元素開始居中 */
        flex: 1;
        text-align: right;
      }

      &:nth-child(4) { /* 想從第前幾個元素結束居中 */
        flex: 1;
        text-align: left;
      }
    }
  }
</style>
複製程式碼
  1. 執行截圖

9.個別元素居左,居中,居右

  1. 完整程式碼

法2:margin- auto*

  1. 思路:對於 flex 佈局的元素也可以通過 margin 來調整位置

  2. 關鍵程式碼(程式碼基本與 法1 類似,可在完整程式碼具體檢視)

<div class='container'>
  <div class='item'>第一項</div>
  <div class='item'>第二項</div>
  <div class='item'>第三項</div>
  <div class='item'>最後一項</div>
</div>

<style>
  /* scss code 整體居左,某幾個元素居右 */
  .container {
    display: flex;

    .item {
      &:nth-last-child(2) { /* 想讓最後幾個元素居右就填幾 */
        margin-left: auto;
      }
    }
  }
</style>

scss code 整體居右,某幾個元素居左
...
複製程式碼
  1. 執行截圖

10.個別元素居左,居中,居右margin

  1. 完整程式碼

四、總結

  1. 多多利用 css3 屬性來幫助我們更好的佈局列表,避免使用 js 控制列表項,做到 css 與 js 解耦,更利於專案的維護

  2. 以上可能未包含所有情況,歡迎提出或者分享其他更好的解決辦法

相關文章