0

I have some colored text to indicate quality (red = bad, green = good).

When the quality is at 50%, the text is yellow and barely legible. Is there any way to have a gradient go from red to green without yellow in the middle?

(The quality could be any value, so setting the colors manually won't work.)

for(i=0;i<=100;i+=10) {
  $('body').append('<div style="color:' + color(i/100) + '">Quality ' + i + '</div>');
}

function color(quality) {
  var h = 355 + 125 * quality;
  var s = 130 - 60 * quality;
  var l = 60;
  return 'hsl(' + h + ', ' + s + '%, ' + l + '%)';
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

An alternative is this function, but it just returns an ugly brown in the middle:

for(i=0;i<=100;i+=10) {
  $('body').append('<div style="color:' + color(i/100) + '">Quality ' + i + '</div>');
}

function color(quality) {
  var r = 255 * (1 - quality);
  var g = 255 * quality;
  var b = 0;
  return 'rgb(' + r + ', ' + g + ', ' + b + ')';
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
Tonald Drump
  • 1,227
  • 1
  • 19
  • 32
  • I fear what I'm asking is physically impossible :D But how have others solved this issue? Surely, gradients red->green aren't uncommon.. – Tonald Drump Apr 12 '21 at 11:07
  • Possible dupe: [Generate colors between red and green for an input range](https://stackoverflow.com/questions/11849308/generate-colors-between-red-and-green-for-an-input-range) – Andreas Apr 12 '21 at 11:12
  • You could split into two ranges, and then you should choose the middle point. Common is white (instead of yellow). You can go via blue/violet (but in this case, choose a light one). – Giacomo Catenazzi Apr 12 '21 at 11:25
  • @Andreas No, the answer in that post is the starting point in mine - a gradient that goes red->yellow->green. That leads to barely legible text at 50% – Tonald Drump Apr 12 '21 at 11:25

2 Answers2

0

Here's a possible way to do it using hue-rotate, but it has the dirty-brown problem rather. I'm including it because it uses a css filter rather than a css color, which might be of interest because it's a different approach. The constant 1.2 was reached by trial and error rather than calculation, so could be adjusted to taste.

for(i=0;i<=100;i+=10) {
  $('body').append('<div style="color:hsl(355, 130%, 60%); filter:hue-rotate(' + i * 1.2 + 'deg)">Quality ' + i + '</div>');
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
Chris Lear
  • 6,592
  • 1
  • 18
  • 26
0

I have modified my function to reduce the l-value the closer it gets to .5 (yellow). Obviously, the yellow is a bit muddy now, but overall I feel this is a good solution :)

for(i=0;i<=100;i+=10) {
  $('body').append('<div style="color:' + color(i/100) + '">Quality ' + i + '</div>');
}

function color(quality) {
  var h = 355 + 125 * quality;
  var s = 130 - 60 * quality;
  var l = 45 + Math.abs(0.5 - quality) * 30;
  return 'hsl(' + h + ', ' + s + '%, ' + l + '%)';
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
Tonald Drump
  • 1,227
  • 1
  • 19
  • 32