aslain.dev
0%
01 Hizmetler 02 Hakkımda 03 Projeler 04 Stack 05 Blog 06 İletişim
← Tüm makaleler Frontend & UI

CSS Variables: A Practical Guide to Theming & Reuse

CSS variables (officially called custom properties) are a browser-native feature that lets you define a value once and reuse it throughout your stylesheet. They centralize values like colors, spacing and fonts without needing a preprocessor such as Sass, and the best part is that they can be changed at runtime with JavaScript. In this article we'll set up CSS variables from scratch, build a real light/dark theme, and cover patterns you'll use every day.

What exactly are CSS variables?

A custom property consists of a name beginning with -- and a value. To read it, you use the var() function. The most common approach is to declare your variables on the :root selector, because :root targets the document's root element (<html>) and variables defined there are available across the whole page.

:root {
  --color-primary: #6c5ce7;
  --color-text: #1a1a1a;
  --space: 16px;
}

.button {
  background: var(--color-primary);
  color: white;
  padding: var(--space);
}

Now when you want to change the primary color you update a single line, and the dozens of rules that depend on it update automatically. Unlike classic hard-coded values, you get a single source of truth.

var() and fallback values

var() can take a second argument: a fallback value. If the variable is undefined or invalid, the fallback kicks in. This is handy for safely accessing a variable that hasn't been defined yet:

.card {
  /* white is used if --card-bg is undefined */
  background: var(--card-bg, #ffffff);
  border-radius: var(--card-radius, 8px);
}

The fallback covers everything after the comma, so even another var() can serve as the fallback: var(--a, var(--b, red)).

Inheritance and scope

The most powerful trait of CSS variables is that they follow normal CSS inheritance. If you define a variable on a specific element, only that element and its descendants see the value. This makes component-scoped theming easy:

.alert {
  --color-accent: #e17055;
}
.alert .title {
  color: var(--color-accent); /* orange */
}

You can define the same --color-accent variable with different values in different containers and change the look of shared components inside them with a single line. This is something you cannot do with Sass variables, because Sass variables are resolved at compile time and have no concept of scope or inheritance.

Practical example: light/dark theme

The most common use of CSS variables is theme switching. You move your colors into variables, then override the values based on a data-theme attribute on <html>:

:root {
  --bg: #ffffff;
  --text: #1a1a1a;
  --card: #f5f5f7;
}

[data-theme="dark"] {
  --bg: #0f0f12;
  --text: #f2f2f5;
  --card: #1c1c22;
}

body { background: var(--bg); color: var(--text); }
.card { background: var(--card); }

Triggering the switch with JavaScript is a one-liner:

const btn = document.querySelector('#toggle-theme');
btn.addEventListener('click', () => {
  const html = document.documentElement;
  const next = html.dataset.theme === 'dark' ? 'light' : 'dark';
  html.dataset.theme = next;
  localStorage.setItem('theme', next);
});

One caveat: if you want the whole page to switch at once, it's wise to temporarily disable your transition animations during the switch; otherwise the browser tries to ease hundreds of elements simultaneously, which can feel sluggish.

Reading and writing variables with JavaScript

Custom properties can be read and written through the DOM. This is powerful for producing dynamic styles based on scroll position, mouse movement or user input:

const root = document.documentElement;

// Write
root.style.setProperty('--color-primary', '#00b894');

// Read
const value = getComputedStyle(root)
  .getPropertyValue('--color-primary')
  .trim();

For instance, you can write the mouse position into a variable and build a glow effect with CSS alone. The logic stays in JavaScript while the visuals live entirely in CSS, which keeps the code clean.

Best practices and pitfalls

  • Use meaningful names. Role-based names like --color-primary are more maintainable than value-based names like --purple, because the name still makes sense even if the value changes.
  • Group your design tokens. Collect groups like colors, spacing, radii and shadows into logical blocks inside :root.
  • They are case-sensitive. --Color and --color are different variables.
  • They hold values, not selectors. You can assign a variable only a value (color, number, length), not a full CSS rule.
  • Browser support is broad. All modern browsers have supported them for years; only very old Internet Explorer versions don't.

Frequently Asked Questions

What's the difference between CSS variables and Sass variables?

Sass variables ($color) are resolved at compile time and don't appear in the final CSS; they're static. CSS variables (--color) stay live in the browser, respect inheritance and can be changed at runtime with JavaScript. For dynamic scenarios like theming, CSS variables are far better suited.

Can I use media queries with custom properties?

Yes. By redefining a variable inside a @media block you can produce responsive values; for example --space: 32px on wide screens and --space: 16px on mobile. Every component using that variable adapts automatically.

What happens if a variable gets an invalid value?

The affected property is flagged as invalid at computed-value time, and the property's inherited or initial value is used instead. That's why adding a var() fallback in critical spots is a safe move.

Want a clean, scalable design system in your project? I can help you build a maintainable, theme-ready interface with CSS variables. Get in touch and let's talk about your project.

Bu kategorideki tüm yazılar →

Devamı için