Sass没有nest-depth()函数,无法运行时获取嵌套层级;实际可用方案为递归@mixin配合列表长度计算,或用map结构模拟层级。

用 nest-depth() 函数获取当前嵌套层级(不,Sass 没这函数)
Sass 本身不提供运行时获取嵌套深度的内置函数,nest-depth() 是常见误解——它不存在。很多人在写多级导航时想靠“自动读取嵌套层数”来算缩进,结果编译报错或返回 undefined。真实可用的是:手动传参、递归 mixin、或用列表长度模拟层级。
真正能落地的方式只有两个:
• 用递归 @mixin 配合列表参数(推荐)
• 用带层级标识的 map 数据结构(适合动态菜单配置)
别试图用 & 或 @at-root “反推”深度,那不可靠,且无法参与计算
用递归 @mixin + length() 动态生成缩进
核心思路是把菜单结构转成 Sass list(如 (item, (subitem, (subsubitem)))),再用递归 mixin 展开每一层,并用 length($path) 当作当前缩进级数。
实操要点:
• 缩进单位建议用 em 或 rem,避免像素硬编码
• 每层缩进 = $base-indent * (length($path) - 1),减 1 是为了根级不缩进
• 必须用 @each 配合 type-of() 判断子项是否为 list,否则递归会崩
• 不要直接在 @content 里调 length($path),需提前赋值给局部变量,否则作用域失效
@mixin nav-indent($path, $base-indent: 1.5rem) {
$level: length($path) - 1;
padding-left: $base-indent * $level;
<p>@if type-of(nth($path, 1)) == list {
@each $sub in nth($path, 1) {
& > ul {
@include nav-indent($sub, $base-indent);
}
}
}
}</p><p>// 调用
.nav {
@include nav-indent((level1, (level2, (level3))));
}
</p>
为什么不用 @for 循环硬写 5 层?
硬写 @for $i from 1 through 5 看似简单,但会带来三个实际问题:
• 所有层级共享同一套样式规则,无法差异化控制某一层的 font-size 或 line-height
• 一旦菜单实际只到第 3 层,第 4–5 层的 CSS 仍会被生成,污染输出体积
• 无法响应式切换缩进逻辑(比如移动端折叠后只展开前两级)
更麻烦的是:Sass 的 @for 是编译期循环,不能根据数据长度自适应。你得同时维护两套逻辑——菜单数据结构 + 循环上限数字,稍有不一致就漏样式或错层级。
map 方式适配 CMS 输出的 JSON 导航结构
如果后端吐的是 JSON 格式菜单(如 {"label":"首页","children":[{"label":"产品","children":[...]}),前端通常转成 Sass map:
$nav-tree: (
"首页": null,
"产品": (
"Web 端": null,
"移动端": (
"iOS": null,
"Android": null
)
),
"关于": null
);
<p>// 用递归函数 flatten-map 获取最大深度,再喂给 mixin
</p>
注意:map-keys() 和 map-get() 可以遍历,但 Sass 没有原生 JSON 解析能力。必须由构建工具(如 Webpack + sass-resources-loader)或 CI 脚本提前把 JSON 转成合法 Sass map 字符串,否则编译直接失败。
真正卡住多数人的不是语法,而是忘了 Sass 是静态编译器——所有“动态”都得在编译前确定好数据形状。缩进可以算,但“哪一层该显示箭头”“哪一层禁用点击”,得靠额外 flag 字段驱动,不能指望运行时判断。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











