DEV Community

Cover image for How to Build a Color Wheel with Tints & Shades
Mads Stoumann
Mads Stoumann

Posted on

How to Build a Color Wheel with Tints & Shades

I've built a handful of color pickers through the years, so when I in this book stumbled upon a color-wheel with “built-in” shades and tints, I had to code it:

Color Wheel with tints and shades

At first, I thought: “That's easy – it's just a conical gradient with hard stops for the colors, and a radial gradient for the tints and shades”.

But, alas, look at how “un-crisp” the edges in the conical gradient are (Chrome, MacOS):

Color Wheel, using conical gradient

So – I had to do it in <svg>.

Each “ring” in the circle is built up by 12 circles with different colors and stroke-dasharray:

<g id="wheel">
  <circle class="c3" cx="16" cy="16" r="16"></circle>
  <circle class="c2" cx="16" cy="16" r="16"></circle>
  <circle class="c1" cx="16" cy="16" r="16"></circle>
...etc
Enter fullscreen mode Exit fullscreen mode

And the CSS:

--u: calc(100 / 12);

.c1 {
  stroke: hsl(0, var(--s), var(--l));
  stroke-dasharray: var(--u) 100;
}
.c2 {
  stroke: hsl(30, var(--s), var(--l));
  stroke-dasharray: calc(2 * var(--u)) 100;
}
.c3 {
  stroke: hsl(60, var(--s), var(--l));
  stroke-dasharray: calc(3 * var(--u)) 100;
}
/* ... etc */
Enter fullscreen mode Exit fullscreen mode

The circles are wrapped in a <g>-tag with id="wheel", so I can use <use> (pun intended) to clone the rings:

<use href="#wheel" class="r3" />
<use href="#wheel" class="r2" />
<use href="#wheel" class="r1" />
etc...
Enter fullscreen mode Exit fullscreen mode

Each ring-class then sets a different --l (lightness) and stroke-width:

.r1 {
  --l: 40%;
  stroke-width: 3;
}
.r2 {
  --l: 45%;
  stroke-width: 6;
}
/* ... etc */
Enter fullscreen mode Exit fullscreen mode

In the final result I've chosen more tints than shades, so it's not as dark as in the book-example. Firefox has issues with setting some svg-attributes in CSS, so check it out in Chrome, Edge or Safari:


Let's have some fun!

How about rotating those color rings – or changing the saturation? Scroll down to see and try the controls, if they're not at the top of the Pen:

To have an automated animation, animating the --r custom property, we need to register a Custom Property:

@property --r {
  syntax: "<angle>";
  initial-value: 0deg;
  inherits: false;
}
Enter fullscreen mode Exit fullscreen mode

And the animation:

@keyframes rotate {
  100% {
    --r: 360deg;
  }
}
Enter fullscreen mode Exit fullscreen mode

Resulting in this (you need Chrome/Edge with Houdini):

Don't stare at it too long – or you'll be hypnotized!

Thanks for reading!

Top comments (11)

Collapse
 
afif profile image
Temani Afif

My CSS only idea: codepen.io/t_afif/pen/VwPqGyj and with rotation: codepen.io/t_afif/pen/KKabxJJ (need more html here)

Collapse
 
shaijut profile image
Shaiju T

Nice 😄, Can you show us how to make CSS based animations like Thank you and Successful and congrats messages to users, using confetti css or some other technique. Like below:

tympanus.net/Development/AnimatedM...

Example:

  1. Google Play Successful Payment animation with a tick mark and Confetti
  2. Hackerearth Congrats Confetti as shown here
Collapse
 
afif profile image
Temani Afif • Edited

are you challenging me ? 😛

Ok, I will think about it, maybe this will be my next post 😉

Thread Thread
 
shaijut profile image
Shaiju T • Edited

Not challenging. Just asking if you have seen those kind of messages anywhere. I dont know how they do those kind of animation maybe using CSS or SVG.

Just want to learn cool CSS animations 😄

Thread Thread
 
afif profile image
Temani Afif

Such animations are generally made using canvas. If you inspect the code you will notice a <canvas> element and then you have to dig into the JS because it's there where you will find the whole logic

Collapse
 
madsstoumann profile image
Mads Stoumann • Edited

Nice! But it has the same issue on Chrome (MacOS), as I encountered - the edges are blurry :-(
That's why I went the svg-way, although the CSS-way is way simpler!
Looks great in Safari, though!

blurry

Collapse
 
afif profile image
Temani Afif • Edited

yes it's a known issue when the gradient contain a lot of color stops. You can fix it by using multiple background instead: codepen.io/t_afif/pen/VwPqEmr

Thread Thread
 
madsstoumann profile image
Mads Stoumann

Wow! I'm super-impressed - also at the speed you've been making these demos!

Collapse
 
yellowbluevase profile image
YellowBlueVase

Hi, but your solution doesn't let pick a color. As I understand for this purpose you HAVE TO have this color wheel on canvas to extract data with ImageData

Collapse
 
braydoncoyer profile image
Braydon Coyer

Lovely! Thanks for sharing!

Collapse
 
madsstoumann profile image
Mads Stoumann

Thank you!