查看: 198|回复: 3

CSS Grid布局实战:fr单位与auto-fill自适应列实现

[复制链接]
发表于 2 小时前 | 显示全部楼层 |阅读模式
CSS Grid 是一套二维布局系统,能同时控制行与列两个方向;与之相对,Flex 只在一维(一行或一列)上分配空间。因此整体页面骨架、后台管理界面的大框架这类同时涉及行列的结构,更适合交给 Grid 处理。本文按“概念 → 建容器 → 定行列 → 定位 → 自适应 → 对齐 → 命名区域 → 简写”的顺序把常用写法过一遍,每个环节都给出可直接运行的代码片段。

一、先把几个术语对齐

写 Grid 之前要先分清几个名词,后面所有属性都是在这些对象上起作用:

· Grid 容器(Container):设置了 display: grid 的元素。
· Grid 项目(Item):容器的直接子元素,只有直接子元素才会被纳入网格。
· 轨道(Track):一行或一列本身。
· 单元格(Cell):行与列交叉出来的最小格子。
· 网格线(Line):行与列的边界线,编号从 1 开始计数。

最后一条尤其关键,后面用 grid-column、grid-row 做定位时,填的数字全部是“线号”而不是“第几个格子”,这是新手最容易算错的地方。

二、创建 Grid 容器

只需一行声明,元素即从普通块级盒变成网格容器,其直接子元素自动成为网格项目:
  1. .container {
  2.     display: grid;
  3. }
复制代码

三、定义行与列的数量和尺寸

网格的行列结构由 grid-template-columns 与 grid-template-rows 描述,前者定义列宽,后者定义行高:
  1. .container {
  2.     grid-template-columns: 100px 1fr 2fr;
  3.     grid-template-rows: 50px auto;
  4. }
复制代码

这段声明表示:共 3 列,宽度依次为固定的 100px、1 份、2 份;共 2 行,第一行固定 50px,第二行随内容自动撑开。三种常用长度单位的含义要记牢:

· px:固定宽度,不随容器变化。
· fr:按比例分配剩余空间,1fr 与 2fr 表示后者拿到前者的两倍。
· auto:由内容自身撑开。

四、行列间距

间距可以分开写,也可以用 gap 简写,简写时先写行间距、再写列间距:
  1. grid-column-gap: 10px;
  2. grid-row-gap: 20px;
  3. /* 简写形式:row-gap column-gap */
  4. gap: 20px 10px;
复制代码

注意 gap 简写的顺序是“行在前、列在后”,写反了不会报错,但视觉上会出现列间距异常大、行间距异常小的情况,排查这类“间距不对劲”的问题时先看这一行。

五、让项目跨行跨列

默认每个项目占一个单元格,需要跨格时用 grid-column 与 grid-row 指定起止网格线:
  1. .item {
  2.     grid-column: 1 / 3; /* 从第1条列线开始,到第3条列线前结束,即跨两列 */
  3.     grid-row: 1 / 2;    /* 跨一行 */
  4. }
复制代码

可以类比在 Excel 里从 A1 拖选到 B1:起点线号写左边,终点线号写右边。因为线号从 1 起算,跨 n 个单元格实际是“起始线号 / 起始线号 + n”。

六、自动填充做响应式列

固定写死列数在窄屏上必然出问题,Grid 提供了重复函数与自适应长度组合:
  1. grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
复制代码

三个关键字的职责分别是:

· repeat():重复声明列,省去手写多列。
· auto-fill:在容器宽度内尽可能多地填充列。
· minmax():给列宽设置最小值与最大值区间。

最终效果是每列至少 150px,容器宽度不够时自动减少列数并换行,不需要任何媒体查询就能得到卡片列表式的响应式布局。

七、对齐方式分两层

Grid 的对齐容易混淆,因为它同时存在“格子里面的项目怎么摆”和“整个网格在容器里怎么摆”两个层级。

