Is there a way in Sass to use the ampersand to select the immediate parent, rather than the parent selector of the entire group? For example:
.wrapper{
background-color: $colour_nav_bg;
h1{
color: $colour_inactive;
.active &{
color: red;
}
}
}
compiles to:
.wrapper h1{
color: grey;
}
.active .wrapper h1{
color: red
}
but what I actually want is:
.wrapper .active h1{
color: red;
}
Is the only option to write the SCSS like so?
.wrapper{
background-color: $colour_nav_bg;
h1{
color: $colour_inactive;
}
.active h1{
color: red;
}
}
The HTML looks like this:
<ul class="wrapper">
<li class="active">
<h1>blah</h1>
</li>
</ul>
As of this writing, there is no Sass selector for the direct parent instead of the root parent of an element. There is &
which (as you know) selects the root parent. There are also %
placeholder selectors which hides a rule until it's been extended.
Sass is open-sourced, so you could contribute a new "direct parent" selector.
You can work around this today with a mixin like this one:
@mixin if-direct-parent($parent-selector) {
$current-sequences: &;
$new-sequences: ();
@each $sequence in $current-sequences {
$current-selector: nth($sequence, -1);
$prepended-selector: join($parent-selector, $current-selector);
$new-sequence: set-nth($sequence, -1, $prepended-selector);
$new-sequences: append($new-sequences, $new-sequence, comma);
}
@at-root #{$new-sequences} {
@content;
}
}
Since the &
is essentially a list of lists, you can use list functions (nth, set-nth, join and append) to create the selector sequence you want. Then use @at-root
to output the new selector at root-level. Here's how you'd use it:
.grandparent-1,
.grandparent-2 {
color: red;
.child {
color: blue;
@include if-direct-parent('.parent') {
color: green;
}
}
}
Which will output:
.grandparent-1,
.grandparent-2 {
color: red;
}
.grandparent-1 .child,
.grandparent-2 .child {
color: blue;
}
.grandparent-1 .parent .child, .grandparent-2 .parent .child {
color: green;
}
You need to wrap @at-root content in {}
.wrapper {
h1 {
@at-root {
.wrapper .active h1 {
color: red;
}
}
}
}
I have often wanted to do what you're asking and its a no go. I heard you can do that sort of thing in Stylus however. But there is another thing you can try which is to use @at-root
to teleport outside of your nesting tree. For instance:
.wrapper{
h1{
@at-root .wrapper .active h1 {
color: red;
}
}
}
This should compile down to the following:
.wrapper .active h1 {
color: red;
}
The nice part is you keep your selector where it logically makes sense in the nesting structure for organizational purposes.