CSS Variables: A Beginner’s Guide to Custom Properties

Written by

in

In the world of web development, CSS (Cascading Style Sheets) is the backbone of visual design. It dictates how your website looks, from the fonts and colors to the layout and responsiveness. As you progress from a beginner to an intermediate developer, you’ll encounter situations where you need to make global changes to your website’s styling. Imagine having to change the primary color of your website, used across dozens of elements. Without a proper system, this can be a tedious and error-prone process. This is where CSS variables, also known as custom properties, come into play. They are a powerful tool that simplifies styling, improves maintainability, and makes your CSS code more dynamic and efficient.

What are CSS Variables?

CSS variables are essentially custom properties that you define in your CSS. They store specific values, such as colors, font sizes, or any other CSS value, and can be reused throughout your stylesheet. Think of them as placeholders that you can easily update in one place, and the changes will automatically reflect everywhere the variable is used. This makes managing and updating your website’s design much easier.

Why Use CSS Variables?

CSS variables offer several significant advantages:

  • Maintainability: Centralize your design values, making it easy to change them in a single location.
  • Readability: Improve the clarity of your code by using meaningful variable names.
  • Flexibility: Create dynamic styles that adapt to user preferences or other conditions.
  • Efficiency: Reduce redundancy and avoid repetitive code.

How to Define CSS Variables

Defining a CSS variable is straightforward. You declare it using the `–` prefix, followed by a descriptive name, and then assign it a value. Here’s the basic syntax:


:root {
  --primary-color: #007bff; /* Example: A blue color */
  --font-size-base: 16px; /* Example: Base font size */
  --padding-small: 0.5rem; /* Example: Small padding value */
}

Let’s break down this example:

  • :root: This is the selector that makes the variables globally available. You can also define variables within specific selectors (e.g., a class or an ID) to limit their scope.
  • --primary-color: #007bff;: This defines a variable named --primary-color and assigns it the hex value for a blue color.
  • --font-size-base: 16px;: This defines a variable for the base font size.
  • --padding-small: 0.5rem;: This defines a variable for a small padding value, using relative units (rem).

How to Use CSS Variables

Once you’ve defined your CSS variables, you can use them in your CSS rules using the var() function. The var() function takes the variable name as an argument.


h1 {
  color: var(--primary-color);
  font-size: var(--font-size-base);
}

p {
  font-size: var(--font-size-base);
  padding: var(--padding-small);
}

In this example:

  • The h1 element’s text color will be the value of --primary-color (blue).
  • Both h1 and p elements will use the base font size defined by --font-size-base (16px).
  • The p element will have a small padding value defined by --padding-small (0.5rem).

Scoped Variables

While variables defined in :root are global, you can also define variables within specific selectors. This limits the scope of the variable, meaning it’s only accessible within that selector and its descendants.


.container {
  --container-background: #f0f0f0;
  padding: var(--padding-small);
  background-color: var(--container-background);
}

.content {
  background-color: white;
  padding: var(--padding-small);
}

In this example:

  • --container-background is only accessible within the .container class.
  • The padding property uses the global --padding-small variable.
  • The .content class doesn’t have access to --container-background unless it’s inherited from the parent.

Inheritance and Cascading

CSS variables follow the rules of inheritance and cascading, just like other CSS properties. If a variable isn’t defined for an element, it will try to inherit it from its parent. If a variable is defined multiple times, the cascade determines which value is used.

Consider the following example:


:root {
  --theme-color: blue;
}

.container {
  --theme-color: green;
  color: var(--theme-color);
}

In this case, any element within the .container will have a text color of green, because the local definition of --theme-color overrides the global definition. Elements outside of .container will have a text color of blue.

Real-World Examples

Let’s look at some practical applications of CSS variables:

1. Theme Switching

One of the most common uses is creating themes. You can define variables for colors, fonts, and other design elements, and then swap the values of these variables to change the website’s theme.


:root {
  --primary-color: #007bff; /* Light theme primary */
  --background-color: #ffffff; /* Light theme background */
  --text-color: #333333; /* Light theme text */
}

.dark-theme {
  --primary-color: #28a745; /* Dark theme primary */
  --background-color: #333333; /* Dark theme background */
  --text-color: #ffffff; /* Dark theme text */
}

body {
  background-color: var(--background-color);
  color: var(--text-color);
}

a {
  color: var(--primary-color);
}

In this example, you can switch between themes by adding or removing the .dark-theme class to the body element. This allows you to create a dynamic theme switcher.

2. Responsive Design

CSS variables can also be used to manage responsive design. You can define variables for breakpoints and use them in media queries.


:root {
  --breakpoint-medium: 768px;
}

.element {
  width: 100%;
}

@media (min-width: var(--breakpoint-medium)) {
  .element {
    width: 50%;
  }
}

This allows you to easily adjust your breakpoints in one place.

3. Component Styling

