Kilian Valkhof
Posted on May 3, 2023
Most developers prefer to keep all their CSS custom properties in one place, and a pattern that has emerged in recent years is to put those on :root
, a pseudo-element that targets the topmost element in your document (so that's always <html>
on web pages). But just because they're in one place and in the topmost element, it doesn't mean they're global.
I first encountered this issue with ::backdrop
: Backdrop doesn't inherit from anywhere but after a recent rendering engine update to Polypane I noticed that all my custom selection colors (also powered by CSS custom properties) suddenly stopped working.
Turns out, ::selection
is also not supposed to inherit styles, and Chromium 111+ is running an experiment to see what effect changing that has. Polypane runs with experimental features turned on, and so my selection styles became broken.
This is going to catch a lot of people off-guard because I, like many others, expect CSS Custom properties defined on :root
to just be available everywhere. I guess I would also expect ::selection
and ::backdrop
to inherit from their "parent" element to allow more dynamic styling, but the spec writes apparently don't want this.
So if :root
isn't global, what is?
Well, the jury's still out.
Discussions are happening in this GitHub issue: Custom properties on :root with a few options being discussed:
- Use @property with an initial value (not cross-browser supported yet, only uses the initial value).
- Make
:root
special. - Create a new
:document
pseudo-element that does propagate custom properties. - Create an new at-rule called
@global
,@root
or@document
that you could define custom properties in. - Make
::selection
etc inherit from their originating element (e.g. "their parent").
That last item would solve both the problems people run into (it not inheriting, and it potentially inheriting directly from :root
so you can't overwrite custom properties in the cascade). I hope spec writers choose to do this regardless.
Specifically, I want/expect this to work:
p {
--selection-bg: #0f0;
&::selection {
background: var(--selection-bg);
}
}
When it comes to "a place to store global variables" I have no strong opinion, though I think it's interesting to keep in mind that in JavaScript there is now window
, global
and globalThis
because the naming across contexts didn't work.
In that light, :document
or @document
seem potentially problematic. For that reason, I like @global
or :global
(I haven't actually seen global as a pseudo-element suggested yet, but it seems to be closest to how people expect things to work now).
In the mean time, you can use the suggestion I made in my ::backdrop
post and replace :root
with :root ::backdrop ::selection
. Sorry about that.
Posted on May 3, 2023
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.
Related
November 27, 2024