响应式菜单断点应依设计稿内容确定(如920px),而非固定768px;隐藏需用visibility/opacity/height组合保障可访问性与动画;遮罩关闭须严格校验target;@mixin参数宜用字符串模式支持扩展。

响应式菜单的断点控制必须和设计稿对齐,别硬套 768px
很多团队直接抄网上例子用 @media (max-width: 768px) 做菜单折叠,结果在 iPad Pro 宽屏竖屏下菜单闪跳、在 Chrome DevTools 的 “Responsive” 预设里表现不一致。根本原因是断点该由内容决定,不是设备尺寸。
实操建议:
- 先在 Figma 或设计稿中标出「导航项开始换行」或「logo 和菜单挤不下」的具体宽度(比如
920px),这个值才是你的断点 - Sass 中用变量统一管理:
$breakpoint-nav-collapse: 920px,所有相关逻辑都引用它 - 避免在多个
@mixin里重复写@media,把断点判断封装进一个基础@mixin responsive-nav,内部再分desktop/mobile分支
用 @mixin 封装显示/隐藏逻辑时,别只切 display
只写 display: none 和 display: flex 看似简单,但会导致两个问题:一是屏幕阅读器仍能读到隐藏菜单(无障碍失败),二是 Safari 在动画中切换 display 会丢掉过渡效果。
实操建议:
- 移动端菜单默认用
visibility: hidden; opacity: 0; height: 0+overflow: hidden组合隐藏,确保可访问性且支持 CSS 动画 - 展开时改用
visibility: visible; opacity: 1; height: auto,并配合transition: opacity 0.2s, height 0.3s ease-in-out - 在
@mixin nav-toggle-state中统一处理这组属性,传参控制是open还是closed
点击遮罩层关闭菜单时,event.target 容易误判
常见错误是监听遮罩 .overlay 的 click,然后直接 hideMenu(),结果用户点到菜单里的链接、按钮甚至子菜单箭头时,菜单也关了——因为这些元素都在遮罩 DOM 内部,事件冒泡触发了关闭。
实操建议:
- 给遮罩层加
data-overlay="true",在事件处理器里检查event.target.dataset.overlay === "true" - 或者更稳妥:用
event.target === overlayEl严格比对 DOM 节点(注意不是=== this) - Sass 层面不用管这个,但 JS 调用
@mixin生成的类名时,要确保遮罩有唯一可识别的选择器,比如.nav-overlay
@mixin 的参数设计要预留扩展性,别只做“开/关”二值
上线后常遇到新需求:比如桌面端 hover 展开二级菜单、移动端滑动呼出、或者某些页面禁用折叠。如果当初 @mixin mobile-nav($show: true) 只接受布尔值,后面就得重写或加一堆 !default 补丁。
实操建议:
- 用字符串参数代替布尔值:
@mixin nav-behavior($mode: "auto"),支持"auto"/"mobile-only"/"desktop-hover"/"disabled" - 每个模式对应一套 CSS 规则块,在 mixin 内用
@if分支处理,避免生成冗余样式 - 对外暴露的类名保持稳定,比如始终是
.nav-menu,内部结构由$mode控制,JS 不用跟着改
真正麻烦的是动画节奏和焦点管理——比如键盘用户按 Tab 进入菜单后,ESC 键是否关闭、关闭后焦点是否回到触发按钮。这些没法靠 Sass 解决,得配合同步的 JS 逻辑,但至少样式层别拖后腿。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











