惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Know Your Adversary
Know Your Adversary
小众软件
小众软件
L
LangChain Blog
月光博客
月光博客
博客园 - Franky
Microsoft Azure Blog
Microsoft Azure Blog
Y
Y Combinator Blog
有赞技术团队
有赞技术团队
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
MongoDB | Blog
MongoDB | Blog
Recorded Future
Recorded Future
V
Visual Studio Blog
TaoSecurity Blog
TaoSecurity Blog
S
Schneier on Security
C
Cybersecurity and Infrastructure Security Agency CISA
P
Privacy & Cybersecurity Law Blog
T
Threat Research - Cisco Blogs
D
DataBreaches.Net
L
LINUX DO - 热门话题
C
Check Point Blog
F
Fortinet All Blogs
Hugging Face - Blog
Hugging Face - Blog
The Hacker News
The Hacker News
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
Microsoft Security Blog
Microsoft Security Blog
酷 壳 – CoolShell
酷 壳 – CoolShell
V
V2EX
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
The GitHub Blog
The GitHub Blog
P
Proofpoint News Feed
L
Lohrmann on Cybersecurity
博客园 - 司徒正美
T
Threatpost
P
Palo Alto Networks Blog
A
About on SuperTechFans
Spread Privacy
Spread Privacy
Engineering at Meta
Engineering at Meta
N
News | PayPal Newsroom
T
Tailwind CSS Blog
The Last Watchdog
The Last Watchdog
Blog — PlanetScale
Blog — PlanetScale
A
Arctic Wolf
量子位
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
博客园 - 聂微东
Google Online Security Blog
Google Online Security Blog
Google DeepMind News
Google DeepMind News
www.infosecurity-magazine.com
www.infosecurity-magazine.com
V
Vulnerabilities – Threatpost
H
Hacker News: Front Page

Matthias Ott

Hello Again, World This, Still Not for Everyone The Shape of Friction WeissKlang L1 – Punching Above Its Weight Continvoucly Morged Value Webspace Invaders To Affinity and Beyond The Mystery of Storytelling Amateurs! Echoes of Connection Linear() Is Not (That) Linear View Transitions: The Smooth Parts Adding AVIF and WebP Support to My Craft CMS Site Challenge Acoustic Room Treatment and Building Sound Panels, Part 1: Planning Play On Overshoot The HTML Output Element Listening Closely Compressed Fluid Typography The Lifeblood of the Web What Could Go Wrong? That’s My Rank Making Space CSS :is() :where() the Magic Happens Visual Regression Testing for External URLs With Playwright Jane Goodall’s Famous Last Words European Tech Alternatives 🇪🇺 Independent Type Foundry Advent Calendar – Day 24: NaN Independent Type Foundry Advent Calendar – Day 23: Typotheque Independent Type Foundry Advent Calendar – Day 22: 205TF Independent Type Foundry Advent Calendar – Day 21: HvD Fonts Independent Type Foundry Advent Calendar – Day 20: Frere-Jones Type Independent Type Foundry Advent Calendar – Day 19: Fontwerk Independent Type Foundry Advent Calendar – Day 18: Vectro Independent Type Foundry Advent Calendar – Day 17: Studio René Bieder Independent Type Foundry Advent Calendar – Day 16: R-Typography Independent Type Foundry Advent Calendar – Day 15: David Jonathan Ross Independent Type Foundry Advent Calendar – Day 14: Interval Type Independent Type Foundry Advent Calendar – Day 13: Newglyph Independent Type Foundry Advent Calendar – Day 12: Swiss Typefaces Independent Type Foundry Advent Calendar – Day 11: Sharp Type Independent Type Foundry Advent Calendar – Day 10: Colophon Foundry Independent Type Foundry Advent Calendar – Day 9: Commercial Type Independent Type Foundry Advent Calendar – Day 8: Letters from Sweden Independent Type Foundry Advent Calendar – Day 7: Lineto Independent Type Foundry Advent Calendar – Day 6: Ohno Type Company Independent Type Foundry Advent Calendar – Day 5: Milieu Grotesque Independent Type Foundry Advent Calendar – Day 4: TypeMates Independent Type Foundry Advent Calendar – Day 3: Klim Type Foundry Independent Type Foundry Advent Calendar – Day 2: Dinamo Independent Type Foundry Advent Calendar – Day 1: Grilli Type The Independent Type Foundry Advent Calendar 2022 A Conversation With ChatGPT ChatGPT, please explain websites in the words of William Shakespeare Transient Frameworks Leaving Twitter Behind Converting Your Twitter Archive to Markdown The Wrong Question It Wasn’t Written Syndicating Posts from Your Personal Website to Twitter and Mastodon Suspension None of Your Business Doing Our Part Patch That Package Brain Dump Generating Accessibility Test Results for a Whole Website With Evaluatory The CSS Cascade, a Deep Dive Updates About Updates How to Delete Your Commit History in Git Unblocking Your Writing Blocks, Part 2: I’m Not an Expert nor a “Thought Leader” Connections No Wrong Notes Better Options Design Debt Finite and Infinite Games Don’t Assume, Validate. Necessity Is the Ultimate Teacher One Egg Go Deep There Is No Secret Code Balancing Risk Blue Eyes, Brown Eyes The Shortcut Boomerang My RSS Feed Collection of Personal Websites Frequency The Illusion of Control The Decisions Journey Write It Down Nownownow Into the Personal-Website-Verse Considering the Opposite What is it for? Unlimited Bowling. Never done. We Are Team Internet. We Need to Save #NetNeutrality. Progressive Search Data loss (also) by JavaScript Books I Will Definitely Maybe Read in 2017 Starting to Write Notes
CSS Custom Properties Beyond the :root · Matthias Ott
Matthias Ott · 2023-04-20 · via Matthias Ott

