“This is the second day of my participation in the First Challenge 2022, for more details: First Challenge 2022”.

Pie charts are common components that allow you to show pieces of the whole, and you can use them for many different scenarios. You’ll find many articles about building such a component, but they usually rely on either SVG or a lot of HTML elements. In this article, I’ll show you how to create a pie chart using CSS and just one element.

Next we make a static pie chart, an animated pie chart, and we can also have rounded corners. All of this, however, is a

element.

In addition, we can easily adjust different values using CSS variables, so we don’t have to worry about changing the CSS code.

The HTML structure of the pie chart

As I mentioned above, we have a single

, and we add the percentage value (pie chart progress) as the main content:
<div class="pie" style="--p:60; --b:10px; --c:purple;" >60%</div>Copy the code

We also add CSS variables to inline styles.

  • --p: This variable should contain the percentage value as a number (no strings)%Symbol). It should be the same as the content.
  • --bThis variable defines the size of the border.
  • --c: This variable will define the primary color.

For the purposes of this article and demonstration, I use single-character variables to keep the code short. But when using code in a production environment, it’s best to consider more explicit variables. Examples are –percentage, –border-thickness, and –main-color.

CSS Settings for pie charts

Let’s start by styling our content. This part is very simple, the code is as follows:

.pie {
  --w: 150px;
  width: var(--w);
  aspect-ratio: 1;
  display: inline-grid;
  place-content: center;
  margin: 5px;
  font-size: 25px;
  font-weight: bold;
  font-family: sans-serif;
}
Copy the code

I defined the element as inline-grid using place-content: center. We use aspect-ratio: 1 to ensure that elements remain square. We could also use height: var(–w), but it’s always good to learn and use new CSS properties.

You may be wondering why I used a variable to define the width instead of simply setting width: 150px. I need to know the value of the width for future use, so I define it as a variable.

All the rest of THE CSS is very basic text style. Feel free to update it.

Let’s move on to the interesting part — the main shape of our component. To do this, we will use pseudo-elements with the following styles:

.pie:before{
  content: "";
  position: absolute;
  border-radius: 50%;
  inset: 0;
  background: conic-gradient(var(--c) calc(var(--p)*1%),#0000 0);
}
Copy the code

A pseudo-element that covers all regions, position: absolute thanks to inset: 0. Yes, it’s another new CSS property, which is short for Top, Right, bottom, and right (you can read more here).

Then we turn it into a circle (border-radius: 50%) and apply a conic-gradient(). Notice the use of CSS variables we defined as inline styles (–c for colors and –p percentages).

So far, this has given us the following results:

We’re getting closer! thisconic-gradient()Is to give us a two-color gradient. from0%top%The main color, and the rest of the color is transparent (defined in hexadecimal values)# 0000).

To keep only the border part, we will use amask to hide the middle part. This time we will use the radial-gradient() :

radial-gradient(farthest-side,red calc(99% - var(--b)),blue calc(100% - var(--b)))
Copy the code

The above background application will provide us with the following information:

Note the use of the variable that defines the border thickness –b (shown blue above).

Now imagine that the red part is invisible and the blue part is visible. If we used the same gradient for the attributes, this is the mask we would get:

Our pie chart contains one element and several lines of CSS code.

.pie {
  --w:150px;
  
  width: var(--w);
  aspect-ratio: 1;
  position: relative;
  display: inline-grid;
  place-content: center;
  margin: 5px;
  font-size: 25px;
  font-weight: bold;
  font-family: sans-serif;
}
.pie:before {
  content: "";
  position: absolute;
  border-radius: 50%;
  inset: 0;
  background: conic-gradient(var(--c) calc(var(--p)*1%),#0000 0);
  -webkit-mask:radial-gradient(farthest-side,#0000 calc(99% - var(--b)),#000 calc(100% - var(--b)));
          mask:radial-gradient(farthest-side,#0000 calc(99% - var(--b)),#000 calc(100% - var(--b)));
}
Copy the code

And HTML:

<div class="pie" style="--p:60; --b:10px; --c:purple;" >60%</div>Copy the code

How do I add rounded edges

To do this, I’ll add an extra gradient layer to round the edge and a pseudo-element to round the other edge. Here is an illustration of an understanding technique:

(1) Code for the edge of the dome:

.pie:before {
  background:
    radial-gradient(farthest-side,var(--c) 98%,#0000) top/var(--b) var(--b) no-repeat,
    conic-gradient(var(--c) calc(var(--p)*1%),#0000 0);
}
Copy the code

In addition to conic-gradient(), we also added a radial-gradient() placed at the top, whose size is equal to the defined border thickness — B. (2) circle the other side of the code:

.pie:after { content: ""; position: absolute; border-radius: 50%; inset: calc(50% - var(--b)/2); background: var(--c); Transform: the rotate (calc (var (p) * 3.6 deg)) translate (calc (50% var (w) / 2)); }Copy the code

This inset attribute sets the size of the pseudo-element to equal –b. Remember, it’s short for top,right and bottom, left. If we have

left = right = 50% - b/2
Copy the code

That means we’re moving from each side to the center minus the offset b over 2 is equal to — so our final width is equal to 2 times b over 2 is equal to b. High logic is the same.

Now we need to place our elements properly, which is why we use the transform property. Our element is initially placed in the center, so we need to rotate it first. With percentages, we use the “rule of three” to get angles:

angle = percentage*360deg/100
Copy the code

Then we do a translation, and here we need the width, because we have to do a translation of half the width (w/2).

Okay, okay — you might be a little lost in all of these formulas. Find an illustration below to understand the logic behind the transformation properties

After that, we color the pseudo-elements with the primary color--cAnd you are done. We have pie charts with rounded edges.

How to animate a pie chart

Static pie charts are good, but animated pie charts are better! To do this, we define the animation percentage value –p from 0. By default, we cannot animate CSS variables, but thanks to the new @property feature, it can now be done.

We register variables:

@property --p{
  syntax: '<number>';
  inherits: true;
  initial-value: 0;
}
Copy the code

We create a KeyFrames:

@keyframes p {
  from {--p:0}
}
Copy the code

Note that we only need to specify from. To do so, by default the browser will set to equal the value we defined (

< / div > 60%).

Finally, we call it animation. You can define the duration/delay as needed.

animation: p 1s .5s both;
Copy the code

Note: This technique is not widely supported. You can test it on Chromium-based browsers (Chrome and Edge), but it will fail on Firefox and Safari. You Can see Can I Use to track support.