移动端导航默认用 display: none + 媒体查询隐藏,配合 checkbox+label 实现无 JS 折叠;禁用 details 和 :hover,避免 iOS Safari 与微信 X5 兼容问题。

移动端导航默认收起,用 display: none + 媒体查询控制显隐
小屏下导航栏必须默认隐藏,否则会挤占内容区、触发横向滚动。别指望 JS 加载完再隐藏——首屏就露出来,体验直接崩。
关键写法:@media (max-width: 768px) { .nav-menu { display: none; } },配合一个可见的汉堡按钮(☰)作为触发入口。这个 display: none 必须写在 CSS 里,不能靠 JS 切 class 动态加,否则页面加载瞬间会闪出一帧完整菜单。
-
.nav-menu是包裹所有导航项的或容器 - 汉堡按钮本身要设
display: block,且仅在max-width: 768px下生效 - 桌面端不写
display: none,让它自然流式显示;移动端才强制隐藏
折叠菜单展开用 input[type="checkbox"] + label + ~ 兄弟选择器
别用 details 嵌套做多级下拉——iOS Safari 和微信 X5 内核根本不认子 details,状态不同步是常态。也别用 :hover,手机上压根没 hover。
最稳方案:一个隐藏 ,紧挨着它放 ,后面紧跟 。CSS 写成:input#menu-toggle:checked ~ nav ul { display: block; }
-
input和label之间**不能有换行、空格或其它标签**,HTML 空白符会被解析为文本节点,~就失效 -
nav ul必须是label的**直接兄弟节点**,中间插个就断链- 展开后菜单需设
position: absolute或top: 100%,否则会撑开布局导致页面跳动子菜单层级必须用
ul嵌套在父li内部,不能脱离结构多级菜单不是靠 JS 拼 DOM 或 CSS 绝对定位硬凑出来的。浏览器和屏幕阅读器只认 DOM 层级关系:子
ul必须是父li的**直接子元素**,否则键盘 Tab 会跳过、aria-expanded同步失败、CSS 选择器匹配错层。正确结构:
;错误结构:- Products
- Laptops
(子- Products
- Laptops
ul在li外)或(插入Products- ...
div破坏父子链)- 每层
ul都要加role="menu",每个可点击项(a或button)加role="menuitem" - 带子菜单的
li必须加aria-haspopup="true"和初始aria-expanded="false" - 移动端必须重置所有子级
.submenu为display: none,不能留“半开”状态
折叠动画别用
display: none切换,改用max-height+overflow: hidden直接切
display: none会导致过渡动画完全丢失,用户感知生硬。但也不能给height设固定值——内容高度不可控,容易裁剪或留白。稳妥做法:默认设
max-height: 0+overflow: hidden,展开时设max-height: 500px(足够高,但别设none),再加transition: max-height 0.3s ease。这样既平滑,又不依赖 JS 计算高度。- 别给
details直接设height: 0——会压垮内部流式内容,布局错乱 - 如果用
input[type="checkbox"]控制,动画规则要写在input:checked ~ .submenu下,不是.submenu自身 - 移动端收起时,除了
max-height,还得同步设pointer-events: none防止触摸穿透
实际项目里最容易被忽略的,是子菜单在移动端的强制收起逻辑——不是“默认关闭”,而是必须用
@media (max-width: 768px)显式重置所有.submenu的display或max-height,否则折叠状态混乱、焦点路径断裂、内容区被挤压到无法操作。 - 展开后菜单需设
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











