實現九宮格佈局,你能想到多少種方法?

最近看到一個面試題:實現一個九宮格佈局,用盡可能多的方式去實現? 搜了一下牛客面經,騰訊、字節跳動、百度、網易、京東等的面經中都出現過這道題目。所以今天就來實現一下,看有多少種實現方式(下面實現的九宮格佈局是自適應頁面大小的)。

實現效果如下:

首先,定義好通用的 HTML 結構:

<div class="box">
  <ul>
    <li>1</li>
    <li>2</li>
    <li>3</li>
    <li>4</li>
    <li>5</li>
    <li>6</li>
    <li>7</li>
    <li>8</li>
    <li>9</li>
  </ul>
</div>

公共樣式:

ul {
 padding: 0;
}

li { 
  list-style: none;
  text-align: center;
  border-radius: 5px;
  background: skyblue;
}

注,很多小夥伴說 HTML 結構有問題,在平時開發中可能定義結構用 span 和 div 多一點,幾乎很少會用 ul 和 li,這裏就不做修改了,主要來看樣式的實現思路~

1. flex 實現

對於九宮格佈局,我首先想到的就是 flex 佈局,flex 佈局實現九宮格很簡單,需要設置一個 flex-wrap: wrap; 使得盒子在該換行的時候進行換行。

由於我們給每個元素設置了下邊距和右邊距,所以最後同一列(3、6、9)的右邊距和最後一行(7、8、9)的下邊距撐大了 ul,所以這裏使用類型選擇器來消除他們的影響。最終的實現代碼如下:

ul {
  display: flex;
  flex-wrap: wrap;
  width: 100%;
  height: 100%;
}

li {
  width: 30%;
  height: 30%;
  margin-right: 5%;
  margin-bottom: 5%;
}

li:nth-of-type(3n){ 
  margin-right: 0;
}

li:nth-of-type(n+7){ 
  margin-bottom: 0;
}

2. grid 實現

grid 佈局相對於 flex 佈局來說,實現九宮格就更加容易了,只需要設置幾個屬性即可:

ul {
  width: 100%;
  height: 100%;
  display: grid;
  grid-template-columns: 30% 30% 30%; 
  grid-template-rows: 30% 30% 30%; 
  grid-gap: 5%; 
}

其中 grid-template-columns 屬性用來設置每一行中單個元素的寬度,grid-template-rows 屬性用來設置每一列中單個元素的高度,grid-gap 屬性用來設置盒子之間的間距。

其實 Grid 佈局還是很有用,很方便的,近期會有一篇詳解 grid 佈局的文章,有想了解的小夥伴可以關注一波嗷~

3. float 實現

這裏需要給每個盒子設置固定的寬高,爲了讓它自動換行,可以使用 float 來實現,由於子元素的浮動,形成了 BFC,所以父元素 ul 使用 overflow:hidden;來消除浮動帶來的影響。最終的實現代碼如下:

ul {
  width: 100%;
  height: 100%;
  overflow: hidden;
}

li {
  float: left;
  width: 30%;
  height: 30%;
  margin-right: 5%;
  margin-bottom: 5%;
}

li:nth-of-type(3n){ 
  margin-right: 0;
}

li:nth-of-type(n+7){ 
  margin-bottom: 0;
}

4. inline-block 實現

其實 inline-block 的作用和上面 float 的作用是一樣的,都是用來讓元素換行的,實現代碼如下:

ul {
  width: 100%;
  height: 100%;
  letter-spacing: -10px;
}

li {
  width: 30%;
  height: 30%;
  display: inline-block;
  margin-right: 5%;
  margin-bottom: 5%;
}

li:nth-of-type(3n){ 
  margin-right: 0;
}

li:nth-of-type(n+7){ 
  margin-bottom: 0;
}

需要注意的是,設置爲 inline-block 的元素之間可能會出現間隙,就可能出現下面這種情況:

這裏使用了 letter-spacing 屬性來消除這種影響,該屬性可以用來增加或減少字符間的空白(字符間距)。使用之後就正常了,出現了預期的效果。也可以給 ul 設置 font-size: 0; 來消除盒子之間的字符間距:

ul {
  font-size: 0;
}

5. table 實現

HTML 結構:

<ul class="table">
  <li>
    <div>1</div>
    <div>2</div>
    <div>3</div>
  </li>
  <li>
    <div>4</div>
    <div>5</div>
    <div>6</div>
  </li>
  <li>
    <div>7</div>
    <div>8</div>
    <div>9</div>
  </li>
</ul>

table 佈局也不算太難,首先給父元素設置爲 table 佈局,然後使用 border-spacing 設置單元格之間的間距,最後將 li 設置爲表格行,將 div 設置爲表格單元格,CSS 樣式如下:

.table {
  width: 100%;
  height: 100%;
  display: table;
  border-spacing: 10px;
}

li {
  display: table-row; 
}

div {
  width: 30%;
  height: 30%;
  display: table-cell;
  text-align: center;
  border-radius: 5px;
  background: skyblue;
}

6. 總結

對於上述實現方式,總結如下:

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/fNJcHwo-pLJPRPxbX_-zvg