'sass merge selectors on ampersand
assuming I have an existing SASS rule like:
[dir] .foo {
background-image: ...;
// ... some more
}
And I want to add specific behaviors for ltr / rtl like:
[dir] .foo {
background-image: ...;
[dir='ltr'] & {
padding-right: ...;
}
[dir='rtl'] & {
padding-left: ...;
}
}
this would generate undesired css like:
[dir='rtl'] [dir] .foo {
padding-left: ...;
}
This will not match what I want.
Assuming I cannot change the parent selectors (due to specificity), is there any way I can write such nested selectors in a way that compiles to just [dir='rtl'] .foo {...}
for the nested elements?
Some resources about the ampersand: https://css-tricks.com/the-sass-ampersand/#aa-qualifying-based-on-context
Solution 1:[1]
There is no way that I know to merge selectors as requested.
As you're not allowed to change the parent selector, the only solution I see would be to use the @at-root
rule.
@at-root
The @at-root rule is usually written @at-root { ... } and causes everything within it to be emitted at the root of the document instead of using the normal nesting. It's most often used when doing advanced nesting with the SassScript parent selector and selector functions.
Definition on sass-lang.
Here is an example:
[dir] .foo {
$root: '.foo';
background-image: linear-gradient(black, white);
@at-root {
[dir=ltr] #{$root} {
padding-right: 1em;
}
[dir=rtl] #{$root} {
padding-left: 1em;
}
}
}
This will compile to:
[dir] .foo {
background-image: linear-gradient(black, white);
}
[dir=ltr] .foo {
padding-right: 1em;
}
[dir=rtl] .foo {
padding-right: 1em;
}
You could create a mixin to help you with that:
@mixin dir($dir: ltr, $selector: &) {
@at-root {
[dir=#{$dir}] #{$selector} {
@content;
}
}
}
[dir] .foo {
$root: '.foo';
background-image: linear-gradient(black, white);
@include dir(ltr, $root) {
padding-right: 1em;
}
@include dir(rtl, $root) {
padding-right: 1em;
}
}
Food for thougt
If you don't have to support internet explorer, you might want to check padding-inline-end
and padding-inline-start
properties.
They will free you from the need to have different rules for different directions.
padding-inline-end
The padding-inline-end CSS property defines the logical inline end padding of an element, which maps to a physical padding depending on the element's writing mode, directionality, and text orientation.
padding-inline-start
The padding-inline-start CSS property defines the logical inline start padding of an element, which maps to a physical padding depending on the element's writing mode, directionality, and text orientation.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 |