Skip to Content
CSS Layers & Variables: Advanced CSS Concepts

CSS Layers & Variables: Advanced CSS Concepts

Use Case; Making Themes.

Looking for advanced CSS concept tutorials? Just trying to understand what CSS Layers or CSS Variables are? Well, you found a great place to start! Welcome!

In this article, I discuss my project where I created two separate themes using CSS Variables and CSS Layers. Learn a practical use case to apply these concepts and commit them to memory.

The main goal of this article is to teach you how to design without relying on CSS specificity.

Estimated reading time: 10 minutes

Advanced CSS Concept: CSS Variables

CSS Variables allow you to create pre-defined CSS properties and assign their scope. When defining variables it’s important to consider how they can cut down on your development time in the future. Think about how they’ll allow you to make broad changes with minimal effort.

Variable Scope

One advanced css concept worth considering is how and when to apply the Variable Scope of CSS Variables. When defining the scope of your variables, you can set them to the :root object. That will ensure your variables can be used on all of the document’s elements.

css variable scoping infographic shows the variable color grn being assigned to both the root and container scopes. In the linked example, the green on root is a normal green, the green assigned to the container scope is lime green. Even though the variables are the same name, they have a different scope.

If you have variables that should only be used in certain contexts, for instance variables just for containers, then adjusting the scope of the variables to the .container class makes more sense. See an example of this scoping principal in action.

from the linked scoping project above, the container class has the color grn variable redefined as limegreen and that is being honored even though the root variable definition is below it.

Why Use CSS Variables?

CSS Variables allow you to set any CSS properties in an easy to iterate and easy to update format. IOW idiot proof. For instance, if I define the padding on all of my layout elements to be 4% I might later decide 4% is too much space. In that instance, I would have to go through my stylesheets and replace 4% wherever I find it. This is tedious and mind-numbing.

Instead, I can define a CSS Variable called --padding that equals 4% and use that. If I ever change my mind in the future, I only need to change the –padding value once. The value will be applied to the rest of my layout elements.

Looking for more ways to idiot proof your CSS? Check out my post about the biggest CSS Mistakes to avoid.

CSS Variables in a theme

Let’s consider this some more in the form of a design theme. For my project I want to have a masculine and feminine theme. I am going to be using background svg’s, images, border, font, and color styles to define each theme. Using CSS Variables, I can change the styles for all of my elements across the board.

I’ve also created variables for other things that I use more than once, (like padding and margins), in case I want to update them easily in the future. As you can see, utilizing this advanced css concept can cut down on code refinement and refactoring in the future.

Femme theme variables:

For my default femme theme I am assigning the styles’ scope to the :root element. This means these CSS variables can be applied to any element in the document where the style is applicable.

I’ve defined my variables in the last CSS Layer in the CSS section of my codepen. As you’ll soon find out, the order in which you define your CSS layers determines your styles’ precedence.

 /***
 The Femme theme variables:
 ****/
  :root {
  --full-width: 100%;
  --part-width: 40%;
  --quart-width: 26%;
  --two-per: 2%;
  --one-per: 1%;
  --light-color: white;
  --accent-color: hotpink;
  --font: 'Trebuchet MS', sans-serif;
  --border: 10px;
  --background-svg: url('data:image/svg+xml,%3Csvg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 56 28" width="56" height="28"%3E%3Cpath fill="%239C92AC" ...);
  }

Because I want this theme to be overwritten, I have placed it within a layer.

Masc Theme Variables

Instead of applying the masc theme in the CSS section, I’m assigning these variables dynamically outside of a layer, more about that here.

Below are my Masc Theme CSS Variables. I’m assigning these using the CSS All selector.

* {
    --light-color: #efefef;
    --accent-color: #333;
    --font: "Arial", sans-serif;
    --border: 0px;
    --background-svg: url('data:image/svg+xml,%3Csvg xmlns="http://www.w3.org/2000/svg" width="28" height="49" viewBox="0 0 28 49"%3E%3Cg fill-rule="evenodd"%3E%3Cg id="hexagons" fill="...');
}
}

Advanced CSS Concept: CSS Layers

Why use CSS Layers?

CSS Layers provide a modularity to your design system that can allow you to overcome frustrating issues that arise post launch. With normal CSS, the only way to overwrite styles is to use a more specific selector. Or as a last resort by using the !important directive (ewwww David).

With the advanced css concept of CSS Layers, you can create modules of CSS that will apply to elements under different contexts and you can also prevent writing hyper specific code or using !important when you don’t need to.

It is really, really easy to get confused about CSS Layers and take a scoping approach to using them, but that is not what CSS Layers is used for. Put another way, encapsulation and scope are generally tied to specific DOM-tree fragments, while layering should be available within and across fragments.

TLDR; don’t create one CSS layer for your post content container and one for your sidebar widgets. Instead use layering to define CSS modules for things like normalize.css, utility classes, and theme styling.

If you do need to separate styles by scope, instead use the CSS Variables concept I discussed previously here.

Using CSS Layers in a theme’s design

When it comes to theme-ing, CSS Layers provide you with a way to specify which styles to load and in what order. This is helpful especially if you have different stylesheets for different things.

For instance, you might have a utilities stylesheet that sets the padding, margins, and button properties to given class names. Utilities stylesheets are another css advanced concept. During development, you only need to add those class names to your HTML to see it magically styled in front of your eyes. You could use layers to define when to load utility stylesheets like Bootstrap and Tailwind to your project.

You might also have a special stylesheet that sets a theme for your project.

Scenario: Your theme stylesheet includes padding, margins and other properties set on the same class names as previously styled elements.

Problem 1: Normally, you would have to ensure that all of your elements in your theme stylesheet are more specific by adding their ancestor selectors to them.

Problem 2: You’d also have to be sure that the theme stylesheet is added last in the document’s source order.

Solution 1: By using CSS layers, you can override styled elements without having to change the specificity of an element.

Solution 2: With this advanced css concept, you can use shorthand in a style tag to define the layer precedence like this below. If you define this at the top of your head element, it won’t matter in what order you load your stylesheets 🎉 :

<style>@layer third-most, second-most, most-important;</style>

The Layers In Practice

When you first load my codepen here, you’ll see four total CSS layers applied to this site design. Layout (layer 0), Utilities (layer 1), typography (layer 2), and of course femmeTheme (layer 3).

Layout (Layer 0)

screenshot of the codepen example theme shows the layout layer 0 has styles applied for the body, header, logo, nav and more elements.

In the bottom layer I have defined the shape of the page, or in other words the layout. This layer is telling all of my elements where to be placed. If I want to redefine the layout of any of these elements later, it will be easy to do.

Utilities (Layer 1)

codpen theme shows the utilities layer 1 with classes like flex to define display flex and padding-two where the variable two-per is called on the padding style.

I’m using my utilities layer to define padding and display classes, as well as defining the look of my buttons. I can easily place the classes in my HTML to style my components while I code my content. If I ever want to override these styles, with layers it will be a cinch.

Typography (Layer 2)

codepen project shows the typography layer 2 with font family and size called on the all selector and properties for the h1 and small class elements

In the typography layer, I am setting up the whole document’s font properties, the H1 properties, and a utility class called “small”. This class will allow me to make fonts a smaller size more easily.

Finally, The Femme Theme (Layer 3)

If you open up the inspector tools in Chrome 99 and up and click on the “Toggle CSS layers view” button, you can see the order in which the browser is prioritizing these layers.

Learn more about the state of CSS Layers in 2022.

in the chrome inspector tools in front of the hov and cls buttons in the styles tab is a 'toggle css layers view' which allows us to see the layers and their order of precedence

Check out my post on navigating dev tools to level up your front end dev skills.

Defining the layer order – another advanced CSS concept

These layers mimic the order in which I defined them because that is how they are meant to work. One important thing to note is that styles not defined within a layer will take precedence to those defined within a layer.

You can see this in action once the button is clicked with how the mascTheme-Javascript-variable is inserted into the page. It’s simply a style tag that gets inserted at the beginning of the body tag.

Overwriting elements in the theme layer

In my femmeTheme layer, although the H1 element has properties defined in the typography layer, I don’t need to add a class name to my H1 element to overwrite the previous styles.

Similarly, I don’t need to add additional specificity to the header element to adjust the border-bottom property. The CSS layer does the work for me.

css styles for the h1 and header element that control color and border bottom properties

Switching the Theme using CSS Layers

I’m using Javascript to replace the images, and insert an internal stylesheet into the page. Open the Pen in Full View.

=> When you click the “Change Theme” button, you’ll see the site design change.

Everything from the background svg, background colors, accent color, font family H1 font size etc. changes when you click the button. Most of that is handled in the insertion of the Masc Theme stylesheet.

What’s really going on under the hood?

As you can see in the below image, I’ve used CSS Variables to re-define the properties already in use. I’ve also overwritten the H1 property a second time without having to adjust the specificity at all 😏.

a JS variable whose value is a string of HTML. A style tag with a comment and CSS variables being overwritten on the all selector

When the button is clicked, this stylesheet is inserted after the beginning of the body tag. This ensures that it will have more precedence than any of the layers that were defined before it.

Check out the full project here:

Conclusion

If you’re reading this, then by now you’ve learned some incredibly powerful advanced css concepts. You’ve learned how to utilize CSS Variables, and just how much they can come in handy. You’ve also seen a use case for CSS Layers & CSS Variables. Hopefully, this demonstrates how you can include these advanced techniques in your own projects. Ultimately, I hope you’ve learned how to make a design system that doesn’t rely on specificity or the dreaded !important statement.