A new approach to visibility utility classes based on CSS Variables

This post was inspired by a feature request published on our Nolt board. Since the launch of our Framework and Components library, we’ve welcomed all feedbacks and suggestions on how to improve them.

Luca asked if we could integrate a set of visibility classes, similar to what Bootstrap does. These utility classes are used to show/hide elements at specific breakpoints.

In this article, I’ll explain the method I’m developing for our framework, based on CSS Variables.

🎯 The goal

The primary goal of the display utility classes is toggling the visibility of an element at specific breakpoints. A classic example is hiding some controls on small devices, then showing them past a breakpoint using media queries.

🔍 The current solution

The solution implemented by most frameworks is creating a set of utility classes that allow you to change the value of the display property. In its bare bone form, these classes look like:

Because we can’t take for granted the display value we need is block, we need to include classes for all the display values we wish to include:

To confine a display utility class within a specific breakpoint, you need to add a media query and duplicate all the classes:

You’d have to do the same for all the breakpoints. Finally, it may be safer to add the !important rule to all the display classes. I’m not pasting the final code here for brevity (it’s a lot of classes!), but you can check the final result in this gist.

In HTML, you can use the display classes to hide an element and then toggle its visibility past a media query. Here’s an example:

This approach is totally fine and super easy to work with. The only downsides are 1) the number of utility classes that power it and 2) the idea of using utility classes at a molecular level in a system, like ours, mostly based on components.

🤹🏻‍♂️ A new approach based on CSS Variables

When I started working on the display classes for the CodyHouse Framework, my #1 goal was simplifying things. We’ve done the same for all the other parts of the framework (see Typography and Spacing). It was worth spending some time on this as well and see if we could introduce an alternative approach.

I started the process in reverse. What would look like the simplest approach to visibility classes in HTML? Something like this:

A system based on classes like the ones in the example above should be smart enough to know which display value apply. Because the value is not defined in the class, it should be defined on a component level in CSS. And that’s fine because our framework is not based on utility classes but components.

Let’s start populating our _visibility.scss file!

The obvious issue here is that the display value of the element is inline-block, while the value of the utility class is block. Remember we don’t want to create a new class for each display value. We need to find a way to abstract the display value. CSS Variables to the rescue! Let’s define a --display variable, then we can replace the display value at a component level with the variable:

This tweak has a significant impact! We’ve defined a fallback value for the display value (= block), then we can update this value on a component level by updating the variable itself.

To simplify things even further, let’s assume that the elements with the .display-- class are hidden by default. This makes sense in my opinion because if a .display-- class is applied, that means we want to toggle its visibility at some point. We can do that in CSS with the help of the following selector (target all classes that start with display--):

The last thing to do is replacing the block value of the utility classes with the --display CSS variable. Here we go!

A total of 57 lines vs the 249 lines of the previous approach, and more flexibility IMO! You’re not limited to a subset of display values: you can enter whatever value you want on a component level, and it will be propagated to the display utility classes 🙌.

Feel free to test this method on Codepen:

CodyHouse visibility classes on Codepen

One final tweak could be creating a mixin so that you don’t need to write two lines of code anytime you want to use this technique on a component level. Something like that:

⚠️ You won’t need the mixin if the display value is block because the default value of the variable is block.

This method also opens new possibilities. Think, for example, about the .is-visible and .is-hidden classes we’ve all used so often! These utility classes come with the same dilemma. What should be the display value of .is-visible? Should I create a different class for each display value? Not anymore!

🎉 Conclusion

We’re still in the process of testing this approach. Because we use the postcss-css-variables plugin, this method is supported in all modern browsers. In the browsers that don’s support CSS Variables, however, the variable won’t be updated on a component level (the plugin cannot do that), therefore the value of the --display variable will always be block. It’s a limitation, but the content remains accessible in all browsers.

If you have suggestions about how to improve this technique, please say! I’m all ears 👂

If you’ve enjoyed this article, you should definitely take a look at our Framework and Library of Components!