Skip to content

Instantly share code, notes, and snippets.

@gquittet
Last active July 29, 2024 20:29
Show Gist options
  • Save gquittet/77dd931ebfa7b8a73f2711faee0a7292 to your computer and use it in GitHub Desktop.
Save gquittet/77dd931ebfa7b8a73f2711faee0a7292 to your computer and use it in GitHub Desktop.
tailwind gauge chart
<!-- percent to deg => Math.round(((value / 100) * 180 - 45) * 10) / 10 -->
<div class="relative flex aspect-[2] items-center justify-center overflow-hidden rounded-t-full bg-blue-400">
<div class="absolute top-0 aspect-square w-full rotate-[calc(72deg-45deg)] bg-gradient-to-tr from-transparent from-50% to-white to-50% transition-transform duration-500"></div>
<div class="absolute top-1/4 flex aspect-square w-3/4 justify-center rounded-full bg-blue-100"></div>
<div class="absolute bottom-0 w-full truncate text-center text-[20vmax] leading-none">40%</div>
</div>
@MajeedAB
Copy link

MajeedAB commented Feb 6, 2024

Hey there, thanks for this component! I tweaked it a bit for our use, adding an outer ring with red, orange and green zones to show the "valid" vs "invalid" range of the value being shown, also modifiable with a rotate angle.

So I would like to share my altered version in case it helps someone in the future :)
There:
image_2024-02-05_195908384
EDIT: https://play.tailwindcss.com/HDhRoTJLM9 to try it out

    <div class="relative flex aspect-[2] items-center justify-center overflow-hidden rounded-t-full bg-blue-400">
        <!-- Outer ring with ranges (rotate angles modifiable to get custom range) -->
        <div class="absolute top-0 aspect-square w-full rounded-full rotate-[calc(0deg-45deg)] bg-gradient-to-tr from-transparent from-50% to-red-500 to-50% transition-transform duration-500"></div>
        <div class="absolute top-0 aspect-square w-full rounded-full rotate-[calc(45deg-45deg)] bg-gradient-to-tr from-transparent from-50% to-orange-400 to-50% transition-transform duration-500"></div>
        <div class="absolute top-0 aspect-square w-full rounded-full rotate-[calc(60deg-45deg)] bg-gradient-to-tr from-transparent from-50% to-green-600 to-50% transition-transform duration-500"></div>
        <div class="absolute top-0 aspect-square w-full rounded-full rotate-[calc(140deg-45deg)] bg-gradient-to-tr from-transparent from-50% to-orange-400 to-50% transition-transform duration-500"></div>
        <div class="absolute top-0 aspect-square w-full rounded-full rotate-[calc(145deg-45deg)] bg-gradient-to-tr from-transparent from-50% to-red-500 to-50% transition-transform duration-500"></div>
        <!-- Optional black seperation if the gauge has the same colour as the outer ring -->
        <div class="absolute top-7 flex aspect-square justify-center rounded-full bg-black" style="width: 93%;"></div>
        <!-- Actual gauge, change angle again for a dynamic value -->
        <div class="absolute top-8 flex aspect-square w-11/12 justify-center rounded-full bg-green-500"></div>
        <div class="absolute top-8 aspect-square w-11/12 rounded-full rotate-[calc(100deg-45deg)] bg-gradient-to-tr from-transparent from-50% to-blue-100 to-50% transition-transform duration-500"></div>
        <div class="absolute top-1/3 flex aspect-square w-3/4 justify-center rounded-full bg-blue-100 "></div>
        <div class="absolute bottom-0 w-full truncate text-center text-[20vmax] leading-none">60%</div>
    </div>

@gquittet
Copy link
Author

gquittet commented Feb 6, 2024

Thanks for sharing 👍

@aryomuzakki
Copy link

@gquittet this is great. You have any idea to make it multiple color?

what @MajeedAB have share is great but I still don't understand how to modify it, and I can't make it look right (not responsive too)

@aryomuzakki
Copy link

I come up with this, just a stacked of half circle divs. I Achieved similar solution to @MajeedAB, maybe better.
But actually sometimes there's an extra small pixel visible.

https://play.tailwindcss.com/H4o6E6s6Qf

image

<div class="relative m-8 flex aspect-[2/1] items-center overflow-hidden">
  <!-- outer ring -->
  <div class="absolute h-full w-full rounded-t-full bg-green-500"></div>
  <div class="absolute h-full w-full origin-[50%_100%] rotate-[110deg] rounded-t-full bg-yellow-300"></div>
  <div class="absolute h-full w-full origin-[50%_100%] rotate-[150deg] rounded-t-full bg-red-500"></div>
  <!-- actual gauge -->
  <div class="absolute bottom-0 left-1/2 flex h-[90%] w-[90%] -translate-x-1/2 items-end justify-center rounded-t-full bg-green-100 text-center text-8xl"></div>
  <div class="absolute bottom-0 left-1/2 flex h-[90%] w-[90%] origin-[50%_100%] -translate-x-1/2 -rotate-[60deg] items-end justify-center rounded-t-full bg-blue-600 text-center text-8xl"></div>
  <div class="absolute bottom-0 left-1/2 flex h-[75%] w-[75%] -translate-x-1/2 items-end justify-center rounded-t-full bg-green-100 text-center text-8xl font-semibold">40%</div>
</div>

Your snippet have the extra small pixel visible too, but I managed to modified it. (https://play.tailwindcss.com/8zzqB4iASh)

@aryomuzakki
Copy link

Apparently, I just need to nested it and with a bit modification it can become like this

https://play.tailwindcss.com/bIWB9GkMtB

image

<div class="relative flex aspect-[2] items-center justify-center overflow-hidden rounded-t-full">
  <!-- outer ring -->
  <div class="absolute aspect-square top-0 w-full rotate-[calc(100deg-45deg)] bg-gradient-to-tr from-green-400 from-50% to-transparent to-50% transition-transform duration-500"></div>
  <div class="absolute aspect-square top-0 w-full rotate-[calc(100deg-45deg)] bg-gradient-to-tr from-transparent from-50% to-yellow-400 to-50% transition-transform duration-500"></div>
  <div class="absolute aspect-square top-0 w-full rotate-[calc(140deg-45deg)] bg-gradient-to-tr from-transparent from-50% to-red-400 to-50% transition-transform duration-500"></div>
  
  <!-- actual gauge -->
  <div class="absolute inset-8 flex aspect-[2] items-center justify-center overflow-hidden rounded-t-full border-4 border-b-0 border-slate-600">
    <div class="absolute aspect-square top-0 w-full rotate-[calc(72deg-45deg)] bg-gradient-to-tr from-blue-400 from-50% to-transparent to-50% transition-transform duration-500"></div>
    <div class="absolute aspect-square top-0 w-full rotate-[calc(72deg-45deg)] bg-gradient-to-tr from-transparent from-50% to-blue-100 to-50% transition-transform duration-500"></div>
    <div class="absolute top-1/4 flex aspect-square w-3/4 justify-center rounded-full bg-blue-100"></div>
    <div class="absolute bottom-0 w-full truncate text-center text-8xl leading-none">40%</div>
  </div>
</div>

And for separation we just need to control the border.

@gquittet
Copy link
Author

@aryomuzakki Thanks for sharing! 🙏
Nice solution! 🤟

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment