看到微博和朋友圈都实现了图片九宫格,曾经有次面试也问到了九宫格这个问题,当时想到的是先固定每个单元格的宽高,然后进行浮动。今天想折腾一下,实现自适应父元素宽度的布局。这次我只写了四种方式去实现九宫格,算上inline-block
的话就是五种了。
首先要注意的是九宫格容器是宽高相等的正方形,并且是自适应的,这里关键是实现宽高相等,有些人想到了相对视口宽度 vw,但是它是相对于屏幕可见宽度来设置的,并且会忽略滚动条的宽度,所以这是不可行的。这里我用一种变通方法,看代码…
FlexBox
HTML 结构如下:
1 2 3 4 5 6 7 8 9 10 11 12 13
|
<div class="square"> <ul class="square-inner flex"> <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>
|
抽取公共样式:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
|
.square{ position: relative; width: 100%; height: 0; padding-bottom: 100%;
|
使用Flex的一个好处是不用再担心高度塌陷的问题,而且还可以轻松实现子元素横向竖向甚至按比例伸缩扩展的布局。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
|
.flex{ display: flex; flex-wrap: wrap; } .flex>li{ flex-grow: 1;
|
FlexBox-效果图
Grid
对于网格布局来说,grid 比 flex 更为方便,代码量更少,可以处理更为复杂的结构。
1 2 3 4 5 6 7 8 9 10 11 12 13
|
<div class="square"> <div class="square-inner grid"> <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>9</div> </div> </div>
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14
|
.grid{ display: grid; grid-template-columns: repeat(3, 1fr);
|
Grid-效果图
更多:CSS Grid布局指南
Float
浮动实现九宫格就不多说了,原理同上。
1 2 3 4 5 6 7 8 9 10 11 12 13
|
<div class="square"> <ul class="square-inner float"> <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>
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
|
.float::after{ content: ""; display: block; clear: both; visibility: hidden; } .float>li{ float: left; background-color: #42a59f; text-align: center; color: #fff; font-size: 50px; line-height: 2; } .float>li:nth-of-type(3n){ margin-right: 0; } .float>li:nth-of-type(n+7){ margin-bottom: 0; }
|
Float-效果图
除了浮动,这里 li 也可以使用display: inline-block;
实现同样的效果,不过要注意HTML代码非压缩情况下行块级元素之间会出现默认间隔,不同浏览器下表现还不一样,这时可以给父级元素设置font-size: 0;
Table
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
|
<div class="square"> <table class="square-inner table"> <tbody> <tr> <td>1</td> <td>2</td> <td>3</td> </tr> <tr> <td>4</td> <td>5</td> <td>6</td> </tr> <tr> <td>7</td> <td>8</td> <td>9</td> </tr> </tbody> </table> </div>
|
1 2 3 4 5 6 7 8 9 10 11 12
|
.table{ border-collapse: separate; border-spacing: 0.57em; font-size: 14px; empty-cells: hide; table-layout: fixed; } .table>tbody>tr>td{ text-align: center; background-color: #889ed8; overflow: hidden; }
|
Table-效果图
说下用表格实现九宫格有哪些瑕疵:
- 最后一行最后一列的单元格宽高与前面的不一致,虽然相差不大,但是还是有差异的;
- 与前面的两种方法不同,table 单元格之间的间隔是利用
border-spacing
属性实现的,且不支持百分比,单元格四周都有类似margin的外边距效果,如下图。
浏览器渲染效果图
分析
综上来看,个人认为 FlexBox 适合用于移动端,PC端 IE10 以下不支持;Grid网格布局比较方便,但是规范还未成熟,主流浏览器厂商尚未推广,不推荐使用在项目中;浮动和行块级式声明可以兼容到IE6,移动端和PC端支持的都不错;Table 因为实现有瑕疵所以不推荐使用。