sass prepend root class to current selector - css

I am having trouble prepending the root class to my current selector in sass. I have the following code:
.cta-two-columns {
&__text-holder {
#at-root&#{__inner} {
// also tried #at-root __inner&{#}
// and many others like #at-root__inner
padding: rem(25px);
}
}
}
but this gives me the following:
.cta-two-columns__text-holder__inner {
padding: rem(25px);
}
I don't understand the above - what's the point of at-root as you may as well just do &__inneras it gave me the same as the two things I have shown I tried
how do I get
.cta-two-columns__text-holder .cta-two-columns__inner {
}
without having to resort to
.cta-two-columns {
&__text-holder {
.cta-two-columns__inner {
padding: rem(25px);
}
}
}
Or is this the only way to do it in sass?

#at-root doesn't really work like you may think in this case. #at-root will simply make the declaration outside the nest. To better understand, add another CSS declaration like below:
.cta-two-columns {
&__text-holder {
margin: 10px;
#at-root&#{__inner} {
padding: rem(25px);
}
}
}
This will produce the following CSS code:
.cta-two-columns__text-holder {
margin: 10px;
}
.cta-two-columns__text-holder__inner {
padding: rem(25px);
}
Simply imagine how the selector will be created without #at-root then make it outside.
Without it will produce this:
.cta-two-columns__text-holder {
margin: 10px;
}
.cta-two-columns__text-holder .cta-two-columns__text-holder__inner {
padding: rem(25px);
}
Then we simply omit .cta-two-columns__text-holder.
One idea to obtain what you want is to consider a variable where you can declare the main class then you will be able to nest as many element as you want:
$sel: '.cta-two-columns';
#{$sel}__text-holder {
#{$sel}__inner {
padding: rem(25px);
}
}
Will produce:
.cta-two-columns__text-holder .cta-two-columns__inner {
padding: rem(25px);
}
with more nested elements:
$sel: '.cta-two-columns';
#{$sel}__text-holder {
#{$sel}__outer {
#{$sel}__inner{
#{$sel}__wrap{
padding: rem(25px);
}
}
}
}
Will produce
.cta-two-columns__text-holder .cta-two-columns__outer .cta-two-columns__inner .cta-two-columns__wrap {
padding: rem(25px);
}

Related

scss prepending parent selector

I have a project where legacy code has classes like
promo game-promo
I've got the chance to clean up the css by changing to scss but the issue I'm trying to cover is I'd like to nest promo and have game- prepend the parent.
.promo {
display: flex;
game-& {
color: black;
}
}
I'd have liked the above to work but it doesn't and wondering if anyone has come across any ways of achieving what I'm after?
.game-promo {
color: black;
#at-root .promo {
display: flex;
}
}
It seems its not possible so after re-jigging the code I have now got this.
You can't do what you're trying. The "&" is used to get the current selector, in your case : game-.promo or .game-.promo if you add the class selector but it can't work.
In your case, you can do :
.game-promo {
color: black;
.promo {
display: flex;
}
}
Or rename your classes name : (I give an example with inverting the logic of your names)
Parent with ".promo"
Child with ".promo-game"
So you could do :
.promo {
//properties
&-game {
//properties
}
}
It is possible but not very pretty (code on jsFiddle):
/** see https://gist.github.com/Bamieh/912a6f0b63cbb53f3ad0bd8df7171c6a */
#function parse-dotless($class) {
$this: quote($class);
#return if(str-slice($this, 0, 1) == ".", str-slice($this, 2, str-length($this)), $this);
}
.promo {
color:yellow;
#at-root .game-#{parse-dotless(&)} {
color: blue;
}
}
<span class="promo">Hello</span>
<span class="game-promo">World</span>
You cannot do exactly what your snippet states using only the & feature. Instead you could build modifier classes like this:
.btn {
&-primary {}
&-secondary {}
}
Which is translated to:
.btn-primary {}
.btn-secondary {}
In your code example, you can invert the rule names:
.promo {
display: flex;
&-game {
color: black;
}
}
Read more about the sass-ampersand

Can I add a variable to a mixin function name in Less?

Is this possible to do in some way I don't know? I'm trying to add a variable in the mixin function name.
#mybar: Test;
.mymixin() {
padding: 10px;
}
.mymixin#{mybar}() {
padding: 10px;
}
.test {
.mymixinTest();
}
I think it should work if you do:
.myMixin(#myvar) {
.myMixin#{myvar} {
//your css
}
}

