Home / Blog / Get a site's CSS variables

How to Get Any Website's CSS Variables

Published August 17, 2026 · 8 min read · by the CSS DNA team

Quick answer: Open DevTools, select the <html> element and scroll the Styles pane to the :root rule — every custom property the site defines globally is listed there with its value. To get them all as copyable data instead of a panel, paste the console snippet in Method 2.

Why this is a different job from copying CSS

Copying an element's rules gives you resolved values: color: rgb(242, 242, 247). Useful, and dead. What you usually want is the variable behind it — --tx — because that is the design decision, and it is the thing that appears three hundred times across the page.

Pull the custom properties instead of the computed rules and you get the system rather than a snapshot of one node. That is the difference between recreating a button and recreating a theme.

MethodEffortGets scoped varsOutput
DevTools :root panelLowNoA panel you read
Computed-style snippetLowOnly as resolvedName/value pairs
Stylesheet walkMediumYes, with selectorsFull declarations
One-click extractionNoneYesTailwind, CSS, JSON, tokens

Method 1: The DevTools :root panel

  1. Open DevTools and select the <html> element in the Elements panel.
  2. In the Styles pane, scroll to the :root (or html) rule.
  3. Every global custom property is listed with its declared value, and colors render a swatch you can click to open the picker.

Two things worth knowing that most people miss:

  • Click a var(--foo) to jump to its definition. In Chrome and Edge, the variable reference in a rule is a link straight to the declaring rule. This is the fastest way to answer "where does this actually come from?"
  • Hover a var() to see the resolved value without leaving the rule you are reading.

Firefox and Safari both show custom properties in their inspectors too; Safari's Web Inspector groups them so a long :root stays navigable.

Limitation: this is a panel, not data. If a design system defines 180 variables — and plenty do — you are not transcribing them by hand.

Method 2: Read every custom property from computed styles

Current Chrome and Firefox let you enumerate custom properties directly off a computed style object. Paste this into the Console:

const el = document.documentElement;
Object.fromEntries(
  [...getComputedStyle(el)]
    .filter(p => p.startsWith('--'))
    .map(p => [p, getComputedStyle(el).getPropertyValue(p).trim()])
)

That returns a plain object of every variable in scope on <html>, ready to copy out of the console as JSON. Change document.documentElement to any element — or to document.querySelector('.card') — to see what that subtree sees, including anything overridden further down.

If it returns an empty list, the browser is older than this behaviour. Fall back to Method 3, which reads the stylesheets directly and works everywhere.

Method 3: Walk the stylesheets (the one that finds scoped variables)

Methods 1 and 2 both look at one element. Real design systems scope variables — a dark-mode block, a [data-theme] attribute, a component that redefines --gap. To see all of them with the selectors they belong to, walk the stylesheets:

[...document.styleSheets].flatMap(sheet => {
  try { return [...sheet.cssRules] }
  catch { return [] }                    // cross-origin sheet, skipped
})
.filter(rule => rule.style)
.flatMap(rule =>
  [...rule.style]
    .filter(prop => prop.startsWith('--'))
    .map(prop => `${rule.selectorText}  ${prop}: ${rule.style.getPropertyValue(prop).trim()}`)
)

The try / catch is not defensive padding — it is the whole trick. Reading cssRules from a stylesheet served by another origin throws a SecurityError, and one uncaught throw kills the entire loop. Catching per sheet means a site whose CSS sits on a CDN still returns everything from its same-origin sheets.

This is also the only method here that shows you theme structure: you will see :root and [data-theme="dark"] declaring the same names with different values, which tells you how the site themes itself.

What each method misses

  • Inline style attributes. A variable set on an element by JavaScript is not in any stylesheet. Method 2 catches these; Method 3 does not.
  • Cross-origin stylesheets. Skipped by Method 3, and invisible to all of them if the site loads its theme from a CDN.
  • Unused declarations. None of these tell you whether a variable is actually referenced. Plenty of systems carry dead ones.
  • Variables that are never variables. If the site ships compiled Sass, the values were resolved at build time and there is nothing to find — see copying CSS for that case.

Method 4: Extract the system, not the list

A dump of 180 variable names is raw material, not a design system. What you usually need next is the values grouped by role, the duplicates collapsed, and the whole thing in a format your codebase accepts.

CSS DNA reads the rendered page rather than the source, so it works the same on a site with a tidy :root and on one with minified, framework-generated CSS and no custom properties at all. One click returns colors ranked by how much of the page they cover, the type scale, spacing, radii and shadows — then exports them as CSS custom properties, a Tailwind theme, SCSS, JSON, or W3C design tokens.

It also flags near-duplicates. Most extracted variable lists contain four greys that differ by a rounding error, and the useful output is three greys plus a note.

Converting what you found into your own theme

Once you have the pairs, the shape you want in your own stylesheet is almost always semantic rather than literal:

:root {
  /* literal palette — what you extracted */
  --violet-500: #7c5cff;
  --ink-50:     #f2f2f7;

  /* semantic layer — what your components use */
  --color-action: var(--violet-500);
  --color-text:   var(--ink-50);
}

Components should reference --color-action, never --violet-500. That indirection is the entire reason to have variables: rebranding becomes one edit instead of a find-and-replace. The same two-layer split is what the design tokens format calls aliasing.

Frequently asked questions

How do I see the CSS variables a website uses?

Open DevTools, select the <html> element, and scroll the Styles pane to the :root rule. Every global custom property appears there with its value and a color swatch where relevant.

How do I list all CSS custom properties in the console?

Filter a computed style object for names beginning with two dashes: [...getComputedStyle(document.documentElement)].filter(p => p.startsWith('--')). Map each name through getPropertyValue to get its value.

Why does reading document.styleSheets throw a SecurityError?

Accessing cssRules on a stylesheet from another origin is blocked by CORS. Wrap each sheet in try / catch so cross-origin sheets are skipped instead of killing the whole loop.

How do I find variables that are not on :root?

Walk document.styleSheets and read custom properties off every rule, keeping rule.selectorText. That surfaces theme blocks like [data-theme="dark"] and component-scoped overrides that a :root inspection never shows.

What if a site has no CSS variables at all?

Compiled Sass and older codebases resolve values at build time, so there is nothing to read. Extract from computed styles instead — that reads what the browser rendered, regardless of how the CSS was authored.

Are CSS variables the same as design tokens?

No. CSS custom properties are a browser feature for the web only. Design tokens are platform-neutral data that compile to CSS variables, Swift, or Android XML from one source file.

Can I copy another site's theme legally?

Color values and spacing scales are not themselves protectable, but a wholesale copy of a distinctive visual identity invites a trademark or trade-dress problem. Study the ratios and roles, then build your own.

Get the variables and the system behind them

Colors, type scale, spacing and shadows — exported as CSS, Tailwind, SCSS, JSON or tokens.

Add CSS DNA to Chrome — Free