CSS Color Variables & Custom Properties

Master CSS custom properties for flexible, maintainable color systems. Perfect for theming and design systems.

🎨
Easy Theming
Switch between light/dark modes with a single class change
âš¡
Real-time Updates
Change colors dynamically without recompiling
🔧
Maintainable
Update once, apply everywhere across your design

Basic Syntax

CSS custom properties use the -- prefix and are defined in the :root selector for global access.

:root { /* Define your color variables */ --primary: #2D5BE3; --secondary: #E8453C; --background: #FFFFFF; --text: #1A1A1A; --border: #E5E4E0; } /* Use them with var() function */ .button { background: var(--primary); color: var(--background); border: 2px solid var(--primary); } .card { background: var(--background); color: var(--text); border: 1px solid var(--border); }

HEX vs RGB vs HSL in Variables

Each format has its strengths. Choose based on your use case.

HEX (Simple & Clean)

:root { --color-primary: #2D5BE3; }

✓ Most common, easy to read

✗ Can't adjust opacity easily

RGB (Best for Opacity)

:root { --primary-rgb: 45, 91, 227; } .overlay { background: rgba(var(--primary-rgb), 0.5); }

✓ Perfect for transparency

✓ Works with rgba()

/* HSL - Best for Color Manipulation */ :root { --primary-h: 225; --primary-s: 77%; --primary-l: 53%; --primary: hsl(var(--primary-h), var(--primary-s), var(--primary-l)); } /* Create lighter/darker variants */ .button-light { background: hsl(var(--primary-h), var(--primary-s), 80%); } .button-dark { background: hsl(var(--primary-h), var(--primary-s), 30%); }

Dark Mode Implementation

Use CSS custom properties to build elegant dark mode switching without duplicating CSS.

/* Light theme (default) */ :root { --bg: #FFFFFF; --bg-secondary: #F5F5F5; --text: #1A1A1A; --text-secondary: #6B6B6B; --border: #E5E4E0; --accent: #2D5BE3; } /* Dark theme */ :root.dark-mode { --bg: #0F0F0F; --bg-secondary: #1E1E1E; --text: #FAFAFA; --text-secondary: #A0A0A0; --border: #2A2A2A; --accent: #4169E1; } /* Your CSS stays the same! */ body { background: var(--bg); color: var(--text); } .card { background: var(--bg-secondary); border: 1px solid var(--border); }
// JavaScript to toggle dark mode const toggleDarkMode = () => { document.documentElement.classList.toggle('dark-mode'); localStorage.setItem('theme', document.documentElement.classList.contains('dark-mode') ? 'dark' : 'light' ); }; // Check user preference on load if (localStorage.getItem('theme') === 'dark') { document.documentElement.classList.add('dark-mode'); }

Live Demo

Component Preview

This component uses CSS variables for all colors. Toggle between themes to see how easily colors update.

Complete Design System Example

A production-ready color system with semantic naming and scale.

:root { /* Brand Colors */ --brand-primary: #2D5BE3; --brand-secondary: #E8453C; /* Neutral Scale */ --neutral-50: #FAFAFA; --neutral-100: #F5F5F5; --neutral-200: #E5E5E5; --neutral-300: #D4D4D4; --neutral-400: #A3A3A3; --neutral-500: #737373; --neutral-600: #525252; --neutral-700: #404040; --neutral-800: #262626; --neutral-900: #171717; /* Semantic Colors */ --color-success: #18A558; --color-warning: #F4A940; --color-error: #E8453C; --color-info: #2D5BE3; /* Background Colors */ --bg-primary: var(--neutral-50); --bg-secondary: var(--neutral-100); --bg-tertiary: var(--neutral-200); /* Text Colors */ --text-primary: var(--neutral-900); --text-secondary: var(--neutral-600); --text-tertiary: var(--neutral-400); /* Border Colors */ --border-light: var(--neutral-200); --border-medium: var(--neutral-300); --border-dark: var(--neutral-400); }

Quick Copy Snippets

Ready-to-use patterns for common scenarios.

Opacity Variants with RGB

:root { --primary-rgb: 45, 91, 227; } .overlay-light { background: rgba(var(--primary-rgb), 0.1); } .overlay-medium { background: rgba(var(--primary-rgb), 0.5); } .overlay-heavy { background: rgba(var(--primary-rgb), 0.9); }

Hover State Variations

:root { --primary: #2D5BE3; --primary-hover: #2349BE; --primary-active: #1A3799; } .button { background: var(--primary); transition: background 0.2s; } .button:hover { background: var(--primary-hover); } .button:active { background: var(--primary-active); }

System Preference Detection

/* Automatically respect user's OS preference */ @media (prefers-color-scheme: dark) { :root { --bg: #0F0F0F; --text: #FAFAFA; } }

Pro Tip

Use semantic names like --color-primary instead of --blue. This makes it easier to change your entire color scheme without touching your CSS.