Playing with LESS - optimize css generated by passing ruleset to mixin

I'm just playing with LESS lately. I wanted to generate rules for elements with numeric ID. At some stage I got code like this:
#myRule: {padding: 0;};
.myLoop(#c, #rules) when (#c >= 0) {
.myLoop((#c - 1), #rules);
&[id*=#{c}] { #rules(); }
&[name*=#{c}] { #rules(); }
}
.myClass {
.myLoop(2, #myRule);
}
which compiles to
.myClass[id*=0] {
padding: 0;
}
.myClass[name*=0] {
padding: 0;
}
.myClass[id*=1] {
padding: 0;
}
.myClass[name*=1] {
padding: 0;
}
.myClass[id*=2] {
padding: 0;
}
.myClass[name*=2] {
padding: 0;
}
My question is: can I in any way make it compile to sth like this:
.myClass[id*=0],
.myClass[name*=0],
.myClass[id*=1],
.myClass[name*=1],
.myClass[id*=2],
.myClass[name*=2] {
padding: 0;
}
I was looking for something like 'extending mixins`, 'parametric extend' or 'extending ruleset' but all lead to issues that are either 'wontfix' or 'nice-to-have' :-) So I guess it's not yet possible, but I would just like to reach out to people more familiar with less then I am, to be sure.
Yes, neither extending parametric mixins nor scoped extend are possible currently, so the easiest method to achieve the result is to extend a dummy ruleset. E.g.:
.my-repeat(#i, #f) when (#i >= 0) {
.my-repeat((#i - 1), #f);
&[id*=#{i}], &[name*=#{i}] {#f();}
}
.my-class-style {
padding: 0;
}
.my-class {
.my-repeat(2, {
&:extend(.my-class-style);
});
}
where .my-class-style is the dummy selector to appear in the resulting CSS too.

Simplifying sass attribute selectors

I'm trying to come up with a way to simplify some SCSS attribute selectors. What I end up with is:
[data-attr="opt1"] { ... }
[data-attr="opt2"] { ... }
[data-attr="opt3"] { ... }
What I'm hoping for is to be able to write something closer to:
[data-attr]
&="opt1" { ... }
&="opt2" { ... }
&="opt3" { ... }
via a mixin, or whatever. Can't come up with a solution though. Any clever ideas?
I've come to this idea:
#mixin attrVal($value) {
$attr: str-slice(#{&}, 2, -2); // $attr = "data-attr"
#at-root {
[#{$attr}="#{$value}"] {
#content;
}
}
}
[data-attr] {
#include attrVal('opt1') { width: 10px; }
#include attrVal('opt2') { width: 20px; }
#include attrVal('opt3') { width: 30px; }
}
Output (tested on sassmeister.com)
[data-attr="opt1"] { width: 10px; }
[data-attr="opt2"] { width: 20px; }
[data-attr="opt3"] { width: 30px; }
For this specific example there's no that huge simplification, but with this approach you're actually decoupling the attribute name from its value (in the aim of code reuse).

Extending a Nested Placeholder in SCSS

Is it possible to #extend a SCSS placeholder with nesting, and have that nesting reflected in the resulting class?
Given a nested placeholder:
%my-form-field {
...
&__label {
...
}
&__feedback {
...
}
}
I currently have to do the following:
.one-of-many-targets {
#extend %my-form-field;
&__label {
#extend %my-form-field__label;
}
&__feedback {
#extend %my-form-field__feedback;
}
}
But I'd like to be able to simplify this to:
.one-of-many-targets {
#extend %my-form-field;
}
... and have it resolve to:
.one-of-many-targets { ... }
.one-of-many-targets__label { ... }
.one-of-many-targets__feedback { ... }
Is there a different way to write my placeholder and #extends to make the SCSS cleaner, as in the 2nd example?
You can use a mixin instead:
#mixin my-form-field() {
width: 10px;
&__label {
width: 20px;
}
&__feedback {
width: 30px;
}
}
.one-of-many-targets {
#include my-form-field();
}
will generate:
.one-of-many-targets {
width: 10px;
}
.one-of-many-targets__label {
width: 20px;
}
.one-of-many-targets__feedback {
width: 30px;
}
You could try use selector.append()
See: https://github.com/sass/sass/issues/2808#issuecomment-574413393
Also see more info why parent selector didn't work as you expect in extend-only selectors: https://github.com/sass/sass/issues/2262#issuecomment-291645428

Resources