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.
Related
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;
}
}
}
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.
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;
}
I'm using the SMACSS method of writing my SCSS code, and I have a subclass that I want to reference if it also has another subclass.
HTML
<div class="parent-class parent-class-subclass1 parent-class-subclass2">
SCSS
.parent-class {
&-subclass1.&-subclass2 {
//Styles here
}
}
Any idea how I can do this?
So, when parent element also has subclass1 && subclass2, apply styles?
#katniss.everbean Yes, but the way you wrote it makes you have to duplicate the code.
After searching around for a while I stumbled upon this solution that works perfectly by writing any & references after the first one like #{&}:
SASS
.parent-class {
&#{&}-subclass1#{&}-subclass2{
border: 1px solid red;
}
}
Compiles into (CSS)
.parent-class.parent-class-subclass1.parent-class-subclass2 {
border: 1px solid red;
}
I found it on the SASS GitHub page.
...and I have a subclass that I want to reference if it also has another
subclass.
So, when parent element also has subclass1 && subclass2, apply styles?
You only need one & to join the nested selector to the parent class as a sibling. Then write the two subclasses as a regular sibling selector (next to each other without a space in between to indicate they're both required sibling classes).
The SCSS would look like this:
.parent-class {
//some styles
&.parent-class-subclass1.parent-class-subclass2 {
//subclass styles
}
}
That's equivelant to the following CSS
.parent-class {
//some styles
}
.parent-class.parent-class-subclass1.parent-class-subclass2 {
//some other styles
}
To keep your modular naming structure and not have to write out the whole subclass name, you could try using wildcard selectors. I'm not sure it actually ends up looking any better than just writing out the whole class name though.
Here's a codepen that demonstrates:
http://codepen.io/anon/pen/vXKZYA
And the basic code in that pen for posterity:
<div class="parent-class parent-class-subclass1 parent-class-subclass2">
some text that has all the goods
</div>
.parent-class {
color: #0000ff;
&[class*="-subclass1"][class*="-subclass2"] {
font-size: 20px;
font-family: sans-serif;
}
}
you should do it like this
<div class="parent-class subclass1 subclass2">
.parent-class {
&.subclass1.subclass2 {
//Styles here
}
}
or you can even do it like this
.parent-class {
&.subclass1 {
//subclass1 Styles here
&.subclass2 {
//subclass1 & 2 Styles here
}
}
}
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.