Skip to main content
April 1, 2026Dan Rodney/8 min read

CSS Variables (Custom Properties)

Master CSS Variables for Dynamic Styling

Key Benefits of CSS Variables

Centralized Control

Store values in one location and update them everywhere at once. No more hunting through CSS files to change repeated values.

Dynamic Updates

Unlike preprocessor variables, CSS variables can be changed at runtime using JavaScript, enabling interactive themes and user customization.

Inheritance Power

Variables inherit from parent elements, allowing you to override values for specific sections while maintaining consistent defaults.

Topics Covered in This HTML & CSS Tutorial:

Defining & Using CSS Variables, the Power of Inheritance

Exercise Preview

preview css variables

Exercise Overview

CSS variables (officially called custom properties) represent one of the most significant additions to CSS in the past decade. Like variables in programming languages such as JavaScript, CSS variables allow you to store and reuse values throughout your stylesheets with unprecedented flexibility.

Consider the maintenance nightmare of updating a brand color used across dozens of CSS declarations, or adjusting spacing values throughout a complex design system. Variables eliminate this tedium by letting you define values once and reference them by name throughout your code. When you update the variable's value, every reference updates automatically—a game-changer for maintainable, scalable CSS architecture.

Unlike preprocessor variables (Sass, Less), CSS custom properties are live values that can be manipulated with JavaScript and inherit through the DOM, opening possibilities for dynamic theming and responsive design patterns that were previously impossible or overly complex.

What You'll Build

This tutorial uses a practical product card layout to demonstrate CSS variables in action. You'll work with fonts, spacing, and colors to see how variables make maintenance easier.