When building reusable components, CSS variables are invaluable. You can define variables specific to a component, making it easy to customize its appearance without modifying the core CSS. This is particularly useful in web component libraries.


.button {
  --button-background: var(--primary-color, #007bff); /* Fallback to default if primary-color isn't defined */
  --button-text-color: white;
  background-color: var(--button-background);
  color: var(--button-text-color);
  padding: 10px 20px;
  border: none;
  cursor: pointer;
}

/* Example usage */
.custom-button {
  --primary-color: green;
}

In this example, the .button component uses variables for its background and text colors. The .custom-button class can override the primary color specifically for that instance.

Common Mistakes and How to Fix Them

While CSS variables are powerful, there are a few common pitfalls to avoid:

  • Incorrect Syntax: Make sure you use the double-dash (--) prefix when defining variables and the var() function when using them.
  • Scope Issues: Be mindful of variable scope. If a variable isn’t working, check where it’s defined and whether the element has access to it.
  • Overuse: Don’t define variables for every single value. Use them strategically for values that you want to reuse or easily change.
  • Browser Compatibility: While CSS variables are widely supported, older browsers may not support them. Consider using a preprocessor like Sass or Less for broader compatibility, or provide fallback styles.

Tips for Best Practices

To maximize the benefits of CSS variables, follow these best practices:

  • Use Descriptive Names: Choose names that clearly describe the purpose of the variable (e.g., --primary-color, --font-size-large).
  • Organize Your Variables: Group related variables together (e.g., all color variables, all font variables) for better readability.
  • Comment Your Variables: Add comments to explain the purpose of each variable, especially if the meaning isn’t immediately obvious.
  • Consider Fallbacks: Use fallback values within the var() function (e.g., color: var(--my-color, black);) to provide default values if the variable isn’t defined.
  • Use a Consistent Naming Convention: Establish a consistent naming convention (e.g., kebab-case or camelCase) for your variables.

Summary / Key Takeaways

CSS variables are a powerful tool for modern web development. They enhance maintainability, improve code readability, and enable dynamic styling. By defining and using variables strategically, you can create more flexible and efficient CSS. Remember to use descriptive names, organize your variables, and consider fallback values for maximum effectiveness. Understanding and implementing CSS variables is a crucial step towards becoming a proficient CSS developer, making your stylesheets easier to manage, update, and scale. They are an essential part of any modern web development workflow.

FAQ

1. Can I use CSS variables in JavaScript?

Yes, you can! You can access and modify CSS variables using JavaScript, allowing you to create even more dynamic and interactive experiences. You can use the getPropertyValue() and setProperty() methods of the getComputedStyle() object to read and write CSS variable values.


// Get the value of a variable
const root = document.documentElement;
const primaryColor = getComputedStyle(root).getPropertyValue('--primary-color');
console.log(primaryColor); // Output: the value of --primary-color

// Set the value of a variable
root.style.setProperty('--primary-color', 'red');

2. Are CSS variables the same as preprocessor variables (e.g., Sass)?

No, they are different but serve similar purposes. CSS variables are native to CSS and are processed by the browser. Preprocessor variables (like Sass or Less) are processed during the build step and compile into regular CSS. CSS variables offer more dynamic behavior because they are processed at runtime, allowing for changes based on user interaction or JavaScript. Preprocessor variables offer more advanced features like mixins and functions.

3. What if I need to support older browsers that don’t support CSS variables?

If you need to support older browsers, you have a few options:

  • Use a preprocessor: Preprocessors like Sass and Less compile to regular CSS, which is compatible with all browsers.
  • Provide fallback styles: Define regular CSS properties alongside your CSS variables. The browser will use the last defined property.
  • Use a polyfill: There are JavaScript polyfills that provide CSS variable support for older browsers. However, these can add overhead to your page.

4. Can I use CSS variables for everything?

While CSS variables are incredibly versatile, they aren’t a replacement for all CSS properties. They are best suited for values that you want to reuse or easily change, such as colors, font sizes, and spacing. For properties that are unique to a specific element, it’s often more straightforward to define the property directly on that element.

5. How do CSS variables handle invalid values?

If you assign an invalid value to a CSS variable, the browser will typically ignore that value. However, the variable will still be defined, and if you use that variable in a property that also has an invalid value, the browser might ignore that property as well. Therefore, it’s essential to ensure that the values you assign to your CSS variables are valid for the properties in which you use them.

CSS variables empower developers to write more maintainable, flexible, and efficient CSS. By understanding how to define, use, and manage these variables, you can significantly improve your web development workflow and create more dynamic and adaptable websites. The ability to centrally manage design values, create themes, and build responsive layouts makes CSS variables an indispensable tool for any modern web developer. Mastering CSS variables is not just about writing code; it’s about crafting a more efficient and scalable approach to web design, ensuring your projects are easier to maintain, update, and evolve over time.