纯 css 实现响应式下拉菜单的关键在于:桌面端用 :hover 悬停展开,移动端必须改用点击逻辑(如 :checked + 隐藏复选框),因移动浏览器默认不触发 :hover,且绝对定位易被裁切;需用 @media 分开控制显隐、定位与动画。

纯 CSS 实现响应式下拉菜单,关键不在“能不能”,而在于「桌面悬停」和「移动端点击」必须走两套逻辑——用 @media 切换行为,而不是强行一套规则硬撑全端。
为什么直接用 :hover 在手机上失效
移动浏览器(包括 iOS Safari、Chrome for Android)默认不触发 :hover,除非用户“模拟悬停”(比如长按),但那不是预期交互。更麻烦的是,即使强制启用(如 touch-action: manipulation),手指移开时菜单会立刻收起,根本点不到子项。
- 不要依赖
.nav-item:hover .submenu在小屏生效 - 不要给
.submenu设display: none后指望它在移动端靠 hover 显现 - 检查 DevTools 的 “Emulate touch screen” 模式,真实验证 hover 是否被忽略
@media (max-width: 768px) 内必须重置定位与显隐逻辑
桌面端用 position: absolute 是为了不占流、不推内容;但移动端屏幕窄,绝对定位反而容易被裁切或遮挡导航栏本身。此时应让下拉菜单回归文档流。
- 在断点内把
.submenu的position改为static或relative - 去掉
top: 100%和left偏移,让它自然展开在父项下方 - 用
max-height+overflow: hidden配合transition实现收放动画(display无法过渡) - 隐藏原
:hover规则,改用.nav-item[aria-expanded="true"] .submenu控制显隐
如何不用 JS 切换 aria-expanded
可以,但只适用于简单场景:用隐藏的 <input type="checkbox"> + :checked + 兄弟选择器(~)驱动状态。HTML 结构必须严格满足「复选框在触发按钮之前」且同级。
- 结构示例:
<input id="memories-toggle" type="checkbox"><label for="memories-toggle">Memories</label><div class="submenu">...</div> - CSS 规则:
#memories-toggle:checked ~ .submenu { max-height: 500px; opacity: 1; } - 缺点:无法键盘操作(
Enter不触发 checkbox),且 aria-expanded 无法自动同步 —— 若需无障碍,仍得 JS
真正容易被忽略的点是:下拉菜单的 z-index 在移动端常被视口缩放或 transform 层叠上下文意外截断,尤其当父容器用了 will-change: transform 或 backface-visibility: hidden。测试时务必在真机上打开「层叠上下文」调试面板确认渲染层级。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











