在 Sass 中修改选择器的中间(添加/删除类等) [英] Modifying the middle of a selector in Sass (adding/removing classes, etc.)
问题描述
我的菜单中有以下用于样式链接的 SCSS:
I have the following SCSS for styling links in my menu:
nav {
ul {
li {
a {
color: red
}
}
}
ul.opened {
li {
a {
color: green
}
}
}
}
这会生成以下(正确的)CSS:
Which generates the following (correct) CSS:
nav ul li a {
color: red;
}
nav ul.opened li a {
color: green;
}
我尝试修改我的 JavaScript 以将类应用于导航元素,并在 Sass 中使用 selector-append()
来附加类.但这似乎以错误的顺序进行附加(如果参数颠倒,则将类附加到最后一个元素!):
I tried modifying my JavaScript to apply the class to the nav element instead, and use selector-append()
in Sass to append the class. But that seems to do the appending in the wrong order (and if the arguments are reversed, the class is appended to the last element!):
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,以便正确附加类而无需复制选择器(类似于 selector-append()
方法)?
Is there a way the SCSS can be rewritten so that the class can be correctly appended without having to duplicate selectors (similar to the selector-append()
method)?
推荐答案
简答
由于我们要替换的元素有一个唯一的名称,所以我们要查找的是:
The short answer
Since the element we want to replace has a unique name, what we're looking for is this:
nav {
ul {
li {
a {
color: red;
@at-root #{selector-replace(&, 'ul', 'ul.opened')} {
color: green;
}
}
}
}
}
长答案
操作选择器是非常肮脏的,除非你绝对必须这样做,否则我建议不要这样做.如果您通过指定诸如 table tr td
或 ul li
之类的内容来过度限定选择器,那么首先要简化:tr 和 ul 在这些选择器中都是多余的(除非您重新尝试避免在有序列表下设置样式元素).调整你的嵌套更简单,等等.
The long answer
Manipulating selectors is extremely dirty, and I would advise against it unless you absolutely had to. If you're overqualifying your selectors by specifying things like table tr td
or ul li
, then start by simplifying: tr and ul are both redundant in these selectors (unless you're trying to avoid styling elements under an ordered list). Adjust your nesting to be simpler, etc.
从 Sass 版本 3.4 开始,有 2 个重要功能允许您修改选择器.
Starting with Sass version 3.4, there are 2 important features that allow you to modify selectors.
- 选择器函数
- 父选择器可以存储在变量中
例子:
.foo ul > li a, .bar {
$sel: &;
@debug $sel;
}
你总是会得到一个字符串列表,因为选择器可以用逗号链接在一起,即使你只有一个选择器.
You'll always get a list of list of strings because selectors can be chained together with a comma, even when you have only one selector.
.foo ul > li a, .bar { ... }
(1 2 3 4 5), (1)
您会注意到这里计算了后代选择器(Sass 中的列表可以是空格或逗号分隔).记住这一点非常重要.
You'll note that the descendant selector is being counted here (lists in Sass can be either space or comma delimited). This is extremely important to remember.
selector-replace()
函数在以下情况下不起作用:
The selector-replace()
function does not work in the following cases:
- 您要替换的选择器不是唯一的(例如.
ul ul li
) - 您要插入一个或多个选择器(例如.
ul ul li
->ul ul ul li
) - 你想移除一个选择器(例如
ul > li
->ul li
)
- The selector you want to replace is not unique (eg.
ul ul li
) - You want to insert one or more selectors (eg.
ul ul li
->ul ul ul li
) - You want to remove a selector (eg.
ul > li
->ul li
)
在这种情况下,您需要遍历选择器,并且需要知道要修改哪个位置.以下函数将使用 call() 函数.
In this case, you'll need to loop over the selectors and you'll need to know which position you want to modify. The following function will take a function and apply it to a specific position in your selector using the magic of the call() function.
@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;
}
Append a class (when the selector isn't unique or you don't know its name)
我们这里需要的函数有 2 个参数:原始选择器和您想要附加到它的选择器.使用简单的插值来完成这项工作.
Append a class (when the selector isn't unique or you don't know its name)
The function we need here takes 2 arguments: the original selector and the selector you'd like to append to it. Uses simple interpolation to do the job.
@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;
}
插入选择器
此函数还接受 2 个参数:原始选择器和您要在其之前插入的选择器.
Insert a selector
This function also takes 2 arguments: the original selector and the selector you'd like to insert before it.
@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;
}
移除一个选择器
删除选择器就像用空字符串替换选择器一样简单.
Remove a selector
Removing a selector is as simple as replacing your selector with an empty string.
@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
选择器只是一个列表.任何列表操作函数都可以使用它,您可以循环访问它以根据需要对其进行修改.
TL;DR
Selectors are just a lists. Any list manipulation functions will work on it and you can loop over it to modify it as necessary.
是的,除非您真的真的需要,否则不要这样做.如果您决定仍然需要它,我已将这些函数打包到 selector-nth 库中一个>.
So yeah, don't do it unless you really really really need to. If you've decided you still need it, I've packaged these functions up into the selector-nth library.
这篇关于在 Sass 中修改选择器的中间(添加/删除类等)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!