Correct usage of &. in SCSS - css

What is the correct usage of &. in SCSS
In an SCSS file, what is the difference when you are using &. instead of .
.text-field {
.loading {
-----
}
&.error {
------
}
}

& will join whatever follows it to the parent class.
In your example, it means &.error will evaluate to .text-field.error - styles that will be applied to any elements with both the text-field and error classes.
the .loading class however will evaluate to .text-field .loading - so elements with the loading class that have a parent element with the text-field class.
you can use & without the . as well, for example:
.text-field {
&--loading {
// styles
}
}
will evaluate to a single text-field--loading class.

If you use
&.error
The css is compiled as:
.text-field.error
While if you do not use & (as in your loading example) the compiled result is:
.text-field .loading
Which means the in the first example you are expecting the error class on the same 'parent' dom element, while in the latter you expect a child inside which is supposed to have the class loading.
So, there is no correct usage, it is a matter of what you want to achieve.

The above answers are good, but limited.
The use can be of other means.
Consider using the ampersand also to qualify context like so:
.child {
.parent &{
}
}
// gives .parent .child
This can also be used multiple times, while not rarely helpful and readable, this is still valid:
.child {
& &{
}
}
// gives .child .child
But can become nice with lists:
.a,.b{
& + &{
}
}
// gives .a + .a, .a + .b, .b + .a, .b + .b

Related

Increase specificity weight with double selector via Sass

As mentioned here on Stack Overflow in another question and MDN tells about the specificity of selectors, I want to slightly increase the weight of my selector via Sass to override some existing styles. Here's an example of the (compiled) CSS.
.parent .parent__child.parent__child { color: red; }
It is more specific than just using .parent .parent__child as a selector.
I have a way to do this via Sass, but I think there should be a better way to do this:
.parent {
&__child.parent__child { color: red; }
}
Ideally, this would be the best possible setup (the ampersands have to be directly attached to each other since it's not a child selector):
.parent {
&__child&__child { color: red; }
}
This throws an error and adds a dot between the 'child' selectors. The Sass documentation doesn't say anything about this particular case. Any ideas on how to achieve this?
edit
I know about the interpolation brackets method, but what if the selector is more profound than three or four layers deep? I only want its parent selector to be duplicated, not the whole selector tree.
There's a special trick in SASS for doubling specificity using interpolation brackets (more on that here and here) since two &'s next to each other is invalid SASS syntax.
.parent {
&__child {
&#{&} {
color: red;
}
}
}
// compiles to
// .parent__child.parent__child { color: red; }
// You can also do this with deeper nested elements by
// prefacing the interpolation with the ancestor selectors:
.parent {
&__child {
.some .ancestor .elements &#{&} {
color: red;
}
}
}
// compiles to
// .some .ancestor .elements .parent__child.parent__child { color: red; }
For those of you who stumble upon this and use LESS, double &&'s are allowed:
.parent {
&__child {
&& {
color: red;
}
}
}

control nested mixin behavior based on parent mixin

Here are two mixins
#mixin parent {
.parent & {
#content;
}
}
#mixin child($child) {
.#{$child} & {
#content;
}
}
Both mixin works fine independently.
Things which am looking for:
child can be independent
Also child mixin can be included in parent but opposite
should not be allowed.
In case someone tries to include parent into child there should
be some error message.
In css output .parent should come before .child(see example below for this point)
Point 4 example:
.test {
//some css properties
#include parent {
#include child(childboy) {
color: red;
}
}
}
as you can see this will give following output
.childboy .parent .test {
color: red;
}
As you can see .parent class is coming after .childboy.
How can we make it .parent class to come before .childboy
.parent .childboy .test {
color: red;
}
Is it possible to do with scss??
Please answer only in scss.
Thank you.
I don't think you can do it that way.
Check out this CSS-tricks post:
The & doesn't allow you to selectively traverse up your nested
selector tree to a certain place and only use a small portion of the
compiled parent selector that you want to use.
If I understand correctly, the reason why you're trying to do this with SCSS is because you want to group the .parent .childboy .test selector within .test root selector.
Here's a different way to do this with SASS:
.test {
#at-root .parent .childboy & {
color: red;
}
}
Codepen demo
Note: the trailing & appends the selectors from root downwards - here, just the .test class
From the SASS docs:
The #at-root directive causes one or more rules to be emitted at the
root of the document, rather than being nested beneath their parent
selectors.

Less cascading & refactoring

