實現九宮格佈局,你能想到多少種方法?
最近看到一個面試題:實現一個九宮格佈局,用盡可能多的方式去實現? 搜了一下牛客面經,騰訊、字節跳動、百度、網易、京東等的面經中都出現過這道題目。所以今天就來實現一下,看有多少種實現方式(下面實現的九宮格佈局是自適應頁面大小的)。
實現效果如下:
首先,定義好通用的 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. 總結
對於上述實現方式,總結如下:
-
flex 佈局也是我平時用的比較多的佈局方式,雖然其還有一些兼容性問題,但是由於我做的是 B 端項目,基本不需要考慮兼容問題。其實 flex 佈局主要適用於移動端項目;
-
grid 佈局實現起來非常方便,但是它的規範並未成熟,主流的瀏覽器使用較少,不推薦使用在企業項目中;
-
使用 float 可以使元素脫離文檔流,形成 BFC,在重新渲染時不會影響其他的元素。需要注意使用 float 的元素其父元素會塌陷,需要清除浮動。
-
使用 inline-block 來實現九宮格佈局時,定義了 inline-block 的元素之間會出現間隙,需要清除;
-
table 佈局現在感覺用的比較少了,幾乎很少在項目中使用 table 佈局。
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/fNJcHwo-pLJPRPxbX_-zvg