profile

Diary Of A Dev

#1: Adaptive progress bar text.

Published 2 months ago • 4 min read

Howdy Devs,

Recently I got a task to build a progress bar with % of progress to show at right end of the bar.

Haha, that's fairly straight forward. Turns out it was not.

Once I started to code the solution, a major challenge came up which I couldn't for-see earlier. And it turned out to be pretty tough than what I initially thought.

So, let's dive in to build our first complex frontend feature. [Adaptive progress bar text]

What are we building?

Live Preview: https://stackblitz.com/edit/stackblitz-starters-1ubfc7?file=index.html

Let the coding began.

First I started with the HTML5 <progress> element.

```html
<progress value="80" max="100"></progress>
```

Well, this didn't exactly resulted in what I am looking for. And the native HTML5 progress element is not much customizable. I will have to absolutely position the progress text anyways.

So, why not build a custom progress element with block elements like div from scratch. Building a progress bar with div is a common practice in frontend, due to no to low customization available in native progress element.

The Result:

Progress: 50%

Now this looks pretty close to what I want.

Let's see how it looks when the progress is 80%.

Progress: 80%

Oops! The progress text becomes unreadable because the background is black and text color is also black. As per the requirement I wanted the background and text color both to be `#2d7dd2`. Which results in this.

Progress: 80%

Again the same readability issue. Here the challenge was:

  • I want the text covered by progress bar in white.
  • And rest of the text not covered by progress bar in #2d7dd2.

By now, I started to feel the wrath of this task.

Hmm, my initial thought was to perform dynamic calculation to figure out how much of the text is covered by the progress bar. Then split the text in two parts and change color accordingly.

This is easier said than done. The progress % may change very frequently and splitting the text that frequently may not be a good idea. I don't know I am just doing some guess work here.

To be honest, I was even scared to start doing the dynamic calculations. So, I took a break. And when I came back I decided to do a little research before trying to do the dynamic calculation. And, thank god I made that decision.

While researching I came across a CSS property called mix-blend-mode.

Mix blend mode decides how an element's content should blend with element's parent and element's background. This property have many different values but for our case we will focus on two values `difference` and `screen`.

Let's add this property to our text div.

The result:

Progress: 80%

Ok, the progress text is readable now. But this is not the color combination we want. In order to achieve the required color combination we need to understand how `difference` and `screen` value works in mix-blend-mode.

mix-blend-mode: difference

  • The `difference` blend mode is CSS creates effects based on the difference between the colors of blend layer and the base layer.
  • With Black: Blending any color with black using the difference mode results in no change to the original color. This is because the luminance difference between black (which has a value of 0 in all RGB channels) and any color is the color itself. Therefore, blending a color with black essentially leaves the color unchanged.
  • With White: Blending any color with white (which has the maximum value in all RGB channels) inverts the color. This inversion happens because the difference between the maximum value (white) and any color value will be the inverse of that color. For instance, blending white with a pure blue color will result in its complementary color.

mix-blend-mode: screen

  • The `screen` blend mode in CSS is designed to combine colors in a way that results in lighter color.
  • When you screen any color with black, the result is the original color because black is neutral in this mode. It doesn't change the color it's combined with. This is because black is the lowest value in the color spectrum, and screening it with any color effectively leaves the original color unchanged.
  • When you screen any color with white, the result is always white. This is because white is the highest value in the color spectrum, and screening any color with white will lighten it to the maximum extent, which results in white.

We can utilize these 6 points to achieve the desired output.

First let's setup our HTML for progress bar.

```html
<div class="backdrop">
<div class="source">
<div class="barBg">
<div class="bar"></div>
</div>

<div class="contents">Progress: 82%</div>
</div>
</div>
```

Now let's style it and see the result.

```css
.contents, .bar {
height: 30px;
}
.backdrop {
width: 400px;
border: 1px solid black;
position: relative;
background-color: #2d7dd2;
}
.source {
mix-blend-mode: screen;
}
.barBg {
background-color: white;
}
.bar {
background-color: black;
width: 82%;
}
.contents {
position: absolute;
right: 10px;
top: 5px;
color: white;
font-weight: bold;
mix-blend-mode: difference;
}
```

So, basically source element combines #2d7dd2 with black to result in #2d7dd2 and with white to result in white using the screen value of mix-blend-mode.

And content uses difference value of mix-blend-mode to combine white text with black bg to result in white and white text with white bg to result in black or #2d7dd2 if that's what backdrop background is set to.

The result:

Woohoo! We did it.

And you know what the best part is? Our solution will work for any desired color, you just have to change the #2d7dd2 to your desired color and it will work out of the box.


Phew!

Man that was tough to explain. I have tried my best to explain with as much simplicity as possible. If it is not clear right away, don't sweat over it. It will become clear once you study mix-blend-mode in a little detail.

Alright then, That's it for the first issue of building one complex frontend feature every week. See you next week.

Reply to this email, if you have any suggestion on which feature should I build in future issues.


Whenever you are ready, I can help you in 2 ways.

  • Ask Me Anything: If you have any question related to web development. Ask me here. I reply to all questions.
  • LinkedIn For Developers: Book 1:1 call with me to turn around your LinkedIn profile and attract better opportunities.

Diary Of A Dev

Become better F.E developer in 10 minutes a week.

I am building one complex frontend feature or solving a complex frontend interview question every week. And breakdown the exact steps, thought process, and system design behind it. Join the newsletter to learn with me.

Read more from Diary Of A Dev

Hello Devs! Welcome back to another Tuesday of building a frontend feature. Today we are solving a very commonly asked Interactive JS feature in an interview setup. [An interactive pie chart]. This one is going to be a quick issue as there isn't many moving parts to this question. What are we building? Live preview with code: https://stackblitz.com/edit/vitejs-vite-psytzb?file=index.html Philosophy Here the task is to create a range slider and a pie chart and bind the `pie chart` value with...

about 1 month ago • 1 min read

Hello Devs, The feature we are building today is frequently asked in React interviews. But it doesn't test only your React skills, it test your overall JavaScript and basic logic building skills. So, let's dive into building our fourth frontend feature: [Folder/File explorer UI] What are we building? Live preview with code: https://stackblitz.com/edit/vitejs-vite-4bqecn?file=src%2FApp.jsx Philosophy The basic philosophy behind building a "Folder/File explorer UI" is as following: List all the...

about 2 months ago • 3 min read

Hello Devs, Nowadays, one feature that you will see in almost all sites specially in blogs is theme switching specifically dark mode. And that's what we are building today. [Dark Mode in NextJs page with Tailwind and Shadcn-UI] So, let's dive in to build our third frontend feature. What are we building? Live preview with code: https://stackblitz.com/edit/stackblitz-starters-adalin?file=app%2Fpage.tsx Philosophy. First, let's understand the philosophy and basic system design behind adding dark...

about 2 months ago • 4 min read
Share this post