全出血布局的滚动条宽度 bug 终于被 CSS 修好了,container query units 实测

全出血布局的滚动条宽度 bug 终于被 CSS 修好了,container query units 实测

导语

如果你做过“全出血”风格的页面,大概率被这个问题折腾过:内容区域左右贴边很好看,但一放到有滚动条的页面里,右边就突然多出一段空白,整排文字对不齐。过去几年大家要么用 100vw hack,要么固定加 padding-right: 17px,但这两招本质都是在“赌”用户浏览器有没有滚动条。现在 CSS 终于给了更靠谱的解法,而且已经能稳定用。

正文

问题:全出血为什么会“翻车”

所谓全出血,就是把背景、图片或区块横向延伸到视口边缘,而内容区仍然居中。一个常见写法是:


.full-bleed {
  width: 100vw;
  margin-left: calc(50% - 50vw);
}

初看起来没问题,但一旦页面出现竖向滚动条,100vw 仍然包含滚动条宽度,背景就会向右“冒头”。反过来,如果你用 width: 100% 避免冒头,有滚动条时内容区又会变窄,文字行长不一致。

这是 CSS 里最经典的老问题之一,而且过去几乎没有纯 CSS 的优雅解法。

方案:container query units 才是正确答案

CSS Container Queries 除了能做响应式,还附带了一组容器单位:cqicqwcqhcqb。它们相对于容器尺寸计算,而不是视口。

用这个特性可以这样修全出血:


.content {
  container-type: inline-size;
}

.full-bleed {
  width: 100%;
  margin-left: calc(-1 * cqi(50));
}

这里的 cqi(50) 表示“容器宽度的 50%”。容器就是 .content 自身的内容宽度,所以负边距刚好把区块拉回到视口边缘。而且因为参考的是内容容器,不是视口,滚动条不会再影响计算结果。

落地:最小可用的兼容写法

如果你需要更强的兼容控制,可以加一个基于 scrollbar-gutter 的稳定版:


html {
  scrollbar-gutter: stable;
}

.section {
  container-type: inline-size;
  width: 100%;
  padding-left: 1.5rem;
  padding-right: 1.5rem;
}

.full-bleed {
  width: 100vw;
  width: 100cqi;
  margin-left: calc(50% - 50cqi);
}

scrollbar-gutter: stable 让浏览器提前预留滚动条空间,避免页面抖动。再配合 cqi,不管用户是否显示滚动条,全出血都能精确贴边。

对比:过去几种方案的坑

  • 100vw:滚动条会让背景冒头,移动端尤其明显。
  • 固定 padding-right: 17px:只能适配某系统某浏览器的默认滚动条,换主题、换系统都会穿帮。
  • calc(100% + 2rem):在父容器和视口宽度接近时能蒙混过关,但复杂布局里依旧会出错。

相比之下,cqi 的好处是“相对于内容真实宽度做负偏移”,不再依赖视口或系统默认值。

结论

全出血布局这个十年老问题,现在终于可以用纯 CSS 稳定解决了。核心就两招:container-type: inline-size 建立容器上下文,cqi 做基于内容宽度的负偏移。再加上 scrollbar-gutter: stable 防抖动,基本可以淘汰过去那些滚动条 hack。

如果你还在项目里写 100vw 或者硬编码 padding,是时候换掉了。

收尾

下一步建议:挑一个有滚动条和无滚动条的页面各测一次,对比 100vw、固定 padding、cqi 三种写法的表现。你会发现 cqi 是唯一一个不用写断点、不用猜系统、不用 JS 兜底的方案。

评论区

0 条评论

登录后可评论。

查看完整榜单
查看完整榜单
查看完整榜单