What Is CSS :root and Why Use It for Variables?
This article provides a straightforward guide to the CSS
:root pseudo-class and explains why it has become the
standard location for declaring global CSS variables. You will learn
what the :root selector represents in the Document Object
Model (DOM), how it compares to the <html> selector
in terms of specificity, and the primary technical and structural
benefits of using it to manage global design tokens across your
stylesheets.
What Is the :root
Pseudo-Class?
The :root pseudo-class in CSS matches the root element
of the document tree. In standard HTML documents, the root element is
always the <html> tag. However, :root
acts as a generic selector capable of targeting the root of any markup
format, including SVG and XML files.
While :root and html both target the exact
same node in an HTML document, they differ in CSS specificity:
htmlis an element (type) selector with a specificity score of(0, 0, 1).:rootis a pseudo-class selector with a specificity score of(0, 1, 0).
Because pseudo-classes carry higher specificity than basic tag
selectors, rules declared on :root take precedence over
rules declared on html.
Why
:root Is Preferred for Global CSS Variables
CSS custom properties (variables) follow the standard CSS cascade and
inheritance model. Declaring variables inside :root is the
universally accepted best practice for defining global styles for
several distinct reasons:
1. True Global Scope and Inheritance
Because :root corresponds to the very top of the DOM
tree, any custom properties defined within it automatically cascade down
to every element on the page, from the <body> element
down to deeply nested child components.
:root {
--primary-color: #0066cc;
--font-base: 16px;
--spacing-unit: 8px;
}Any element in the document can consume these properties via the
var() function without needing separate declarations:
button {
background-color: var(--primary-color);
padding: var(--spacing-unit);
}2. Clear Semantic Intent
Declaring variables within :root immediately signals to
other developers that the properties inside are design tokens intended
for global application. It visually separates high-level theme
configuration (colors, spacing scales, typography) from component-level
styling and local variable overrides.
3. Predictable Overriding Behavior
Because :root has a specificity value of
(0, 1, 0), it is strong enough to reliably establish
defaults, but light enough to be easily overridden at the component or
modifier level when scoping variables locally:
/* Global definition */
:root {
--card-bg: #ffffff;
}
/* Local override for dark theme cards */
.card-dark {
--card-bg: #1a1a1a;
}
.card {
background-color: var(--card-bg);
}4. Broad Document Compatibility
Unlike the html selector, :root is agnostic
to the host language. If you are styling an embedded SVG graphic, for
instance, there is no <html> element; the root
element is <svg>. The :root selector
handles both HTML and SVG uniformly, making it the safer and more
portable choice for modular CSS.