Skip to Content
Mohammed Baqer

4 mins read


Pie chart: A bundle-friendly approach to handle charts in your web application

Unleash the power of conic gradients in CSS to transform your pie and donut charts, taking a giant leap towards optimizing bundle sizes.


What is Conic Gradients?

A conic gradient is a gradient with color transitions rotated around a center point.

Why using conic gradiants for charts?

  • apexcharts and chart.js bundle size are very heavy
  • conic gradients are a new feature in CSS
  • Reduce bundle size from +200kb into less than 1kb
  • Improve the performance
  • Improve the user experience
  • Create charts with less code

What are the drawbacks of using conic gradiants for charts?

  • Limited documentation

Basic usage as pie chart

<!doctype html>
<html>
  <head>
    <style>
      #pie-chart {
        height: 200px;
        width: 200px;
        background-color: red; /* For browsers that do not support gradients */
        background-image: conic-gradient(#04364a 0deg, #04364a 140deg, #176b87 140deg, #176b87 320deg, #64ccc5 320deg);
        border-radius: 50%;
      }
    </style>
  </head>
  <body>
    <div id="pie-chart"></div>
  </body>
</html>

output:

Dynamic usage as pie chart

The dynamic values that will be passed

AttibutetypeDescription
namestringTag for the groub
valuenumberValue of your data
colorColorColor of the groub
const value = [
  {
    name: "Paid bills",
    value: 10,
    color: "#6366f1",
  },
  {
    name: "Unpaid bills",
    value: 5,
    color: "#eef2ff",
  },
];

The functoin that is used to generate conic gradiant string from the values we prvodied

interface DataProps {
  name: string;
  value: number;
  color: string;
  count?: number;
  startValue?: number;
  endValue?: number;
  startPercent?: number;
  endPercent?: number;
  startDegrees?: number;
  endDegrees?: number;
}
 
const conicGradientValue = data
  .reduce((items: DataProps[], item, index, array) => {
    const count = item.count || 0;
    const startValue = array[index - 1]?.count ? array[index - 1].count : 0;
    const endValue = count + item.value;
 
    const startPercent = convertToPercent(startValue!);
    const endPercent = convertToPercent(endValue);
 
    const startDegrees = convertToDegrees(startPercent);
    const endDegrees = convertToDegrees(endPercent);
 
    items.push({
      ...item,
      count,
      startValue,
      endValue,
      startPercent,
      endPercent,
      startDegrees,
      endDegrees,
    });
 
    return items;
  }, [])
  .map((chart: any) => {
    const { color, startDegrees, endDegrees } = chart;
    return `${color} ${startDegrees}deg ${endDegrees}deg`;
  })
  .join();

The svelte component and how the conicGradientValue get injected into the svelte component

<div class="relative flex grow flex-col p-10">
  <svg viewBox="0 0 100 100" class="h-full w-full rounded-full">
    <foreignObject x="0" y="0" width="100" height="100" clip-path="url(#hole)">
      <div class="h-full w-full" style="background: conic-gradient({conicGradientValue});"></div>
    </foreignObject>
  </svg>
</div>

Now you can pass what ever data you want with this dynamic approach

Series: Performant charts in web applications

Episodes: (1/2)