纯 css 实现不了商城侧边分类栏与主内容双向联动滚动,必须依赖 js 驱动高亮、锚点滚动和同步;position: sticky 因布局复杂、父容器未设 overflow 或存在 transform 等原因极易失效;scrollintoview 与 intersectionobserver 是最稳定组合;需严格遵循可访问性规范并避免 display 切换导致的交互问题。

纯 CSS 实现不了「商城侧边分类栏 + 主内容双向联动滚动」——position: sticky 只能单向吸附,而分类高亮、锚点滚动、滚动同步这三件事必须靠 JS 驱动。
为什么 position: sticky 在商城分类栏里大概率失效
商城侧边栏通常嵌在复杂布局中:顶部有固定 header、中间是 flex 容器、父层可能带 transform 或 filter。这些都会让 sticky 退化为 relative,连基本固定都做不到。
- 侧边栏直系父容器没设
max-height+overflow-y: auto,浏览器找不到“可滚动祖先” - 页面用了
body { transform: translateZ(0) }做硬件加速?它隐式创建新层叠上下文,sticky直接失能 - 想用
bottom: 20px让分类栏离页脚留白?Firefox 和 Safari 下基本不认这个值 - 移动端键盘弹出时视口高度突变,
top: 64px这类固定值会把栏位顶出可视区
scrollIntoView + IntersectionObserver 是当前最稳的联动组合
分类点击跳转、滚动时自动高亮对应项、主内容滚到某区块时侧边栏同步定位——这三件事靠监听 scroll 事件写方向判断太重,且性能差。用 IntersectionObserver 监听主内容区域的锚点元素,再配合 scrollIntoView 反向控制侧边栏,逻辑更解耦、触发更精准。
- 给每个主内容区块加唯一
id(如id="category-electronics"),侧边栏对应<a href="#category-electronics"></a> - 用
IntersectionObserver观察这些区块的isIntersecting状态,只在进入视口时触发高亮,避免频繁重绘 - 侧边栏点击时调用
document.querySelector(href).scrollIntoView({ block: 'start', behavior: 'smooth' }),不手动计算 offsetTop - 避免同时监听
scroll和resize——移动端键盘弹出会连续触发 resize,导致 observer 重复初始化
侧边栏 DOM 结构必须支持可访问性与语义化
商城分类不是普通导航,而是功能型控件。屏幕阅读器要能识别层级、当前状态、折叠/展开意图,否则 WCAG 2.1 AA 就过不了。
- 根容器用
<nav aria-label="商品分类"></nav>,而非<div class="sidebar"> <li>每级分类用 <code><button aria-expanded="false"></button>控制展开,不要用<a href="#"></a>冒充按钮 - 当前激活的分类项加
aria-current="page",CSS 用[aria-current="page"]选择器高亮 - 子菜单用
<ul role="group"></ul>包裹,避免被读屏器误判为独立导航 - JS 动态插入的 DOM 必须补全
role和aria-*属性,不能只靠 class 控制显隐 - 子菜单初始设
max-height: 0+overflow: hidden,展开时设为具体像素值(如max-height: 300px) - 过渡用
transition: max-height 0.3s ease-in-out,别加height——它无法从auto过渡 - JS 控制展开前先强制 reflow:
el.style.maxHeight = el.scrollHeight + 'px',再加 class 触发动画 - 避免在
@media (max-width: 768px)里直接display: block,改用transform: translateX(0)配合opacity做滑入效果
移动端收起/展开必须用 max-height 过渡,别碰 display
用 display: none 切换会导致 IntersectionObserver 失效、焦点丢失、动画卡顿。CSS transition 对 display 完全无效,这是初学者最常踩的坑。
真正难的不是写出能动的侧边栏,而是让它在 iOS Safari 的 iframe 里、Android WebView 的旧内核下、屏幕阅读器聚焦时、键盘导航中途、横屏切竖屏瞬间,都保持行为一致——这些细节不会报错,但用户一用就卡住。别省略 prefers-reduced-motion 查询,也别跳过 focus-visible 样式重置。