I am trying to refactor some css looking like this:
path.myClass {
//some CSS
}
.someOtherClass.myClass {
//some other CSS
}
I am struggling to find the right syntax for the first part. I am trying to have something looking like this:
.myClass {
path.& {
// some CSS
}
.someOtherClass {
// some other CSS
}
}
How can I refactor this correctly?
You can do it like below. Since the top level selector already has . there is no need to add it again before the parent selector (&) in the inner selector. The second one is fairly straightforward as you can append the parent selector either at the start or at the end. The order of classes doesn't matter.
(Note: There should be no space before the parent selector as it would change the meaning.)
.myClass {
path&{
color: red;
}
.someOtherClass& { /* can do &.someOtherClass also, order doesn't matter */
color: blue;
}
}
Below is the compiled CSS output:
path.myClass {
color: red;
}
.someOtherClass.myClass {
color: blue;
}

Sass back nesting issue

I'm trying to figure out how to back nest specifically to the parent of the css nest I'm in. Meaning, my current set up is a parent class to a span to a before pseudo. I need to change a style on the pseudo based on a modifier on the parent. If I do this:
.parent {
span {
&:before {
// styles
.modifier & {
// Other styles
}
}
}
}
The output is .modifier .parent span:before What I need is .parent.modifier span:before
Isn't there a way to do this without adding the modifier to the parent and pathing to the pseudo again? This is what I want to avoid.
.parent {
span {
&:before {
// styles
}
}
&.modifier {
span {
&:before {
// Other Styles
}
}
}
}
This is certainly possible, it does require the use of some of the less known sass functions #at-root, & ampersand and string interpolation #{}.
Basically it works in the following manner;
Use #at-root to jump outside of the class, to the 'root'.
We place our class after that, I've used .--modifer-is-red.
We attach the classes that we jumped outside of by using interpolation of the &, #{&}.
Live Example
Example used for clarity
.parent {
span {
&:before {
// styles
color: black;
// Modifiers attached to the parent
#at-root .--modifier-is-red#{&} {
color: red;
}
}
}
}
// output
// .--modifier-is-red.parent span:before {
// color: red;
// }
Exact example to reflect your code
.parent {
span {
&:before {
// styles
#at-root .modifier#{&} {
// Other styles
}
}
}
}
There is some limitations to this, also it does look slightly odd that the modifier is placed before the parent in the output, but the browser doesn't mind.
I hope this solves your problem.
Isn't there a way to do this without adding the modifier to the parent and pathing to the pseudo again?
No, because you only have the & variable to work with, which is always a single unit consisting of the entire complex selector. You can't specify where exactly in the middle of the complex selector you want your modifier to go. The best you can do is attach it as a compound selector or use it with a combinator.

LESS CSS nesting classes

I'm using LESS to improve my CSS and am trying to nest a class within a class. There's a fairly complicated hierarchy but for some reason my nesting doesn't work.
I have this:
.g {
float: left;
color: #323a13;
.border(1px,#afc945);
.gradient(#afc945, #c8da64);
.common;
span {
.my-span;
.border-dashed(1px,rgba(255,255,255,0.3));
}
.posted {
.my-posted;
span {
border: none;
}
}
}
I can't get the .g.posted to work. it just shows the .g bit.
If i do this it's fine:
.g {
float: left;
color: #323a13;
.border(1px,#afc945);
.gradient(#afc945, #c8da64);
.common;
span {
.my-span;
.border-dashed(1px,rgba(255,255,255,0.3));
}
}
.g.posted {
.my-posted;
span {
border: none;
}
}
I'd like to nest the .posted in .g though. Any ideas?
The & character has the function of a this keyword, actually (a thing I did not know at the moment of writing the answer). It is possible to write:
.class1 {
&.class2 {}
}
and the CSS that will be generated will look like this:
.class1.class2 {}
For the record, #grobitto was the first to post this piece of information.
[ORIGINAL ANSWER]
LESS doesn't work this way.
.class1.class2 {} - defines two classes on the same DOM node, but
.class1 {
.class2 {}
}
defines nested nodes. .class2 will only be applied if it is a child of a node with the class class1.
I've been confused with this too and my conclusion is that LESS needs a this keyword :).
.g {
&.posted {
}
}
you should add "&" before .posted
If the ampersand is located right next to the child element in nesting, it is compiled into a double class selector. If there is space between & and selector it will be compiled into child selector. Read more about nesting in Less here.

Resources