DEV Community

Cover image for Unique approach of CSS custom property
Hasibul Alam Ratul
Hasibul Alam Ratul

Posted on

Unique approach of CSS custom property

CSS Custom Properties offers great flexibility and modularity to a stylesheet. Allows developers to centralize values and simplify maintaining and updating multiple elements simultaneously across the entire project. Custom properties can go from simple color and shadow values to dynamic changes to styles based on user interactions or other events using JavaScript. Recently, I came across an example by Lea Verou that used custom property in a way that was quite unique. So, let's see the approach.

Introduction

cover

Suppose we have multiple cards with different background colors, button variants, and hover effects like the image above. Typically, the best approach will be to have a class for the card element with all the default styling and then use individual classes for the different cards and change the colors one by one, as shown in the example below.

.card {
  position: relative;
  min-height: 200px;
  background-color: #f0f0f0;
  padding: 20px;
  border-radius: 5px;
  background-color: white;
  display: flex;
  flex-direction: column;
  gap: 10px;

    &.js {
        background-color: #fefce8;
    }
}
Enter fullscreen mode Exit fullscreen mode

However, there is a much easier way you can achieve the same result. You need to first understand the concept, which may not seem simple at first, but it makes more sense when you understand it.

Pseudo-private custom property approach:

The aim is to mimic the behaviour of private properties in JavaScript within the realm of CSS. The analogy drawn here is to JavaScript, where developers used naming conventions (like underscores or other prefixes) to signify private properties before introducing actual private properties in the language. Similarly, in CSS, this creates a distinction between the properties used internally and exposed. Although the private custom properties aren’t private in practicality, they are put in place for a clear distinction.

.card {
    --_background: var(--background, white);
    --_border: var(--border, #333);
    --_button-hover: var(--button, #333);
    --_shadow: var(--shadow, white);
}
Enter fullscreen mode Exit fullscreen mode

For this example we will change the background, border, button hover and shadow color. So, we define the respective custom properties with an underscore like --_background and set variable which is exposed --background in the card class. Here, we can set fallback values, which also act as a default value for each of the cards. Now, the only thing is to set the private properties internally, such as changing the background-colour property with the private property and doing the same with the rest of the properties.

.card {
    background-color: var(--_background);
    &::after {
      background: var(--_shadow);
    }
    .btn {
    background-color: var(--_border);
      &:hover {
        border-color: var(--_border);
        background-color: var(--_button-hover);
      }
   }
     img {
         border: 4px solid var(--_border);
     }
}
Enter fullscreen mode Exit fullscreen mode

As the default structure is set, to apply styles, all you need to do is set your desired value to the properties that are exposed, and if no style is set, then it will apply the fallback values. Here is an example with and without style.

Code:

.js {
  --shadow: var(--clr-yellow-dark);
  --background: var(--clr-yellow);
  --border: var(--clr-yellow-dark);
  --button: var(--clr-yellow);
}
.python {
    /* no value set in this card */
}

.ruby {
  --shadow: var(--clr-red-dark);
  --background: var(--clr-red);
  --border: var(--clr-red-dark);
  --button: var(--clr-red);
}
Enter fullscreen mode Exit fullscreen mode

Preview:

preview example

You can see that with this approach, you are only setting values to the custom properties and having the option for a set of default values in place. For details explanation checkout the reference section.

Layout Change:

Although changing colors is okay, you can change the entire layout by defining another custom property. By adding data attributes and JavaScript a lot can be done. Checkout CodePen for the whole code.

layout change example

CodePen:
https://codepen.io/ratul16/pen/NWJqGRv

Reference:
https://lea.verou.me/blog/2021/10/custom-properties-with-defaults/

Top comments (0)