:root
Matches the document’s root element, the html tag in HTML. The usual place for CSS variables shared across the whole page.
Example
#:root {
--brand: #7c3aed;
--surface: #18181b;
--radius: 12px;
}
.card {
padding: 14px;
border-left: 4px solid var(--brand);
border-radius: var(--radius);
background: var(--surface);
}<div class="card">
<strong>Module 3: pseudo-classes</strong>
<p style="margin: 4px 0 0; color: #a1a1aa;">The bar color, background, and rounding all come from variables stored on :root.</p>
</div>Definition and usage
#The :root pseudo-class selects the root of the document tree. On an HTML page that’s always the <html> element, so :root and html point to the same element. They differ in weight: :root as a pseudo-class has a specificity of (0, 1, 0), while html as a type selector has only (0, 0, 1).
This is the usual place to keep CSS variables (custom properties) for the whole page: brand colors, spacing, corner radii. Variables inherit down the tree, so anything set on :root is available on every element through var(--name).
:root is also where you set things that apply to the whole document: color-scheme, the base font-size that rem units are calculated from, and scroll-behavior. You can switch between a dark or light theme by overriding the variables in one place, for example inside @media (prefers-color-scheme: light) or a :root[data-theme="light"] rule.
Syntax
#:root { --name: value; }Common uses
#- One color variable changes the button and the badge at once.
- The corner radius of every element, set in a single place.
- Several variables at once make a ready-made theme. The components don’t change, only the values do.
- The document’s base font size. Text set in
remgrows along with it.
Common uses in practice
#--brand
:root { --brand: #7c3aed; }--radius
:root { --radius: 999px; }--brand and --radius
:root { --brand: #10b981; --radius: 12px; }font-size
rem grows along with it.:root { font-size: 20px; }More examples
#:root {
--bg: #18181b;
--fg: #e5e5e5;
}
:root[data-theme="light"] {
--bg: #f4f4f5;
--fg: #18181b;
}
.panel {
background: var(--bg);
color: var(--fg);
}<div class="panel" style="padding: 14px; border-radius: 12px; transition: background-color 0.2s, color 0.2s;">
<p style="margin: 0 0 10px;">This panel’s colors come from variables.</p>
<button type="button" onclick="const r = document.documentElement; r.dataset.theme = r.dataset.theme === 'light' ? 'dark' : 'light'" style="padding: 6px 12px; border: 0; border-radius: 8px; background: #7c3aed; color: #fff; font: inherit; cursor: pointer;">Switch theme</button>
</div>Click the button. The script only changes the data-theme attribute on the <html> element, and the colors swap through the variables.
Browser support
#Widely available
Works in all modern browsers, phones included. You can use it without worry.
- Chrome
- Edge
- Firefox
- Safari
Good practices
#- Name variables after their role, not their value:
--color-accentinstead of--purple. Changing the theme won’t then require renaming anything. - Variables on
:rootare global. Values only needed inside a single component belong on that component instead, e.g..card { --gap: 12px; }. - Remember that
:rootoutweighshtml. Ahtml { … }rule won’t override a property set on:root, even if it comes later in the file.
Related entries
#- SpecificityA selector’s weight, which decides which rule wins when several rules set the same property on the same element.
- Type selectorSelects every element with a given tag name, for example every p paragraph or every li list item.
- :where()Works like :is(), but always has zero specificity. Ideal for base styles that should be easy to override.
- font-sizeSets the font size.
Spotted a mistake or missing an example? Write to us.