I keep finding myself re-remembering that everything is a moving target. It’s been a very long time since I’ve worked with straight CSS, only using it abstracted out through SASS or React. So I’ve missed most of the major enhancements to the spec and there’s much that can be done without a framework now.
One I just used was CSS Variables. I remember being extremely frustrated that CSS didn’t have variable support and doing all sorts of hacky thing to templatize my CSS, before turning to LESS and SCSS.
More recently, I was working in a pared-down environment and started to get really tired of copy-and-pasting the key theme colors. It also got annoying when I decided to edit to the scheme a little and had to remember which hex value was actually the one I wanted. This would be about the time I would have to burn the time to add a CSS processor to the build pipeline. So I was thrilled to find out that I didn’t have to.
CSS variables have been pretty available since 2016 and though the syntax is somewhat clunky, they work.
Defining a CSS variable
You can define a variable within a context. So if you wanted to define a variable that would only be available to elements with a specific class, you would do:
.my_special_class {
--text-color: #42403A;
}
Variable names are differenciated from property names with the --
prefix.
I feel this is a little awkward looking, but it’s also pretty conflict free in the broader CSS ecosystem.
You can also define CSS variables globally with the special :root
signifier.
:root {
--text-color: #42403A; /* Available to all elements */
}
Using a CSS variable
You can reference the variable with the var()
function. var()
also takes an optional second parameter to be the default.
.my_cool_component {
color: var(--text-color);
/* `--bg-color` is not defined, so the default #f1f1f1 will be used */
background-color: var(--bg-color, #f1f1f1);
var()
is not semantically aware, nor does it do anything special.
You can essentially think of it as doing a straight string replacement in the location it is specified.
CSS variables can also only been used in property values.
In other places it will be invalid syntax and ignored.
Utilizing the above for easier color management
A common need in this particular project was to use colors with varying opacities.
(Clearly this project is design by developer).
Since var()
is kinda text replacement, but also kinda not, so you can’t do color: var(--text-color)88;
.
What does work is specifying a color triple and using the rgb()
and rgba()
functions.
So if I wanted to be able to control the alpha channel, I’d have to write my css vars like the following.
:root {
--main-color: 66,64,58;
}
.text {
color: rgb(var(--main-color)); /* Use the color without an alpha channel */
border-color: rgba(var(--main-color, 0.8)); /* Add an alpha channel */
}
Why bother?
There are ways of accomplishing this goal, with arguably cleaner syntax, in the common tooling that would accompany a component framework. In my case, most of the CSS was trivial and this was the only template like feature I needed. Adding the overhead of more tooling was overkill.
For larger projects, there is inevitably going to be disagreements about which framework is best. CSS variables allow you to separate your branding from developer preferences and keep the user experience more cohesive. I’ve been through enough framework upgrades and enhancements to find pushing stuff into the native layers useful. It’s one less thing to worry about when making a change.
Did you like this content?
Related Posts:
SvelteKit testing with Vitest
When looking to write some tests for my new SvelteKit project I first turned to my old standby Jest. But it turns out that Vitest is a better alternative.
Showing the Right Data with Out-of-Order Responses in Javascript
Javascript is an asynchronous language, which means sometimes things don't happen in the order you expect. This pattern ensures that the right response is shown.
The Rise and Fall of a Personal Cargo-Cult
Cargo-cults are common when confronted with the unfamiliar and new. This is not that story. Instead this is a story about forgotten knowledge around a complex interaction.