CSS Variables and ::before/::after content


#1

Currently, it seems the following is not possible:

.x {
    --color: #3acfb6;
    background-color: var(--color);
}

.x::after {
    content: var(--color);
}

The reason is it produces content: #3acfb6 instead of content: '#3acfb6' — which makes sense.

However it seems there is no way to add quotes or otherwise convert --color to string within content: definition. Something similar is provided by attr(), but not by var(), which seems unfortunate.

I am not sure what would be the right solution here, but some way to do conversions would be very useful.


#2

Correct, there’s no way to convert between types of values like that. What’s the use-case? This looks like it’s just a debugging aid?


#3

Now that I think of it, practical scenarios might be limited, though color showing color would also be useful in a color swatch (but you could argue attr() is a better choice for that). My specific case case was an educational figure on sizing where I wanted to both show the sizes and apply the sizes – which is kind of a debugging scenario.

However I only just started using CSS vars, so not sure yet.


#4

I ran into this today as well. I had --width and --height variables for the size of a slide deck (for cases where you want to rehearse the exact resolution of the projector), and I wanted to display a box with these dimensions as well as text inside it (like 1024 × 768).

I can see a lot of cases where authors want to use numerical variables for CSS values and print them out too, and not all are debugging. OTOH, if we add concat(), then that could handle converting to a string too. Perhaps it could even be called string() instead of concat().


#5

Can you actually demonstrate a use-case for that outside of debugging, slide decks, or other hyper-niche cases that don’t appear on real public sites? I’m legitimately curious. :slight_smile:


#6

Any time your variables are real, useful data and not CSS values (which is the recommended practice), there are cases where you want to do this. Off the top of my head: A slider that displays its value and uses it for styling, a bar chart that displays the values on each bar and uses them for the heights of the bars, a pie chart that displays values on each slice etc. But even the niches you mention, keep in mind that the union of enough niches is not niche anymore :slight_smile:


#7

Slider is invoking JS to do the update; cleaner and better in general for the JS to just update real text content with the value (in addition to setting a variable). Same for charts - the values shouldn’t be in CSS generated content, they should be on the actual page. (And even then, the only way they’re possibly useful is if you’re doing a % and have your coordinate systems set up just right to use that % directly.)


#8

Do we actually have a real and clear cut answer about whether data/content that is in the markup in the form of attributes and should be visually presented to the user is best handled by JS creating actual DOM nodes for it as opposed to using CSS Generated content?

It doesn’t seem obviously wrong to me, but it doesn’t seem obviously right either.

EDIT: never mind. I skimmed the thread too fast, and assumed we were talking about stuff pulled out of attr().


#9

You’re saying a lot of shoulds here, but not backing any of them up with reasoning. People use generated content for these kinds of things since generated content existed. Is paving the cowpaths only useful as an argument when you like the cowpaths?


#10

Yeah, I’m saying these things because they agree with every piece of accessibility advice ever published. Don’t put significant content in your ::before/etc., even if it’s “easier”. In this case it isn’t even easier - the functionality doesn’t exist, and you’re asking for it to be added with the only examples given being ones that directly go against common guidance. Or, in the first example of the slider, where just adding another line to your already-existing event handler (which obviously exists, since it’s required to update the property) is just as easy, works today, and has better accessibility.


#11

Such accessibility advice exists from before it was specified that screen readers should read generated content.

Anyhow, here is a non-niche use case for you: Using variables in paths. Also, in SVG data URIs. Sure, that needs concatenation as well, but also conversion to string.


#12

For numerical values, this counter-based trick seems to work: https://jsfiddle.net/psuwgexq/


#13

Hi there! Here is a use case I ran into today:

I am trying to transition the color of dynamic text without painting the page. For this reason, I am not transitioning the color property of the element. Instead, I am transitioning the opacity of a pseudoelement that is overlaid on top of the element, to give the appearance that the text color has changed.

Because the content is dynamic, it is less convenient to specify a CSS class for each item.

The plan was to specify the value of a CSS Variable in JavaScript that is the content of the container. That way, the pseudoelement could reference that value as its content.

It’d be pretty cool if this worked. Or, if someone else has another idea on how to transition text color without painting the page, I’d love to hear more.

Thanks for reading!


#14

I don’t see a need for the concat() function. CSS concatenates strings if you put them next to each other. Example: https://codepen.io/textmonster404/pen/PeMmqO?editors=1100 Your string() function is a really good idea though. We need some way to convert variable types.


#15

A really good idea would be a convert() function.

.x::after {
    content: convert(var(--color) string);
}

#16

Ha, I wish. That’s special to the content property. It doesn’t work anywhere else where strings are accepted.