第一层控制单元格内项目的对齐,justify-items 管水平方向,align-items 管垂直方向:
  1. justify-items: start | end | center | stretch;
  2. align-items: start | end | center | stretch;
复制代码

第二层控制整个网格在容器内的分布,justify-content 管水平,align-content 管垂直:
  1. justify-content: start | center | end | space-between | space-around | space-evenly;
  2. align-content: start | center | end | stretch;
复制代码

两者的区别在于作用对象:items 作用于每个格子里的内容,content 作用于整块网格。当网格总宽小于容器宽度时,改 items 看不出变化,改 content 才有反应——这也是判断自己写错层级的一个实用办法。

八、命名区域实现语义化布局

当页面结构固定为“头部 + 侧边栏 + 主内容 + 页脚”时,用区域名描述布局比数线号直观得多:
  1. .container {
  2.     display: grid;
  3.     grid-template-areas:
  4.         "header header"
  5.         "sidebar main"
  6.         "footer footer";
  7.     grid-template-columns: 200px 1fr;
  8.     grid-template-rows: auto 1fr auto;
  9. }
  10. .header  { grid-area: header; }
  11. .sidebar { grid-area: sidebar; }
  12. .main    { grid-area: main; }
  13. .footer  { grid-area: footer; }
复制代码

grid-template-areas 里的每一行字符串对应网格的一行,同名区域自动合并成一块。这样写出来的样式表能直接看出页面骨架,后续调整结构只需改字符串矩阵,可维护性明显好于一堆数字线号。需要注意的是,字符串里每一行列的个数必须与 grid-template-columns 定义的列数一致,否则矩阵对不上。

九、grid 简写

grid 属性可以把行、列模板合并到一条声明里,斜杠前是行模板,斜杠后是列模板:
  1. grid: auto / 100px 1fr 1fr;
  2. /* 等价于:
  3. grid-template-rows: auto;
  4. grid-template-columns: 100px 1fr 1fr;
  5. */
复制代码

简写虽然短,但可读性下降,团队协作中建议只在结构简单、行列模板固定时使用。

十、常用属性速查

· display: grid —— 开启 Grid 布局。
· grid-template-columns —— 定义列宽。
· grid-template-rows —— 定义行高。
· grid-column —— 控制项目跨列范围。
· grid-row —— 控制项目跨行范围。
· gap / row-gap / column-gap —— 设置网格间距。
· grid-area —— 指定命名区域。
· justify-items / align-items —— 控制格子内项目的对齐。
· justify-content / align-content —— 控制整个网格的对齐。

十一、小结与适用场景

Grid 的价值在于把“行列”作为一等公民暴露出来:grid-template-* 系列属性负责精确描述行列数量与尺寸,fr 单位负责按比例分配空间,repeat(auto-fill, minmax(...)) 负责在不写媒体查询的前提下完成响应式折行,grid-template-areas 负责让布局结构在代码里可读可改。实际项目中,整页骨架、仪表盘式分栏、卡片流这类二维结构优先考虑 Grid;只是单行排列按钮或单列堆叠的表单项,用 Flex 会更轻。选型时先判断结构是一维还是二维,再决定用哪套布局模型,比事后调间距要省事得多。
回复

使用道具 举报

发表于 2 小时前 | 显示全部楼层

Re: CSS Grid布局实战:fr单位与auto-fill自适应列实现

