html
/

CSS Variables (Custom Properties)

Last Sync: Today

On this page

15
0%
5 min read
Remaining
5 minleft

Click any section to jump — progress syncs automatically

html

CSS Variables (Custom Properties)

What are CSS Variables?

CSS custom properties (commonly called CSS variables) are entities that store specific values for reuse throughout a document. Unlike preprocessor variables (Sass/Less), CSS variables are dynamic, follow the cascade, can be updated at runtime, and are accessible via JavaScript.

Basic Syntax

CSSRead-only
1
:root {
  --primary-color: #3498db;
  --spacing-unit: 8px;
  --font-size-base: 16px;
  --border-radius: 4px;
}

.element {
  color: var(--primary-color);
  margin: var(--spacing-unit);
  font-size: var(--font-size-base);
  border-radius: var(--border-radius);
}

Declaration & Usage Patterns

ConceptSyntaxExampleScope
Declaration--name: value;--theme-dark: #1a1a1a;Element scope
Usagevar(--name)color: var(--theme-dark);Inherited
With fallbackvar(--name, fallback)color: var(--accent, blue);Fallback if undefined
Global scope:root { }Available everywhereDocument root
Local scope.component { }Available only in componentComponent tree

Scoping & Inheritance

CSSRead-only
1
/* Global scope (available everywhere) */
:root {
  --color: blue;
  --spacing: 8px;
}

/* Component scope (overrides global) */
.card {
  --color: darkblue;
  --spacing: 12px;
  color: var(--color); /* darkblue */
  padding: var(--spacing); /* 12px */
}

/* Nested scoping inherits from parent */
.parent {
  --size: 16px;
  --weight: normal;
}

.parent .child {
  font-size: var(--size); /* inherits 16px */
  font-weight: var(--weight); /* inherits normal */
}

/* Different values per instance */
.alert {
  --alert-color: red;
  --alert-bg: #ffeeee;
  background: var(--alert-bg);
  color: var(--alert-color);
}

.alert.warning {
  --alert-color: orange;
  --alert-bg: #fff0e0;
  /* Only affects this instance */
}

.alert.success {
  --alert-color: green;
  --alert-bg: #e0ffe0;
}

Fallback Values

CSSRead-only
1
/* Single fallback when variable not defined */
.element {
  color: var(--undefined-color, black);
  background: var(--theme-bg, white);
}

/* Nested fallbacks (cascading defaults) */
.element {
  padding: var(--spacing, var(--default-spacing, 16px));
  margin: var(--margin, 20px);
}

