Skip to content

PaulieScanlon/css-conic-gradient-charts

Repository files navigation

paulie.dev

CSS conic-gradient Charts

Create Donut or Pie Charts using the CSS conic-gradient

Principle

Learn the principle behind this approach from Shruti Balasa. You can also see an example in the mdn web docs.

Dynamic

The above example by Shruti Balasa works if you know the values upfront and hardcode the color stops using E.g. pink 0deg 90deg yellow 90deg 180deg etc. However, in a lot of cases data will be dynamic and the values won't correspond to deg values that can be used to construct a conic-gradient() string.

The examples in this repo create a css_string suitable for use with conic-gradient() using dynamic data values.

CSS String from Data

const data = [
  {
    name: 'Cluster 1',
    value: 210,
  },
  {
    name: 'Cluster 2',
    value: 30,
  },
  {
    name: 'Cluster 3',
    value: 180,
  },
  {
    name: 'Cluster 4',
    value: 260,
  },
  {
    name: 'Cluster 5',
    value: 60,
  },
].sort((a, b) => a.value - b.value);

const total_value = data.reduce((a, b) => a + b.value, 0);
const convertToPercent = (num) => Math.round((num / total_value) * 100);
const convertToDegrees = (num) => Math.round((num / 100) * 360);

const css_string = data
  .reduce((items, item, index, array) => {
    items.push(item);

    item.count = item.count || 0;
    item.count += array[index - 1]?.count || item.count;
    item.start_value = array[index - 1]?.count ? array[index - 1].count : 0;
    item.end_value = item.count += item.value;
    item.start_percent = convertToPercent(item.start_value);
    item.end_percent = convertToPercent(item.end_value);
    item.start_degrees = convertToDegrees(item.start_percent);
    item.end_degrees = convertToDegrees(item.end_percent);

    return items;
  }, [])
  .map((chart, index) => {
    const { start_degrees, end_degrees } = chart;
    return ` var(--color-violet-${(index + 1) * 100}) ${start_degrees}deg ${end_degrees}deg`;
  })
  .join();

Example Output

var(--color-violet-100) 0deg 14deg,
var(--color-violet-200) 14deg 43deg,
var(--color-violet-300) 43deg 130deg,
var(--color-violet-400) 130deg 234deg,
var(--color-violet-500) 234deg 360deg

Usage

<svg viewBox='0 0 100 100' xmlns='http://www.w3.org/2000/svg' className='rounded-full'>
  <foreignObject x='0' y='0' width='100' height='100'>
    <div
      xmlns='http://www.w3.org/1999/xhtml'
      className='w-full h-full'
      style={{
        background: `conic-gradient(${css_string})`,
      }}
    />
  </foreignObject>
</svg>

CSS

CSS class names are from TailwindCSS

Bugs

Firefox

About

Create Donut or Pie Charts using the CSS conic-gradient

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages