必须用语义结构,禁用div模拟;子菜单需嵌套并同步控制aria-expanded、焦点与动画状态,确保键盘导航闭环。

nav + ul + li 结构必须用语义化标签打底
不套 常见错误现象: 只写 使用场景:移动端点击汉堡图标、桌面端 hover + keyboard 触发下拉、ESC 键关闭所有展开项 很多人把 分析 Java Spring Boot 后端 Controller 代码,自动生成 Markdown 格式的接口文档。当用户说“生成 Java 接口文档”、“生成 API 文档”、“从 Spring 代码生成文档”时触发。 性能影响:频繁 resize 触发重排,尤其在 Chrome DevTools 模拟设备时更明显 CSS 里写 容易踩的坑:
实际项目中最容易被忽略的,是键盘交互闭环:用户用 Tab 进入导航,用 ↓/↑ 切换菜单项,用 Enter 展开/跳转,用 ESC 退出,整个过程不能中断焦点流。这比视觉动效难调试,但却是区分“能用”和“可用”的关键分水岭。、硬塞 aria-expanded 属性失效,甚至某些浏览器的键盘焦点逻辑错乱。结构必须是 嵌套,子菜单用嵌套 ,不能靠 JS 动态拼 HTML 字符串来生成主干结构。
– 点击汉堡图标后菜单不展开,但控制台无报错
– 键盘 Tab 切换跳过整个导航区域
– 移动端双击缩放后菜单项错位
必须包含一个 (哪怕 href="#"),否则 focus() 行为异常aria-haspopup="true" 和 aria-expanded="false"
需紧跟在对应 内,不能用绝对定位“飞出去”再塞进 DOMtoggleClass 不够用,得手动控制 aria-expanded 和 focus 状态
element.classList.toggle("open") 是懒办法。CSS 里用 .submenu.open { display: block; } 看似简单,但可访问性直接归零——屏幕阅读器根本不知道这个菜单“现在打开了”。必须同步操作 ARIA 属性和焦点链。
时,先 event.preventDefault(),再切换 aria-expanded 值submenu.querySelector("a").focus() 把焦点移到第一个子链接[aria-expanded="true"] 元素,设为 "false" 并收起对应 .submenu
:hover 实现下拉,它在触摸设备上无效;hover 只能作为桌面增强,核心逻辑必须由 JS 控制响应式断点要和 JS resize 监听解耦
window.addEventListener("resize", ...) 当成万能响应方案,结果一拖拽窗口就卡顿,或者小屏下误触发桌面逻辑。真实项目里,JS 不该“感知尺寸”,而应“响应状态”。
.navbar 的 display 或 visibility,JS 只监听 matchMedia("(max-width: 768px)").matches 的变化initMobileNav(),只在媒体查询匹配时调用一次 加 overflow: hidden,防止背景滚动动画和 transition 要配 JS 的 class 切换节奏
.submenu { transition: max-height 0.3s ease; } 看起来平滑,但 max-height 从 0→具体像素值时,如果高度不确定(比如子项动态加载),动画会抽搐或提前结束。JS 控制动画节奏比纯 CSS 更稳。
– 子菜单展开后内容被截断
– 关闭动画没执行完就再次点击,状态错乱
– Safari 下 transform: scaleY() 动画闪白
transform: scaleY(0) → scaleY(1) + opacity,避免触发布局计算submenu.style.height = "0",强制重绘,再加类触发 transitiongetComputedStyle(submenu).height 获取最终高度后,再设回 "auto",确保动画结束后样式干净.open 类,别让 JS 和 CSS transition “抢状态”
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










