CSS :root Pseudo-Class
The CSS :root pseudo-class selects the root element of a document or document tree. In HTML documents, the root element is <html>. The :root pseudo-class is commonly used to define global CSS custom properties, establish document-wide styles, and manage reusable design values.
:root Syntax
:root {
property: value;
}
The :root pseudo-class selects the document's root element. It does not accept arguments or require parentheses.
Basic Example
:root {
color: #333;
background-color: #fff;
}
Applies text and background colors to the root element. The text color can be inherited by descendants.
Custom Property Example
:root {
--primary-color: #006699;
}
Defines a custom property that descendants can use through the var() function.
Using a Custom Property
h2 {
color: var(--primary-color);
}
Uses the custom property defined on the root element to set heading colors.
No Parentheses
The correct syntax is :root, not :root().
How :root Works
Every document tree has a root element. The :root pseudo-class matches that element, allowing styles to be applied at the top of the document's element hierarchy.
HTML Structure
<html lang="en">
<head>
<title>Example</title>
</head>
<body>
<h1>CSS Example</h1>
<p>Example content.</p>
</body>
</html>
In this document, :root matches the <html> element.
CSS Example
:root {
font-family: Arial, sans-serif;
color: #333;
}
The root element receives these styles. Inherited properties, such as font-family and color, can pass their values to descendant elements.
One Root Element
An ordinary HTML document has one root element. The selector does not match every element on the page.
Not a Parent Selector
The :root pseudo-class does not select the parent of an arbitrary element. It specifically matches the root element of the document tree.
Styles and Inheritance
Not all CSS properties inherit. For example, defining a border on :root does not automatically give every descendant the same border.
The Root Element
The root element is the top-level element in a document's element tree. Its identity depends on the document type.
HTML Documents
<html lang="en">
<head></head>
<body></body>
</html>
In HTML documents, the <html> element is the root.
CSS Selection
:root {
--page-background: #f5f7fa;
}
The custom property is defined on the root and normally inherited by descendants.
Document Body
The <body> element is not the document root. It is a descendant of <html>.
Nested Elements
Elements such as <main>, <section>, and <div> are not matched by :root simply because they contain other elements.
Document-Wide Values
Defining reusable values on the root is convenient because most descendants can inherit those values without repeating declarations.
:root vs. html
In an HTML document, both :root and html select the same element. However, they have different specificity values.
HTML Selector
html {
background-color: #fff;
}
Matches the HTML document's root element by its element name.
Root Pseudo-Class
:root {
background-color: #f2f2f2;
}
Matches the same element by its position as the document root.
Specificity Difference
| Selector | Specificity |
|---|---|
html | 0-0-1 |
:root | 0-1-0 |
Cascade Example
:root {
color: #006699;
}
html {
color: #333;
}
When both declarations have the same origin, importance, and cascade layer, the :root declaration wins because its specificity is higher, even though the html rule appears later.
Which Should You Use?
Both selectors work for document-level styling in HTML. The :root selector is especially common for CSS custom properties and reusable design tokens.
CSS Custom Properties
CSS custom properties are reusable values defined with names beginning with two hyphens. They are commonly declared on :root so that descendant elements can access them.
Define Custom Properties
:root {
--primary-color: #006699;
--secondary-color: #444;
--page-background: #fff;
--border-radius: 6px;
--content-spacing: 16px;
}
Use Custom Properties
.button {
background-color: var(--primary-color);
border-radius: var(--border-radius);
padding: var(--content-spacing);
}
The var() function retrieves the computed custom property value from the element.
Multiple Uses
h1,
h2 {
color: var(--primary-color);
}
a {
color: var(--primary-color);
}
Several rules can reuse the same custom property, making updates easier.
Changing One Value
:root {
--primary-color: #8a2be2;
}
Changing the root custom property updates elements that use the inherited value, unless a more local definition overrides it.
Case Sensitivity
Custom property names are case-sensitive. For example, --primary-color and --Primary-Color are different names.
Custom Property Inheritance
Ordinary custom properties declared with the two-hyphen syntax inherit by default. This allows descendants to use values defined on :root.
Root Definition
:root {
--text-color: #333;
}
Descendant Usage
article {
color: var(--text-color);
}
The article can use the inherited custom property without defining it again.
Nested Elements
<article>
<h2>CSS Custom Properties</h2>
<p>Reusable values simplify stylesheets.</p>
</article>
Descendants can inherit custom property values through the element tree.
Custom Property vs. Normal Property
Defining a custom property does not automatically change an element's appearance. The value must be used in another CSS declaration.
Registered Custom Properties
Custom properties registered with @property can specify different inheritance behavior. The default inheritance described here applies to ordinary unregistered custom properties.
Overriding Custom Properties
Custom properties defined on :root can be overridden on individual elements or containers. This allows components to use different values without changing the global defaults.
Global Value
:root {
--accent-color: #006699;
}
Component Override
.warning-box {
--accent-color: #b3261e;
}
Shared Usage
.info-box,
.warning-box {
border-left: 4px solid var(--accent-color);
}
The info box uses the inherited blue value, while the warning box uses its local red value.
Nested Override
:root {
--text-color: #333;
}
.dark-panel {
--text-color: #fff;
}
.panel-text {
color: var(--text-color);
}
A .panel-text element inside .dark-panel inherits the local white value, while one outside it uses the root value.
Inheritance and Cascade
A custom property explicitly declared on an element takes precedence over an inherited value from an ancestor, subject to the CSS cascade.
Fallback Values
The var() function supports fallback values when a referenced custom property is missing or has the guaranteed-invalid value.
Basic Fallback
h2 {
color: var(--heading-color, #006699);
}
If --heading-color is unavailable or guaranteed-invalid, the fallback color is used.
Root Value
:root {
--heading-color: #444;
}
h2 {
color: var(--heading-color, #006699);
}
The heading uses #444 because the custom property is defined.
Nested Fallback
h2 {
color: var(--heading-color, var(--primary-color, #006699));
}
The browser first attempts to use --heading-color, then --primary-color, and finally the literal color.
Invalid Values
A fallback does not automatically correct a custom property that resolves to a value invalid for the receiving property. For example, a defined custom property containing a length cannot be used as a valid color merely because var() includes a color fallback.
Fallback Best Practice
Use fallbacks where a custom property may be undefined, especially in reusable components that can appear outside their original styling context.
Global Document Styles
The :root pseudo-class can also establish document-wide values for inherited properties and root-level behavior.
Font Family
:root {
font-family: Arial, Helvetica, sans-serif;
}
Sets a font family that descendants can inherit unless they have their own font declarations.
Text Color
:root {
color: #333;
}
Defines a root text color that can be inherited by descendant elements.
Color Scheme
:root {
color-scheme: light dark;
}
Indicates that the document supports light and dark color schemes, allowing the browser to adjust supported user-interface elements.
Scroll Behavior
:root {
scroll-behavior: smooth;
}
Requests smooth scrolling for navigation within the document's viewport when supported and permitted by user preferences.
Background Color
:root {
background-color: #f5f7fa;
}
Sets the root background, which can contribute to the canvas background in an HTML document.
Root Font Size and rem Units
The CSS rem unit is relative to the root element's font size. The :root pseudo-class can be used to define that base size.
Root Font Size
:root {
font-size: 16px;
}
Using rem
h1 {
font-size: 2rem;
}
p {
font-size: 1rem;
}
.card {
padding: 1.5rem;
}
With a root font size of 16px, 2rem computes to 32px and 1.5rem computes to 24px.
Root vs. Parent
The rem unit uses the root font size. The em unit generally depends on the font size of the element or its parent, depending on the property.
Respecting User Preferences
:root {
font-size: 100%;
}
Using a percentage allows the root font size to follow the user's configured browser default more naturally than forcing a fixed pixel size.
Accessibility
Relative units help create layouts that respond to font-size preferences. Test text enlargement and browser zoom to ensure content remains readable.
Themes and Color Schemes
Root-level custom properties make it easier to manage light and dark themes or other site-wide design variations.
Default Theme
:root {
--background-color: #fff;
--text-color: #333;
--accent-color: #006699;
}
Dark Theme
:root[data-theme="dark"] {
--background-color: #1f2933;
--text-color: #fff;
--accent-color: #80cfff;
}
Apply Theme Values
body {
background-color: var(--background-color);
color: var(--text-color);
}
a {
color: var(--accent-color);
}
Elements using these custom properties update when the root theme attribute changes.
HTML Theme Attribute
<html lang="en" data-theme="dark">
The attribute selector in :root[data-theme="dark"] matches when the root has the specified theme value.
System Color Preference
@media (prefers-color-scheme: dark) {
:root {
--background-color: #1f2933;
--text-color: #fff;
}
}
Uses the user's preferred color scheme to change root custom properties in supporting browsers.
Theme Overrides
Explicit theme selectors and system-preference rules can be combined. Plan their cascade order so a user-selected theme is not unintentionally overridden.
JavaScript and :root
JavaScript can access the root element and change its attributes or custom properties. CSS updates automatically when those values change.
Access the Root Element
const root = document.documentElement;
The documentElement property references the document's root element.
Select the Root with CSS
const root = document.querySelector(":root");
The querySelector() method can select the root element using the pseudo-class.
Set a Custom Property
document.documentElement.style.setProperty("--primary-color", "#8a2be2");
Changes the custom property on the root element.
Read a Custom Property
const styles = getComputedStyle(document.documentElement);
const color = styles.getPropertyValue("--primary-color").trim();
console.log(color);
Reads the computed custom property value from the root element.
Change a Theme Attribute
document.documentElement.dataset.theme = "dark";
Sets the root's data-theme attribute to dark.
Remove a Theme Attribute
document.documentElement.removeAttribute("data-theme");
Removes the attribute so the root returns to the styles selected by the remaining CSS rules.
Other Document Types
The :root pseudo-class is not limited to HTML. It matches the root element in other document types that support CSS selectors.
HTML
<html lang="en">
<body>
<p>HTML document</p>
</body>
</html>
The root is the <html> element.
SVG
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
<circle cx="50" cy="50" r="40" fill="blue" />
</svg>
In a standalone SVG document, the outermost <svg> element is the root.
XML
In an XML document, :root matches the document's root element, whatever its element name may be.
Embedded SVG
An <svg> element embedded inside an HTML document is not the HTML document root. In that document, :root still matches <html>.
Document Context Matters
The matched element depends on the document tree in which the selector is evaluated.
:root Specificity
The :root pseudo-class contributes a specificity of 0-1-0, like other standard pseudo-classes.
Specificity Examples
| Selector | Specificity |
|---|---|
:root | 0-1-0 |
html | 0-0-1 |
html:root | 0-1-1 |
:root[data-theme="dark"] | 0-2-0 |
:root.theme-dark | 0-2-0 |
:root:not(.dark) | 0-2-0 |
:where(:root) | 0-0-0 |
Specificity Example
html {
--primary-color: #333;
}
:root {
--primary-color: #006699;
}
When both declarations have the same origin, importance, and cascade layer, the :root declaration wins because its selector has greater specificity.
Low-Specificity Alternative
:where(:root) {
--primary-color: #006699;
}
The :where() pseudo-class gives the selector zero specificity, making it easier for other rules to override the values.
Practical Uses
The :root pseudo-class is useful for reusable CSS values, global styling, and document-wide configuration.
Brand Colors
:root {
--brand-primary: #006699;
--brand-secondary: #444;
}
Defines reusable brand colors for a stylesheet.
Spacing Values
:root {
--space-small: 8px;
--space-medium: 16px;
--space-large: 24px;
}
Creates consistent spacing values that components can reuse.
Border Radius
:root {
--radius-small: 4px;
--radius-medium: 8px;
}
Defines reusable corner-radius values.
Global Typography
:root {
font-family: Arial, Helvetica, sans-serif;
font-size: 100%;
}
Sets a root font family and a relative root font size.
Smooth Scrolling
@media (prefers-reduced-motion: no-preference) {
:root {
scroll-behavior: smooth;
}
}
Requests smooth scrolling when the user has not expressed a preference for reduced motion.
Theme Management
:root {
--page-background: #fff;
}
:root[data-theme="dark"] {
--page-background: #1f2933;
}
Changes a reusable background value based on a theme attribute.
Limitations
The :root pseudo-class selects the root element, but it does not automatically apply every declared style to all descendants.
Only Matches the Root
It does not match every element or every parent container.
Not Every Property Inherits
Properties such as borders, padding, and margins do not automatically inherit from the root.
Custom Properties Must Be Used
Defining --primary-color does not change text or background colors until another declaration uses it.
Local Overrides
Descendant elements can override inherited custom properties, so the root value is not necessarily used everywhere.
Invalid Custom Property Values
A custom property can contain a value that is invalid for a receiving CSS property. The browser applies CSS value validation when the custom property is substituted.
Document Scope
Root-level custom properties in one document do not automatically apply inside separate iframe documents or across independent document trees.
Shadow DOM
Inherited custom properties can cross into shadow trees through their hosts, but values can be overridden and registered properties can have different inheritance rules.
Higher Specificity
The :root selector has higher specificity than the html type selector. Consider this when organizing global styles.
Best Practices
- Use
:rootto define reusable custom properties that should be available throughout the document. - Give custom properties descriptive names such as
--primary-coloror--content-spacing. - Group related custom properties to keep global styles organized.
- Use
var()to reference custom properties instead of repeating values. - Use local overrides when components need different values from the global defaults.
- Provide fallback values where a custom property may be undefined.
- Remember that
:rootandhtmlselect the same element in HTML but have different specificity. - Prefer relative font sizing that respects user preferences.
- Use theme attributes or media queries to manage document-wide color schemes.
- Test custom property inheritance and overrides when working with nested components or shadow DOM.
:root Example
This example defines colors, spacing, and border-radius values on :root. The card and button use those values through var(). Click Change Theme to update the root custom properties and change the card's appearance.
HTML
<div class="root-demo">
<div class="demo-card">
<h2>CSS Custom Properties</h2>
<p>This card uses values defined on :root.</p>
<button type="button" id="theme-toggle">Change Theme</button>
</div>
</div>
CSS
:root {
--demo-primary: #006699;
--demo-background: #eaf6fc;
--demo-text: #333;
--demo-spacing: 16px;
--demo-radius: 8px;
}
:root[data-demo-theme="alternate"] {
--demo-primary: #8a2be2;
--demo-background: #f3e8ff;
--demo-text: #333;
}
.root-demo .demo-card {
padding: var(--demo-spacing);
border: 2px solid var(--demo-primary);
border-radius: var(--demo-radius);
background-color: var(--demo-background);
color: var(--demo-text);
}
.root-demo .demo-card h2 {
margin-top: 0;
color: var(--demo-primary);
}
.root-demo button {
padding: 8px 12px;
border: 0;
border-radius: var(--demo-radius);
background-color: var(--demo-primary);
color: #fff;
cursor: pointer;
}
JavaScript
const button = document.getElementById("theme-toggle");
button.addEventListener("click", () => {
const root = document.documentElement;
const alternate = root.dataset.demoTheme === "alternate";
if (alternate) {
root.removeAttribute("data-demo-theme");
} else {
root.dataset.demoTheme = "alternate";
}
button.textContent = alternate ? "Change Theme" : "Restore Theme";
});
Browser Result
Note: The card initially uses blue colors defined on :root. Click Change Theme to apply alternate purple values. Click Restore Theme to return to the original colors. The example changes the root element's theme attribute without changing individual component styles.
Browser Support
Baseline: Widely available. The :root pseudo-class is supported in Chrome, Edge, Firefox, Safari, and other major browsers. Support for related features, such as registered custom properties and newer color functions, should be checked separately.
For current compatibility information, visit Can I Use? and search for :root.
Specifications
The :root pseudo-class is defined in CSS Selectors Level 4 as a structural pseudo-class that matches the root element of a document tree.
