How to Change Look & Feel of Pseudo Elements using JavaScript and CSS Custom Properties

Subscribe to my newsletter and never miss my upcoming articles

Changing the UI of pseudo elements through JavaScript can become difficult sometimes. Let's see how we can make it easy with help from CSS Custom Properties.

The Problem

In general, if we want to change anything in pseudo elements through JavaScript, we do it in the following way:

  1. Create CSS classes on element, which will change pseudo elements' UI
  2. Get the element using querySelector
  3. Modify the classes using classList

Above approach works fine. But, if we need more customizations in pseudo elements, we will end-up creating many classes to handle all scenarios.

CSS Custom Properties to the rescue

Custom properties (sometimes referred to as CSS variables or cascading variables) are entities defined by CSS authors that contain specific values to be reused throughout a document. They are set using custom property notation (e.g., --main-color: black;) and are accessed using the var() function (e.g., color: var(--main-color);). - Source

Let's take an example to see it in action.

Initial Markup

  1. Create HTML for checkmark
<span class="checkmark"></span>
  1. CSS for .checkmark
.checkmark {
  display: inline-block;
  width: 20px;
  height: 20px;
  border-radius: 10px;
  background: #61d345;
  position: relative;
  transform: rotate(45deg);
}
.checkmark::after {
  content: '';
  box-sizing: border-box;
  position: absolute;
  border-right: 2px solid;
  border-bottom: 2px solid;
  border-color: #fff;
  bottom: 6px;
  left: 6px;
  height: 10px;
  width: 6px;
}

After above, the result will look like below:

checkmark

Great, checkmark looks neat... 😅

Usage of CSS Custom Properties

Now, let's assume that in your website you want to allow users to change colors of this checkmark as they need on runtime. Let's see how we can change colors of element and its pseudo element with CSS Custom Properties.

Change colors in CSS like this:

.checkmark {
  /* rest remains same */
  background: var(--check-primary);
}
.checkmark::after {
  /* rest remains same */
  border-color: var(--check-secondary);
}

👉 Note: Custom property names are case sensitive — --my-color will be treated as a separate custom property to --My-color.

Now, from your JavaScript, you would do like below to update the colors:

// 1. Get the element
const element = document.querySelector(".checkmark");

function changeColor() {
  // 2. Modify its custom css properties
  element.style.setProperty("--check-primary", "#607d8b");
  element.style.setProperty("--check-secondary", "#303030");
}

Cool! Now whenever you call changeColor, it will update the colors. And it will look like below:

checkmark with changed colors

But wait, there is still one more problem. After updating the CSS, when you initially render it, it looks like below:

initial checkmark after updating css

The reason it happened is we used CSS variables to assign colors, but those variables don't have any initial values.

We can solve this in 2 ways:

1st - Initialize variables with class or :root.

:root {
  --check-primary: #61d345;
  --check-secondary: #fff;
}

// or

.checkmark {
  --check-primary: #61d345;
  --check-secondary: #fff;
}

2nd - Give fallback value in var() function:

.checkmark {
  background: var(--check-primary, #61d345);
}
.checkmark::after {
  border-color: var(--check-secondary, #fff);
}

That's it! The final CSS looks like below:

.checkmark {
  display: inline-block;
  width: 20px;
  height: 20px;
  border-radius: 10px;
  background: var(--check-primary, #61d345);
  position: relative;
  transform: rotate(45deg);
}
.checkmark::after {
  content: '';
  box-sizing: border-box;
  position: absolute;
  border-right: 2px solid;
  border-bottom: 2px solid;
  border-color: var(--check-secondary, #fff);
  bottom: 6px;
  left: 6px;
  height: 10px;
  width: 6px;
}

I have also created a Codepen:


Thank you for reading this article. Let me know your feedback and thoughts in comments section. I am also available on twitter via @shhdharmen.

Happy Coding.

🌲 ğŸŒž 😊

No Comments Yet