Manuel asked:

Is there a good reason why we’re defining global custom properties on :root/​html and not on body?”

It’s a great question: Everybody just seems to define most of their global custom properties (aka CSS variables) on the :root selector without giving it a second thought – and so am I. But why :root?

The answer is that there is no real reason. It’s just a convention. Defining custom properties on the :root selector might make them look a bit more like global variables, because :root is the equivalent of the root element of your document. In HTML, this is the html element. In SVG, it is the svg element. But besides this potential gain of flexibility – in case you ever wanted to apply the same properties to different types of documents – there is no real technical benefit. You could just as well define all global custom properties on the body element and they would still work exactly the same way.

Sure, you would need to write your JavaScript in a slightly different way, if you wanted to work with your custom properties in JS. Instead of accessing them via the document root element like this:

getComputedStyle(document.documentElement).getPropertyValue("--color")

you would need to retrieve or set their values on the body element:

getComputedStyle(document.body).getPropertyValue("--color")

But this also is just a matter of preference.

Also, the fact that :root has a higher specificity than html might be interesting to know but also doesn’t really make a difference in practice.

The Limits of Inheritance #

So yes, there seem to be no real differences between using :root and body. And therefore, using :root, as it is the outermost element, seems to make the most sense. However, Manuel pointed me to the fact that because of how the CSS inheritance model works, using :root does not always guarantee that a custom property is indeed inherited into all elements. It doesn’t currently work for the ::backdrop pseudo-element, for example, which is the element behind elements in full screen mode like

, as well as for the ::selection pseudo-element that lets you style the parts of a document that a user has selected. In both cases, trying to use a custom property that has been defined on :root will prove fruitless. The CSS Working Group is discussing ways to solve this. But it is definitely an issue many people might not be aware of.

Avoiding :root Growth #

Regardless of those inconsistencies in inheritance and although we could also define them on , using the :root selector to define our global custom properties has become a common practice. But what’s really interesting to me is that by using this convention, we also seem to have become a bit complacent in the way we use custom properties. Because defining most or all of your custom properties on :root can also become a problem. Kevin Powell has written about this on CSS-Tricks: if you just use this single place for all your custom properties, you might be able to manage all the “settings” of your CSS in one place, but you will also lose a lot of flexibility. When building components, for example, it is important to design and code them in such a way that you can easily change the implementation or add or remove them without affecting the global code around them or even breaking other parts of the system. Globally defined local properties would make that a lot harder. There is just no reason to define local custom properties in :root that actually belong to individual components.

As Lea Verou noted in her brilliant talk CSS Variable Secrets at CSS Day last year, we are also still not leveraging the full potential of custom properties when it comes to their depth, meaning how many properties inherit or include values from other properties. Or, to put it in another way, we don’t put custom properties inside each other very often. One reason might be that we are still mostly treating CSS custom properties like constants. We mostly use them as replacements for fixed values that we only have to define in one central place, which often happens to be, you guessed it, :root. Leaving this habit behind, however, and understanding that custom properties can do so much more is the key to unlocking their full potential.

To give you just one example derived from Lea’s talk, you can use custom properties locally that are basically like private variables but based on a global variable. Sounds complicated? Imagine a simple button component with a background color stored in a global custom property:

/* tokens.css */
:root {
	--color: hsl(160, 100%, 75%);
}

/* button.css */
button {
  background-color: var(--color);
}

This would work well in general and would also inherit the color value nicely into the button component. In a design system (or a modular website), this is exactly what you want. However, it is always a good idea to provide a fallback for custom properties, also because the component would then still work well even without the --color property being defined. With a local custom property that is based on the global property but already has the fallback baked in, you maintain the flexibility of being able to manipulate the color from the outside of the component. At the same time, you make the implementation much more robust:

/* tokens.css */
:root {
	--color: hsl(160, 100%, 75%);
}

/* button.css */
button {
  --_color: var(--color, black)
  background-color: var(--_color);
}

If we now use the button component within a system that provides a --color, the button has a background in the color we defined. If not, the component still works and uses the fallback color, black, instead. Inside of our component, we can use the local custom property (written with an underscore, again a convention) to define hover styles, borders, box-shadows, and more. And, we can still manipulate or set the --color variable from the outside of our component without breaking it. As Lea puts it: CSS variables effectively allow us to create a higher-level styling API.

This is just one powerful example which shows that combining global with local properties can lead to much more flexible and robust CSS. So while it might be still a good idea to define your global custom properties on :root as a best practice, also try to think beyond that. You can use CSS custom properties everywhere all at once.

~

28 Webmentions

11 Reposts

12 Likes

ⓘ Webmentions are a way to notify other websites when you link to them, and to receive notifications when others link to you. Learn more about Webmentions.