CSS custom properties


Generally, when building an application, we have common areas where we declare properties that are used repeatedly.

Custom properties

Custom properties allow us to define stand-ins for CSS properties in a central place. It follows the DRY principle i.e., “Don’t Repeat Yourself.”. Custom properties help in making code easier to maintain. We can update the value at one central place and, it will be reflected at multiple places wherever used.

Before

Consider the below example for a better understanding of how it was before and after the introduction of the custom properties.

  a {
    color: #cd2653;
  }

  .social-icons a {
    background: #cd2653;
  }

  .wp-block-button.is-style-outline {
    color: #cd2653;
  }

Here we are using the same color multiple times. The problem with this approach is if we want to change the color #cd2653 to something else, we have to update it at all the places to maintain consistency. This is no much annoying.

CSS custom properties fixes this problem.

After

  :root {
    --global--color-primary: #28303d;
  }

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

  .social-icons a {
    background: var(--global--color-primary);
  }

With this change, we can assign a color to a variable once and then input that variable as the CSS property every time we want to use it.

Suppose we want to change color to red, we have to change the value at one place, and that change will reflect everywhere. How cool is that!

Let us look into some more details of Custom properties.

Rules for defining custom properties -

  1. Custom properties must be within a selector and start with two dashes (–):
  2. Also, custom properties can be defined in the :root {} selector so that if we want to change a variable, we have to change it in roots.
  3. After defining custom properties via (--), we can use them anywhere in the document via var().
  4. Inside the var() function, we can define fallback values in custom properties.

Inheritance of custom properties -

CSS custom properties inherit, which means if no value is present for the custom property on the child element, then the value of the parent element is inherited.

Let us take a look at the below example.

  <div class="apple">
    Apple
    <div class="orange">
      Orange
      <div class="banana">Banana</div>
      <div class="grapes">Grapes</div>
    </div>
  </div>
  :root {
    --border: 1px solid;
    --box-padding: 10px;
  }

  .apple {
    border:  var(--border);
    padding: var(--box-padding);
    margin-bottom:  var(--test);
  }

  .orange {
    --test: 10px;
    border:  var(--border);
    padding: var(--box-padding);
  }

  .banana {
    --test: 2em;
    border:  var(--border);
    padding: var(--box-padding);
  }

  .grapes {
    border:  var(--border);
    padding: var(--box-padding);
    margin-bottom:  var(--test);
  }

Firstly, all the properties from :root will be inherited down the tree.

For --test results would be

  1. .orange: { --test: 10px; } // 10px
  2. .banana: { margin-bottom: 2em} // 2em
  3. .grapes: { margin-bottom: var(--test);} // 10px (inherited from it’s parent that is .orange)
  4. .apple: { margin-bottom: var(--test);} // invalid (invalid property, default value of any custom property)

So in the above example, .apple will not have a margin-bottom value as its value is not defined. However, there is a solution for it which is fallback values.

Fallback Values -

Fallback values are a substitute for the custom properties. Suppose custom property is not present for an element, then its substitute value (fallback value) is considered. Thus, we can pass multiple fallback values one after another.

Syntax -

var(–custom-proerty, fallback value);

In the var function, the fallback value is passed as the second parameter.

  .orange {
    color: var(--outer-color, red) /* red color will be used if --outer-color is not defined */
  }

  .banana {
    background-color: var(--my-color, var(--my-bg, yellow)) /* yellow if --my-color & --my-bg are not defined */
  }

  .banana {
    background-color: var(--my-color, --my-bg, yellow) /* This is invalid  */
  }

Code in the second example is a correct way to define more than one fallback value.

Browser support -

CSS custom properties are supported in all major browsers.

Image Credit