Short answer
Since the element that we want to replace has a unique name, we are looking for:
nav { ul { li { a { color: red; @at-root
Long answer
Manipulating selectors is extremely dirty, and I would advise him to do it, unless you needed it. If you redefine your selectors by setting things like table tr td or ul li , then start with the simplification: tr and ul are redundant in these selectors (unless you try to avoid styling the elements in an ordered list). Adjust your nesting easier, etc.
Starting with Sass 3.4, there are two important functions that allow you to change the selector.
Example:
.foo ul > li a, .bar { $sel: &; @debug $sel; }
You will always get a list of string lists, because selectors can be associated with a comma, even if you have only one selector.
.foo ul > li a, .bar { ... } (1 2 3 4 5), (1)
You will notice that the descendant selector is counted here (lists in Sass can be either spaces or commas). This is very important to remember.
If selector-replace() not working
The selector-replace() function does not work in the following cases:
- The selector you want to replace is not unique (e.g.
ul ul li ) - Do you want to insert one or more selectors (e.g.
ul ul li → ul ul ul li ) - Do you want to remove the selector (e.g.
ul > li → ul li )
In this case, you will need to iterate over the selector, and you will need to know which position you want to change. 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; }
Add a class (when the selector is not unique or you do not know its name)
The function we need contains 2 arguments: the original selector and the selector you want to add to it. Simple interpolation is used to complete the task.
@function append-class($a, $b) { @return
Output:
.foo ul > li a, .bar ul > li a { color: red; } .foo ul > li.baz a, .bar ul > li.baz a { color: blue; }
Insert selector
This function also takes 2 arguments: the original selector and the selector that you want to insert before it.
@function insert-selector($a, $b) { @return $b $a; } .foo, .bar { ul > li a { color: red; @at-root
Output:
.foo ul > li a, .bar ul > li a { color: red; } .foo ul > .baz li a, .bar ul > .baz li a { color: blue; }
Delete selector
Removing the selector is as simple as replacing the selector with an empty string.
@function remove-selector($sel) { @return ''; } .foo, .bar { ul > li a { color: red; @at-root
Output:
.foo ul > li a, .bar ul > li a { color: red; } .foo ul > a, .bar ul > a { color: blue; }
TL; DR
Selectors are just lists. Any list manipulation functions will work on it, and you can iterate over it to change it as needed.
So yes, don't do this if you really really don't need to. If you decide what you still need, I have packaged these functions into the selector nth library .