ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

CSS九宫格布局:五种主流实现方案对比

CSS九宫格布局:五种主流实现方案对比 九宫格布局这四个字估计每个写过前端页面的人都绕不开。图标导航栏、商品分类入口、仪表盘的数据卡片、手机端的数字键盘、图片墙……只要页面上需要三行三列、整整齐齐的结构就一定会掉进这个坑里。我这些年接手过的项目里九宫格相关的样式问题出现频率相当高尤其是老项目改造的时候经常看到有人在 float 和 inline-block 之间反复横跳改一行崩三处。这篇文章就把我实际用过的五种做法完整过一遍Grid 布局、Flex 布局、table 布局、float 浮动定位以及 inline-block 配合 letter-spacing 属性。每种方案我都会把关键参数、计算过程、适用场景和踩过的坑讲清楚代码可以直接抄走用。不管你是刚学 CSS 布局的新手还是需要维护历史代码的老手应该都能从中找到对自己有用的部分。1. 九宫格布局这件事先把需求和选型逻辑说透很多人一上来就问九宫格用哪个方案最好这个问题本身就是不完整的。选型从来不是看哪个技术新而是看你的运行环境、维护成本和后续扩展需求。所以先把需求拆开看选型才有依据。1.1 什么场景会真正用到九宫格九宫格在本质上就是一个等分网格容器被均分成 N 行 N 列每个单元大小一致、间距一致、内容居中。它的变体很多比如 2 行 3 列的分类入口、4 列的商品瀑布、每行 3 个的图集缩略图逻辑都是同一套。我把常见场景归成三类。第一类是纯展示型比如首页金刚区图标入口格子里的内容固定不会动态增减这类对布局方案的容错率最高。第二类是数据驱动型格子数量由后端返回的数组决定可能是 7 个也可能是 11 个这就要求布局方案在最后一行不满的情况下也不能错位这是最容易翻车的地方。第三类是响应式型PC 端一行 3 个平板一行 2 个手机端一行 1 个需要配合媒体查询或自适应单位切换列数。还有一个容易被忽略的维度格子内部的内容是否等高。如果每个格子里有标题和描述文字文字长度不一致时行高就会参差不齐。Grid 和 table 天然处理得好float 和 inline-block 就很容易出现下一行顶上来的问题。搞清楚自己属于哪一类后面的选型就不会盲目。1.2 五种方案各自的定位与选型逻辑五种方案我按现代项目优先级排一下序。Grid 布局是第一顺位。它是专门为二维网格设计的一个grid-template-columns: repeat(3, 1fr)就把列定义完了间距用gap一行搞定最后一行不满也不会错位。除了老版本浏览器几乎没有理由不用它。Flex 布局是第二顺位主要用于需要一维流动、动态换行的场景或者项目需要兼容较老的移动端 WebView。它的核心是靠flex-wrap: wrap加百分比宽度来模拟网格间距需要自己算这是它比 Grid 麻烦的地方。table 布局的定位是老项目里的稳定器。表格天然的单元格对齐能力让它在内容高度不一时表现得非常稳早期邮件模板、后台管理系统大量使用。现在新项目不建议用它做整体布局但理解它的原理仍然有价值因为display: table这套模拟写法在垂直居中场景里依然好用。float 浮动定位属于历史遗留方案。它在 IE 时代是主流现在写新项目基本不会主动选它。但你要维护十年前的代码就必须要能看懂并且知道它的两个死穴浮动高度塌陷和每行最后一个元素的边距处理。inline-block 加 letter-spacing是最取巧的一种。它利用负字间距把行内元素之间的空白字符缩掉从而实现无缝拼接的网格。这个方案我很长一段时间没怎么用了但它依然是面试高频题也是理解 CSS 空白符渲染机制的一个绝佳案例。一句话总结选型逻辑新项目无脑 Grid需要兼容旧环境或做一维流动用 Flex维护老代码用 table 或 float理解原理用 inline-block。2. Grid 方案一行代码定骨架最省心的正统解法Grid 是我现在写九宫格的第一选择没有之一。它把行列定义和间距这两件事彻底解耦了写出来的代码量最少可读性最高。2.1 grid-template 与 fr 单位的分配逻辑先讲清楚fr这个单位。fr是 fraction 的缩写意思是剩余空间的分配份额。注意关键词是剩余空间也就是说容器总宽度会先减去所有gap占用的空间剩下的部分才按fr的份数去分。举个例子。假设容器宽度是 320px三列gap: 10px。列间隙有两处三列之间总共占 20px。剩余空间是 320 - 20 300px。三个1fr平分每个格子宽度是 100px。这个计算过程你要心里有数因为当你把1fr换成100px固定宽度、再和响应式需求混合使用时就很容易算出溢出。grid-template是一个简写属性它同时定义行和列的模板语法是grid-template: 行定义 / 列定义。九宫格通常写成grid-template: repeat(3, 1fr) / repeat(3, 1fr)意思是三行三列、每份等宽等高。repeat()函数的作用是重复repeat(3, 1fr)完全等价于1fr 1fr 1fr但列数多了以后写法更清爽。如果你的格子需要是正方形最省事的做法是给每个格子加aspect-ratio: 1浏览器会自动根据宽度算出高度比用padding-top: 100%的古老技巧干净太多。2.2 一份可以直接跑的完整代码下面这份是我常用的基础模板改改颜色和间距就能直接上项目。div classgrid-box div classgrid-item1/div div classgrid-item2/div div classgrid-item3/div div classgrid-item4/div div classgrid-item5/div div classgrid-item6/div div classgrid-item7/div div classgrid-item8/div div classgrid-item9/div /div.grid-box { display: grid; grid-template-columns: repeat(3, 1fr); grid-template-rows: repeat(3, 1fr); gap: 10px; width: 100%; } .grid-item { display: flex; align-items: center; justify-content: center; aspect-ratio: 1 / 1; background: #f5f5f5; border-radius: 6px; font-size: 16px; }这里有个小细节值得说.grid-item内部我又套了一层display: flex用来做内容居中。Grid 负责格子怎么排Flex 负责格子里内容怎么放两者分工明确这是我最推荐的组合方式。你也可以用place-items: center直接在容器上一次性搞定所有格子的居中代码更短.grid-box { display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px; place-items: center; }place-items是align-items和justify-items的简写写一行等于写两行实际项目里我用得比较多。2.3 Grid 实操中的几个注意点第一gap 是纯间距不参与元素尺寸计算。这一点和 margin 有本质区别。用 margin 做间距时你得自己算calc((100% - 20px) / 3)这种表达式还得处理每行最后一个元素的边距归零用 gap 就完全不用管浏览器帮你处理好了。所以只要能用 gap就别用 margin 拼间距。第二1fr和minmax()搭配能解决内容溢出的问题。如果你的格子里塞了很长的英文单词或不换行的数字1fr的默认行为是minmax(auto, 1fr)最小值是 auto内容撑大了就会把格子挤变形。稳妥写法是grid-template-columns: repeat(3, minmax(0, 1fr))把最小值强制为 0让内容去换行而不是把布局撑破。这个坑我踩过一次排查了快半小时。第三用grid-auto-rows处理数量不确定的格子。如果格子数量是后端返回的、不确定有几个你就没法写死grid-template-rows。这时候只定义列让行自动生成grid-template-columns: repeat(3, 1fr); grid-auto-rows: 100px;。自动生成的行会按grid-auto-rows的高度走整齐度依然能保证。第四媒体查询切换列数非常直观。手机端一行 3 个平板一行 4 个直接改grid-template-columns就行其他代码一行不用动这是 Grid 相比 Flex 百分比方案的一大优势。3. Flex 方案兼容老项目又灵活但间距要算清楚Flex 是一维布局模型用它做二维网格其实是降维打击需要靠换行来模拟。虽然绕了一点但在需要兼容老版本 Android WebView 的项目里Flex 基本是唯一选择。3.1 flex-wrap 加百分比宽度的核心思路核心就两步容器设display: flex和flex-wrap: wrap子元素给一个百分比宽度。当一行放不下时后面的元素自动换到下一行就形成了网格。这里最容易搞混的就是宽度到底该写多少。假设三列每列之间有 10px 的间隙容器宽度是 W。如果你给子元素写width: 33.333%那么三个加起来是 99.999%理论上放得下但一旦有间隙就会溢出换行。所以有两种处理思路。思路 A 是外间距法用margin做间隙宽度用calc()计算.flex-box { display: flex; flex-wrap: wrap; width: 100%; } .flex-item { width: calc((100% - 20px) / 3); margin-right: 10px; margin-bottom: 10px; box-sizing: border-box; } .flex-item:nth-child(3n) { margin-right: 0; }这里的计算逻辑是一行三个元素之间有两个间隙每个 10px所以横向间隙总量是 20px用容器宽度减去它再除以 3就是每个格子的宽度。nth-child(3n)用来把每行最后一个元素的右边距清零否则整行会向右偏移 10px。思路 B 是内边距法用padding做间隙宽度直接写百分比.flex-box { display: flex; flex-wrap: wrap; margin: -5px; } .flex-item { width: 33.333%; padding: 5px; box-sizing: border-box; } .flex-item .inner { background: #f5f5f5; border-radius: 6px; }思路 B 的精髓在于box-sizing: border-box。因为 padding 被算进了元素宽度里所以 33.333% 就是实打实的宽度三个刚好 99.999%不会换行。为了让最外圈也有间隙我给容器加了margin: -5px来抵消首尾的 padding这是很经典的一个小技巧。不过要注意格子里的背景色和圆角必须加在内层容器上加在外层会被 padding 撑成大色块。3.2 两种间距方案怎么选我一般这样判断如果格子里是图片或纯色块用内边距法更稳因为浮点百分比不会因为 margin 累加而溢出如果格子里需要做 hover 高亮、边框描边用外间距法更合适因为元素边界清晰border和box-shadow不会被内边距干扰。有个细节要提醒用nth-child(3n)处理最后一列边距时一定要确认格子数量是 3 的倍数或者最后一行不满也不会出问题。如果最后一行只有 2 个那第 4 个也就是第二行第一个的margin-right是正常的但第二行第二个的nth-child序号是 5不是 3 的倍数所以它右侧会保留 10px 间距看起来会略微偏左。这种情况用内边距法就完全没事这也是我更偏爱内边距法的原因之一。3.3 flex gap 的兼容性边界现代浏览器早就支持 Flex 容器的gap属性了写法极简.flex-box { display: flex; flex-wrap: wrap; gap: 10px; } .flex-item { width: calc((100% - 20px) / 3); }但要注意Flex 的 gap 在部分老版本浏览器上不生效比如一些基于老内核的 Android WebView 和早期的 Safari。如果你的项目需要兼容这类环境gap会静默失效——间隙变成 0所有格子挤在一起而且不会报错排查起来挺费劲。我的做法是先确认项目的浏览器支持范围不确定就老老实实用 padding 方案。这不算保守而是省事。还有一个容易忽略的点Flex 容器的align-items默认值是stretch如果你没有显式设置子元素高度它们会被拉伸到和最高元素一样高。这在九宫格场景里通常是好事但如果你希望格子严格等高且固定最好显式写align-items: flex-start或给子元素设置固定高度避免出现某一行特别高的视觉失衡。4. Table 布局最古老但最不容易出错的对齐方案一说 table 布局很多人第一反应是淘汰了。但如果你去看早期后台系统、富文本邮件模板表格布局到处都是。它的价值不在于现代而在于稳定。4.1 表格为什么天生适合九宫格HTML 的表格模型本身就是网格结构table是容器tr是行td是单元格。单元格在同一列里自动对齐、自动等高这是它最核心的能力。你用 float 或 inline-block 做布局时最头疼的就是格子高度不齐导致下一行错位而表格模型根本不会出现这个问题因为同一行里所有单元格的高度由最高的那个决定浏览器会自动拉伸。所以如果你的九宫格内容里包含长度不一的描述文字用表格布局反而比 float 更省心。当然这不意味着要用table标签去写布局用display: table在 div 上模拟即可。4.2 border-spacing 与 table-layout 的参数细节如果你的场景确实需要真实的表格比如展示结构化数据下面这几个属性要掌握。.data-grid { width: 100%; table-layout: fixed; border-collapse: separate; border-spacing: 10px 10px; } .data-grid td { background: #f5f5f5; text-align: center; vertical-align: middle; height: 80px; }几个参数解释一下。table-layout: fixed是关键。默认值是auto列宽由内容决定如果某一列内容特别长列宽就会失衡九宫格就不等分了。改成fixed后列宽由表格宽度和列数平均分配不再受内容影响稳定性大幅提升。border-collapse: separate配合border-spacing是模拟间隙的标准做法。注意border-collapse默认值就是separate但很多人在做表格时习惯性写collapse去合并边框一旦写成collapseborder-spacing就会失效。这两个属性互斥这点一定要记住。border-spacing: 10px 10px的第一个值控制水平间距第二个控制垂直间距。如果你只写一个值水平和垂直会同时生效。vertical-align: middle控制单元格内容的垂直居中text-align: center控制水平居中。这两个属性在表格里配合使用居中的效果比 flex 更自然因为它是表格模型的原生行为。table-layout: fixed还有一个副作用要注意它会让width为 auto 的单元格平均分配剩余宽度同时也让内容溢出时不会自动撑开列宽——如果你的单元格里有长文本需要自己加overflow: hidden和text-overflow: ellipsis来处理。4.3 用 div 模拟 table 的现代写法不想用table标签又想借表格模型的对齐能力可以用display: table系列属性div classtable-box div classtable-row div classtable-cell1/div div classtable-cell2/div div classtable-cell3/div /div div classtable-row div classtable-cell4/div div classtable-cell5/div div classtable-cell6/div /div div classtable-row div classtable-cell7/div div classtable-cell8/div div classtable-cell9/div /div /div.table-box { display: table; width: 100%; border-spacing: 10px; } .table-row { display: table-row; } .table-cell { display: table-cell; width: 33.333%; height: 80px; text-align: center; vertical-align: middle; background: #f5f5f5; }这种写法的好处是 DOM 结构是普通 div可以用媒体查询、伪元素做更多控制缺点是必须手动套一层table-row格子数量变化时 HTML 结构也要跟着改不像 Grid 那样扁平。所以它适合结构固定、不需要动态增删格子的场景。另外display: table-cell有个非常好用的隐藏特性它天然支持vertical-align: middle垂直居中不需要知道父元素高度。在 Flex 还没普及的年代这是最常用的垂直居中方案。现在虽然有了 flex 和 grid但知道这个套路依然有用因为它的兼容性极好。5. Float 浮动定位老项目的常客清理浮动和边距是两大关Float 方案我平时写新项目基本不用了但维护老代码时经常遇上所以还是得说清楚。它的实现套路很简单所有格子左浮动宽度给定百分比每行第 N 个清除右边距。5.1 float 实现九宫格的标准写法.float-box { width: 100%; } .float-box::after { content: ; display: block; clear: both; } .float-item { float: left; width: 33.333%; box-sizing: border-box; padding: 5px; } .float-item .inner { height: 80px; background: #f5f5f5; text-align: center; line-height: 80px; }这里的::after伪元素加clear: both是清除浮动的标准手段学名叫clearfix。因为浮动元素脱离了普通文档流父容器不会自动计算它们的高度如果不清理父容器高度就会塌陷成 0后面的元素会顶上来覆盖九宫格。这是 float 布局最经典的坑。用padding做间隙加上box-sizing: border-box可以让宽度百分比的计算变得干净这一点和 Flex 的内边距法思路一致。用line-height等于高度来做单行文本的垂直居中也是常见技巧但要注意它只适用于单行文本多行文本会溢出。5.2 浮动的三个经典坑坑一高度塌陷。前面说的 clearfix 就是解药。还有一种做法是给父容器加overflow: hidden来触发 BFC块级格式化上下文父容器就会包含浮动子元素。但overflow: hidden会裁切超出容器的内容比如 hover 时弹出的小气泡所以我不太推荐用它来清理浮动除非你确定没有溢出需求。坑二百分比宽度的精度问题。33.333%乘以 3 等于99.999%能放下。但如果你写成33.34%乘以 3 就是100.02%第三个元素就会被挤到下一行形成3 个格子变成 21的诡异布局。百分比宽度永远要向下取值留一点点余量。我一般用33.33%而不是33.333%宁可留 0.01% 的缝隙也不要冒险换行。坑三每行最后一个元素的边距。如果用margin-right做间隙就必须用nth-child(3n)把第三个、第六个的右边距归零和 Flex 外间距法的处理方式一样。但如果格子数量是动态的最后一行不足 3 个时序号计算就会出错。所以我更推荐用 padding 方案从根本上绕开这个问题。还有一个坑是 float 元素不能自动等高。英语里这叫 float height mismatch。同一行里两个浮动元素一个内容高一个内容低低的那边下面就会留空下一个浮动元素会尝试贴着它往上跑形成锯齿状的错位。要解决这个问题要么给所有格子固定高度要么换 Grid 或 table。6. inline-block 加 letter-spacing最取巧也最容易被问到的解法这个方案是我在面试里被问过最多的一种也是最能考察对 CSS 空白符渲染理解程度的一种。它的思路是把格子设成display: inline-block然后用负的letter-spacing把元素之间的空白字符吃掉。6.1 那个恼人的间隙到底从哪来先说清楚根源。当多个inline-block元素写在一起时如果 HTML 源码里它们之间有换行或空格浏览器会把这段空白渲染成一个空格字符宽度大约是该元素font-size的一部分通常在这个字体的空格宽度范围大概 0.25em 到 0.35em 之间具体取决于字体。这个空格不是 margin也不是 padding是你用浏览器的盒模型面板看不到的所以很多人第一次遇到时会一脸懵。举个例子如果字号是 16px三列布局每列 33.333%三个加起来 99.999%再加上两个空格字符的宽度假设每个 4~5px总宽度就超过 100% 了第三个格子必然被挤到下一行变成两个一行的错乱布局。解决方案有几种我按推荐度排列。最省事的方案父容器font-size: 0。.ib-box { font-size: 0; } .ib-item { display: inline-block; width: 33.333%; font-size: 16px; box-sizing: border-box; padding: 5px; }原理很直白空白字符的宽度是相对于父元素字号的字号变成 0空格宽度也就是 0 了。但注意子元素必须显式恢复字号否则里面的文字会一起消失。这个副作用如果忘了处理排查起来也要花点时间——文字凭空消失这种问题思路不对的时候挺折磨人的。经典方案父容器负 letter-spacing。.ib-box { letter-spacing: -0.5em; } .ib-item { display: inline-block; width: 33.333%; letter-spacing: normal; vertical-align: top; box-sizing: border-box; padding: 5px; }letter-spacing是字间距它会给每个字符包括元素之间的那个空白字符后面加间距。设成负值就相当于把空白字符的宽度缩掉甚至变成负数。-0.5em是一个经验值实际用多少需要根据字体和字号微调因为不同字体的默认空格宽度不完全一致。这就是它比font-size: 0麻烦一点的地方。给子元素重置letter-spacing: normal是必须的否则子元素里的文字也会挤在一起阅读体验非常糟糕。补救方案一margin-left: -4px。简单粗暴给每个子元素左边加负边距抵消空格宽度。缺点是不同浏览器、不同字体下空格宽度不同这个 -4px 不一定准缩放页面时可能出现细微错位。补救方案二HTML 里删掉换行。把标签写成紧挨着的形式或者用 HTML 注释吃掉换行div classib-item1/div!-- --div classib-item2/div!-- --div classib-item3/div这个做法的缺点是 HTML 可读性急剧下降而且后续如果代码格式化插件自动给 HTML 加了缩进换行间隙就又会冒出来。所以它只适合临时使用不推荐在正式项目里用。6.2 别忘了 vertical-align用 inline-block 做网格还有一个必须处理的属性vertical-align。因为 inline-block 元素的默认垂直对齐方式是baseline也就是按文字基线对齐。如果同一行里的两个格子内容不一样一个只有一行字一个有图片加两行字它们的基线位置不同会导致整个行高度的错位看起来像一个格子高一个格子低上边缘没有对齐。解决办法是给所有格子加vertical-align: top让它们统一按顶边对齐。这是 inline-block 布局里最容易被忽略的一个点也是看起来差不多但就是对不齐这类玄学问题的常见根因。6.3 三种去间隙方式的对比方案写法优点缺点font-size: 0父容器 0子元素恢复精准、无副作用、兼容性好子元素必须显式设字号letter-spacing 负值父容器 -0.5em子元素 normal不依赖字号可微调值需按字体调整不精确HTML 去换行标签紧贴或注释隔断不写额外 CSS可读性差易被格式化破坏我个人的选择是font-size: 0因为它最可控。letter-spacing那套写法在面试里讲原理很好用实际项目里我会优先选更稳的。另外提醒一句如果你在格子里放的是a标签记得处理一下默认样式。链接自带下划线用text-decoration: none去掉就行别误写成line-through那会变成删除线效果视觉上很怪。7. 五种方案横向对比一张表看清怎么选讲完五种实现我把关键指标整理成一张表方便你按自己的项目情况直接定位。7.1 五维对比表维度GridFlexTableFloatinline-block定位模型二维网格一维流动表格模型脱离文档流行内流间距实现gap 一行搞定calc 或 paddingborder-spacingpadding 或 margin需去空白符自动等高天然支持支持stretch天然支持不支持不支持最后一行不满不会错位用 padding 不出错不会错位容易出现偏移容易出现偏移动态格子数量支持良好支持良好需手动改结构一般一般移动端兼容现代浏览器均支持兼容性很好极好极好极好代码可读性高中中低低主要适用新项目首选兼容型项目结构化数据老项目维护原理学习7.2 一句一场景的选型建议我把这张表转化成更直接的判断路径。你要做的是新项目、现代浏览器、格子数量可能变的九宫格直接上 Gridrepeat(3, minmax(0, 1fr))加gap收工。你要做的是需要兼容较老 Android WebView 或老版 iOS用 Flex宽度用百分比间距用padding加box-sizing: border-box避开 flex gap。你要展示的是真实的表格数据比如报表、课程表、排班表用 table 标签配table-layout: fixed和border-spacing别用 div 硬拼。你要接管一个十年前的页面看到满屏 float别急着重构先加 clearfix 把手头问题解决再评估重构成本。你要准备面试或者教别人把 inline-block 加 letter-spacing 这套原理讲透因为这道题背后考的是空白符渲染、字号继承、基线对齐三块基础知识。8. 常见问题与排查技巧实录这部分是我这些年在实际项目里积累的问题清单基本上覆盖了九宫格布局 90% 的翻车场景。8.1 问题速查表现象可能原因排查方向第三个格子总是掉到下一行百分比宽度总和超过 100%或存在空白符间隙检查宽度值改用向下取整的百分比父容器高度变成 0内容被下方元素压住浮动未清除父容器高度塌陷加 clearfix 或换 flex/grid格子之间的间隙忽大忽小用 margin 做间隙但未清零末位边距用 nth-child 清零或改用 padding格子内容偏上没有垂直居中vertical-align 默认是 baseline设 vertical-align: top 或用 flex 居中子元素文字突然消失父容器 font-size: 0 后子元素未恢复给子元素显式设置 font-sizeGrid 格子被长内容撑变形1fr 的默认最小值是 auto改成 minmax(0, 1fr)表格单元格宽度不均等table-layout 默认是 auto改成 table-layout: fixedborder-spacing 不生效同时写了 border-collapse: collapse两属性互斥去掉 collapse8.2 几个踩过才知道的细节细节一box-sizing: border-box一定要全局设。我见过太多因为 padding 把宽度撑爆的案例。在样式表顶部写一个全局规则*, *::before, *::after { box-sizing: border-box; }关于通配符选择器的性能一直有争议。早年的说法是*会影响性能但在现代浏览器上这个选择器的匹配开销已经小到可以忽略。真正需要注意的是它会影响::before和::after的宽度计算如果你在伪元素上依赖content-box的行为就要单独覆盖。总体来看全局 border-box 带来的收益远大于成本。细节二移动端 0.5px 边框用 transform 缩放实现。有些设计稿要求九宫格之间有极细的分隔线如果你用border: 0.5px在某些设备上会被渲染成 1px 甚至消失。稳妥做法是用 1px 边框加transform: scaleY(0.5)缩放或者用伪元素画线。这个和布局方案无关但九宫格场景里经常遇到。细节三hover 高亮不要用 margin 或 padding 改变尺寸。如果 hover 时改变 padding 或 border 宽度会导致格子尺寸变化进而影响整个网格的排布出现鼠标移上去整行都动了的现象。正确做法是用background-color、box-shadow加 inset 参数或outline来做这些属性不影响布局。细节四动态格子的最后一行对齐。如果格子数量不固定最后一行往往不满。Grid 默认行为是左对齐第二行不足的部分留空这个行为需要确认如果有特殊要求就得用grid-column手动定位。Flex 如果最后一行用justify-content: space-between最后一行会出现两端贴边、中间大间隙的情况这时候通常要用space-around或者干脆保持左对齐。我个人建议最后一行不满时保持左对齐是最稳妥的视觉上最不突兀。细节五文本溢出处理。九宫格里的文字通常需要限制行数两行超出就省略。用-webkit-line-clamp配合display: -webkit-box可以做到.grid-item .title { display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }这个组合目前在主流浏览器上都能用。要注意的是它需要overflow: hidden和display: -webkit-box同时存在少一个都不生效。细节六图片作为背景时的尺寸控制。如果格子里放图片记得加width: 100%; height: 100%; object-fit: cover。object-fit: cover保证图片按比例填满容器并裁切多余部分object-fit: contain则是完整显示但可能留白。九宫格场景里我基本都用cover视觉上更整齐。如果是用background-image的话对应的是background-size: cover和background-position: center。最后再分享一个我自己的小习惯。做任何一种九宫格方案之前我都会先把格子的数量、是否需要动态、内容是否等高、需要兼容的最老环境这四个问题写下来然后对照上面的选型表确定方案。这个习惯帮我省下了不少返工时间——尤其是内容是否等高这一条很多看起来只是对齐歪了的问题本质上都是布局模型选错了。Grid 和 table 天生处理等高float 和 inline-block 就得自己想办法这一步想清楚后面写代码就顺了。
返回列表