Skip to Main Content
TWIL
CSS
HTML
Featured image for TWIL blog post illustrating dynamic CSS property updates with HTML integration for smarter, JavaScript-free styling.

Dive into the latest edition of TWIL, our weekly series that sparks curiosity and fosters continuous learning in the realm of software development. In this installment, Katie demystifies Dynamic Values with Inline Custom Properties in CSS. Witness how CSS var() function advancements create a new realm of possibilities, enabling effortless thematic changes and innovative styling without the heavy lifting of JavaScript. From tooltips with pseudo-elements to vibrant, customized progress bars, learn how HTML attributes and CSS custom properties team up to elegantly code an array of web components.

Dynamic Values with Inline Custom Properties in CSS

I’ve been trying for years to do clever things with the CSS attr() function and being able to dynamically set styling values via HTML attributes (without having to manipulate styles with JavaScript), but it has not been able to accomplish everything I’ve wanted it to do. I’ve recently learned that what I could not do with attr(), I can instead achieve with the clever use of CSS’s var() function instead.

attr()

This function can be really handy for pulling content from an element to use in it’s styling; something like a tooltip or popover that uses ::before or ::after pseudo-elements, for example, can pull the content value directly from the element if it’s defined there. For example:

<span class="list-title" separator=":">Here follows a list of things</span>

<!-- Or, a more useful example using Rails/ERB and variable content: -->
<span class="list-title" separator="<%= preferences.separator %>">
	<%= list.title %>
</span>
.list-title::after {
  content: attr(separator); 
  /* You can concat this too, like so:
  content: 'Hot Tip: ' attr(tooltip) ' ...JSYK';
  */
}

This, however, only works with strings. If you wanted to pull a value for use with a numeric property, for example (e.g., to dynamically set element widths for a horizontal proportion/progress bar), attr() won’t work for that.

var()

This function allows you to use custom properties, like variables, in your style definitions.

:root {
  --thing-color: #BADA55;
  --thing-size: 10em;
}

.thing {
  color: var(--thing-color);
  font-size: var(--thing-size);
}

The Special Sauce

While this has obvious benefits in use cases such as defining themes or simply reducing duplication, I had not considered the ability to define custom properties outside my CSS to then use within my CSS.

A quick example with simple progress bars:

<div class="progress-bar" style="--progress: 50%; --bar-color: #BADA55;"></div>
<div class="progress-bar" style="--progress: 25%; --bar-color: red;"></div>
<div class="progress-bar" style="--progress: 75%; --bar-color: green;"></div>
.progress-bar {
  height: 20px;
  background-color: var(--bar-color);
  width: var(--progress);
}

Approach one, where progress bar is set with both background color and width %

.progress-bar {
  background-color: var(--bar-color);
  height: 20px;
  position: relative;
  width: 100%;
}
.progress-bar::after {
  background-color: white;
  content: "";
  display: block;
  height: 100%;
  position: absolute;
  right: 0;
  width: calc(100% - var(--progress));
}

Approach two, a more complex (if admittedly contrived) setup to demonstrate that we can still use var() within calc() (etc.) to set the progress bar to the full color, then essentially cover the remaining % with an ::after pseudo-element.

With just the HTML and CSS (either approach produces the same visual result) above, we get this. I should have set a border or background on the whole body to prove that the bottom bar is 75% wide, but here we are.

Resources

  • CSS
  • HTML
Katie Linero's profile picture
Katie Linero

Senior Software Engineer

Related Posts

Image for TWIL post depicting ActiveRecord range query examples in Ruby on Rails, enhancing database search efficiency.
September 16, 2020 • Frank Valcarcel

TWIL 2020-09-11

This week’s TWIL features Katie’s guide to using new range syntax in ActiveRecord queries, revealing how to efficiently search databases in Ruby on Rails.

Featured blog post image of a Bash script in action, highlighting the use of automated linters for enhanced coding practices and learning.
July 6, 2023 • Frank Valcarcel

TWIL 2023-06-30

Learn this week how a bash function can optimize your coding workflow, automating linters and turning git commit prep into a valuable learning experience.