语义化纵向导航结构必须用包裹,每个内仅含一个指向真实id的,目标区块用id而非class,配合scroll-margin-top避让fixed头部;高亮需js监听滚动并设aria-current="page"。

直接用 <nav></nav> + <ul></ul> + 锚点跳转就能跑通,不需要 JS 也能纵向滚动定位,但加几行 JS 能让体验更稳。
怎么写语义化纵向导航结构
纵向导航本质是「列表项对应页面区块」,必须用 <nav></nav> 包裹,否则屏幕阅读器和 SEO 都识别不了这是导航区。每个链接必须指向真实存在的 id,不能只写 href="#" 占位。
-
<nav></nav>下直接放<ul></ul>,中间别塞<div> 或其他容器 <li>每个 <code><li>里只放一个<a href="#xxx"></a>,xxx必须和目标区块的id完全一致(区分大小写) - 目标区块用
<section id="xxx"></section>或<div id="xxx">,不要用 class 替代 id <li>如果页面顶部有固定 header,得给目标区块加 <code>scroll-margin-top,否则锚点会卡在 header 下面 - 给所有锚点目标加统一偏移:
section[id] { scroll-margin-top: 80px; }(数值按 header 实际高度调) - 或者用
scroll-behavior: smooth配合 JS 手动滚动,兼容性更好但要多写几行 - 别依赖
margin-top或padding-top模拟偏移——这会导致布局错位,且响应式下容易失效 - 推荐监听
scroll事件,用getBoundingClientRect()判断哪个section在视口内 - 匹配到后给对应
<a></a>加aria-current="page"——比 class 更语义,读屏软件能识别 - 别用
offsetTop做判断:页面有动态内容、字体加载延迟时,值会不准 - 首次加载时也要触发一次,否则刷新页面后高亮丢失
- 默认用
flex-direction: column,别强行flex-wrap: wrap想“铺开”,纵向就是一条线到底 -
<a></a>至少设min-height: 44px,符合 iOS 触摸最小尺寸规范 - 别给
<nav></nav>设white-space: nowrap,否则文字在窄屏直接溢出不可见 - 如果导航项太多(比如超过 8 个),考虑加滚动容器或折叠逻辑,纯静态长列表体验差
为什么点击后跳转位置不准
最常见原因是没处理固定头部遮挡。浏览器原生锚点跳转不会自动避开 position: fixed 的 header,结果目标内容被盖住一半。
怎么让当前页导航项自动高亮
HTML 本身不判断路径,必须靠 JS 匹配 window.location.hash 或监听滚动。硬写 class="active" 在所有链接上是错的,会全部高亮或全不亮。
移动端纵向导航要防什么坑
小屏下纵向导航常被误当成横向菜单来写,结果一行挤不下、文字折行、点击热区太小。
真正麻烦的不是写代码,而是滚动定位偏差和高亮不同步——这两个问题在字体加载完成前、动态插入内容后、fixed header 高度变化时都会冒出来,得留心测。











