SCSS变量+@mixin封装Flex样式更稳易维护,关键在按内容撑开宽度定断点(如$nav-breakpoint: 576px)、用max-height+overflow实现折叠动画、Safari下必须加min-width: 0和flex-shrink: 0防错位。

直接用 SCSS 变量 + @mixin 封装 Flex 基础样式,比手写一堆重复的 display: flex 更稳、更易维护。关键不是“能不能做”,而是“断点怎么定”“折叠动画怎么过渡”“Safari 为什么错位”这些真实问题。
SCSS 断点变量必须按内容撑开宽度来定,不能硬写 768px
把断点值写死在每个 @media 里,等于埋下后续改不动的雷。实际导航项文字多、图标宽、字体大时,可能 576px 就换行了,768px 反而撑不开。
- 定义统一变量:
$nav-breakpoint: 576px(不是凭经验,而是测出菜单项开始折行的最小宽度) - 侧边栏展开/折叠宽度也用变量:
$nav-sidebar-width: 240px和$nav-sidebar-collapsed-width: 60px - 在
:root注入 CSS 变量:::root { --sidebar-width: #{$nav-sidebar-width}; },方便 JS 动态读取和修改
@mixin nav-flex-base() 必须包含 min-width: 0 和 flex-shrink: 0
漏掉这两条,Safari 就会撑开容器、子项被压缩变形——这不是 bug,是 Flex 默认行为没兜住。
-
min-width: 0防止子项(比如a标签)继承父容器宽度,导致横向溢出 - 给每个直接子
li加flex-shrink: 0,避免小屏下被 Flexbox 强制缩小 - 内嵌
a默认加white-space: nowrap和text-decoration: none,防文字断行错位 - 调用时只需一行:
@include nav-flex-base();,不用再记哪几行不能少
折叠动画必须用 max-height + overflow: hidden,别碰 height: auto
height: auto 无法 transition,display: none 会切断 DOM 流、破坏屏幕阅读器和焦点管理——这是无障碍和可测性的硬伤。
PigX UI Pro 前端开发指南 - Vue 3 + TypeScript + Element Plus。当用户提到 PigX UI、PigX 前端、lgb-mgui 项目、Vue 3 企业级后台开发、Element Plus 后台开发时使用此技能。
立即学习“前端免费学习笔记(深入)”;
- 收起状态:
max-height: 0; overflow: hidden; - 展开状态:
max-height: 480px(实测覆盖最多 8 个菜单项足够,太小会截断,太大收起有延迟) - 过渡只写:
transition: max-height 0.3s ease-in-out,比 JS 控制transform更轻量 - 别用
opacity单独过渡,它不解决布局塌陷问题
移动端优先时,@media 必须用 max-width,且 .nav-list 初始隐藏
用 min-width 容易导致 Safari 初始解析延迟、布局闪一下;更重要的是,语义上桌面是完整态,移动端是降级态,逻辑要对齐。
@media (max-width: $nav-breakpoint) { .nav-list { display: none; } }- 汉堡按钮和菜单必须同级 DOM:
<button class="hamburger"></button><nav class="nav-menu"></nav>,否则:checked ~ .nav-menu不生效 - 激活态靠类切换:
.nav-menu.active { display: flex; },别依赖:hover(移动端无效) - 确保父容器没设
overflow: hidden,否则弹出菜单被截断
最难的不是写对 flex-direction: column,而是想清楚:断点值到底由什么决定、折叠动画的 max-height 上限设多少才不卡顿、以及 Safari 下 min-width: 0 漏掉后为什么整个导航栏往右偏移一截——这些细节不处理,光套 Flexbox 模板,上线后第一周就会被 QA 打回来。

















