Skip to Content
CSS Variables for Brand Colors You Change Once
Intermediate
0 likes
Tutorials

CSS Variables for Brand Colors You Change Once

Migrate a button to shared brand tokens, override one section, and check hover, keyboard focus and fallback behaviour in a complete local example.

If the same brand colour appears in a button, its hover rule and several page sections, changing one hex value will leave the others behind. Custom properties let those rules share a name. The useful test is whether the normal, hover and keyboard-focus states still agree after a change.

This walkthrough turns one button component into two scoped brands. You need a text editor and a browser. If you already use root tokens, run the example and continue to Trace an override that did not work.

Find the colours that belong together

Search the stylesheet for your repeated brand hex. Separate its roles before replacing it: the normal background, hover background and text on that background may need different values. A variable named --color-brand is easier to reuse than --home-blue. A one-off illustration colour does not need a token just because it is a hex value.

Run a complete component

Save the following as brand-tokens.html and open it in your browser. All the styling is inside the file, so there is no build step or stylesheet path to configure.

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>One component, two brand colours</title>
  <style>
    :root {
      --color-brand: #034bff;
      --color-brand-hover: #003acc;
      --color-on-brand: #ffffff;
      --color-ink: #080b0e;
      --color-line: #dce3ed;
    }
    * { box-sizing: border-box; }
    body {
      margin: 0;
      padding: 1rem;
      font: 1rem/1.6 system-ui, sans-serif;
      color: var(--color-ink);
      background: #ffffff;
    }
    main { max-width: 42rem; margin-inline: auto; }
    .card {
      padding: 1.5rem;
      border: 1px solid var(--color-line);
      border-radius: 0.75rem;
      margin-block: 1rem;
    }
    .button {
      display: inline-block;
      padding: 0.65rem 1rem;
      border-radius: 0.5rem;
      color: var(--color-on-brand);
      background: var(--color-brand);
      text-decoration: none;
    }
    .button:hover { background: var(--color-brand-hover); }
    .button:focus-visible {
      outline: 3px solid var(--color-brand);
      outline-offset: 3px;
    }
    .promo {
      --color-brand: #0a7a3e;
      --color-brand-hover: #08632f;
    }
    .badge {
      background: var(--color-accent, #f2f8ff);
      padding: 0.25rem 0.5rem;
    }
  </style>
</head>
<body>
  <main>
    <h1>Change the brand without rewriting the button</h1>
    <section class="card">
      <h2>Standard plan</h2>
      <p>The normal brand comes from the document root.</p>
      <a class="button" href="#details">Read the plan</a>
    </section>
    <section class="card promo">
      <h2>Community plan</h2>
      <p>The same button uses this section's green brand.</p>
      <a class="button" href="#details">Read the plan</a>
    </section>
    <p id="details"><span class="badge">Example plans</span>
      This page demonstrates styling; it does not sell a plan.</p>
  </main>
</body>
</html>

You should see two cards. The first link has a blue background; the second is green. Both links move to the example details when activated. Move the pointer over each link, then press Tab to focus them: hover darkens the corresponding brand and keyboard focus has a visible outline.

Change the brand and check every state

  1. Change the root --color-brand to #626976 and its hover token to #454b56.
  2. Save and reload. The first button should become grey and darken on hover.
  3. Check the second button. It should remain green because .promo defines its own brand tokens.
  4. Tab through both links. Their outlines should follow their respective brand colours.

The browser resolves a custom property where it is used. The second button inherits the values from its closest ancestor that supplies them, the promo section. You have changed the context around the component without adding a second button implementation.

Changing a token does not establish accessible contrast by itself. Check normal and hover text against their backgrounds when choosing real brand colours. Keep a visible keyboard-focus state too.

Trace an override that did not work

If the second button stays blue, inspect the button in DevTools. Find its background rule and the inherited custom properties. Confirm that the section actually has the promo class and that the property name matches exactly. Custom property names are case-sensitive.

Next, look for an old rule such as .promo .button { background: #034bff; }. That declaration supplies a literal background, so changing the token cannot affect it. Replace the value with var(--color-brand), then check hover and focus rules for the same problem. Work through one component at a time instead of replacing unrelated colours across the whole site.

Know what the fallback does

The badge uses var(--color-accent, #f2f8ff). No accent token is defined, so the pale fallback is used. Add --color-accent: #dce3ed to the root and the badge background changes.

A fallback does not validate the value for its destination. If you set --color-accent: 24px, that token exists, but a length cannot be a background colour. The fallback is not selected merely because the substituted value has the wrong type; the background declaration becomes invalid at computed-value time. Use a valid colour or remove the bad token.

Try a third brand

Duplicate the promo card and change its class to card partner. Add a .partner rule that defines the normal brand as #626976 and hover as #454b56. Leave the .button rules alone.

Expected result: blue, green and grey buttons share the same component CSS. Changing the root affects the first card; changing the partner tokens affects only the third. If all three change, the override is probably on a shared ancestor instead of the intended section.

Continue with the multi-brand theming tutorial when you need a broader theme. For the property rules and inheritance details, see MDN's custom properties guide.

About

Migrate a button to shared brand tokens, override one section, and check hover, keyboard focus and fallback behaviour in a complete local example.

Responsible
John G
Last Update
08/27/2026
Reading Time
5 min
Was this helpful?
​ 0 ​ 0

Comments (0)

Sign in to comment

No comments yet.