/* Multiple fallbacks for different scenarios */
.button {
  background: var(--button-bg, #0066cc);
  border-color: var(--button-border, var(--primary-color, #004499));
  color: var(--button-text, var(--text-light, white));
}

/* Invalid variable - uses fallback */
.element {
  /* If --bad-value is invalid/undefined, uses fallback */
  color: var(--bad-value, fallback, 16px); /* 'fallback' is used */
}

/* Fallback can be any valid CSS value */
.element {
  font-family: var(--custom-font, 'Arial', sans-serif);
  box-shadow: var(--shadow, 0 2px 4px rgba(0,0,0,0.1));
}

Dynamic Theming System

CSSRead-only
1
/* Light theme (default) */
:root {
  /* Backgrounds */
  --bg-primary: #ffffff;
  --bg-secondary: #f5f5f5;
  --bg-tertiary: #e8e8e8;
  
  /* Text colors */
  --text-primary: #1a1a1a;
  --text-secondary: #666666;
  --text-muted: #999999;
  
  /* Borders */
  --border-color: #e0e0e0;
  --border-focus: #3498db;
  
  /* Shadows */
  --shadow-sm: 0 1px 2px rgba(0,0,0,0.05);
  --shadow-md: 0 2px 4px rgba(0,0,0,0.1);
  --shadow-lg: 0 10px 15px rgba(0,0,0,0.1);
  
  /* Status colors */
  --success: #10b981;
  --warning: #f59e0b;
  --error: #ef4444;
  --info: #3b82f6;
}

/* Dark theme */
[data-theme="dark"] {
  --bg-primary: #1a1a1a;
  --bg-secondary: #2d2d2d;
  --bg-tertiary: #3d3d3d;
  
  --text-primary: #ffffff;
  --text-secondary: #b3b3b3;
  --text-muted: #808080;
  
  --border-color: #404040;
  --border-focus: #60a5fa;
  
  --shadow-sm: 0 1px 2px rgba(0,0,0,0.3);
  --shadow-md: 0 2px 4px rgba(0,0,0,0.4);
  --shadow-lg: 0 10px 15px rgba(0,0,0,0.5);
}

/* Applying theme variables */
body {
  background: var(--bg-primary);
  color: var(--text-primary);
  transition: background 0.3s ease, color 0.3s ease;
}

.card {
  background: var(--bg-secondary);
  border: 1px solid var(--border-color);
  box-shadow: var(--shadow-md);
  color: var(--text-secondary);
}

.card:hover {
  box-shadow: var(--shadow-lg);
}

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

.button-success {
  background: var(--success);
  color: white;
}

Responsive Design with Variables

CSSRead-only
1
:root {
  /* Mobile defaults */
  --spacing: 8px;
  --font-size: 14px;
  --container-width: 100%;
  --grid-columns: 1;
  --border-radius: 4px;
}

/* Tablet */
@media (min-width: 768px) {
  :root {
    --spacing: 12px;
    --font-size: 16px;
    --container-width: 90%;
    --grid-columns: 2;
    --border-radius: 6px;
  }
}

/* Desktop */
@media (min-width: 1024px) {
  :root {
    --spacing: 16px;
    --font-size: 18px;
    --container-width: 1200px;
    --grid-columns: 3;
    --border-radius: 8px;
  }
}

/* Large desktop */
@media (min-width: 1440px) {
  :root {
    --container-width: 1400px;
    --grid-columns: 4;
  }
}

/* Applying responsive variables */
.container {
  max-width: var(--container-width);
  padding: var(--spacing);
  margin: 0 auto;
}

body {
  font-size: var(--font-size);
}

.grid {
  display: grid;
  grid-template-columns: repeat(var(--grid-columns), 1fr);
  gap: var(--spacing);
}

.card {
  border-radius: var(--border-radius);
  padding: var(--spacing);
}

JavaScript Integration

JavaScriptRead-only
1
// Get CSS variable value
const root = document.documentElement;
const primaryColor = getComputedStyle(root).getPropertyValue('--primary-color');
console.log(primaryColor); // "#3498db"

// Get variable from specific element
const card = document.querySelector('.card');
const cardPadding = getComputedStyle(card).getPropertyValue('--card-padding');
console.log(cardPadding);

// Set CSS variable value
root.style.setProperty('--primary-color', '#ff6347');

// Set variable on specific element
card.style.setProperty('--card-padding', '20px');

// Set multiple variables dynamically
function setTheme(theme) {
  const colors = {
    light: { bg: '#fff', text: '#333', primary: '#3498db' },
    dark: { bg: '#1a1a1a', text: '#fff', primary: '#60a5fa' },
    forest: { bg: '#1a2e1a', text: '#e0e0e0', primary: '#4ade80' }
  };
  
  const themeColors = colors[theme];
  for (const [key, value] of Object.entries(themeColors)) {
    root.style.setProperty(`--color-${key}`, value);
  }
}

// Remove variable (reverts to inherited value)
card.style.removeProperty('--card-padding');

// Dynamic theme switching
document.getElementById('theme-toggle').addEventListener('click', () => {
  const currentTheme = document.documentElement.getAttribute('data-theme');
  const newTheme = currentTheme === 'dark' ? 'light' : 'dark';
  document.documentElement.setAttribute('data-theme', newTheme);
});

// React example
function ThemeSwitcher() {
  useEffect(() => {
    document.documentElement.style.setProperty('--primary-color', '#ff6347');
  }, []);
  
  return <div className="themed-component">Dynamic Theme</div>;
}

// Observing variable changes
const observer = new MutationObserver((mutations) => {
  mutations.forEach((mutation) => {
    if (mutation.attributeName === 'data-theme') {
      console.log('Theme changed to:', document.documentElement.getAttribute('data-theme'));
    }
  });
});

observer.observe(document.documentElement, { attributes: true });

Design System Implementation

CSSRead-only
1
/* Complete design token system */
:root {
  /* ===== Colors ===== */
  /* Primary palette */
  --color-primary-50: #eff6ff;
  --color-primary-100: #dbeafe;
  --color-primary-200: #bfdbfe;
  --color-primary-300: #93c5fd;
  --color-primary-400: #60a5fa;
  --color-primary-500: #3b82f6;
  --color-primary-600: #2563eb;
  --color-primary-700: #1d4ed8;
  --color-primary-800: #1e40af;
  --color-primary-900: #1e3a8a;
  
  /* Semantic colors */
  --color-primary: var(--color-primary-500);
  --color-primary-dark: var(--color-primary-700);
  --color-secondary: #8b5cf6;
  --color-success: #10b981;
  --color-warning: #f59e0b;
  --color-error: #ef4444;
  --color-info: #06b6d4;
  
  /* ===== Spacing scale ===== */
  --space-0: 0;
  --space-1: 4px;
  --space-2: 8px;
  --space-3: 12px;
  --space-4: 16px;
  --space-5: 20px;
  --space-6: 24px;
  --space-8: 32px;
  --space-10: 40px;
  --space-12: 48px;
  --space-16: 64px;
  --space-20: 80px;
  --space-24: 96px;
  
  /* ===== Typography ===== */
  --font-sans: system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
  --font-serif: Georgia, 'Times New Roman', serif;
  --font-mono: 'Courier New', monospace;
  
  --text-xs: 12px;
  --text-sm: 14px;
  --text-base: 16px;
  --text-lg: 18px;
  --text-xl: 20px;
  --text-2xl: 24px;
  --text-3xl: 30px;
  --text-4xl: 36px;
  --text-5xl: 48px;
  
  --font-weight-normal: 400;
  --font-weight-medium: 500;
  --font-weight-semibold: 600;
  --font-weight-bold: 700;
  
  --line-height-tight: 1.25;
  --line-height-normal: 1.5;
  --line-height-loose: 1.75;
  
  /* ===== Shadows ===== */
  --shadow-xs: 0 1px 2px rgba(0,0,0,0.05);
  --shadow-sm: 0 1px 3px rgba(0,0,0,0.1);
  --shadow-md: 0 4px 6px rgba(0,0,0,0.07);
  --shadow-lg: 0 10px 15px rgba(0,0,0,0.1);
  --shadow-xl: 0 20px 25px rgba(0,0,0,0.1);
  --shadow-2xl: 0 25px 50px rgba(0,0,0,0.25);
  
  /* ===== Border Radius ===== */
  --radius-none: 0;
  --radius-sm: 2px;
  --radius-md: 4px;
  --radius-lg: 8px;
  --radius-xl: 12px;
  --radius-2xl: 16px;
  --radius-full: 9999px;
  
  /* ===== Transitions ===== */
  --transition-fast: 150ms ease;
  --transition-base: 250ms ease;
  --transition-slow: 350ms ease;
}

/* Component usage */
.button {
  background: var(--color-primary);
  padding: var(--space-2) var(--space-4);
  border-radius: var(--radius-md);
  font-family: var(--font-sans);
  font-size: var(--text-sm);
  font-weight: var(--font-weight-medium);
  box-shadow: var(--shadow-sm);
  transition: all var(--transition-fast);
}

.button:hover {
  background: var(--color-primary-dark);
  box-shadow: var(--shadow-md);
  transform: translateY(-1px);
}

.button-large {
  padding: var(--space-3) var(--space-6);
  font-size: var(--text-base);
}

.card {
  background: white;
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-md);
  padding: var(--space-6);
}

.card-title {
  font-size: var(--text-xl);
  font-weight: var(--font-weight-semibold);
  margin-bottom: var(--space-4);
  line-height: var(--line-height-tight);
}

Advanced Techniques

CSSRead-only
1
/* 1. Variables in calc() */
:root {
  --base-unit: 8px;
  --multiplier: 2;
  --scale: 1.5;
}

.element {
  padding: calc(var(--base-unit) * var(--multiplier));
  margin: calc(var(--spacing) + var(--base-unit));
  font-size: calc(var(--text-base) * var(--scale));
}

/* 2. CSS variables with custom properties animation */
@property --gradient-angle {
  syntax: '<angle>';
  inherits: false;
  initial-value: 0deg;
}

.gradient-box {
  --gradient-start: #3498db;
  --gradient-end: #e74c3c;
  background: linear-gradient(var(--gradient-angle), var(--gradient-start), var(--gradient-end));
  transition: --gradient-angle 0.5s ease;
}

.gradient-box:hover {
  --gradient-angle: 180deg;
}

/* 3. Conditional styling with variables */
.message {
  --type: info;
  --message-bg: var(--info-bg, #e0f2fe);
  --message-color: var(--info-color, #0369a1);
  background: var(--message-bg);
  color: var(--message-color);
  border-left: 4px solid var(--message-border, var(--color-info));
}

.message[data-type="error"] {
  --type: error;
  --message-bg: #fee2e2;
  --message-color: #991b1b;
  --message-border: var(--color-error);
}

.message[data-type="success"] {
  --type: success;
  --message-bg: #dcfce7;
  --message-color: #166534;
  --message-border: var(--color-success);
}

/* 4. Variable-based animations */
@keyframes slide {
  from { 
    transform: translateX(var(--start-x, 0));
    opacity: var(--start-opacity, 0);
  }
  to { 
    transform: translateX(var(--end-x, 100px));
    opacity: var(--end-opacity, 1);
  }
}

.animated {
  --start-x: -50px;
  --end-x: 0;
  --start-opacity: 0;
  --end-opacity: 1;
  animation: slide 0.3s ease forwards;
}

/* 5. Dynamic progress bar */
.progress {
  --progress: 50%;
  width: 100%;
  background: #e0e0e0;
  border-radius: var(--radius-full);
  overflow: hidden;
}

.progress-bar {
  width: var(--progress);
  background: var(--color-primary);
  padding: var(--space-1);
  transition: width 0.3s ease;
}

/* 6. CSS variables with container queries */
@container (min-width: 400px) {
  .card {
    --card-padding: var(--space-6);
    --card-font-size: var(--text-lg);
  }
}

.card {
  padding: var(--card-padding, var(--space-4));
  font-size: var(--card-font-size, var(--text-base));
}

Best Practices

  • Use semantic naming – --color-primary not --blue-500 (except design tokens)
  • Group by category – Colors, spacing, typography, shadows, etc.
  • Provide fallbacks – Critical for older browsers and defensive programming
  • Avoid over-nesting – Deep variable dependencies are hard to debug
  • Use for theming – Perfect for light/dark mode and brand variations
  • Document your variables – Create a living style guide
  • Combine with calc() – Powerful dynamic sizing and spacing
  • Use kebab-case – CSS is case-sensitive, kebab-case is conventional
  • Set variables as high as needed – :root for global, components for local
  • Avoid overusing !important – Breaks variable cascade benefits
  • Test fallbacks – Ensure graceful degradation in unsupported browsers
  • Use @property for type checking – Enables smooth transitions of custom properties

Common Mistakes

  • CamelCase naming – Variables are case-sensitive (--myVar ≠ --myvar). Use kebab-case.
  • Missing var() wrapper – Using --color instead of var(--color)
  • Spacing issues – var(--color) not var( --color )
  • Assuming IE support – IE doesn't support CSS variables (have fallbacks)
  • Overusing !important – Breaks variable cascade and inheritance
  • Not using fallbacks – Variables can be undefined or invalid
  • Overly specific selectors – Increases specificity and reduces reusability
  • Mutation without transition – Variables can be transitioned with @property
  • Using variables in media query conditions – Media queries don't support var()
  • Creating circular dependencies – --a: var(--b); --b: var(--a); (invalid)

Browser Support & Fallbacks

CSSRead-only
1
/* Feature detection with @supports */
.element {
  /* Fallback for older browsers */
  background: #3498db;
  color: white;
}

@supports (--css: variables) {
  .element {
    background: var(--primary-color, #3498db);
    color: var(--text-color, white);
  }
}

/* PostCSS fallback example (for IE support) */
.button {
  background: #0066cc; /* Fallback */
  background: var(--button-bg, #0066cc);
  padding: 10px; /* Fallback */
  padding: var(--button-padding, 10px);
}

/* Using @property for better type checking (modern browsers) */
@property --primary-color {
  syntax: '<color>';
  inherits: true;
  initial-value: #3498db;
}

@property --spacing {
  syntax: '<length>';
  inherits: false;
  initial-value: 8px;
}

/* Progressive enhancement pattern */
.feature {
  /* Basic styles for all browsers */
  width: 100%;
  
  /* Enhanced styles for modern browsers */
  @supports (width: calc(100% - var(--spacing, 0px))) {
    width: calc(100% - var(--spacing, 20px));
    margin: var(--spacing, 20px);
  }
}

Real-World Complete Example

HTMLRead-only
1
<!-- HTML -->
<div class="theme-switcher">
  <button data-theme="light">☀️ Light</button>
  <button data-theme="dark">🌙 Dark</button>
  <button data-theme="forest">🌲 Forest</button>
  <button data-theme="ocean">🌊 Ocean</button>
</div>

<div class="card">
  <img class="card__image" src="https://picsum.photos/300/200" alt="Demo">
  <div class="card__content">
    <h3 class="card__title">Dynamic Themed Card</h3>
    <p class="card__description">
      This card responds to theme changes using CSS variables.
      The colors, spacing, and shadows all update dynamically.
    </p>
    <div class="card__actions">
      <button class="button button--primary">Learn More</button>
      <button class="button button--secondary">Dismiss</button>
    </div>
  </div>
</div>

<div class="progress">
  <div class="progress-bar" style="--progress: 75%"></div>
</div>

<div class="message" data-type="success">
  ✓ Operation completed successfully!
</div>
CSSRead-only
1
/* CSS */
:root {
  /* Light theme (default) */
  --bg-primary: #ffffff;
  --bg-secondary: #f8f9fa;
  --text-primary: #212529;
  --text-secondary: #6c757d;
  --border-color: #dee2e6;
  --card-bg: #ffffff;
  --primary-color: #3498db;
  --secondary-color: #95a5a6;
  --shadow: 0 2px 8px rgba(0,0,0,0.1);
  --transition: all 0.3s ease;
}

[data-theme="dark"] {
  --bg-primary: #1a1a1a;
  --bg-secondary: #2d2d2d;
  --text-primary: #ffffff;
  --text-secondary: #b3b3b3;
  --border-color: #404040;
  --card-bg: #2d2d2d;
  --primary-color: #60a5fa;
  --secondary-color: #6b7280;
  --shadow: 0 2px 8px rgba(0,0,0,0.3);
}

[data-theme="forest"] {
  --bg-primary: #1a2e1a;
  --bg-secondary: #2a3e2a;
  --text-primary: #e0e0e0;
  --text-secondary: #a0a0a0;
  --border-color: #3a4e3a;
  --card-bg: #2a3e2a;
  --primary-color: #4ade80;
  --secondary-color: #22c55e;
  --shadow: 0 2px 8px rgba(0,0,0,0.3);
}

[data-theme="ocean"] {
  --bg-primary: #1a2a3e;
  --bg-secondary: #2a3a4e;
  --text-primary: #e0e0e0;
  --text-secondary: #a0b0c0;
  --border-color: #3a4a5e;
  --card-bg: #2a3a4e;
  --primary-color: #38bdf8;
  --secondary-color: #0284c7;
  --shadow: 0 2px 8px rgba(0,0,0,0.3);
}

body {
  background: var(--bg-primary);
  color: var(--text-primary);
  font-family: system-ui;
  transition: var(--transition);
  padding: 20px;
}

.card {
  background: var(--card-bg);
  border: 1px solid var(--border-color);
  border-radius: 12px;
  overflow: hidden;
  max-width: 400px;
  margin: 20px auto;
  box-shadow: var(--shadow);
  transition: var(--transition);
}

.card:hover {
  transform: translateY(-4px);
  box-shadow: 0 4px 12px rgba(0,0,0,0.2);
}

.card__image {
  width: 100%;
  height: 200px;
  object-fit: cover;
}

.card__content {
  padding: 20px;
}

.card__title {
  margin: 0 0 10px 0;
  color: var(--text-primary);
}

.card__description {
  color: var(--text-secondary);
  line-height: 1.5;
  margin-bottom: 20px;
}

.card__actions {
  display: flex;
  gap: 10px;
}

.button {
  padding: 8px 16px;
  border: none;
  border-radius: 6px;
  cursor: pointer;
  font-weight: 500;
  transition: var(--transition);
}

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

.button--secondary {
  background: var(--secondary-color);
  color: white;
}

.button:hover {
  transform: translateY(-1px);
  filter: brightness(1.05);
}

.progress {
  max-width: 400px;
  margin: 20px auto;
  background: var(--border-color);
  border-radius: 10px;
  overflow: hidden;
}

.progress-bar {
  width: var(--progress, 0%);
  height: 20px;
  background: var(--primary-color);
  transition: width 0.3s ease;
}

.message {
  max-width: 400px;
  margin: 20px auto;
  padding: 12px;
  border-radius: 8px;
  border-left: 4px solid;
}

.message[data-type="success"] {
  background: #dcfce7;
  color: #166534;
  border-left-color: #10b981;
}

.theme-switcher {
  display: flex;
  gap: 10px;
  justify-content: center;
  margin-bottom: 30px;
}

.theme-switcher button {
  padding: 8px 16px;
  background: var(--primary-color);
  color: white;
  border: none;
  border-radius: 6px;
  cursor: pointer;
  transition: var(--transition);
}

.theme-switcher button:hover {
  transform: translateY(-2px);
}
JavaScriptRead-only
1
// JavaScript
const buttons = document.querySelectorAll('[data-theme]');
buttons.forEach(button => {
  button.addEventListener('click', () => {
    const theme = button.getAttribute('data-theme');
    document.documentElement.setAttribute('data-theme', theme);
    localStorage.setItem('theme', theme);
    
    // Optional: dispatch event for other components
    window.dispatchEvent(new CustomEvent('themechange', { detail: { theme } }));
  });
});

// Load saved theme
const savedTheme = localStorage.getItem('theme') || 'light';
document.documentElement.setAttribute('data-theme', savedTheme);

// Dynamic progress update
let progress = 0;
const interval = setInterval(() => {
  progress = (progress + 10) % 110;
  document.querySelector('.progress-bar').style.setProperty('--progress', `${progress}%`);
  if (progress >= 100) clearInterval(interval);
}, 500);

// Listen for theme changes
window.addEventListener('themechange', (e) => {
  console.log(`Theme changed to: ${e.detail.theme}`);
  // Analytics tracking
  // Update other UI components
});

Conclusion

CSS variables revolutionize how we write and maintain CSS. They enable dynamic theming, reduce repetition, make responsive design more manageable, and provide a bridge between CSS and JavaScript. With near-universal browser support (except IE), CSS custom properties are essential for modern frontend development. Use them for design systems, theme switching, responsive designs, and creating more maintainable, scalable stylesheets. Combine with JavaScript for powerful interactive experiences, and always provide fallbacks for legacy browsers.

Try it yourself

:root {
  --primary: #3498db;
  --secondary: #2ecc71;
  --spacing: 8px;
  --border-radius: 8px;
  --shadow: 0 2px 4px rgba(0,0,0,0.1);
  --font-size: 16px;
}

.demo {
  background: var(--primary);
  color: white;
  padding: calc(var(--spacing) * 2);
  border-radius: var(--border-radius);
  box-shadow: var(--shadow);
  text-align: center;
  transition: all 0.3s ease;
  font-family: system-ui;
  font-size: var(--font-size);
}

.demo:hover {
  --primary: #e74c3c;
  --spacing: 16px;
  --shadow: 0 8px 16px rgba(0,0,0,0.2);
  --font-size: 20px;
}

/* Try modifying the variables above or adding new ones! */
/* Variables can be updated in :root or specific elements */
/* They cascade down to children and can be used in calc() */

Test Your Knowledge

Q1
of 7

How do you declare a CSS variable?

A
$variable: value;
B
@variable: value;
C
--variable: value;
D
#variable: value;
Q2
of 7

How do you use a CSS variable?

A
$variable
B
var(--variable)
C
@variable
D
var($variable)
Q3
of 7

Where should global variables typically be declared?

A
html {}
B
body {}
C
:root {}
D
* {}
Q4
of 7

Which browsers don't support CSS variables?

A
Chrome
B
Firefox
C
Safari
D
Internet Explorer
Q5
of 7

Can CSS variables be updated with JavaScript?

A
No
B
Yes, with element.style.setProperty()
C
Only in Chrome
D
Yes, but only in :root
Q6
of 7

What's the recommended naming convention for CSS variables?

A
camelCase
B
PascalCase
C
kebab-case
D
snake_case
Q7
of 7

Can CSS variables be used in calc()?

A
No
B
Yes, always
C
Only with numbers
D
Only in Chrome

Frequently Asked Questions

Are CSS variables case-sensitive?

Yes! --primary-color and --Primary-Color are different variables. The convention is kebab-case.

Do CSS variables work in Internet Explorer?

No, Internet Explorer doesn't support CSS variables. Always provide fallback values for critical properties when supporting IE.

Can I use CSS variables in media queries?

No, media queries don't support CSS variables directly. But you can set different variable values inside media query blocks.

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

CSS variables are dynamic and work at runtime, can be updated with JavaScript, follow DOM inheritance, and are native to browsers. Preprocessor variables (Sass/Less) are static, compile at build time, and can't be changed at runtime.

Can CSS variables be animated?

Yes! With @property, CSS variables can be smoothly animated with transitions, enabling gradient and color animations that were previously impossible.

What's the scope of CSS variables?

CSS variables follow the cascade and inheritance. They're scoped to the element they're declared on and inherited by descendants, similar to regular CSS properties.

Can I use CSS variables in SVG?

Yes, CSS variables work in inline SVG and can be used to style SVG elements dynamically.

How many CSS variables can I create?

No practical limit, but performance can be affected by thousands of variables. Use them judiciously for theming and design tokens.

Previous

css filters

Next

css calc

Related Content

Need help?

Explore our comprehensive docs or start a chat with our tech experts.