LESS CSS nesting classes - css

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.

Related

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.

How to reference multiple sub-classes on the same element with SASS

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
}
}
}

Nesting CSS classes

Can I do something like the following?
.class1{some stuff}
.class2{class1;some more stuff}
Update 1: There is a CSS3 spec for CSS level 3 nesting. It's currently a draft.
https://tabatkins.github.io/specs/css-nesting/
Update 2 (2019): We now have a CSSWG editors draft
https://drafts.csswg.org/css-nesting-1/
Update 3 (2022): We now have a W3C First Public Working Draft https://www.w3.org/TR/css-nesting-1/
If approved, the syntax would look like this:
table.colortable {
& td {
text-align:center;
&.c { text-transform:uppercase }
&:first-child, &:first-child + td { border:1px solid black }
}
& th {
text-align:center;
background:black;
color:white;
}
}
.foo {
color: red;
#nest & > .bar {
color: blue;
}
}
.foo {
color: red;
#nest .parent & {
color: blue;
}
}
Not possible with vanilla CSS. However you can use something like:
Sass
Sass makes CSS fun again. Sass is an
extension of CSS3, adding nested
rules, variables, mixins, selector
inheritance, and more. It’s translated
to well-formatted, standard CSS using
the command line tool or a
web-framework plugin.
Or
Less
Rather than constructing long selector
names to specify inheritance, in Less
you can simply nest selectors inside
other selectors. This makes
inheritance clear and style sheets
shorter.
Example:
#header {
color: red;
a {
font-weight: bold;
text-decoration: none;
}
}
Not with pure CSS. The closest equivalent is this:
.class1, .class2 {
some stuff
}
.class2 {
some more stuff
}
Not directly. But you can use extensions such as LESS to help you achieve the same.
No.
You can use grouping selectors and/or multiple classes on a single element, or you can use a template language and process it with software to write your CSS.
See also my article on CSS inheritance.
I do not believe this is possible. You could add class1 to all elements which also have class2. If this is not practical to do manually, you could do it automatically with JavaScript (fairly easy to do with jQuery).
If you cannot wait until native CSS nesting goes official, you can use Container Queries to do it. As of now, it is supported (partially) by Chrome & Edge 105+, as well as Safari 16+.
It will looks like this:
.class1 {
container-type: inline-size;
container-name: my-container;
// other style rules
}
#container my-container (min-width: 0px) {
.class2 {
// some style rules
}
}
More details can be found at here.
Try this...
Give the element an ID, and also a class Name. Then you can nest the #IDName.className in your CSS.
Here's a better explanation
https://css-tricks.com/multiple-class-id-selectors/

Resources