CSS custom properties in generated content

Cassie posted a neat tiny lesson that she’s written a reduced test case for.

Here’s the situation…

CSS custom properties are fantastic. You can drop them in just about anywhere that a property takes a value.

Here’s an example of defining a custom property for a length:

:root {
    --my-value: 1em;
}

Then I can use that anywhere I’d normally give something a length:

.my-element {
    margin-bottom: var(--my-value);
}

I went a bit overboard with custom properties on the new Patterns Day site. I used them for colour values, font stacks, and spacing. Design tokens, I guess. They really come into their own when you combine them with media queries: you can update the values of the custom properties based on screen size …without having to redefine where those properties are applied. Also, they can be updated via JavaScript so they make for a great common language between CSS and JavaScript: you can define where they’re used in your CSS and then update their values in JavaScript, perhaps in response to user interaction.

But there are a few places where you can’t use custom properties. You can’t, for example, use them as part of a media query. This won’t work:

@media all and (min-width: var(--my-value)) {
    ...
}

You also can’t use them in generated content if the value is a number. This won’t work:

:root {
    --number-value: 15;
}
.my-element::before {
    content: var(--number-value);
}

Fair enough. Generated content in CSS is kind of a strange beast. Eric delivered an entire hour-long talk at An Event Apart in Seattle on generated content.

But Cassie found a workaround if the value you want to put into that content property is numeric. The CSS counter value is a kind of generated content—the numbers that appear in front of ordered list items. And you can control the value of those numbers from CSS.

CSS counters work kind of like variables. You name them and assign values to them using the counter-reset property:

.my-element {
    counter-reset: mycounter 15;
}

You can then reference the value of mycounter in a content property using the counter value:

.my-element {
    content: counter(mycounter);
}

Cassie realised that even though you can’t pass in a custom property directly to generated content, you can pass in a custom property to the counter-reset property. So you can do this:

:root {
    --number-value: 15;
}
.my-element {
    counter-reset: mycounter var(--number-value);
    content: counter(mycounter);
}

In a roundabout way, this allows you to use a custom property for generated content!

I realise that the use cases are pretty narrow, but I can’t help but be impressed with the thinking behind this. Personally, I would’ve just read that generated content doesn’t accept custom properties and moved on. I would’ve given up quickly. But Cassie took a step back and found a creative pass-the-parcel solution to the problem.

I feel like this is a hack in the best sense of the word: a creatively improvised solution to a problem or limitation.

I was trying to display the numeric value stored in a CSS variable inside generated content… Turns out you can’t do that. But you can do this… codepen.io/cassie-codes/p… (not saying you should, but you could)

Have you published a response to this? :

Responses

Martin Auswöger

I’m a little bit confused by your second “This won’t work” example. In my tests this worked in all major browsers: codepen.io/anon/pen/NJOyaY Did you mean numerical values instead? Like this: :root { —foo: 123 } .my-element::before { content: var(—foo) }

越智です

見てる。カスタムプロパティで設定した値をcontentプロパティで使うためにcounter-resetで指定してcounter()をかます。頭いい。/adactio.com/journal/14970

2 Likes

# Liked by jalbertbowdenii on Wednesday, March 20th, 2019 at 8:16pm

# Liked by Nico Schober on Thursday, March 21st, 2019 at 11:04am

Related posts

Who knows?

Had you heard of these bits of CSS? Me too/neither!

Workaround

Browsers and bugs.

Supporting logical properties

Using the CSS trinity of feature queries, logical properties, and unset.

Let’s get logical

Let me hear your blocky talk.

Faulty logic

CSS logical properties here, they just aren’t evenly distributed yet.

Related links

New CSS that can actually be used in 2024 | Thomasorus

Logical properties, container queries, :has, :is, :where, min(), max(), clamp(), nesting, cascade layers, subgrid, and more.

Tagged with

My Modern CSS Reset | jakelazaroff.com

I like the approach here: logical properties and sensible default type and spacing.

Tagged with

Can you feel the rhythm‽ · 13 March 2024

Adam makes a very good point here: the term “vertical rhythm” is quite chauvanistic, unconciously defaulting to top-to-bottom writing modes; the term “logical rhythm” is more universal (and scalable).

Tagged with

Light-DOM-Only Web Components are Sweet – Frontend Masters Boost

The main reason I’m so hot on Light DOM is that I find the styling story of Web Components using Shadow DOM annoying.

Tagged with

Shadow DOM is for hiding your shame

This is an excellent step-by-step walkthrough by Tess of creating a web component, with real thought given to what should be in the HTML (which will act as a fallback) and what’s better generated in the Shadow DOM (like buttons for interactivity).

This perfectly mirrors something Chris was saying in a recent episode of the Shop Talk Show:

I think of the image comparison one. That’s a classic example in Web component. What’s inside is just two IMG tags. That’s it. When it fails, you don’t want a weird div with little arrows on it being rendered on the page. That’s not doing anything because it has failed to load the JavaScript.

Tagged with

Previously on this day

14 years ago I wrote Reflection

A little bit of navel-gazing on this year’s geekout in Austin.

20 years ago I wrote Going up

My latest submission to the Mirror Project does quite a job at capturing the spirit of South by SouthWest.

20 years ago I wrote What's hot in Austin

Plenty of people have been writing about the contents of individual panels and presentations from South by SouthWest. I thought it might be interesting to give a broader overview and take a look at some recurring themes.

22 years ago I wrote No War On Monaghan

Let us hope that in the fog of war, no bombs intended for Iraq are used to bomb county Monaghan in Ireland.

23 years ago I wrote Pong: The Text-Based Game

There are many online emulators of classic arcade games.