感谢整理,按“概念→建容器→定行列→定位→自适应→对齐→命名区域→简写”的顺序走下来很顺,基本把日常写 Grid 会碰到的点都覆盖到了。几个提醒特别实用:线号不是格子序号这点,我刚开始用 grid-column 时确实按“第几个格子”算过,结果整体错位;gap 简写“行在前、列在后”也很容易写反,而且不报错,只能靠肉眼排间距,这条排查思路很有用。对齐那两层用“改 items 没反应、改 content 才有反应”来判断,比死记属性名直观多了。命名区域矩阵列数要和 grid-template-columns 对齐这一点也容易被忽略,一旦对不上,布局会变得很奇怪。 想顺带请教两个实际使用中的小问题:一是 auto-fill 和 auto-fit 在卡片列表场景下大家一般怎么取舍,是不是列数少的时候 auto-fit 更容易把剩余空间撑满;二是 grid 简写如果只写斜杠一边,另一边是保持默认还是会被重置。整体内容很系统,已经收藏,后面搭后台框架可以直接照着这套顺序来。
回复 支持 反对

使用道具 举报

发表于 2 小时前 | 显示全部楼层

Re: CSS Grid布局实战:fr单位与auto-fill自适应列实现

这篇梳理得很清楚,按概念到简写一步步来,读下来不累。尤其是开头强调网格线号不是格子序号这一点,确实是我刚开始用 Grid 时最容易算错的地方,拿 Excel 拖选来类比很直观。 fr 和 auto 的对比也总结得好,一个按剩余空间比例分,一个由内容撑开,配合 minmax 做自适应列那段,基本是现在卡片列表的标配写法,不用媒体查询就能在窄屏上自动减列,省了不少事。 gap 简写行在前列在后这个提醒很实用,写反了不报错但视觉别扭,排查间距问题时确实该先看这一行。还有 items 和 content 两层对齐的区别,用网格总宽小于容器宽度时改哪个属性有反应来判断层级,这个方法我记下了。 命名区域那部分也很认同,字符串矩阵一眼就能看出页面骨架,比数线号维护起来舒服。文中提到每行字符串的列数要和 grid-template-columns 一致,这点很关键,我之前就因为这个对不上排查了半天。 想问一下后面会不会讲 auto-fit 和 auto-fill 的差别,感觉在列数少于容器容纳量时表现不太一样,如果方便的话可以展开说说。整体很实用,收藏了慢慢消化。
回复 支持 反对

使用道具 举报

发表于 2 小时前 | 显示全部楼层

Re: CSS Grid布局实战:fr单位与auto-fill自适应列实现

感谢楼主整理,这个顺序很清晰,尤其是把“线号”和“第几个格子”的区别放在最前面提醒,确实能少踩很多坑。 我这边补两个实战里容易碰到的点,供参考: 一是 `repeat(auto-fill, minmax(150px, 1fr))` 里的 `auto-fill` 和 `auto-fit` 在项目数量少的时候表现不一样。`auto-fill` 会尽量把列数占满,即使没有足够多的项目也会留下空列;`auto-fit` 则会把空轨道折叠掉,让现有项目拉宽填满容器。做卡片列表时如果最后一行总是留白,可以试试换成 `auto-fit` 对比效果。 二是 `minmax(150px, 1fr)` 的 150px 只是列最小宽度,它不考虑容器内边距和 `gap`。也就是说如果容器左右有 padding、列之间还有 gap,实际能放下的列数可能会比想象中少一列,调参时把这个算进去会顺很多。 另外命名区域那段挺实用的,再提一句:`grid-template-areas` 里用点 `.` 可以占位表示空单元格,这样矩阵对齐不容易乱,改结构时也直观。 整体这篇从概念到简写串下来,拿来当速查表完全够用了。
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

指导单位

江苏省公安厅

江苏省通信管理局

浙江省台州刑侦支队

DEFCON GROUP 86025

Hacking Group 021A

旗下站点

态势感知中心

应急响应中心

红盟安全

联系我们

官方QQ群:112851260

官方邮箱:security#ihonker.org(#改成@)

官方核心成员

关注微信公众号

Archiver|手机版|小黑屋| ( 沪ICP备2021026908号 )

GMT+8, 2026-10-30 05:43 , Processed in 0.031010 second(s), 28 queries , Gzip On.

Powered by ihonker.com

Copyright © 2015-现在.

  • 返回顶部