如何单行列出Sass Map/List所有值以生成连续:not()选择器
问题原因
你之前的写法不生效有两个核心问题:
- 你定义的
$text-type-map实际是Sass列表(List)而非映射(Map),调用map-keys()方法本身就不匹配数据类型 - 你没有使用
#{}插值语法解析Sass变量/方法的返回值,直接把Sass代码写在CSS选择器位置不会被自动编译
解决方案1:兼容所有浏览器的连续:not写法
可以通过循环拼接选择器片段的方式生成你需要的连续:not()结构,完整实现代码如下:
// 文本类型列表,把后缀从map改成list避免语义混淆 $text-type-list: h1, h2, h3, h4, h5, h6, p, a, span, ul, li; // 示例阴影尺寸映射,可保留你自己的原有定义 $shadow-size-map: ( sm: 2px, md: 4px, lg: 6px ); $dark: #000; @each $name, $size in $shadow-size-map { // 原有文本元素text-shadow逻辑保持不变 @each $type in $text-type-list { #{$type}.shadow-#{$name} { text-shadow: 0 #{$size} rgba($dark, 0.5); } } // 拼接连续:not选择器 $not-selector: ""; @each $type in $text-type-list { $not-selector: $not-selector + ":not(#{$type})"; } // 给非文本元素设置box-shadow .shadow-#{$name}#{$not-selector} { box-shadow: 0 #{$size} rgba($dark, 0.5); } }
编译后会生成符合你预期的CSS结构:
.shadow-md:not(h1):not(h2):not(h3):not(h4):not(h5):not(h6):not(p):not(a):not(span):not(ul):not(li) { box-shadow: 0 4px rgba(0, 0, 0, 0.5); }
解决方案2:现代浏览器简化写法
现在所有现代浏览器都支持:not()选择器传入多参数,无需连续写多个:not(),代码可以大幅简化:
@each $name, $size in $shadow-size-map { // 原有文本元素text-shadow逻辑保持不变 @each $type in $text-type-list { #{$type}.shadow-#{$name} { text-shadow: 0 #{$size} rgba($dark, 0.5); } } // 直接用join方法把列表转为逗号分隔的字符串塞到:not里 .shadow-#{$name}:not(#{join($text-type-list, ", ")}) { box-shadow: 0 #{$size} rgba($dark, 0.5); } }
编译后生成的CSS更简洁:
.shadow-md:not(h1, h2, h3, h4, h5, h6, p, a, span, ul, li) { box-shadow: 0 4px rgba(0, 0, 0, 0.5); }
如果不需要兼容IE浏览器,优先使用该方案。
内容的提问来源于stack exchange,提问作者Calvin Bonner
相关产品推荐
相关产品推荐

