CSS Custom Properties: Your Magic Paintbox 🎨
Imagine you have a magic paintbox. Instead of mixing the same blue color over and over, you mix it once, give it a name like “Sky Blue,” and use that name everywhere. When you want a different shade? Just change the original mix—everything updates instantly!
That’s exactly what CSS Custom Properties (also called CSS Variables) do for your styles.
What Are CSS Variables?
CSS Variables are like labeled jars in your paintbox. You put a value inside (a color, a size, anything!), give it a name, and use that name throughout your styles.
Why is this amazing?
- Change one jar → everything using it updates
- No more hunting through hundreds of lines
- Your code becomes easier to read and maintain
1. CSS Variables Declaration
The Magic Spell: -- (Double Dash)
To create a variable, start with two dashes followed by a name:
:root {
--main-color: #3498db;
--big-space: 20px;
--font-cool: 'Karla', sans-serif;
}
Simple Analogy
Think of :root as the master paintbox at the art room entrance. Everyone in the school can use colors from it!
graph TD A[":root #40;Master Paintbox#41;"] --> B["--main-color"] A --> C["--big-space"] A --> D["--font-cool"] B --> E["Used in buttons"] B --> F["Used in links"] C --> G["Used in cards"]
Quick Rules
| Rule | Example |
|---|---|
Must start with -- |
--my-var ✅ |
| Case-sensitive | --Color ≠ --color |
| Can hold any CSS value | colors, sizes, fonts |
2. Using var() Function
Open the Jar!
To use your variable, wrap it with var():
.button {
background: var(--main-color);
padding: var(--big-space);
font-family: var(--font-cool);
}
Real-Life Story
Before variables:
“I need to change the brand color. Let me search 47 files and replace #3498db everywhere…” 😩
After variables:
“I’ll just change
--main-coloronce. Done!” 🎉
/* Change this ONE line */
:root {
--main-color: #e74c3c;
}
/* Everything using var(--main-color)
now turns red automatically! */
3. Variable Fallback Values
The Safety Net
What if a variable doesn’t exist? Your design could break! That’s why var() has a backup plan:
.card {
/* If --card-bg doesn't exist,
use white instead */
background: var(--card-bg, white);
}
Multiple Fallbacks
You can even chain them:
.text {
color: var(--text-color,
var(--default-color, black));
}
Story Time: The Umbrella
You’re going outside. You check for your favorite blue umbrella (
--blue-umbrella). Not there? You grab any umbrella (--any-umbrella). Still nothing? You take the emergency raincoat (black).
graph TD A["Need a color"] --> B{"--text-color exists?"} B -->|Yes| C["Use --text-color"] B -->|No| D{"--default-color exists?"} D -->|Yes| E["Use --default-color"] D -->|No| F["Use black"]
4. Variable Scope
Where Can You Use Your Jars?
Variables follow scope rules—like how you can only use school supplies inside school!
Global Scope (Everyone Can Use)
:root {
--global-color: purple;
}
/* Available everywhere! */
Local Scope (Only This Area)
.navbar {
--nav-height: 60px;
}
/* Only .navbar and its children
can use --nav-height */
Visual Map
graph TD A[":root #40;Global#41;"] --> B["--brand-color: blue"] A --> C[".header"] A --> D[".main"] A --> E[".footer"] C --> F["Can use --brand-color ✅"] C --> G["--header-bg: gray<br>#40;Local to .header#41;"] D --> H["Can use --brand-color ✅"] D --> I["Cannot use --header-bg ❌"]
Override Example
Children can override parent variables:
:root {
--color: blue;
}
.special-section {
--color: red;
}
<div>Blue text</div>
<div class="special-section">
Red text here!
</div>
5. The @property Rule
Super-Powered Variables!
Regular variables are like plain jars. But @property creates smart jars that know:
- What type of value they hold
- What their starting value should be
- Whether children can inherit them
@property --my-angle {
syntax: '<angle>';
inherits: false;
initial-value: 0deg;
}
Why Is This Magical?
Animate custom properties! Regular variables can’t be animated, but @property ones can:
@property --gradient-angle {
syntax: '<angle>';
inherits: false;
initial-value: 0deg;
}
.rotating-bg {
background: linear-gradient(
var(--gradient-angle),
red, blue
);
transition: --gradient-angle 1s;
}
.rotating-bg:hover {
--gradient-angle: 180deg;
}
Property Options Explained
| Option | What It Does | Example |
|---|---|---|
syntax |
Type of value | '<color>', '<length>', '<number>' |
inherits |
Pass to children? | true or false |
initial-value |
Default value | Any valid value for the syntax |
Common Syntax Types
/* Colors */
@property --my-color {
syntax: '<color>';
inherits: true;
initial-value: black;
}
/* Lengths (px, em, rem, etc.) */
@property --my-size {
syntax: '<length>';
inherits: false;
initial-value: 0px;
}
/* Numbers */
@property --my-scale {
syntax: '<number>';
inherits: false;
initial-value: 1;
}
/* Percentages */
@property --my-opacity {
syntax: '<percentage>';
inherits: false;
initial-value: 100%;
}
Putting It All Together
Here’s a complete example combining everything:
/* 1. Declare with @property */
@property --card-shadow-blur {
syntax: '<length>';
inherits: false;
initial-value: 5px;
}
/* 2. Global variables in :root */
:root {
--primary: #667eea;
--spacing: 16px;
}
/* 3. Use with var() + fallback */
.card {
background: var(--card-bg, white);
padding: var(--spacing);
box-shadow: 0 4px
var(--card-shadow-blur)
rgba(0,0,0,0.1);
transition:
--card-shadow-blur 0.3s;
}
/* 4. Scoped override */
.card:hover {
--card-shadow-blur: 20px;
}
Quick Summary
| Feature | What It Does |
|---|---|
--name: value |
Declare a variable |
var(--name) |
Use a variable |
var(--name, fallback) |
Use with backup |
:root { } |
Global scope |
.class { --var } |
Local scope |
@property |
Type-safe, animatable variables |
You Did It! 🎉
You now understand CSS Custom Properties! You can:
✅ Create reusable variables
✅ Use them anywhere with var()
✅ Add safety nets with fallbacks
✅ Control where variables work with scope
✅ Create animatable, typed variables with @property
Go forth and make your CSS cleaner, smarter, and more magical! ✨
