CSS var() Function

The CSS var() function inserts the value of a CSS custom property into another property declaration.

It allows reusable values for colors, spacing, sizes, fonts, and other CSS settings. The function can also provide a fallback when a custom property is missing or has an invalid computed value.

Syntax

var(--custom-property)
var(--custom-property, fallback)

The first argument is the name of a custom property. The optional second argument supplies a fallback value.

Examples:

color: var(--text-color);
background-color: var(--primary-color, #3498db);
padding: var(--spacing, 20px);
font-size: var(--font-size, 1rem);
width: var(--content-width, 100%);

Custom property names begin with two hyphens (--) and are case-sensitive.

For example, --main-color and --Main-Color are different custom properties.

The var() function is used within CSS property values and cannot replace a property name, selector, or at-rule name.

Parameters

The var() function accepts one required argument and one optional fallback.

Parameter Description
--custom-property Required. The name of the custom property whose value should be substituted.
fallback Optional. A replacement value used when the referenced custom property has the guaranteed-invalid value.

For example:

.box {
  color: var(--text-color, #333);
}

If --text-color is not defined, the browser uses #333.

The fallback may contain commas because everything after the first separating comma belongs to the fallback.

For example:

.box {
  font-family: var(--font-stack, Arial, Helvetica, sans-serif);
}

The fallback is the complete font-family list.

A fallback can also be empty:

var(--optional-value,)

This substitutes an empty sequence of tokens when the referenced custom property is unavailable.

How It Works

The var() function substitutes the computed value of a custom property into another CSS declaration.

For example:

:root {
  --primary-color: #3498db;
}
.button {
  background-color: var(--primary-color);
}

The --primary-color custom property stores the color value.

The var() function retrieves that value when the browser computes the button's background color.

Changing the custom property updates declarations that depend on it:

:root {
  --primary-color: #16a085;
}

The button now uses the new color without requiring a change to its background-color declaration.

Custom properties participate in the CSS cascade and inheritance rules.

The browser resolves var() references at computed-value time, allowing values to depend on the element's inherited and locally defined custom properties.

Defining Custom Properties

Custom properties are defined using property names that begin with two hyphens.

For example:

:root {
  --primary-color: #3498db;
  --secondary-color: #16a085;
  --text-color: #333;
  --spacing: 20px;
  --border-radius: 6px;
}

Defining custom properties on :root makes them available through inheritance to elements throughout the document unless they are overridden.

The values can then be used with var():

.card {
  padding: var(--spacing);
  color: var(--text-color);
  background-color: var(--primary-color);
  border-radius: var(--border-radius);
}

Custom properties can also be defined on individual elements or classes:

.alert {
  --alert-color: #e74c3c;
  border-left: 4px solid var(--alert-color);
}

In this example, --alert-color is defined on elements matching .alert and can be inherited by their descendants.

Custom properties are not limited to single values. They can store lists and other sequences of CSS tokens.

Fallback Values

The optional fallback argument provides a value when the referenced custom property has the guaranteed-invalid value.

For example:

.box {
  background-color: var(--box-color, #3498db);
}

If --box-color is undefined, the browser uses #3498db.

If the property is defined, its value is substituted:

.box {
  --box-color: #16a085;
  background-color: var(--box-color, #3498db);
}

The background color becomes teal because --box-color is available.

Fallbacks Do Not Validate the Final Property

The fallback is not automatically used when a custom property contains a value that is invalid for the destination property.

For example:

.box {
  --box-color: 20px;
  background-color: var(--box-color, red);
}

The value 20px is substituted, but it is not a valid background color.

The declaration becomes invalid at computed-value time. The browser does not use the red fallback.

Instead, the affected property takes its inherited or initial value, depending on the property's inheritance behavior.

Fallbacks are designed to handle unavailable or guaranteed-invalid custom property values, not every invalid final declaration.

Nested Fallbacks

The var() function can be nested to provide multiple fallback choices.

For example:

.box {
  color: var(--primary-text, var(--secondary-text, #333));
}

The browser uses the first available valid custom property value in the fallback chain.

The resolution follows this order:

  1. Use --primary-text if it has a usable computed custom property value.
  2. Otherwise, use --secondary-text if available.
  3. If neither is available, use #333.

Nested fallbacks are useful for theme values that have component-level, section-level, and global defaults.

For example:

.button {
  background-color: var(--button-color, var(--primary-color, #3498db));
}

The button first looks for its own color setting, then the primary theme color, and finally the hard-coded fallback.

Nested var() functions should be kept readable, since long fallback chains can become difficult to maintain.

Inheritance and Scope

Custom properties defined using names beginning with -- inherit by default.

For example:

.container {
  --text-color: #3498db;
}
.container p {
  color: var(--text-color);
}

Paragraphs inside .container inherit the custom property value.

Custom properties are resolved according to the element on which they are used.

A descendant can override an inherited value:

.container {
  --text-color: #3498db;
}
.container .highlight {
  --text-color: #e74c3c;
}
.container p {
  color: var(--text-color);
}

Paragraphs with the highlight class use the red value, while other paragraphs use blue.

Element-Specific Values

A custom property can be assigned directly to an HTML element:

<div class="box" style="--box-color: #16a085;">
  Example
</div>
.box {
  background-color: var(--box-color, #3498db);
}

The inline custom property overrides the fallback color.

Registered custom properties can have different inheritance behavior when defined using @property.

Overriding Custom Properties

Custom properties follow the CSS cascade, so their values can change according to selectors, states, and media queries.

For example:

.button {
  --button-color: #3498db;
  background-color: var(--button-color);
}
.button:hover {
  --button-color: #2471a3;
}

The button uses the darker color when hovered.

Custom properties can also be overridden by modifier classes:

.button {
  --button-color: #3498db;
  background-color: var(--button-color);
}
.button.success {
  --button-color: #16a085;
}
.button.danger {
  --button-color: #e74c3c;
}

Each button variant changes the custom property without repeating the background-color declaration.

This makes it easier to maintain consistent styling across reusable components.

Using var() with Calculations

The var() function can be combined with CSS mathematical functions such as calc(), min(), max(), and clamp().

For example:

:root {
  --base-spacing: 10px;
}
.box {
  padding: calc(var(--base-spacing) * 2);
}

The calculated padding is 20px.

Responsive Widths

.container {
  --max-width: 1100px;
  width: min(100% - 40px, var(--max-width));
}

The container uses the smaller of the available width minus 40px or the specified maximum width.

Fluid Font Sizes

:root {
  --minimum-size: 1rem;
  --preferred-size: 2vw;
  --maximum-size: 2rem;
}
.heading {
  font-size: clamp(var(--minimum-size), var(--preferred-size), var(--maximum-size));
}

The font size adjusts with the viewport while remaining within the specified limits.

Numeric Values

.box {
  --scale-factor: 1.2;
  transform: scale(var(--scale-factor));
}

The custom property supplies a numeric value to the scale() function.

The substituted value must be compatible with the CSS function or property receiving it.

Responsive Design

CSS custom properties can change inside media queries to support responsive layouts.

For example:

:root {
  --page-spacing: 15px;
  --column-gap: 10px;
}
.layout {
  padding: var(--page-spacing);
  gap: var(--column-gap);
}
@media (min-width: 768px) {
  :root {
    --page-spacing: 30px;
    --column-gap: 20px;
  }
}

On smaller screens, the layout uses the smaller spacing values.

When the viewport reaches 768px, the custom properties are updated.

All declarations using those properties automatically receive the new values.

This avoids repeating the same property declarations in multiple media queries.

Important Distinction

The var() function cannot be used directly as the value of a media query condition.

For example, this does not work:

:root {
  --breakpoint: 768px;
}
@media (min-width: var(--breakpoint)) {
  .layout {
    display: grid;
  }
}

Media query conditions are evaluated independently of the element-specific custom property substitution performed by var().

Use literal media query values or supported CSS features designed for responsive conditions.

Registered Custom Properties

The @property at-rule allows a custom property to be registered with a defined syntax, inheritance behavior, and initial value.

For example:

@property --box-color {
  syntax: "<color>";
  inherits: false;
  initial-value: #3498db;
}
.box {
  background-color: var(--box-color);
}

The custom property is registered as a color.

Its initial value is blue, and it does not inherit from parent elements.

Registered custom properties can provide type validation and enable interpolation for supported value types.

For example:

@property --rotation {
  syntax: "<angle>";
  inherits: false;
  initial-value: 0deg;
}
.box {
  transform: rotate(var(--rotation));
  transition: --rotation 0.3s ease;
}
.box:hover {
  --rotation: 15deg;
}

The registered angle property can be animated smoothly between its values.

The var() function works with both registered and unregistered custom properties.

Registration is optional for ordinary reusable CSS values.

Example

The following example uses custom properties to style three boxes with shared spacing and individual background colors.

HTML:

<div class="var-demo">
  <div class="var-box var-blue">Blue</div>
  <div class="var-box var-green">Green</div>
  <div class="var-box var-purple">Purple</div>
</div>

CSS:

.var-demo {
  --box-spacing: 15px;
  display: flex;
  flex-wrap: wrap;
  gap: var(--box-spacing);
}
.var-box {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 120px;
  height: 75px;
  color: #fff;
  background-color: var(--box-color);
}
.var-blue {
  --box-color: #3498db;
}
.var-green {
  --box-color: #16a085;
}
.var-purple {
  --box-color: #8e44ad;
}
Browser Result
Blue
Green
Purple

All three boxes use the same background-color declaration.

Each modifier class supplies a different value for --box-color.

The shared --box-spacing custom property controls the gap between the boxes.

Fallback Example

The following example demonstrates how var() uses fallback values when custom properties are not defined.

HTML:

<div class="var-fallback-demo">
  <div class="var-fallback-box">Fallback Color</div>
  <div class="var-fallback-box var-custom">Custom Color</div>
</div>

CSS:

.var-fallback-demo {
  display: flex;
  flex-wrap: wrap;
  gap: 15px;
}
.var-fallback-box {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 150px;
  height: 75px;
  color: #fff;
  background-color: var(--background-color, #3498db);
}
.var-custom {
  --background-color: #16a085;
}
Browser Result
Fallback Color
Custom Color

The first box uses the fallback color because --background-color is not defined for that element.

The second box uses the custom teal value.

This allows a component to have a default appearance while supporting individual overrides.

Theme Example

The following example demonstrates how custom properties can control a reusable component's appearance.

HTML:

<div class="var-theme-demo">
  <div class="var-theme-card">
    <h3>Default Theme</h3>
    <p>This card uses the default colors.</p>
  </div>
  <div class="var-theme-card var-theme-dark">
    <h3>Dark Theme</h3>
    <p>This card overrides the colors.</p>
  </div>
</div>

CSS:

.var-theme-demo {
  display: flex;
  flex-wrap: wrap;
  gap: 20px;
}
.var-theme-card {
  --card-background: #eaf2f8;
  --card-text: #2c3e50;
  --card-border: #3498db;
  flex: 1 1 200px;
  padding: 20px;
  color: var(--card-text);
  background-color: var(--card-background);
  border-left: 5px solid var(--card-border);
}
.var-theme-card h3 {
  margin-top: 0;
  color: inherit;
}
.var-theme-card p {
  margin-bottom: 0;
  color: inherit;
}
.var-theme-dark {
  --card-background: #2c3e50;
  --card-text: #fff;
  --card-border: #16a085;
}
Browser Result

Default Theme

This card uses the default colors.

Dark Theme

This card overrides the colors.

Both cards use the same CSS declarations for text, background, and border colors.

The dark theme overrides the custom property values instead of repeating the component's styling rules.

This approach is useful for light and dark themes, component variants, and reusable design systems.

Common Uses

The var() function is useful whenever CSS values need to be reused or changed consistently.

  • Color palettes: Store primary, secondary, background, and text colors.
  • Spacing systems: Reuse margin, padding, and gap values.
  • Typography: Define reusable font sizes, font families, and line heights.
  • Component variants: Change a component's appearance through custom property overrides.
  • Theme switching: Apply different colors and other design values to sections or entire pages.
  • Responsive design: Update shared values through media queries.
  • Calculations: Combine custom properties with CSS mathematical functions.
  • Animations: Control transform values, durations, and other animatable properties.
  • Fallbacks: Provide default values when custom properties are unavailable.

For example:

:root {
  --primary-color: #3498db;
  --spacing: 20px;
  --radius: 6px;
}
.card {
  padding: var(--spacing);
  border: 2px solid var(--primary-color);
  border-radius: var(--radius);
}
.button {
  padding: calc(var(--spacing) / 2);
  background-color: var(--primary-color);
  border-radius: var(--radius);
}

The card and button share the same design values, making future changes easier to maintain.

Limitations

The var() function has several requirements and behaviors to consider.

  • The first argument must be a valid custom property name beginning with two hyphens.
  • Custom property names are case-sensitive.
  • The function substitutes values, not CSS property names or selectors.
  • It cannot be used directly in media query conditions.
  • It cannot be used to construct a URL inside url().
  • Fallback values are used when the referenced custom property has the guaranteed-invalid value, not whenever the final property value is invalid.
  • Unregistered custom properties inherit by default.
  • Circular dependencies between custom properties can make their values invalid.
  • Substituted values must be valid for the property receiving them.
  • Custom properties defined on an element do not automatically become available to unrelated elements.
  • Unregistered custom properties generally animate discretely rather than interpolating smoothly between arbitrary values.

Valid Examples

color: var(--text-color);
color: var(--text-color, #333);
padding: var(--spacing, 20px);
font-family: var(--font-stack, Arial, sans-serif);
background-color: var(--button-color, var(--primary-color, blue));

Invalid Examples

color: var();
color: var(primary-color);
var(--property-name): 20px;
background-image: url(var(--image-path));

The first example omits the custom property name.

The second example does not use the required two-hyphen prefix.

The third attempts to substitute a CSS property name.

The fourth attempts to construct a URL using a custom property inside url().

Circular References

Custom properties can reference other custom properties, but circular dependencies are invalid.

.box {
  --first: var(--second);
  --second: var(--first);
  color: var(--first, black);
}

The two custom properties form a dependency cycle and receive the guaranteed-invalid value.

The color declaration therefore uses the fallback black.

Invalid Values at Computed-Value Time

Consider the following declarations:

.box {
  color: green;
  --text-color: 20px;
  color: var(--text-color, red);
}

The final color declaration becomes invalid at computed-value time because 20px is not a color.

The browser does not return to the earlier color: green declaration or use the red fallback.

Instead, the color property behaves as though the CSS-wide keyword unset had been specified. Because color is inherited, the element inherits its parent's color.

For properties that do not inherit, the initial value is used.

Browser Support

The CSS var() function is Baseline Widely available and is supported by modern versions of Chrome, Edge, Firefox, Safari, and other major browsers.

CSS custom properties and var() have been supported for many years. Older browsers, including Internet Explorer, do not support CSS custom properties.

Some related features, such as registering custom properties with @property, have separate browser compatibility requirements.

For current compatibility information, visit Can I Use? and search for CSS variables or custom properties.

Specifications

The var() function is defined in the CSS Custom Properties for Cascading Variables Module Level 1 specification.

The specification defines custom property substitution, fallback values, inheritance, and invalid-value handling.

Related features include CSS custom properties, the @property at-rule, calc(), env(), and CSS cascade rules.