修改Sass中select器的中间(添加/删除类等)

我有我的菜单中的样式链接以下SCSS:

nav { ul { li { a { color: red } } } ul.opened { li { a { color: green } } } } 

其中生成以下(正确的)CSS:

 nav ul li a { color: red; } nav ul.opened li a { color: green; } 

我尝试修改我的JavaScript来将类应用于nav元素,并在Sass中使用selector-append()来追加类。 但是这似乎是以错误的顺序进行追加(如果参数颠倒过来,则该类将被追加到最后一个元素!):

 nav { ul { li { a { color: red; @at-root #{selector-append('.opened', &)} { color: green; } } } } } 

输出(不正确!):

 nav ul li a { color: red; } .openednav ul li a { color: green; } 

是否有一种方法可以重写SCSS,以便类可以正确追加而不必重复select器(类似于selector-append()方法)?

简短的回答

由于我们要replace的元素具有唯一的名称,因此我们要查找的是:

 nav { ul { li { a { color: red; @at-root #{selector-replace(&, 'ul', 'ul.opened')} { color: green; } } } } } 

长的答案

操作select器是非常肮脏的,我会build议反对它,除非你绝对必须。 如果通过指定table tr tdul li等选项来过度限定select器,则可以先简化:tr和ul在这些select器中都是多余的(除非您试图避免在有序列表下面使用样式元素)。 调整你的嵌套更简单等

从Sass版本3.4开始,有两个重要的特性允许你修改select器。

  • select器function
  • 父select器可以存储在一个variables中

例:

 .foo ul > li a, .bar { $sel: &; @debug $sel; } 

总是会得到一个string列表的列表,因为即使只有一个select器,select器也可以用逗号连接在一起。

 .foo ul > li a, .bar { ... } (1 2 3 4 5), (1) 

你会注意到后代select器正在计数(在Sass中的列表可以是空格或逗号分隔的)。 这是非常重要的记住。


selector-replace()不起作用时

在以下情况下, selector-replace()函数不起作用:

  • 您要replace的select器不是唯一的(例如, ul ul li
  • 你想插入一个或多个select器(例如, ul ul li – > ul ul ul li
  • 你想删除一个select器(例如, ul > li – > ul li

在这种情况下,您需要循环select器,并且需要知道要修改的位置。 下面的函数将使用call()函数的魔法将一个函数应用到select器中的特定位置。

 @function selector-nth($sel, $n, $f, $args...) { $collector: (); @each $s in $sel { $modified: call($f, nth($s, $n), $args...); $collector: append($collector, set-nth($s, $n, $modified), comma); } @return $collector; } 

附加一个类(当select器不是唯一的或者你不知道它的名字时)

我们在这里需要的函数需要2个参数:原始select器和select器,你想追加到它。 使用简单的插值来完成这项工作。

 @function append-class($a, $b) { @return #{$a}#{$b}; } .foo, .bar { ul > li a { color: red; @at-root #{selector-nth(&, -2, append-class, '.baz')} { color: blue; } } } 

输出:

 .foo ul > li a, .bar ul > li a { color: red; } .foo ul > li.baz a, .bar ul > li.baz a { color: blue; } 

插入一个select器

这个函数也需要2个参数:你想在它之前插入的原始select器和select器。

 @function insert-selector($a, $b) { @return $b $a; } .foo, .bar { ul > li a { color: red; @at-root #{selector-nth(&, -2, insert-selector, '.baz')} { color: blue; } } } 

输出:

 .foo ul > li a, .bar ul > li a { color: red; } .foo ul > .baz li a, .bar ul > .baz li a { color: blue; } 

删除select器

删除select器就像用空stringreplaceselect器一样简单。

 @function remove-selector($sel) { @return ''; } .foo, .bar { ul > li a { color: red; @at-root #{selector-nth(&, -2, remove-selector)} { color: blue; } } } 

输出:

 .foo ul > li a, .bar ul > li a { color: red; } .foo ul > a, .bar ul > a { color: blue; } 

TL; DR

select器只是一个列表。 任何列表操作函数都可以在它上面工作,并且你可以循环它来根据需要修改它。

所以是的,除非你确实需要,否则不要这样做。 如果你已经决定你还需要它,我已经将这些函数打包到select器的第n个库中 。