SCSS中content值必须加引号,变量插值用#{$var};attr()和counter()不可动态生成;封装mixin需限定类型;var()回退值勿加引号且需透传作用域。

SCSS里写content必须加引号,不加就失效
原生 CSS 要求 content 的字符串值必须带引号,SCSS 编译后也得遵守这条铁律。但很多人在 SCSS 里直接写 content: $icon; 或 content: $prefix $suffix;,结果编译出来是 content: arrow right; —— 浏览器直接当非法值忽略,伪元素白写了。
正确做法是:所有字符串拼接必须显式用引号包裹,变量插值用 #{$var}:
content: "#{$arrow} #{$separator} #{$label}";- 避免
content: $arrow $separator $label;(编译后无引号,非法) - Unicode 字符也要转义并包引号:
content: "\2713";,不能写成content: \2713;
attr() 和 counter() 在 SCSS 中不能动态生成,别硬套变量
SCSS 是编译时预处理器,而 attr() 和 counter() 是运行时由浏览器计算的。你写 content: attr(#{$dataAttr}); 看似聪明,实际编译后变成 content: attr("data-status"); —— 这没问题;但若写成 content: attr($dataAttr);,SCSS 会报错或输出字面量 $dataAttr,CSS 解析失败。
真正要小心的是误以为能“用 SCSS 控制 counter 行为”:
立即学习“前端免费学习笔记(深入)”;
-
counter-reset和counter-increment必须写在真实选择器里,SCSS 只能帮你批量生成规则,不能替代逻辑 - 想按层级动态设
counter()格式?老老实实写content: counters(section, ".");,别试图用@each拼字符串 -
attr()的属性名必须和 HTML 中完全一致,SCSS 变量只是帮你少打几个字,不是魔法
用 SCSS 函数封装常用 content 模式,但别过度抽象
重复写 content: attr(data-tip); 或 content: "•"; 很烦,可以封装 mixin,但得守住边界:只封装**结构固定、参数有限**的模式。
比如这个安全的图标前缀 mixin:
@mixin icon-before($char, $size: 1em) {
&::before {
content: "#{$char}";
display: inline-block;
font-size: $size;
}
}
.btn-primary { @include icon-before("\2713"); }
但别写这种:
// ❌ 危险:把 attr()、counter()、url() 全塞进一个参数,后期维护全靠猜
@mixin dynamic-content($type, $value) { ... }
理由很实在:不同 content 类型语义和渲染机制完全不同,混在一起只会让调试变慢、团队理解成本上升。
SCSS 中读取 CSS 自定义属性(var())要留神作用域和回退值
SCSS 本身不解析 var(--color),它只是原样输出。所以你在 SCSS 里写 color: var(--primary, #007acc); 完全 OK,但要注意两点:
- 回退值不能带引号:
var(--color, red)✅,var(--color, "red")❌(整个声明失效) - 伪元素不继承自定义属性,必须在宿主选择器里“透传”一次:
.card { --icon-color: #666; } .card::before { color: var(--icon-color); }—— SCSS 可以帮你用@extend或嵌套减少重复,但逻辑不能省 - 如果用
@use引入颜色变量模块,记得它和运行时var()是两套体系:前者编译时确定,后者运行时可被 JS 修改
最易被忽略的点:当你用 SCSS 生成大量伪元素规则时,很容易忘记给每个宿主都显式声明所需变量,导致 ::before 里 var() 取不到值,最终显示默认色或透明。这不是 SCSS 的锅,是 CSS 作用域规则本身如此。


















