CSS Weekly

Subscribe
Archives
July 10, 2025

CSS Weekly #3: CSS Custom Properties Deep Dive

CSS Weekly #3: CSS Custom Properties Deep Dive 🎯

Hey ,

CSS Custom Properties (aka CSS Variables) are more powerful than you might think. Let's go beyond --primary-color and explore what's really possible!

Beyond Basic Variables

Most tutorials stop here:

:root {
  --primary-color: #007bff;
  --spacing: 1rem;
}

But we're just getting started!

🚀 Advanced Techniques

1. Scoped Properties

.card {
  --card-padding: 1rem;
  padding: var(--card-padding);
}

.card.compact {
  --card-padding: 0.5rem;
  /* Padding automatically updates! */
}

2. Calculated Properties

.container {
  --base: 4px;
  --scale: 1.5;

  padding: calc(var(--base) * var(--scale));
  margin: calc(var(--base) * var(--scale) * 2);
}

3. Property Toggles (Mind = Blown 🤯)

.element {
  --show: 1;
  opacity: var(--show);
  transform: scale(var(--show));

  /* Hide element by changing one property! */
  &.hidden {
    --show: 0;
  }
}

Real-World Example: Theme Switching

Here's my favorite pattern for theme switching:

:root {
  /* Light theme (default) */
  --bg: #ffffff;
  --text: #333333;
  --surface: #f5f5f5;

  /* Store dark theme values */
  --dark-bg: #1a1a1a;
  --dark-text: #e0e0e0;
  --dark-surface: #2d2d2d;
}

/* Apply dark theme */
[data-theme="dark"] {
  --bg: var(--dark-bg);
  --text: var(--dark-text);
  --surface: var(--dark-surface);
}

/* Use semantic variables everywhere */
body {
  background: var(--bg);
  color: var(--text);
}

🎨 Dynamic Properties with JavaScript

The real magic happens when you combine CSS Variables with JS:

// Reactive mouse-follow effect
document.addEventListener('mousemove', (e) => {
  document.body.style.setProperty('--mouse-x', e.clientX + 'px');
  document.body.style.setProperty('--mouse-y', e.clientY + 'px');
});
.cursor-glow {
  position: fixed;
  left: var(--mouse-x);
  top: var(--mouse-y);
  transform: translate(-50%, -50%);
}

Performance Tip

Custom Properties are inherited, so be strategic:

/* ❌ Don't: Causes unnecessary inheritance */
:root {
  --card-specific-padding: 1rem;
}

/* ✅ Do: Scope to where needed */
.card {
  --padding: 1rem;
}

This Week's Challenge

Create a "sizing system" using custom properties:

:root {
  --size-base: 1rem;
  --size-scale: 1.25;
  --size-xs: calc(var(--size-base) / var(--size-scale));
  --size-sm: var(--size-base);
  --size-md: calc(var(--size-base) * var(--size-scale));
  /* Continue the pattern... */
}

🔥 Hot Tip: Space Toggles

This blew my mind when I first saw it:

.button {
  /* Note the space after the fallback! */
  --primary: ;
  background: var(--primary, lightgray);
}

.button.primary {
  --primary: blue;
}

Empty custom property + fallback = conditional styles!


This week's sponsor: Polypane - The browser for ambitious developers. Test all viewports at once! Use code CSSWEEKLY for 20% off.

Next week: Advanced animations with @keyframes!

— Sarah from CSS Weekly

P.S. What's your favorite custom property trick? Reply and share!

Unsubscribe | Sponsor CSS Weekly

Don't miss what's next. Subscribe to CSS Weekly:
Start the conversation:
Powered by Buttondown, the easiest way to start and grow your newsletter.