
用 <nav></nav> 包裹才是语义正确的导航栏
浏览器和读屏软件靠 HTML 语义识别导航区域,<nav></nav> 不是可有可无的装饰标签。不用它,只用 <div> 套一堆 <code><a></a>,SEO 和无障碍支持会打折扣。
常见错误现象:
– 导航链接被当成普通段落链接,屏幕阅读器不提示“这是导航”
– 搜索引擎无法区分主导航、页脚导航、侧边相关链接
- 每个页面最多用 1–2 个
<nav></nav>,主菜单一个,页脚快捷入口可另加一个 - 不要嵌套
<nav></nav>—— 子菜单用<ul></ul>/<li>即可,语义上属于同一导航上下文 - 如果导航纯属视觉分隔(比如文章内锚点跳转区),用
<section></section>或<div> 更合适 <h3>CSS 实现横向排列时,<code>display: flex比float更可靠float用来做导航栏是上世纪的妥协方案,现在会触发清除浮动、父容器塌高等隐性问题;display: flex天然支持对齐、换行、等宽分配,适配响应式也更直接。使用场景:
– 需要居中、右对齐或自动撑满容器宽度
– 要在小屏下折叠成汉堡菜单(配合@media切换flex-direction)立即学习“前端免费学习笔记(深入)”;
- 给
<nav></nav>设置display: flex,子元素<a></a>或<li>默认水平排列 - 避免对
<a></a>设float: left—— 它会让父<nav></nav>高度丢失,且与现代布局工具链(如 CSS Grid)冲突 - 移动端慎用
white-space: nowrap强制单行,容易导致横向溢出,应优先用flex-wrap: wrap或媒体查询控制
下拉菜单必须用
<ul></ul>+<li>结构,不能只靠 CSS 悬停模拟仅用
:hover显示隐藏<div> 块,会导致键盘用户无法聚焦子菜单项,也不满足 WCAG 2.1 的焦点顺序和可操作性要求。 <p>错误现象:<br>– Tab 键跳过整个下拉区域<br>– 移动端点击一级菜单后,下拉一闪而逝,无法点击子项<br>– 屏幕阅读器读不出“此菜单包含 3 个子选项”</p> <ul> <li>结构必须是 <pre class="brush:php;toolbar:false;"><li><a>产品</a><ul><li><a>Web</a></li></ul></li></li> <li>用 <code>aria-haspopup="true"</pre> 和 <code>aria-expanded控制状态,JavaScript 配合切换属性值 - 给
- 不要依赖纯 CSS 实现多层下拉 —— 第二级菜单需 JavaScript 监听焦点移入/移出,否则在触摸设备或键盘导航下失效
响应式断点别硬写 768px,优先按内容撑开逻辑定
所谓“平板宽度” 768px 是典型拍脑袋断点,实际中导航文字长度、图标数量、字体缩放都会影响换行临界点。强行卡固定值,常导致小屏下文字折行错乱或大屏留白过多。
性能影响:
– 过多的 @media 规则增加 CSS 解析负担(虽小但累积)
– 固定断点 + vw 字体混合使用,可能造成字号突变
- 先写移动端(mobile-first),用
flex-wrap: wrap让菜单自然折行,观察真实内容何时挤不下 - 用
min-width而非max-width定义扩展断点,例如@media (min-width: 48em)表示“内容足够宽时才展开横排” - 避免在同一个
<nav></nav>上同时用display: flex和display: grid切换 —— 浏览器重排成本高,且 Safari 对 flex/grid 混合切换支持不稳定
最麻烦的其实是焦点管理:下拉展开后,键盘用户按 Tab 应该进入子菜单,而不是跳到下一个导航项。这点连很多框架都漏处理,得自己补 focus() 和 focusout 逻辑。










