先记住这个答案
看 Grid 的列宽,先确认容器内容盒到底有多宽,再看列模板。固定长度列先占确定的空间,相邻列的 gap 也要扣除,余量交给 fr 轨道。若列有内容的自动最小尺寸、百分比或 minmax() 限制,最终值还要满足这些约束。因此「容器宽减去固定列」只是起点,不能忽略沟槽与最小值。
- 计算基准是容器内容盒
- 固定长度和
gap先占宽度 fr分剩下的可用空间- 内容最小尺寸可能改变最终轨道宽度
用确定宽度手算两列
假设内容盒宽 720px,列模板为 180px 1fr,列间距 24px。右列可用 516px。如果容器还有 20px 左右内边距,而 CSS 的 width: 720px 按默认内容盒模型解释,那么内容盒仍是 720px,外框则更宽;若换为 box-sizing: border-box,内容盒要从 720px 中再扣内边距和边框。
.shell {
box-sizing: border-box;
display: grid;
width: 720px;
padding: 0 20px;
grid-template-columns: 180px minmax(0, 1fr);
column-gap: 24px;
}
/* 无边框时内容盒 680px,右列为 476px */先从 720px 扣左右各 20px 的内边距,得到内容盒 680px。再扣 180px 侧栏和 24px 沟槽,右列就是 476px。这里用 minmax(0, 1fr),避免右列的一段不换行文本把轨道的自动最小值撑大;文本仍应单独处理换行或滚动。
百分比和函数不能一概而论
50% 轨道通常相对容器内容盒的相应尺寸计算,但若容器的该轴尺寸本身依赖内容,百分比在固有尺寸计算阶段不能总当作一个已知长度。minmax(200px, 1fr) 表示轨道至少 200px,分到的自由空间不够时仍不能缩到该值以下。fit-content() 也带上限及内容约束,和固定长度不等价。
工程上先用浏览器的 Grid 高亮工具看内容盒、轨道与沟槽,再查某个项目的自动最小尺寸。若计算与预期差几十像素,优先检查 padding、border、box-sizing 与 gap,不要急着怀疑 fr 的比例规则。
计算轨道宽度时要从 Grid 容器的内容盒出发,不能直接拿视口宽度。一个外框 800px、左右各 20px 内边距的容器,内容盒只有 760px;若还设了 gap: 20px,固定列扣除后余量才分给 fr。百分比列参考哪个尺寸还会受到容器是否有确定内联尺寸影响。面试手算前先写出“容器内容宽”,否则数字看似精确却从起点错了。
容易答错的地方
- 直接拿视口宽度算百分比列
- 百分比相对的是网格容器相关尺寸,不一定是视口。容器若在更窄的父元素里,结果随父元素变化。
- 忘了内边距与沟槽
- 轨道铺在内容盒内,
gap则位于轨道之间。用外框宽度直接分给列,会把宽度算大。
面试官还会怎么问?
两列都是 1fr 就一定平分吗?
在最小尺寸不阻碍时通常平分;某列不可断内容过宽时,自动最小值可能让它扩张。
minmax(200px, 1fr) 在容器很窄时会怎样?
该列不能小于 200px;若总最小宽度超过容器,布局可能产生横向溢出。
如何让右侧内容列保持可收缩?
用 minmax(0, 1fr) 明确允许轨道收缩,再对图片、代码或长文本设置相应的溢出处理。
参考资料
示例用于理解所注明的运行环境与边界;延伸学习可结合原文中的更多案例。