CSS Gradients that avoid the “gray dead zone”
joshwcomeau.com
joshwcomeau.com
I finally managed to complete the work last week and I'm quite happy with the results. Using the library people can set the colors of graphical objects or gradients using any CSS color space string (RGB, HSL, HWB, LAB, LCH) and the color should render as expected. The reduce-noise filter uses LAB internally to calculate color distances, but in the end I compromised and used euler distances for the algorithm rather than one of the more modern algorithms.
Work is still on a branch in the library[1] but I'm hoping to merge it into the main code in the next week or so (after testing across devices/screens/etc).
Aside: Safari has gone ahead and introduced support for HWB, LAB and LCH color strings in CSS. Sadly, they're not recognised by Safari's canvas engine (yet). Also, their HSL and HWB gradients seem to be the same as the RGB gradients; their LAB/LCH gradients seem to dodge the dreaded Gray Zone.
[1] - https://github.com/KaliedaRik/Scrawl-canvas/tree/dec-21-dith...
The book you mention seems to cover similar ground: http://www.yorku.ca/eye/toc.htm
I had some fun modeling the color space in 3d on codepen: https://codepen.io/torleifw/pen/jOwjPxp
(or a more boring slider option here: https://codepen.io/torleifw/pen/OJgdyPJ)
One of latest papers I've read recommended using a matrix to transform color spaces, which i've also done a codepen for.
Interestingly the opponent process mirrors the LAB color space, which is soon going to be available in Safari. This is pretty cool and can enable developers to color coordinate easier.
I'm going to give the webpage you linked a good read, looks very interesting.
[1] https://github.com/KaliedaRik/Scrawl-canvas/blob/master/sour...
I have had some success manually using Photoshop to generate a reduced color space image to only 5 distinct colors (probably optimally chosen by the algorithm) and then remapping those 5 colors to 5 the 5 colors I actually have. There must be better ways
I do agree about the rainbow of colours though. As someone who understands how RGB works and has worked with colour a lot for decades, this tool is kind of un-intuitive at a glance. That's probably alright though. I can continue hand-crafting gradients because I know how to. Most people using a generator likely don't know how to.
Otherwise it's also a great exercise in learning about and then teaching these things, which Josh is great at.
Edit: or it will produce the full spectrum between red and blue but that’s obviously not your preference.
The fixed points define only the end points of the splines. The space between the end points corresponds to the color value along the interpolation curve.
If we are in an rgb cube, we notice the "gray zone" is along the diagonal from (0,0,0 to 1,1,1).
If we take two colors opposite of this diagonal (say color_a={r=0.5, g=0.5, b=0.0} and color_b = {0.5,0.5,1 0} we notice if we linearly interpolate we go through gray (0.5,0.5,0.5) in the middle.
If in stead we move along a curved path that avoids the diagonal, trying to maintain the saturation we get a much nicer result.
This "curved path of roughly equal saturation" is easier to define in a colorspace such as HSV where the saturation is one of the spatial coordinates.
But as I always say, there is no theoretically "correct" way to define a gradient, only techniques optimized for some specific use case.
My personal opinion is that generally linear interpolation in RGB results in the least satisfying gradients but that is just my _taste_.
This is perhaps not possible in theory, but just adjusting the gradient curve so that the effect is minimized should be possible.
A bit nitpicky but: Hue is an angle, degree is it's unit.
Like the width of a football field is a length, meter is it's unit.
Otherwise, good point!
https://en.wikipedia.org/wiki/Football#Etymology
> It is widely assumed that the word "football" (or the phrase "foot ball") refers to the action of the foot kicking a ball. There is an alternative explanation, which is that football originally referred to a variety of games in medieval Europe, which were played on foot. There is no conclusive evidence for either explanation.
https://en.wikipedia.org/wiki/Football_(word)
> In some cases, the word has been applied to games which involved carrying a ball and specifically banned kicking. For example, the English writer William Hone, writing in 1825 or 1826, quotes the social commentator Sir Frederick Morton Eden, regarding a game – which Hone refers to as "Foot-Ball" – played in the parish of Scone, Perthshire [in which kicking the ball was prohibited]
> Conversely, in 1363, King Edward III of England issued a proclamation banning "...handball, football, or hockey; coursing and cock-fighting, or other such idle games", suggesting that "football" was in fact being differentiated from games that involved other parts of the body.
It seems unlikely that King Edward III meant to ban games that involved walking on your hands, or perhaps brachiating.
But this argument assumes that the etymology of 'handball' must be the same as 'football'. Football could be called that because you play it on foot, and handball could simultaneously be called that because you use your hand to strike the ball. There's no contradiction there.
If you followed this argument you'd be confused why we have basketball when netball already covers games that involve a net and a ball. Not all games are named by the same person with the same naming ideas.
You can compare monochromatic scales between various color space interpolations and order them by contrast (great for accessibility work). Lab is from the 70s, the newest one there is CIECAM2 from the 2000s, also looking most natural to my eyes.
There are multiple ways to look at differences in LAB space unfortunately. Each one more mathematically complex, yet more perceptually accurate: http://zschuessler.github.io/DeltaE/learn/
For a ton of useful equations and calculators: http://www.brucelindbloom.com/index.html
I think anybody that has to choose between the "gray dead zone" and the "rainbow" will ALWAYS settle for the "gray dead zone" if the initial requirement is to make a "yellow to blue gradient".
Does it contain valuable information? Yes. Does it avoid the "gray dead zone" problem? Not at all, unless you claim that bringing another problem magnitudes larger is "avoiding the problem".
I've tried the gradient generator, and I found it actually a bit difficult to pick colors that produced a significant grey zone.
Many similar problems to solve as in the gradient generator, but approached from a different point of view, and with some novel ideas.
But obviously this is admitting that this control isn't intuitive enough.
But my favorite gradient generator at the moment (most pleasant gradients IMO) is still [1].
- About gradients in particular: https://youtu.be/Uh95jZPTDfw?t=1111
- Original episode about color spaces: https://youtu.be/cGyLHxn16pE
Shout-out to to HSLUV which does exactly that.
wow, the "Ok" family is clearly much better at modeling human perception.
For instance, on your page, try to pick the most intense green using one of the Ok pickers. The edges of the physically representable colour space can be pretty important for many tasks.
Congrats to the author for such a cool product!
But everyone that ever did achieve it only did so with practice.
Blue pill: keep ignorant of graphic design, enjoy mocking the trivial and meaningless exploits of designers, laugh at their talk of the energy or feelings of a font (idolising even just one minute part of a single character), remain happy in your ignorance. The cost is that you will always feel something is missing in your life and work. There is a worthwhile struggle for meaning in the dark arts, you will miss out on the pleasure of creating form from the void.
There are profound joys of creating something beautiful. Engineering is easier but more restricted because the definition of engineering is compromising to meet limitations: design has fewer limits and they are mostly created by your society within your own mind. A aesthetic sense will get you widespread respect, because people can appreciate it. Great engineering is a lonely vice that is usually not even appreciated by your fellow engineers. As an engineer you can subversively affect graphic design and you often have massive control over aesthetics. Comparatively, graphic designers are chained artists that often bleed away their soul slowly until they become corporate zombies with minds of mush.
You can enjoy music without being a professional musician.
At least they let me invert the scroll wheel so that its behavior matches everything else in the world.
Everything else in the world has largely inverted, too :P
For most of my career I was a hybrid designer/developer. There's definitely a dialog between them, and engineering enables and constrains some elements of the esthetics, but in general I would say it works the other direction more often than not.
That's why when I read about von Tiesenhausen’s Law of Engineering Design, it really rang true for me: "If you want to have a maximum effect on the design of a new engineering system, learn to draw. Engineers always wind up designing the vehicle to look like the initial artist’s concept."
We're just talking about esthetics, rather than functionality or purpose or process, which are much more of a give-and-take.
This is why I eventually just moved straight over to design: so much of product development is path-dependent, and designers exert a ton of leverage just by creating documents upstream of engineers.
§ 12.1 Color space for interpolation https://www.w3.org/TR/css-color-4/#interpolation-space
https://www.da.vidbuchanan.co.uk/widgets/css-gradient-fixer/
Interpolaring in a perceptual colorspace might make sense in certain applications, but if arithmetic on color values is involved then a linear colorspace is a good default (and premultiplied alpha, but that's an other story).
Gamma correction is the bane of computer graphics, and in 2022 there is absolutely no excuse for not using linear colorspaces for all image processing. We have the RAM. 8-bit non-linear colorspaces are a compression technique and should be only used for file formats, not image processing, ever. So many things would look much better and correct if we stopped trying to incorrectly process images in a compressed representation without uncompressing them first.
For comparison: nobody has used A-law or mu-law audio compression ever since digital POTS lines, and we certainly don't process audio in that form, ever. It's the same exact concept as storing pixel values in 8-bits with a gamma function. But somehow we think we can get away with processing images in that domain. I guess it's because if you try to do that with audio, the result is obviously wrong to any human ear, while if you try to do it with images it only looks somewhat wrong, not completely wrong...
Really insightful deep dives into a very misunderstood technology, presented with a fun, lighthearted writing style that I find myself trying to emulate in my own technical writing.
(it didn't dawn on me until I accidentally bumped a slider and realized the page was interactive)
> How to use: Click and drag within the color gradient, or focus the color square and use the left/right arrow keys.
The HSV gradients look wonky; the HSV space was designed for easy color picking UI with efficient calculations on 1980's hardware, not for interpolation.
I found this site where you can play with interpolation via various color spaces:
https://colordesigner.io/gradient-generator
LAB looks good; but interestingly, going from yellow to blue, it doesn't interpolate through green at all. Which makes sense, since yellow-blue is one axis in LAB, whereas red-green is another.
[0] https://web.archive.org/web/*/https://www.joshwcomeau.com/cs...
It's useful, but not a substitute for really carefully picking your colors so it all works.
One of the harder things in creative projects is when you have two individual elements you want to use, but you don't like what happens if you add both.
I took a deep dive into gradients some time ago. Not CSS but custom calculations that evened out things like brightness, luminescence, contrast and so on. My key takeaway was that my preferred way of doing gradients was to use similar hues and also play around with the saturation of the colors. One does not need complimentary colors to get that gradient feel.
https://developer.mozilla.org/en-US/docs/Web/CSS/color_value...
I'm in mobile. sorry for not investigating this myself
##[class*="ToastySubscribe" i]
##[class*="FloatingSidebar" i]I remember years ago using non-linear functions to avoid a similar problem in a different field. I bet the same solution would work here and wouldn't look so "wrong". You could pick some non-linear fun to interpolate between values. And you could interpolate different RGB channels at an offset. The reult would be less gray in the middle.
The solution is to do linear interpolation in HSL instead of in RGB. It's a simple and useful insight and the article does a fantastic job explaining and motivating it. And then goes so far as to supply an interactive tool to try it out!
What you’re describing would result in a yellow to blue gradient having green in the middle - at least that’s what would be interpreted by the human eye.