CSS - Custom Properties

-

Syntax and Usage

Declaring Custom Properties

To declare a custom property in CSS, you use the double-dash (--) syntax followed by the name of the property. You define custom properties inside a CSS ruleset or the :root pseudo-class, which represents the root element of the document tree.

Example: Declaring Custom Properties

:root {
  --primary-color: #007bff;
  --font-size: 16px;
  --spacing: 1rem;
}

We declare three custom properties: --primary-color, --font-size, and --spacing. We assign them values of #007bff, 16px, and 1rem, respectively. By declaring custom properties in the :root pseudo-class, they become globally accessible throughout the document.

Using Custom Properties

To use a custom property, you reference it using the var() function. The var() function allows you to get the value of a custom property and use it as a value for another CSS property.

Example: Using Custom Properties

.button {
  background-color: var(--primary-color);
  font-size: var(--font-size);
  padding: var(--spacing);
}

We apply the custom properties to the .button class. The background-color property is set to the value of --primary-color, the font-size property is set to the value of --font-size, and the padding property is set to the value of --spacing. The var() function retrieves the corresponding values of the custom properties.

Scope and Inheritance

Custom properties follow the same scoping and inheritance rules as other CSS properties. They are subject to the cascade and can be overridden by more specific rules. Custom properties defined in a parent element are inherited by its child elements.

Example: Scope and Inheritance

:root {
  --text-color: black;
}

.container {
  --text-color: blue;
}

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

We define the --text-color custom property in the :root pseudo-class with a value of black. We then redefine --text-color inside the .container class with a value of blue. The <p> elements inside the .container will inherit the value of --text-color from the nearest ancestor, which is .container. As a result, the text color of the paragraphs inside .container will be blue, while paragraphs outside of .container will have the default black color.

By using the scoping and inheritance behavior of custom properties, you can create modular and reusable styles in your CSS code.

Practical Examples

Theming

Custom properties give a way to implement theming in your CSS. By defining custom properties for theme colors, you can switch between different color schemes without changing the individual CSS rules.

Example: Define Custom Properties for Theming

:root {
  --primary-color: #007bff;
  --secondary-color: #6c757d;
  --text-color: #333;
  --background-color: #fff;
}

.dark-theme {
  --primary-color: #0056b3;
  --secondary-color: #495057;
  --text-color: #fff;
  --background-color: #222;
}

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

.button {
  background-color: var(--primary-color);
  color: var(--background-color);
}

We define custom properties for the primary color, secondary color, text color, and background color in the :root pseudo-class. These are the default theme colors. We then define a .dark-theme class that overrides the values of the custom properties to create a dark theme.

By applying the .dark-theme class to the <body> element, you can switch the entire theme of your website. The color and background-color of the <body> and the .button class will adapt to the new theme colors.

You can switch themes using JavaScript by toggling the .dark-theme class on the <body> element.

Example: Switch Themes with JavaScript

const body = document.body;
const toggleThemeButton = document.getElementById('toggleTheme');

toggleThemeButton.addEventListener('click', () => {
  body.classList.toggle('dark-theme');
});

Responsive Design

Custom properties can be used for responsive design by letting you adjust styles based on screen size. You can update the values of custom properties using media queries to change the look of your website at different breakpoints.

Example: Responsive Design with Custom Properties

:root {
  --font-size: 16px;
  --spacing: 1rem;
}

@media (max-width: 768px) {
  :root {
    --font-size: 14px;
    --spacing: 0.75rem;
  }
}

.container {
  font-size: var(--font-size);
  padding: var(--spacing);
}

We define custom properties --font-size and --spacing with default values. Then, we use a media query to update their values when the screen width is less than or equal to 768px. The .container class will adapt its font-size and padding based on the screen size.

Reusable Components

Custom properties let you create reusable UI components with flexible styling. By defining custom properties for component-specific styles, you can customize the look of components without changing their individual CSS rules.

Example: Create Reusable UI Components

.button {
  --button-color: #007bff;
  --button-text-color: #fff;
  --button-padding: 0.5rem 1rem;

  background-color: var(--button-color);
  color: var(--button-text-color);
  padding: var(--button-padding);
}

.primary-button {
  --button-color: #28a745;
}

.large-button {
  --button-padding: 1rem 2rem;
}

We create a .button class with custom properties for the button color, text color, and padding. These custom properties are the default styles for the button.

To create variations of the button, we define additional classes like .primary-button and .large-button that override specific custom properties. This lets you customize the button styles without copying the entire CSS rule.

By combining these classes, you can create buttons with different colors and sizes while keeping a consistent base style.

Custom properties give a flexible and maintainable way to build reusable UI components in your CSS code.

Combining with Other CSS Features

Using Custom Properties with CSS Preprocessors (Sass, Less)

Custom properties work with CSS preprocessors such as Sass and Less. These preprocessors give more features and flexibility in writing CSS code. When using custom properties with preprocessors, you can use variables, functions, and mixins.

Sass supports custom properties from version 4.0 and later. You can define custom properties in Sass using the $ syntax for variables.

Sass Example

$primary-color: #007bff;

:root {
  --primary-color: #{$primary-color};
}

.button {
  background-color: var(--primary-color);
}

We define a Sass variable $primary-color with the value #007bff. Then, we use the interpolation syntax #{$variable} to assign the value of the Sass variable to the --primary-color custom property. The .button class can then use the custom property as usual.

Less also supports custom properties in a similar way. You can define custom properties using the @ syntax for variables.

Less Example

@primary-color: #007bff;

:root {
  --primary-color: @primary-color;
}

.button {
  background-color: var(--primary-color);
}

We define a Less variable @primary-color with the value #007bff. We assign the value of the Less variable directly to the --primary-color custom property. The usage of the custom property remains the same.

Using custom properties with CSS preprocessors lets you use the features of the preprocessor while still benefiting from the dynamic nature of custom properties in the generated CSS.

Integrating Custom Properties with CSS-in-JS Libraries

Custom properties can also be integrated with CSS-in-JS libraries such as styled-components and emotion. These libraries allow writing CSS code directly in JavaScript, providing a more component-based approach to styling.

When using custom properties with CSS-in-JS libraries, you can define and use them within the JavaScript code.

CSS-in-JS Example (Styled Components)

import styled from 'styled-components';

const Button = styled.button`
  --button-color: #007bff;
  --button-text-color: #fff;

  background-color: var(--button-color);
  color: var(--button-text-color);
  padding: 0.5rem 1rem;
`;

const PrimaryButton = styled(Button)`
  --button-color: #28a745;
`;

We define custom properties --button-color and --button-text-color within the Button component. These custom properties are used to style the button. We then create a PrimaryButton component that extends the Button component and overrides the --button-color custom property.

By integrating custom properties with CSS-in-JS libraries, you can use the power of custom properties while enjoying the component-based architecture and JavaScript functionality provided by these libraries. Custom properties provide a flexible and interoperable way to combine them with other CSS features and tools, enabling you to write more modular and maintainable CSS code.