What are CSS variables (custom properties)?
CSS variables, formally known as custom properties for cascading variables, are user-defined entities that allow authors to store specific values to be reused throughout a stylesheet. They significantly enhance the reusability, maintainability, and flexibility of CSS code by providing a native variable system.
What are CSS Variables?
CSS variables are a powerful feature that allows developers to define their own custom properties with specific values. These values can then be reused throughout a CSS document, making it easier to manage and update styles across a project.
Officially called 'custom properties,' they behave much like variables in other programming languages, holding a value that can be referred to later. This reduces repetition and makes stylesheets more organized and dynamic, especially for theming or complex designs.
Syntax
Custom properties are declared with a double-hyphen prefix (--) followed by the variable name and its value. They are typically declared within a CSS rule-set, often on the :root pseudo-class for global access.
:root {
--primary-color: #3498db;
--font-stack: 'Helvetica Neue', Helvetica, Arial, sans-serif;
--spacing-unit: 16px;
}
.component {
--component-bg: var(--primary-color); /* Variables can use other variables */
}
To use a custom property, you reference it using the var() function, passing the variable name as an argument. The browser will then substitute the var() function with the actual value of the custom property.
body {
font-family: var(--font-stack);
background-color: var(--background-color, #f4f4f4); /* Example with fallback */
}
.button {
background-color: var(--primary-color);
padding: var(--spacing-unit);
color: white;
}
Benefits
- Reusability: Define a value once and use it in multiple places, avoiding repetitive declarations for colors, fonts, or spacing.
- Maintainability: Easily update a theme, specific color, or spacing value by changing it in a single declaration, affecting all instances throughout the stylesheet.
- Dynamic Theming: Variables can be changed via JavaScript, enabling dynamic themes (e.g., dark/light mode toggle) or user-configurable styles directly in the browser.
- Cascading and Scope: They naturally inherit and cascade like standard CSS properties, allowing for localized variables within specific elements or components.
- Readability: Using meaningful variable names makes the CSS more self-documenting and easier for developers to understand and collaborate on.
Scope and Cascading
Like all CSS properties, custom properties are subject to the cascade. This means they can be declared on any element, and their value will be inherited by its descendants unless overridden by a more specific rule.
The most common practice is to declare global variables within the :root pseudo-class, which represents the <html> element. This makes them accessible throughout the entire document, providing a global scope.
:root {
--global-font-size: 16px;
}
.card {
--card-bg-color: lightgray; /* Scoped to .card and its children */
background-color: var(--card-bg-color);
font-size: var(--global-font-size);
}
.card-header {
--card-bg-color: gray; /* Overrides the .card variable for this element */
background-color: var(--card-bg-color);
}
Fallback Values
The var() function also accepts an optional second argument, which acts as a fallback value. If the specified custom property is not defined or evaluates to an invalid value, the fallback value will be used instead. This is useful for providing default styles or handling situations where a variable might not be set.
.element {
/* If --undefined-color is not found, red will be used */
color: var(--undefined-color, red);
}
.another-element {
/* If --primary-font is not found, sans-serif will be used */
font-family: var(--primary-font, sans-serif);
}
Browser Support
CSS custom properties are widely supported by all modern browsers (Chrome, Firefox, Safari, Edge, Opera) since around 2016-2017. The primary exception is Internet Explorer, which does not support them at all. For projects requiring IE support, a fallback mechanism (like using the second argument in var()) or a CSS pre-processor (like PostCSS) might be necessary to provide compatible styles.