必须用 结构: 定义导航区域, 表明并列关系, 支持键盘焦点, 自带可访问性;禁用 替代、 内嵌非 元素、无 href 的链接;推荐 flex 布局配 gap,移动端用 checkbox 模拟汉堡菜单,active 类须动态添加。

直接用 <nav></nav> 包裹 <ul></ul> + <li> + <a></a> 是唯一推荐的语义化起点,其他写法(比如 <div> 堆链接、<code><ul></ul> 里塞 <div>)会在可访问性、SEO 和后续维护上持续埋雷。
<h3>为什么必须用 <code><nav><ul><li><a></a></li></ul></nav> 这套结构
浏览器和读屏软件靠 <nav></nav> 知道“这是导航区”,不是装饰;<ul></ul> 表明这些是并列项,不是随意排列的块;<li> 是列表单元,天然支持键盘 Tab 顺序和焦点管理;<a></a> 本身可聚焦、可点击、自带默认行为——省掉一堆 JS 修复。
- 别写
<nav><div>首页</div> <div>关于</div></nav>:语义丢失,屏幕阅读器会读成“导航区域,首页,关于”,没结构感 - 别在
<ul></ul>里放<div> 或 <code><span></span>:HTML5 规范只允许<li>作为直接子元素 - 每个
<a></a>必须有href属性(哪怕暂时是href="#"),否则无法被键盘聚焦,也违反 WAI-ARIA 最小可访问性要求 - 给
<nav></nav>设display: flex,再加gap: 1rem控制间距,比手动写margin-right干净得多 - 避免给
<nav></nav>加white-space: nowrap:小屏下内容会横向溢出,用户得左右拖拽,体验极差 - 如果要居中整个导航栏,用
justify-content: center,不是给父容器设text-align: center——后者对 flex 子项无效 - IE 不支持
gap?那就退到margin-right,但记得给最后一个<li>加margin-right: 0,不然右边多一截空白 - 结构上:隐藏
<input id="menu-toggle">,用<label for="menu-toggle">☰</label>绑定点击 - CSS 上:菜单
<ul></ul>默认display: none,触发条件写成#menu-toggle:checked ~ ul(注意是兄弟选择器,不是子代) - 下拉层必须加
position: absolute,且它的父级<li>要设position: relative,否则定位基准错乱 - 别漏
<meta name="viewport" content="width=device-width, initial-scale=1">,没有它,媒体查询和 touch 事件都会失效 - 服务端渲染项目:由后端根据请求路径注入
class="active" - 前端单页应用(SPA):路由库(如 React Router、Vue Router)自动处理
- 纯静态多页网站:用 JS 在页面加载后匹配
window.location.pathname,再加 class。示例逻辑:
display: flex 比 float 或 inline-block 稳得多
老式布局容易因换行符、空格、字体渲染差异导致横向错位,flex 一行对齐、等距、居中都可控,且现代浏览器全覆盖(IE10+ 支持基本 flex,IE9 及以下已无必要强兼容)。
移动端折叠菜单不能只靠 display: none
纯 CSS 实现汉堡菜单的关键是状态模拟,<input type="checkbox"> 是目前最轻量、最可靠的方式,不依赖 JS 加载,失败也不影响基础导航可用性。
生成可在 deepbi 沙箱 iframe 内运行或作为独立文件运行的交互式 HTML 页面,使用 `window.deepbi` JS SDK 实现数据查询、空间管理、文件浏览及用户操作。当用户提出以下需求时启用该能力: - 创建 KPI 仪表盘、数据表格、文件浏览器、成员列表、管理页面; - 明确要求“转成 dhtml”、“转译成 HTML”、“把 XX 页面转成……”、“控制台页面”、“管理后台”、“DeepBI 页面迁移”; - 提及位于 `apps/console/src/featur
立即学习“前端免费学习笔记(深入)”;
active 类不能硬编码,必须动态加
HTML 静态页面无法自己判断当前路径,所以所有页面里把某个 <a></a> 写死 class="active" 是典型错误——会导致高亮错位、SEO 混淆、多页维护成本爆炸。
document.querySelectorAll('nav a').forEach(link => {
if (link.href === window.location.href ||
link.href === window.location.origin + window.location.pathname) {
link.classList.add('active');
}
});
这个判断要小心处理结尾斜杠(/about vs /about/)、查询参数、哈希值,否则容易漏判或误判。


















