When organizing my Much less CSS information in a multi-page net software (MPA), I usually have a folder stuffed with modules through which every .much less file represents a novel part. For essentially the most half, the order through which these modules are imported is irrelevant since they symbolize remoted definitions. The exception to this rule is the theming and design system modules. In an effort to work with the CSS cascade, it is essential that these design system modules be imported first such that different modules can override properties regionally with out having to fret about CSS selector specificity. Fortunately, Much less CSS makes this straightforward with its automated (default) deduplication of import paths.
For this exploration, I’m utilizing this bundle.json file:
{
"scripts": {
"construct": "lessc --glob ./src/principal.much less ./dist/principal.css"
},
"devDependencies": {
"much less": "4.2.0",
"less-plugin-glob": "3.0.0"
}
}
The much less bundle is the Much less CSS compiler; and the less-plugin-glob bundle permits me to make use of * and ** in my @import paths.
Now, think about my modules folder with the next .much less information (I am together with the content material of every file in a single snippet right here to be able to scale back the noise):
/* file: ./modules/a.much less */
.a::earlier than {
content material: "a" ;
}
/* file: ./modules/b.much less */
.b::earlier than {
content material: "b" ;
}
/* file: ./modules/c.much less */
.c::earlier than {
content material: "c" ;
}
/* file: ./modules/design-system.much less */
.design-system::earlier than {
content material: "Design System" ;
}
If my principal .much less file seemed like this:
@import "./modules/*.much less" ;
… then, compiling the CSS file will import every .much less file into my principal.css. The much less information will likely be imported in lexicographic order (ie, alphabetically) by file title. Which ends up in the next CSS output:
.a {
content material: "a";
}
.b {
content material: "b";
}
.c {
content material: "c";
}
.design-system {
content material: "Design System";
}
As you’ll be able to see, every file was imported in lexicographic order by file title. And, sadly, this places our design system content material on the very finish, which is problematic from an overrides perspective. Contemplate this HTML:
<h1>
Testing CSS Cascade
</h1>
<p class="design-system c"></p>
The intent right here is use the bottom kinds from .design-system after which override a few of these kinds with .c. Nonetheless, as a result of CSS cascade guidelines, rendering this HTML web page leads to the next output:
As you’ll be able to see, .c did not override the .design-system as a result of the .design-system was outlined final within the CSS file (and has the identical specificity).
To repair this, we will replace the primary .much less file to particularly import high-priority Much less CSS information first, earlier than executing our globbing import:
// In an effort to work with the cascade, we have to embody our design system definitions
// first. This manner, all different modules can devour after which override properties of the
// design system, even when the selector specificities are the identical (final one wins).
@import "./modules/design-system.much less" ;
// NOTE: The design-system will NOT BE included twice.
@import "./modules/*.much less" ;
As you’ll be able to see, each @import statements reference the ./modules/ folder. However, we’re explicitly importing the design-system.much less file first earlier than globbing the remainder of the ./modules/ folder. And, once we compile the CSS file this time, we get the next output:
.design-system::earlier than {
content material: "Design System";
}
.a::earlier than {
content material: "a";
}
.b::earlier than {
content material: "b";
}
.c::earlier than {
content material: "c";
}
This time, the design-system.much less file content material was positioned on the high of the compiled CSS output on account of our specific @import. And, most significantly, it wasn’t included a second time as a part of the *.much less globbing. It is because the Much less CSS compiler will not import the identical file twice (the default habits).
Now, if we go to render the earlier HTML web page, we get the next output:
This time, for the reason that design-system.much less file was included first, out c.much less file definition is ready to override the content material property.
This can be a slightly useful habits when the execution / import order of a small variety of .much less information is essential. It signifies that we might be specific about importing a number of information first after which simply brute-force globbing the remainder of the information with out having to fret about duplication. This retains life easy.
Epilogue on CSS Layers
Current releases of contemporary browsers are actually implementing CSS layers. CSS layers provides us extra management over the cascade specificity, whatever the order through which CSS properties are declared. I’ve by no means truly checked out this earlier than; however, let’s hack one thing collectively as a proof-of-concept.
In our design-system.much less file, let’s wrap the CSS property block in an @layer known as ds:
@layer ds {
.design-system::earlier than {
content material: "Design System" ;
}
}
Now, in our principal.much less file, as an alternative of explicitly together with this design-system.much less file first, we will simply declare the ds layer first:
@layer ds ;
@import "./modules/*.much less" ;
Once we compile our Much less CSS, we get the next CSS output:
@layer ds;
.a::earlier than {
content material: "a";
}
.b::earlier than {
content material: "b";
}
.c::earlier than {
content material: "c";
}
@layer ds {
.design-system::earlier than {
content material: "Design System";
}
}
This tells the browser to push the ds layer onto the layer stack instantly. Then, when the next design-system.much less block is executed, it’ll push kinds onto the already-defined ds layer. This places the ds layer above the “nameless” layer—that’s, the block of unlayered CSS in .a, .b, and .c—though the .design-system block continues to be outlined final.
And, once we run the above HTML with the layered CSS, we get the next output:
As you’ll be able to see, though our design-system.much less file was the final to be imported, the .c block was nonetheless capable of override the content material property as a result of it was declared in an nameless layer larger up within the layer stack.
This native layering stuff is fairly cool! Undoubtedly one thing value trying into.
Need to use code from this publish?
Try the license.
https://bennadel.com/go/4630

