fr单位本质是剩余空间按比例分配,非依赖父容器总宽;其计算分三步:先扣固定尺寸与gap,再将剩余空间按fr份数切分,过程无舍入误差且不涉百分比换算。

fr单位不是“更精确”,而是计算逻辑完全不同——它不依赖父容器总宽,只对扣除固定尺寸后的剩余空间做等分。 百分比布局在 Grid 中容易因 gap、边框、内容撑开或嵌套容器高度未显式声明而偏移;fr 则天然绕过这些干扰,只要剩余空间存在,分配就稳定。
fr 的计算过程:先扣再分,不是按比例猜
浏览器处理 grid-template-columns 时,会严格按三步走:
- 第一步:提取所有非弹性轨道的尺寸(如
200px、30%、minmax(200px, auto)),累加它们占用的空间 - 第二步:从容器总宽中减去上述尺寸,再减去
column-gap总和,得到「剩余可用空间」 - 第三步:把剩余空间按 fr 份数切分,
1fr 2fr就是 1:2,1fr 1fr 1fr就是均分
比如 grid-template-columns: 200px 1fr 2fr 在 900px 宽容器中:
剩余空间 = 900px − 200px − gap总和 假设 gap=10px,两处 gap → 20px → 剩余空间 = 680px → 1fr = 680px × 1/3 ≈ 226.67px,2fr = 453.33px
这个过程完全不涉及百分比换算,也无需 JS 或 Sass 预计算,无舍入误差链。
百分比在 grid-template-columns 中为什么容易错位
百分比是直接按容器总宽计算的,它不关心其他列有没有固定宽度、有没有 gap、有没有内容溢出。典型问题包括:
-
grid-template-columns: 200px 50% 50%→ 第二列先拿走 450px(900px×50%),第三列再拿 450px,总宽直接超 1100px,触发横向滚动 -
grid-column-gap: 10px不参与百分比计算,但占真实像素,导致视觉列宽 ≠ 期望值 - 含长单词或 URL 的网格项若没设
min-width: 0,会撑爆百分比列,而 fr 列会自动压缩(前提是约束得当)
更隐蔽的是:百分比列在容器宽度由 fit-content 或 max-content 决定时可能坍缩为 0,而 fr 仍可基于实际渲染后宽度继续分配。
fr 失效的四个真实场景,比想象中更常见
fr 不是魔法,它只在有明确「剩余空间」时才起作用。以下情况它会退化或表现异常:
- 父容器没设
display: grid或display: inline-grid—— fr 只在 Grid 上下文生效,写在 Flex 或 Block 容器里完全被忽略 - 网格容器自身高度为
auto,且父级没给明确高度 →grid-template-rows: 150px 1fr中的1fr行会塌成内容高度,必须加height: 100%继承 - 所有列都是固定单位(如
200px 300px),无剩余空间 → fr 完全不参与计算 - 混用
%和fr时顺序不当,例如1fr 30% 1fr:浏览器仍先算 30%,再把剩下空间分给两个1fr,中间列反而最窄,不符合直觉
什么时候该坚持用百分比,而不是硬套 fr
fr 擅长「弹性延展」,但不擅长「比例锚定」。以下场景百分比仍有不可替代性:
- 需要某列始终占容器宽度的固定比例(如侧边栏恒为 25%),且不随窗口缩放而低于某个像素阈值 → 用
minmax(25%, 200px),而非25% 1fr - 与媒体查询配合做断点式栅格,如
repeat(auto-fit, minmax(30%, 1fr)):30% 控制最小占比,1fr 负责填满剩余,二者在minmax()内协同安全 - Grid 外部布局(如 margin、padding、width)仍需响应式比例控制,此时百分比仍是标准手段,别试图用 fr 替代
真正容易被忽略的是:fr 的「剩余空间」依赖整个布局链的显式尺寸声明。一个没设 height 的外层 div,会让内层 Grid 的 1fr 行失去计算基准——这不是 fr 的缺陷,而是 CSS 高度继承规则的刚性要求。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