Getting Started

  1. Open the file variables.html which is located in Desktop > Class Files > Advanced HTML CSS Class.
  2. Preview variables.html in Chrome (we'll be using its DevTools for real-time experimentation).

    We're working with a simplified page structure to keep focus on the variable implementation techniques rather than complex layout concerns.

  3. Keep the page open in Chrome for live reloading as you make changes—you'll see the power of variables in real-time.

Setup Process

1

Open File

Navigate to variables.html in Desktop > Class Files > Advanced HTML CSS Class

2

Preview in Chrome

Open the file in Chrome browser to use DevTools for testing

3

Keep Editor Open

Have both code editor and browser open for live testing as you make changes

Defining a CSS Variable

The foundation of CSS variables lies in proper declaration and scope management. Let's start by creating your first custom property.

  1. Switch back to variables.html in your code editor.

    While we've embedded CSS in this HTML file for simplicity, these techniques work identically in external stylesheets—and that's where they truly shine in production environments.

  2. Let's create a variable for the primary font (Google's Coiny font, already linked to the page). This establishes a single source of truth for typography decisions. Add the following code at the start of the style tag:

    <style>
       :root {
          --primary-font: Coiny, sans-serif;
       }
       body {

    The :root pseudo-class is your global variable container. According to Mozilla's MDN documentation, it "matches the root element of a tree representing the document"—essentially the <html> element, but with higher specificity. More importantly for our purposes, :root makes variables available to all descendant elements through CSS inheritance.

    You have complete control over variable naming (following CSS identifier rules). The primary-font name is descriptive and semantic—a best practice for maintainable code. Always use meaningful names that describe the variable's purpose rather than its current value.

The :root CSS pseudo-class matches the root element of a tree representing the document. In HTML, :root represents the <html> element and is identical to the selector html, except that its specificity is higher.
Mozilla MDN documentation explaining why :root is the preferred location for global CSS variables
Variable Naming Convention

CSS variables must start with two dashes (--). The name after that is entirely your choice - 'primary-font' is a custom name, not a CSS keyword.

Using the Variable

Now we'll implement our variable using the var() function, which retrieves custom property values at runtime.

  1. In the h1, h2 rule, replace the hardcoded font name with our variable reference:

    h1, h2 {
       font-family: var(--primary-font);
       font-weight: normal;
  2. Apply the same pattern to the .product-name rule:

    .product-name {
       font-family: var(--primary-font);
       font-size: 18px;
    }
  3. Save the file and reload in Chrome. The visual output remains identical, but you've just implemented a powerful abstraction layer. One variable now controls typography across multiple selectors—let's test that power.

Implementation Steps

0/3

Updating the Variable

Here's where CSS variables demonstrate their true value: centralized control over distributed properties.

  1. Return to your code editor.
  2. Change the font from Coiny to Bungee (another loaded Google font):

    :root {
       --primary-font: Bungee, sans-serif;
    }
  3. Save and reload the page in Chrome. Every element using var(--primary-font) now displays in Bungee.

    This single change updated multiple selectors instantly. In enterprise-scale applications with hundreds of font references, this approach saves hours of manual updates and eliminates the risk of inconsistent implementations.

Before vs After Variables

FeatureWithout VariablesWith Variables
Font UpdatesChange in multiple placesChange once in :root
ConsistencyRisk of missing instancesGuaranteed consistency
MaintenanceTime-consumingInstant updates
Recommended: Variables eliminate repetition and reduce maintenance overhead significantly

Doing More with Variables

Typography is just the beginning. Let's explore how variables excel at managing spatial relationships and enable mathematical operations within your CSS.

  1. Return to your code editor.
  2. Consistent spacing is fundamental to professional design systems. Create a spacing variable that can serve as your design token:

    :root {
       --primary-font: Coiny, sans-serif;
       --standard-spacing: 15px;
    }
  3. Replace the hardcoded margin in the .card rule:

    .card {

    Code Omitted To Save Space

    margin: var(--standard-spacing);

    Code Omitted To Save Space

    }

  4. CSS variables integrate seamlessly with the calc() function, enabling dynamic mathematical relationships. For h2 elements, we want double the standard spacing:

    h2 {
       margin-top: calc(var(--standard-spacing) * 2);
    }

    Note the spaces around the multiplication operator—they're required for proper calc() parsing.

  5. Save and reload to verify the changes. The visual result remains consistent, but your code now expresses spatial relationships mathematically rather than through magic numbers.

  6. Let's tackle a common design challenge: compensating for text line-height in padding calculations. Currently, our cards use 10px vertical padding and 15px horizontal padding—the difference accounts for visual spacing created by line-height.

  7. Return to your code editor and examine the current .card padding values.
  8. Replace the horizontal padding with our variable:

    .card {

    Code Omitted To Save Space

    padding: 10px var(--standard-spacing);

    Code Omitted To Save Space

    }

  9. Now express the vertical padding as a mathematical relationship to our standard spacing:

    .card {

    Code Omitted To Save Space

    padding: calc(var(--standard-spacing) - 5px) var(--standard-spacing);

    Code Omitted To Save Space

    }

    This approach makes the relationship explicit: vertical padding is standard spacing minus 5px for line-height compensation.

  10. Save and reload to confirm visual consistency.
  11. Ctrl+click (Mac) or Right-click (Windows) anywhere on the page and select Inspect to open Chrome DevTools.
  12. In the Elements panel, select the <html lang="en"> element.
  13. In the Styles panel, locate the :root selector displaying your custom properties.
  14. Click the 15px value next to --standard-spacing to select it.
  15. Use the Up Arrow key to increase the value and watch the page update in real-time!

    This demonstrates the live nature of CSS variables—they recalculate all dependent values instantly. Try values around 30px for better visual hierarchy.

  16. Return to your code editor.
  17. Update the spacing variable to your preferred value:

    :root {
       --primary-font: Coiny, sans-serif;
       --standard-spacing: 30px;
    }
Combining Variables with calc()

You can use CSS variables inside calc() functions to perform mathematical operations, like doubling spacing values or subtracting fixed amounts for precise alignment.

Advanced Variable Techniques

1

Create Base Values

Define fundamental measurements like standard-spacing that serve as building blocks

2

Use Math Operations

Combine variables with calc() to create proportional relationships like var(--standard-spacing) * 2

3

Test with DevTools

Use Chrome DevTools to modify variable values in real-time and see instant updates

The Power of Inheritance

CSS custom properties inherit through the DOM tree, creating opportunities for contextual theming that would be impossible with traditional CSS approaches. This inheritance model allows you to redefine variable values for specific page sections while maintaining the same property names.

  1. Add a color variable to your root declarations:

    :root {
       --primary-font: Bungee, sans-serif;
       --standard-spacing: 30px;
       --card-bgcolor: #45e;
    }
  2. Apply this variable to the card background:

    .card {
       background-color: var(--card-bgcolor);

    Code Omitted To Save Space

    }

  3. Create a complementary text color variable:

    :root {
       --primary-font: Bungee, sans-serif;
       --standard-spacing: 30px;
       --card-bgcolor: #45e;
       --card-text-color: white;
    }
  4. Apply the text color variable to both color and border properties:

    .card {
       background-color: var(--card-bgcolor);
       color: var(--card-text-color);
       border: 4px double var(--card-text-color);

    Code Omitted To Save Space

    }

  5. Save and reload to verify the white-on-blue color scheme remains intact.
  6. Return to your code editor and experiment with the text color:
  7. Change the text color variable:

    :root {
       --primary-font: Bungee, sans-serif;
       --standard-spacing: 30px;
       --card-bgcolor: #45e;
       --card-text-color: #8f3;
    }
  8. Save and reload to see the coordinated color change across text and borders.

    Now let's demonstrate inheritance by creating a contextual color scheme for the monthly specials section.

  9. Return to your code editor and examine the HTML structure:
  10. Notice the organizational hierarchy:

    • Four .card elements exist on the page
    • Cards are grouped into .featured and .specials containers
    • We'll target the .specials container to create a different visual theme
  11. Add a new CSS rule that redefines our color variables for the specials section:

    .specials {
       --card-bgcolor: #ccc;
       --card-text-color: black;
    }

    This demonstrates CSS custom properties' inheritance behavior: when no value exists on an element, it inherits from its parent. By redefining variables on .specials, all descendant .card elements will inherit these new values, overriding the :root defaults.

  12. Save and reload the page in Chrome.

    The bottom two cards now display with gray backgrounds and black text, while the top two maintain the original blue theme. You've created a contextual design system using the same CSS properties with different inherited values.

CSS Variable Inheritance Examples

Global Defaults

Variables defined in :root are available to all elements as fallback values throughout the document.

Local Overrides

Child elements can redefine variables to override parent values for specific sections like the specials div example.

Contextual Theming

Different page sections can have unique color schemes while maintaining the same variable structure.

Browser Support

CSS custom properties enjoy excellent support across all modern browsers as of 2026, with implementation dating back to 2016-2017. However, legacy browsers (notably Internet Explorer, which Microsoft discontinued support for in 2022) lack support entirely. Unlike progressive enhancement features, missing variable support often breaks layouts completely, making fallback strategies essential for legacy browser requirements.

For current browser compatibility data, consult caniuse.com/#feat=css-variables. In most contemporary web development contexts, CSS variables are considered a standard tool rather than an experimental feature.

CSS Variables Browser Support Status

Modern Browsers95%
Legacy Browsers5%
Internet Explorer Limitation

CSS variables are not supported in Internet Explorer. Check your target audience before implementation, as variables may not degrade gracefully in legacy browsers.

CSS Variables, Preprocessors, & JavaScript

CSS custom properties offer a significant advantage over preprocessor variables (Sass, Less, Stylus): they're live DOM values accessible to JavaScript. This creates powerful possibilities for dynamic theming, user customization, and responsive design patterns that adapt based on runtime conditions.

Consider implementing user-controlled themes, accessibility preferences, or responsive typography that adjusts based on viewport characteristics. JavaScript can modify CSS variables instantly, and all dependent styles update automatically across your entire application.

For advanced implementation strategies, Smashing Magazine's Strategy Guide To CSS Custom Properties provides comprehensive coverage: tinyurl.com/css-var-strategy

This JavaScript-CSS bridge represents a paradigm shift in how we approach dynamic styling, moving logic from preprocessor build steps to runtime browser capabilities.

CSS Variables vs Preprocessor Variables

FeatureCSS VariablesSass/Less Variables
Runtime ChangesYes - via JavaScriptNo - compile time only
Browser ProcessingNative CSS featureCompiled to static values
InheritanceFull CSS inheritanceNo inheritance model
Dynamic ThemingBuilt-in supportRequires compilation
Recommended: CSS variables offer runtime flexibility that preprocessors cannot match

Key Takeaways

1CSS variables allow you to store reusable values in one location and reference them throughout your stylesheet using the var() function
2Variables defined in :root are globally accessible to all elements, making them perfect for design system values like colors, fonts, and spacing
3CSS variables support inheritance, allowing child elements to override parent variable values for contextual theming
4Unlike preprocessor variables, CSS variables can be modified at runtime using JavaScript, enabling dynamic user interfaces
5Variables work seamlessly with CSS calc() function to create mathematical relationships between design values
6Chrome DevTools allows real-time editing of CSS variable values, making it easy to test and refine your designs
7Modern browser support for CSS variables is excellent, but Internet Explorer lacks support entirely
8CSS variables provide superior flexibility compared to Sass or Less variables due to their runtime capabilities and inheritance model

RELATED ARTICLES