如何修改SASS混合宏,实现嵌套调用时合并html父选择器类?
问题
现有如下SCSS代码:
@mixin one() { html.one & { @content; } } @mixin two() { html.two & { @content; } } div { background: green; @include one() { background: blue; @include two() { background: yellow; } } }
编译后得到的CSS结果为:
div { background: green; } html.one div { background: blue; } html.two html.one div { background: yellow; }
需要修改上述混合宏,使最终生成的CSS中html元素同时拥有one和two两个类,期望的编译结果为:
div { background: green; } html.one div { background: blue; } html.one.two div { background: yellow; }
要求嵌套调用混合宏时,无论内外层调用顺序如何,html标签上的类始终会被合并。
解决方案
可以通过检测父选择器是否已包含html标签,来决定是新增类还是合并类,利用Sass的选择器处理函数实现:
修改后的SCSS代码:
@mixin add-html-class($class) { @if selector-parse(&)[0] == html { // 父选择器已是html,直接追加类 &#{$class} { @content; } } @else { // 父选择器不是html,嵌套html.类结构 html#{$class} & { @content; } } } // 基于通用宏定义one和two @mixin one() { @include add-html-class('.one') { @content; } } @mixin two() { @include add-html-class('.two') { @content; } } div { background: green; @include one() { background: blue; @include two() { background: yellow; } } }
原理说明
- 定义通用的
add-html-class混合宏,接收目标类名作为参数 - 使用
selector-parse(&)[0]解析当前父选择器的首个节点,判断是否为html - 若父选择器已是
html,则直接在其后方追加传入的类;否则生成html.类 &的嵌套选择器 - 原有的
one和two混合宏改为调用该通用宏,传入对应类名即可
编译后得到的CSS结果完全符合预期:
div { background: green; } html.one div { background: blue; } html.one.two div { background: yellow; }
即使调换混合宏的嵌套顺序,比如先调用two再调用one:
div { background: green; @include two() { background: orange; @include one() { background: purple; } } }
编译后依然会自动合并html标签上的类:
div { background: green; } html.two div { background: orange; } html.two.one div { background: purple; }
内容的提问来源于stack exchange,提问作者jor
相关产品推荐
相关产品推荐

