CSS variables (also called custom properties) are powerful tools for creating maintainable and dynamic styles. When combined with JavaScript, they enable real-time style updates without directly manipulating individual CSS properties. This guide shows you how to get CSS variables and change CSS variables using JavaScript.
What Are CSS Variables?
CSS variables are custom properties defined with a double hyphen prefix (--variable-name) that can
be reused throughout your stylesheet. They're typically defined in the :root selector for global
access.
:root {
--primary-color: #3498db;
--font-size: 16px;
--spacing: 20px;
}
.element {
color: var(--primary-color);
font-size: var(--font-size);
margin: var(--spacing);
}
Getting CSS Variables with JavaScript
To get a CSS variable value in JavaScript, use getComputedStyle() combined
with getPropertyValue(). This
reads the computed value of the CSS variable.
Basic Usage
// Get CSS variable from :root (document.documentElement)
const rootStyles = getComputedStyle(document.documentElement);
const primaryColor = rootStyles.getPropertyValue('--primary-color');
console.log(primaryColor); // "#3498db" (includes spaces, use trim() to remove)
// Get CSS variable from a specific element
const element = document.querySelector('.my-element');
const elementStyles = getComputedStyle(element);
const fontSize = elementStyles.getPropertyValue('--font-size').trim();
console.log(fontSize); // "16px"
Helper Function
// Helper function to get CSS variable
function getCSSVariable(variableName, element = document.documentElement) {
return getComputedStyle(element)
.getPropertyValue(variableName)
.trim();
}
// Usage
const primaryColor = getCSSVariable('--primary-color');
const fontSize = getCSSVariable('--font-size');
const spacing = getCSSVariable('--spacing', document.querySelector('.container'));
console.log(primaryColor); // "#3498db"
console.log(fontSize); // "16px"
console.log(spacing); // "20px"
Getting Multiple Variables
// Get multiple CSS variables at once
function getCSSVariables(variableNames, element = document.documentElement) {
const styles = getComputedStyle(element);
const variables = {};
variableNames.forEach(name => {
variables[name] = styles.getPropertyValue(name).trim();
});
return variables;
}
// Usage
const theme = getCSSVariables([
'--primary-color',
'--secondary-color',
'--font-size',
'--spacing'
]);
console.log(theme);
// {
// '--primary-color': '#3498db',
// '--secondary-color': '#2ecc71',
// '--font-size': '16px',
// '--spacing': '20px'
// }
Changing CSS Variables with JavaScript
To change a CSS variable, use the setProperty() method on an
element's style object.
This updates the variable value, and all elements using that variable will reflect the change.
Basic Usage
// Change CSS variable on :root
document.documentElement.style.setProperty('--primary-color', '#e74c3c');
// Change CSS variable on a specific element
const element = document.querySelector('.my-element');
element.style.setProperty('--font-size', '20px');
// Change CSS variable with priority (important)
document.documentElement.style.setProperty('--spacing', '30px', 'important');
Helper Function
// Helper function to set CSS variable
function setCSSVariable(variableName, value, element = document.documentElement) {
element.style.setProperty(variableName, value);
}
// Usage
setCSSVariable('--primary-color', '#e74c3c');
setCSSVariable('--font-size', '20px');
setCSSVariable('--spacing', '30px', document.querySelector('.container'));
Removing CSS Variables
// Remove a CSS variable (resets to initial value)
document.documentElement.style.removeProperty('--primary-color');
// Or set to empty string
document.documentElement.style.setProperty('--primary-color', '');
Practical Examples
Example 1: Dynamic Theme Switcher
// Theme switcher using CSS variables
const themes = {
light: {
'--bg-color': '#ffffff',
'--text-color': '#333333',
'--primary-color': '#3498db'
},
dark: {
'--bg-color': '#1a1a1a',
'--text-color': '#ffffff',
'--primary-color': '#9b59b6'
}
};
function setTheme(themeName) {
const theme = themes[themeName];
if (!theme) return;
Object.entries(theme).forEach(([variable, value]) => {
document.documentElement.style.setProperty(variable, value);
});
}
// Usage
setTheme('dark');
setTheme('light');
Example 2: Interactive Color Picker
// Update CSS variable from color input
const colorPicker = document.querySelector('#color-picker');
colorPicker.addEventListener('input', (e) => {
const color = e.target.value;
document.documentElement.style.setProperty('--primary-color', color);
});
// HTML: <input type="color" id="color-picker" value="#3498db">
Example 3: Responsive Spacing Control
// Adjust spacing with range input
const spacingSlider = document.querySelector('#spacing-slider');
spacingSlider.addEventListener('input', (e) => {
const spacing = `${e.target.value}px`;
document.documentElement.style.setProperty('--spacing', spacing);
// Display current value
const currentSpacing = getComputedStyle(document.documentElement)
.getPropertyValue('--spacing')
.trim();
console.log(`Current spacing: ${currentSpacing}`);
});
// HTML: <input type="range" id="spacing-slider" min="10" max="50" value="20">
Example 4: Real-time Font Size Adjustment
// Font size control
function adjustFontSize(delta) {
const currentSize = parseInt(
getComputedStyle(document.documentElement)
.getPropertyValue('--font-size')
.trim()
);
const newSize = currentSize + delta;
document.documentElement.style.setProperty('--font-size', `${newSize}px`);
}
// Usage with buttons
document.querySelector('#increase-font').addEventListener('click', () => {
adjustFontSize(2);
});
document.querySelector('#decrease-font').addEventListener('click', () => {
adjustFontSize(-2);
});
Example 5: Animation with CSS Variables
// Animate CSS variable value
function animateVariable(variableName, from, to, duration = 1000) {
const startTime = performance.now();
const element = document.documentElement;
function animate(currentTime) {
const elapsed = currentTime - startTime;
const progress = Math.min(elapsed / duration, 1);
// Linear interpolation
const current = from + (to - from) * progress;
element.style.setProperty(variableName, current);
if (progress < 1) {
requestAnimationFrame(animate);
}
}
requestAnimationFrame(animate);
}
// Usage: animate --primary-color from #3498db to #e74c3c
animateVariable('--primary-color', '#3498db', '#e74c3c', 2000);
Complete Interactive Example
Here's a complete example combining getting and setting CSS variables:
<!-- HTML -->
<div class="controls">
<label>Primary Color:</label>
<input type="color" id="primary-color" value="#3498db">
<label>Font Size:</label>
<input type="range" id="font-size" min="12" max="24" value="16">
<span id="font-size-display">16px</span>
<button id="reset">Reset</button>
</div>
<div class="content">
<p>This text uses CSS variables!</p>
</div>
/* CSS */
:root {
--primary-color: #3498db;
--font-size: 16px;
}
.content {
color: var(--primary-color);
font-size: var(--font-size);
}
// JavaScript
// Get initial values
const initialColor = getComputedStyle(document.documentElement)
.getPropertyValue('--primary-color')
.trim();
const initialSize = getComputedStyle(document.documentElement)
.getPropertyValue('--font-size')
.trim();
// Color picker
document.querySelector('#primary-color').addEventListener('input', (e) => {
document.documentElement.style.setProperty('--primary-color', e.target.value);
});
// Font size slider
const fontSizeSlider = document.querySelector('#font-size');
const fontSizeDisplay = document.querySelector('#font-size-display');
fontSizeSlider.addEventListener('input', (e) => {
const size = `${e.target.value}px`;
document.documentElement.style.setProperty('--font-size', size);
fontSizeDisplay.textContent = size;
});
// Reset button
document.querySelector('#reset').addEventListener('click', () => {
document.documentElement.style.setProperty('--primary-color', initialColor);
document.documentElement.style.setProperty('--font-size', initialSize);
document.querySelector('#primary-color').value = initialColor;
fontSizeSlider.value = parseInt(initialSize);
fontSizeDisplay.textContent = initialSize;
});
Best Practices
1. Use :root for Global Variables
Define global CSS variables in :root for easy access and
modification:
:root {
--primary-color: #3498db;
--secondary-color: #2ecc71;
--spacing: 20px;
}
2. Always Trim Values
getPropertyValue()
returns values with leading/trailing spaces. Always use .trim():
// Good
const value = getComputedStyle(element)
.getPropertyValue('--variable')
.trim();
// Bad - may include unwanted spaces
const value = getComputedStyle(element).getPropertyValue('--variable');
3. Cache getComputedStyle() Results
For performance, cache getComputedStyle() results
when reading multiple variables:
// Good - cache the result
const styles = getComputedStyle(document.documentElement);
const color = styles.getPropertyValue('--primary-color').trim();
const size = styles.getPropertyValue('--font-size').trim();
// Bad - calls getComputedStyle() multiple times
const color = getComputedStyle(document.documentElement)
.getPropertyValue('--primary-color')
.trim();
const size = getComputedStyle(document.documentElement)
.getPropertyValue('--font-size')
.trim();
4. Use setProperty() for Dynamic Updates
Always use setProperty() instead of
directly setting style properties:
// Good
element.style.setProperty('--primary-color', '#e74c3c');
// Bad - doesn't work for CSS variables
element.style['--primary-color'] = '#e74c3c';
5. Handle Missing Variables
Always check if a CSS variable exists before using it:
function getCSSVariable(variableName, element = document.documentElement) {
const value = getComputedStyle(element)
.getPropertyValue(variableName)
.trim();
if (!value) {
console.warn(`CSS variable ${variableName} not found`);
return null;
}
return value;
}
Common Issues and Solutions
Issue 1: Variable Returns Empty String
Problem: getPropertyValue() returns
an empty string if the variable doesn't exist.
// Solution: Check for empty string
const value = getComputedStyle(document.documentElement)
.getPropertyValue('--non-existent')
.trim();
if (value) {
console.log(value);
} else {
console.log('Variable not found');
}
Issue 2: Variable Not Updating
Problem: Changes to CSS variables might not reflect if the element doesn't use the variable.
// Make sure the element actually uses the CSS variable
// CSS
.element {
color: var(--primary-color); /* Must use var() */
}
// JavaScript
document.documentElement.style.setProperty('--primary-color', '#e74c3c');
// Now .element will update
Issue 3: Performance with Frequent Updates
Problem: Calling setProperty() in rapid
succession can cause performance issues.
// Solution: Debounce or throttle updates
function debounce(func, wait) {
let timeout;
return function executedFunction(...args) {
const later = () => {
clearTimeout(timeout);
func(...args);
};
clearTimeout(timeout);
timeout = setTimeout(later, wait);
};
}
const updateVariable = debounce((variable, value) => {
document.documentElement.style.setProperty(variable, value);
}, 100);
// Usage
slider.addEventListener('input', (e) => {
updateVariable('--spacing', `${e.target.value}px`);
});
Browser Compatibility
CSS variables and JavaScript methods have excellent browser support:
- CSS Variables: All modern browsers (Chrome 49+, Firefox 31+, Safari 9.1+, Edge 15+)
- getComputedStyle(): All browsers (IE9+)
- setProperty(): All browsers (IE9+)
Conclusion
CSS variables combined with JavaScript provide a powerful way to create dynamic, interactive styling. By using
getComputedStyle().getPropertyValue()
to read variables and setProperty() to update
them, you can build theme switchers, color pickers, responsive controls, and real-time style adjustments without
directly manipulating individual CSS properties.
Remember to always trim values when reading CSS variables, cache getComputedStyle() results
for performance, and handle edge cases like missing variables. With these techniques, you'll be able to create
more maintainable and interactive web applications.