CSS Custom Properties Tutorial: Dynamic Theming with CSS Variables

15 Mar 2026·8 min read

CSS custom properties, commonly known as CSS variables, have revolutionized how we approach dynamic styling and theming in modern web development. This comprehensive css custom properties tutorial will guide you through everything from basic implementation to advanced theming techniques that will transform your CSS workflow.

Unlike traditional CSS where values are static, css variables allow you to store reusable values that can be updated dynamically, making your stylesheets more maintainable and enabling powerful features like theme switching without JavaScript manipulation of individual properties.

What Are CSS Custom Properties and How They Work

CSS custom properties are entities defined by CSS authors that contain specific values to be reused throughout a document. They follow a specific syntax using two dashes (--) as a prefix and are case-sensitive.

:root { --primary-color: #3498db; --secondary-color: #2ecc71; --font-size-large: 2rem; } .button { background-color: var(--primary-color); font-size: var(--font-size-large); }

The power of CSS custom properties lies in their inheritance and scope. When defined in the :root selector, they become global variables accessible throughout your entire document. However, you can also define them within specific selectors to create scoped variables.

Live Demo: This box uses CSS variables for its gradient colors and can be easily updated by changing just the variable values.

Setting Up CSS Variables with :root Selector

The :root selector is the foundation of dynamic theming css. It represents the document's root element and provides the highest level of specificity for your css root variables. Here's how to establish a solid variable system:

:root { /* Color Variables */ --color-primary: #2c3e50; --color-secondary: #3498db; --color-accent: #e74c3c; --color-text: #2c3e50; --color-background: #ffffff; /* Spacing Variables */ --spacing-xs: 0.25rem; --spacing-sm: 0.5rem; --spacing-md: 1rem; --spacing-lg: 1.5rem; --spacing-xl: 2rem; /* Typography Variables */ --font-family-primary: 'Inter', sans-serif; --font-size-sm: 0.875rem; --font-size-base: 1rem; --font-size-lg: 1.125rem; --font-size-xl: 1.25rem; }

When organizing your variables, group them by category and use consistent naming conventions. The double-dash prefix followed by a descriptive name makes your code self-documenting and easier to maintain.

Creating Dynamic Color Themes with CSS Variables

The real magic of css variables shines when creating dynamic themes. By defining different sets of color variables for each theme, you can completely transform your site's appearance with minimal code changes.

/* Light Theme (Default) */ :root { --theme-bg: #ffffff; --theme-text: #2c3e50; --theme-primary: #3498db; --theme-card-bg: #f8f9fa; --theme-border: #e9ecef; } /* Dark Theme */ [data-theme="dark"] { --theme-bg: #1a1a1a; --theme-text: #ffffff; --theme-primary: #64b5f6; --theme-card-bg: #2d2d2d; --theme-border: #404040; } /* Apply theme variables */ body { background-color: var(--theme-bg); color: var(--theme-text); transition: background-color 0.3s ease, color 0.3s ease; } .card { background-color: var(--theme-card-bg); border: 1px solid var(--theme-border); transition: background-color 0.3s ease, border-color 0.3s ease; }

Try it yourself → Create cohesive color schemes for your themes with our advanced color palette generator that helps you find perfect color combinations.

Open Colour Palette Generator

This approach allows you to switch themes by simply changing a data attribute on the body or html element, and all your components will automatically adapt to the new color scheme.

Advanced Techniques: Responsive Variables and Calculations

CSS custom properties become even more powerful when combined with calc() functions and media queries. You can create responsive variables that adapt to different screen sizes:

:root { /* Fluid typography */ --fluid-font-size: clamp(1rem, 2.5vw, 1.5rem); /* Dynamic spacing */ --container-padding: calc(var(--spacing-md) + 2vw); /* Responsive grid gap */ --grid-gap: 1rem; } @media (min-width: 768px) { :root { --grid-gap: 2rem; --container-padding: 3rem; } } /* Advanced calculations */ .progressive-enhancement { margin-top: calc(var(--spacing-lg) * 2); padding: var(--container-padding); font-size: var(--fluid-font-size); }

You can also create variables that depend on other variables, creating a cascading system that makes your CSS incredibly flexible:

:root { --base-unit: 1rem; --small-space: calc(var(--base-unit) * 0.5); --medium-space: calc(var(--base-unit) * 1.5); --large-space: calc(var(--base-unit) * 3); /* Color transparency variations */ --primary-rgb: 52, 152, 219; --primary-alpha-10: rgba(var(--primary-rgb), 0.1); --primary-alpha-50: rgba(var(--primary-rgb), 0.5); }

Real-World Example: Building a Complete Theme Switcher

Let's put everything together and build a complete theme switching system that demonstrates the full power of dynamic theming css:

/* Complete theme system */ :root { /* Default (Light) Theme */ --bg-primary: #ffffff; --bg-secondary: #f8f9fa; --text-primary: #212529; --text-secondary: #6c757d; --accent-color: #0d6efd; --border-color: #dee2e6; --shadow-color: rgba(0, 0, 0, 0.1); } /* Dark Theme */ [data-theme="dark"] { --bg-primary: #121212; --bg-secondary: #1e1e1e; --text-primary: #ffffff; --text-secondary: #b3b3b3; --accent-color: #4dabf7; --border-color: #333333; --shadow-color: rgba(0, 0, 0, 0.3); } /* Blue Theme */ [data-theme="blue"] { --bg-primary: #f0f8ff; --bg-secondary: #e6f3ff; --text-primary: #1a365d; --text-secondary: #2c5282; --accent-color: #3182ce; --border-color: #bee3f8; --shadow-color: rgba(49, 130, 206, 0.15); }

The corresponding HTML structure and JavaScript for theme switching:

/* Theme switcher component styling */ .theme-switcher { background: var(--bg-secondary); border: 1px solid var(--border-color); border-radius: 8px; padding: 1rem; box-shadow: 0 2px 8px var(--shadow-color); transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); } .theme-option { background: var(--accent-color); color: white; border: none; padding: 0.5rem 1rem; border-radius: 4px; cursor: pointer; margin-right: 0.5rem; transition: transform 0.2s ease; } .theme-option:hover { transform: translateY(-2px); }
Interactive Demo: This demo box responds to theme changes automatically. The background, border, and text colors all update based on the current theme variables.

The JavaScript to handle theme switching is minimal and clean:

// Simple theme switcher function function switchTheme(themeName) { document.documentElement.setAttribute('data-theme', themeName); localStorage.setItem('preferred-theme', themeName); } // Initialize theme from localStorage const savedTheme = localStorage.getItem('preferred-theme') || 'light'; if (savedTheme !== 'light') { switchTheme(savedTheme); }

This complete system demonstrates how css custom properties create a maintainable, scalable theming solution. By changing just one data attribute, your entire application adapts to a new visual theme with smooth transitions.

Try it yourself → Generate professional color palettes for your theme systems with our intuitive color palette generator that creates harmonious color combinations.

Open Colour Palette Generator

CSS custom properties have transformed how we approach styling and theming in modern web development. From simple color variables to complex responsive systems, they provide the foundation for maintainable, dynamic, and user-friendly interfaces. The techniques covered in this css custom properties tutorial will help you build more flexible and maintainable stylesheets that can adapt to any design requirement.

Start implementing CSS variables in your projects today, and you'll quickly discover how they simplify maintenance, enable dynamic theming, and make your CSS more powerful and expressive than ever before.