Using Custom Properties to Modify Components

Avatar of Robin Rendle
Robin Rendle on

Instead of using custom properties to style whole portions of a website’s interface I think we should use them to customize and modify tiny components. Here’s why.

Whenever anyone mentions CSS custom properties they often talk about the ability to theme a website’s interface in one fell swoop. For example, if you’re working at somewhere like a big news org then we might want to specify a distinct visual design for the Finance section and the Sports section – buttons, headers, pull quotes and text color could all change on the fly.

Custom properties would make this sort of theming easy because we won’t have to add a whole bunch of classes to each component. All we’d have to do is edit a single variable that’s in the :root, plus we can then edit those custom props with JavaScript which is something we can’t do with something like Sass variables.

A while back Chris wrote about this use case in a post about custom properties and theming and the example he gave looked like this:

:root {
  --mainColor: #5eb5ff;
}

header {
  background: var(--mainColor);
}

footer {
  background: var(--mainColor);
}

See the Pen Theming a site with CSS Custom Properties by Chris Coyier (@chriscoyier) on CodePen.

But the more I learn about building big ol’ systems with CSS, the more I think that changing global styles like this is really difficult to keep the code clean and consistent over the long haul. And if you’re working on any large web app then you’re probably using something like React where everything is made of tiny reusable components anyway, especially because at this scale the cascade can be scary and dangerous.

If we’re working on larger, more complex systems then how should we be using custom properties then? Well I think the best option is to keep them on the component level to help make our CSS really clean. So instead of adding variables to the root element we could bind them to the component instead, like this:

.btn {
  --btnColor: #5eb5ff;
}

After which we could set properties such as color or border to use this variable:

.btn {
  --btnColor: #5eb5ff;
  border: 1px solid var(--btnColor);
  color: var(--btnColor);
  
  &:hover {
    color: white;
    background-color: var(--btnColor);
  }
}

So far so good! We can then add modifier classes that simply change the value of the custom property:

.btn-red {
  --btnColor: #ff6969;
}

.btn-green {
  --btnColor: #7ae07a;
}

.btn-gray {
  --btnColor: #555;
}

See the Pen Custom Properties by Robin Rendle (@robinrendle) on CodePen.

See how nice and tidy that is? With just a few lines of CSS we’ve created a whole system of buttons – we could easily change the font-size or add animations or anything else and keep our classes nice and small without messing with the global scope of our CSS. Especially since all this code is likely to live in a single file like buttons.scss it’s helpful that all the logic exists in one place.

Anyway, for sure this method of using custom properties on a component level isn’t as exciting or stylish as using a single variable to style every part of a website but I’m not entirely sure how useful that sort of theming is anyway. A lot of the time a design will require a bunch of tiny adjustments to each component for usability reasons so it makes sense to break everything down to the component level.

What do you think is the most useful thing about custom properties? I’d love to hear what everyone thinks about this stuff in the comments below.