一次 Header 宽度幽灵问题的完整排查

· 更新于

记录今天如何定位并修复 Header 右侧漏底、TOC 错位与容器宽度联动回归问题。

今天花了很长时间处理一个看起来“很玄学”的 UI 问题:

  • 在某个宽度附近(大约 778px)开始出现
  • Header 右侧会露出一块区域,能看到正文内容“透出来”
  • 改一个地方会牵出一串回归:横向滚动条、TOC 位置异常、宽屏布局不同步

这篇文章按时间线整理:问题现象 → 错误假设 → 根因确认 → 最终修复


现象复盘

最初看到的是:Header 背景没有覆盖满可见区域,右侧有一条漏底区域。

后来又发现几个关联现象:

  1. TOC 在宽屏时有时跑到正文上层或位置不稳定
  2. 窄屏时 TOC 隐藏行为异常(看起来像媒体查询失效)
  3. Header 原本“宽屏更宽、滚动后收缩到正文宽度”的过渡有时失效

这些问题看起来互不相关,但实际上都与“容器宽度计算是否一致”有关。


先踩过的坑(错误方向)

1) 只盯 site-header 背景色

我们一开始把精力集中在颜色本身,比如 bg-[Canvas]、显式颜色、系统色等。

这只解决了“看起来是什么颜色”,但没有解决“为什么右侧会漏出”。

2) 直接把 Header 改成 100vw

100vw 确实能强行覆盖右侧槽位,但很容易引入副作用:

  • 在某些情况下出现横向滚动条
  • 与居中容器计算叠加后,定位补偿更复杂

3) 在 global.css 到处补丁

把局部问题全靠全局补丁压住,短期可见“好了”,长期会出现更多联动回归。


真正的根因

关键点是这句:

site-header-inner: w-full + px-4

如果是默认 content-box 盒模型,那么:

  • w-full 只计算内容盒
  • px-4 会额外再加宽度
  • 内层可能比外层更宽,导致视觉上出现“漏底/不对齐”

同样的问题也会出现在 mainfooter:只要是 w-full + padding,就需要统一盒模型策略。


最终修复策略

1) 所有关键容器统一 box-border

核心容器统一成“padding 算进宽度里”:

  • site-header-inner
  • main
  • footer

这样 w-full 才不会因为 padding 导致实际渲染宽度溢出。

2) 容器变量与实际宽度保持同一语义

为了保持“视觉内容宽度”不变,同时使用 box-border,把容器变量改成包含两侧 padding:

:root {
  --site-container-wide: calc(72ch + 2rem);
  --site-container-prose: calc(65ch + 2rem);
}

这保证了:

  • Header 宽屏状态与 footer 宽度仍对齐
  • Header 滚动收缩目标与正文主列仍对齐
  • TOC 偏移公式可继续基于统一变量计算

3) TOC 偏移公式改为变量驱动

把 TOC 的 left 改成使用 --site-container-prose

left: calc(50% + var(--site-container-prose) / 2 + 2rem);

避免“正文宽度改了但 TOC 公式还写死旧值”的错位。


这次排查的经验

  1. 先确认几何问题,再谈颜色问题:先看谁更宽、谁溢出。
  2. 容器系统要一致header/main/footer 不能各用一套宽度语义。
  3. 变量要代表真实布局语义:变量名和实际计算含义必须一致。
  4. 回归往往来自联动:一个宽度修复可能影响 TOC、动画、响应式行为。

小结

这次不是“某一行 CSS 写错了”这么简单,而是典型的布局体系一致性问题

  • 盒模型
  • 容器宽度变量
  • 定位公式
  • 响应式规则

只修一个点,通常会在别处反弹;把整条链路统一之后,问题才会真正稳定。

如果你也碰到“看起来像随机出现”的前端 bug,可以按这个顺序排:

盒模型 → 宽度来源 → 溢出路径 → 定位公式 → 响应式边界