修改Sass中的选择器的中间(添加/删除类等) [英] Modifying the middle of a selector in Sass (adding/removing classes, etc.)

查看:143
本文介绍了修改Sass中的选择器的中间(添加/删除类等)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

  nav {
ul {
li {
a {
color:red
}
}
}

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

这会生成以下(正确)CSS:

  nav ul li a {
颜色:红色;
}
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;
}
}
}
}
}


$ b b

输出(不正确!):

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

有一种方法可以重写SCSS, (类似于 selector-append()方法)?

解决方案

简短的回答



由于我们要替换的元素有一个唯一的名称,我们正在寻找的是:

  nav {
ul {
li {
a {
color:red;

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


$ b b

长回答



操作选择器是非常脏,我建议反对,除非你绝对必须。如果你通过指定 table tr td ul li 来过度选择你的选择器,那么首先简化:tr和ul在这些选择器中都是多余的(除非你试图避免在有序列表下的样式元素)。



从Sass 3.4版开始,有两个重要功能可以让您修改选择器。





p>

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

你总是会得到一个字符串列表的列表,因为选择器可以链接以及逗号,即使只有一个选择器。

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


$ b b

你会注意到,后代选择器在这里被计数(Sass中的列表可以是空格或逗号分隔)。这是非常重要的。






selector-replace()不起作用



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


  • 您要替换的选择器不是唯一的(例如 ul ul li

  • 您要插入一个或多个选择器(例如 ul ul li - > ul ul ul li )

  • 您要移除选择器(例如 ul> li - > ul li



在这种情况下,您需要循环选择器你需要知道你要修改的位置。以下函数将使用函数并将其应用于选择器中的特定位置,使用 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;
}



追加类(当选择器不唯一时,知道其名称)



我们需要的函数有两个参数:原始选择器和要附加到它的选择器。使用简单插值来完成这项工作。

  @function append-class($ a,$ b){
@ return#{$ a}#{$ b};
}

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

@-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-selector($ a,$ b){
@return $ b $ a;
}

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

@-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;
}



删除选择器



删除选择器与用空字符串替换选择器一样简单。

  @function remove-selector($ sel) {
@return'';
}

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

@-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 < h1>

选择器只是一个列表。任何列表操作函数都可以处理它,你可以循环遍历它并根据需要修改它。



所以,不要这样做,除非你真的真的需要。如果您决定仍需要此功能,请将这些功能打包到 selector-nth library a>。


I have the following SCSS for styling links in my menu:

nav {
    ul {
        li {
            a {
                color: red
            }
        }
    }

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

Which generates the following (correct) CSS:

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

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;
                }
            }
        }
    }
}

Output (incorrect!):

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

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;
                }
            }
        }
    }
}

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.

Starting with Sass version 3.4, there are 2 important features that allow you to modify selectors.

Example:

.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)

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.


When selector-replace() doesn't work

The selector-replace() function does not work in the following cases:

  • 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)

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)

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;
        }
    }
}

Output:

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

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;
        }
    }
}

Output:

.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;
        }
    }
}

Output:

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


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.

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