二级标题滚走是因为与一级标题不在同一可滚动祖先容器内,需确保所有标题共用同一滚动父容器并设递增top值(如一级top:0、二级top:48px),且避免虚拟滚动包裹、条件渲染隔离及层级/单位错误。

为什么加了 position: sticky 和 top: 0,一级标题吸顶了,二级标题却滚走了?
根本不是二级标题没写对,而是它和一级标题没在同一个“粘性锚定链”里。浏览器只认**最近的、可滚动的祖先容器**作为 sticky 的参考边界。如果一级标题在 .category-group 里,而二级标题被包进了另一个 div(比如虚拟滚动切片或条件渲染块),那它就锚定到那个新容器去了——而那个容器很可能设了 overflow: hidden 或压根不可滚动。
实操建议:
立即学习“前端免费学习笔记(深入)”;
- 用开发者工具选中二级标题,逐层往上点父节点,看第一个带
overflow: auto/scroll/hidden的元素是谁;重点盯body、#app、框架路由容器、虚拟滚动 wrapper - 确保所有分类标题(一级、二级、三级)的**共同直接父容器**是同一个,并且该容器:
- 有明确高度或
max-height+overflow-y: auto - 没设
overflow: hidden(改用overflow: clip更安全) - 自身不是
display: flex或display: grid的直接子项(某些 Safari 版本会干扰)
- 有明确高度或
- 不要把二级标题塞进
React.memo、v-if块或react-window的itemData渲染函数内部——它必须和一级标题平级,同属一个滚动容器的直系子元素
top 值怎么设才让多级标题“接力”不打架?
sticky 不是“全固定”,而是按 DOM 顺序和 top 值“排队上岗”。后一个元素的 top 是从它**原始位置**算起的,而这个原始位置已被前一个吸顶元素推高了。所以不能全设 top: 0。
实操建议:
立即学习“前端免费学习笔记(深入)”;
- 一级分类标题:设
top: 0 - 二级分类标题:先量出一级标题的实际渲染高度(含 padding/border/margin),比如是
48px,那就设top: 48px - 三级标题:再叠加二级标题高度,例如
top: 96px - 所有标题必须共用同一套
z-index(比如都设z-index: 10),否则层级错乱会导致遮挡或穿透 - 避免用
em或rem写top——字体缩放时高度会变,导致错位;一律用px或vh这类绝对单位
吸顶后内容上钻、留白、或者标题叠一起了怎么办?
position: sticky 不脱离文档流,吸顶后仍占原始位置空间。后续内容若没避让,就会重叠;若避让过度,又会出现空白。这不是 JS 动态计算的问题,而是布局锚点被破坏的信号。
实操建议:
立即学习“前端免费学习笔记(深入)”;
- 别给 sticky 标题本身加
margin-top或动态改height——这会让浏览器重新计算锚点位置,引发跳变 - 需要避让时,给**紧跟在 sticky 标题后面的第一个普通内容元素**加
margin-top,值等于该 sticky 标题的高度 - 如果标题用了
transform: scale(0.9)或filter: drop-shadow(),立刻去掉——它们会创建新层叠上下文,切断 sticky 参考系 - 检查是否有
will-change: transform应用在祖先元素上,Safari 15.4–16.3 会因此直接禁用 sticky
Vue/React 里 key 没设对,标题就乱跳或卡住
框架复用 DOM 节点时,如果不同分类的标题被当成同一个节点更新,sticky 状态就丢了。典型表现:滑动几屏后,二级标题突然跳回顶部,或两个不同分类的标题同时“钉”在顶部。
实操建议:
立即学习“前端免费学习笔记(深入)”;
- 每个分类标题必须带唯一、稳定、与数据强绑定的
key,例如:key={category.id}或:key="subCategory.path" - 不要用数组索引
:key="index"——列表排序或增删时,索引会变,节点被错误复用 - 在 React 中,避免把 sticky 标题放在
useMemo或React.memo包裹的子组件里;Vue 中避免套在v-for外层的v-if或keep-alive里 - 如果用了虚拟滚动(如
react-virtualized),sticky 标题必须放在虚拟区域**之外**,作为滚动容器的直接子元素存在
top 值,而是让所有标题始终锚定在同一个滚动容器里——而这个容器,往往藏在框架默认包裹层、性能优化 hack 或条件渲染逻辑的最深处。


















