4

I want font colour on my html page to change to black if the background colour of the row is light and black if the background is white

I'm using jsp in my page. is there a way to say something like this

if colour < ##0686FF then fontcolour = #000000 for example

edit: looking for a scriptlet or javascript

124697
  • 22,097
  • 68
  • 188
  • 315
  • 1
    I think you should try JavaScript to achieve this. – Harry Joy Jan 13 '11 at 11:54
  • you could cut it fast by using the inverse of your color - thus you can be sure that the text is always visible *inverted_color = hex value of FFFFFF - your_color* – Lucius Jan 13 '11 at 12:04

5 Answers5

12

This solution uses the java.awt.Color class to derive the brightness value of the colour and use that to determine which background colour should be used.

edit: This solution is differs from some of the other solutions because the other solutions will consider some bright colours to be dark eg. primary red (#FF0000). Whereas this solution, will consider primary red to be one of the brightest colours you can have. I suppose it depends on your preferences. Do you want to read red on black or red on white?

String fontColor = "#0cf356";

// remove hash character from string
String rawFontColor = fontColor.substring(1,fontColor.length());

// convert hex string to int
int rgb = Integer.parseInt(rawFontColor, 16);

Color c = new Color(rgb);

float[] hsb = Color.RGBtoHSB(c.getRed(), c.getGreen(), c.getBlue(), null);

float brightness = hsb[2];

if (brightness < 0.5) {
   // use a bright background
} else {
   // use a dark background
}

HSB stands for Hue, Saturation, Brightness -- brightness is also known as luminosity. With the Color class values are between 1 and 0. Ergo, 0.5 brightness is the the halfway point between the brightest colours and the darkest colours).

The interplay between hue, saturation and brightness are a little more complex than red, blue and green. Use this tool experiment with different colours and find the relationships between RGB and HSB

Dunes
  • 37,291
  • 7
  • 81
  • 97
  • Great works good. can you tell me what 0.5 means. what colour would that be? – 124697 Jan 13 '11 at 14:32
  • also with your code the brightness of green(#45A61F) comes out brighter than lightblue(#99CCCC) how do you fix it – 124697 Jan 13 '11 at 14:41
  • 1
    Are sure about the green and the blue. I quickly ran the program and it produces a brightness of 0.8 for the blue and 0.65 for the green. (Where 1 is the brightest and 0 is the darkest). Will add an edit about what hsb and 0.5 means. – Dunes Jan 13 '11 at 14:54
10

By "color" we usually mean 24-bit RGB color: 1 byte (8 bits) for red, green, blue. That is, every channel has value from 0-255, or 0x00 to 0xff in hexadecimal display.

White color is all channels at full: #FFFFFF, black is all channels turned off: #000000. Obviously, lighter color means higher values in channels, darker color means lower values in channels.

How exactly you choose your algorithm is up to you, simple one would be:

//pseudo-code
if (red + green + blue <= (0xff * 3) / 2) //half-down, half-up
  fontcolor = white;
else
  fontcolor = black;

Edit: asker asks for more complete example, so he/she can have better start, so here it is:

public static void main(String[] args) throws IOException {

String value =
       // new Scanner(System.in).nextLine(); //from input
        "#112233"; //from constant
int red = Integer.parseInt(value.substring(1, 1 + 2), 16);
int green = Integer.parseInt(value.substring(3, 3 + 2), 16);
int blue = Integer.parseInt(value.substring(5, 5 + 2), 16);

System.out.println("red = " + Integer.toHexString(red)
        + ", green = " + Integer.toHexString(green)
        + ", blue = " + Integer.toHexString(blue));

if (red + green + blue <= 0xff * 3 / 2)
    System.out.println("using white color #ffffff");
else
    System.out.println("using black color #000000");

String colorBackToString = "#" + Integer.toHexString(red) +
        Integer.toHexString(green) +
        Integer.toHexString(blue);
System.out.println("color was " + colorBackToString);
}

It produces output:

red = 11, green = 22, blue = 33
using white color #ffffff
color was #112233

And shows technique of splitting color in format #aabbcc into rgb channels, joining them later (if needed), etc.

peenut
  • 3,366
  • 23
  • 24
3

A more natural approach might be using the HSL colorspace. You can use the third component ("lightness") to figure out how light a colour is. That will work for most purposes.

Plenty of descriptions out there by googling. Basically you take the colour component with the highest value (let's say it's red) and the one with the lowest (say, green). In this case:

L = (red + green) / (255*2.0)

Assuming you extracted your colours as values from 0 to 255. You'll get a value between 0 and 1. A light colour could be any colour with a lightness above a certain arbitrary value (for instance, 0.6).

wds
  • 31,873
  • 11
  • 59
  • 84
  • @Dunes, ah well, I'll +1 you anyway for using the `Color` API. I was too lazy to look it up. :-) – wds Jan 13 '11 at 13:33
1
function isTooLightYIQ(hexcolor)
{
      var r = parseInt(hexcolor.substr(0,2),16);
      var g = parseInt(hexcolor.substr(2,2),16);
      var b = parseInt(hexcolor.substr(4,2),16);
      var yiq = ((r*299)+(g*587)+(b*114))/1000;
      return yiq >= 128;
}

The color picker used in http://www.careerbless.com/services/css/csstooltipcreator.php works good

Kiran
  • 896
  • 1
  • 6
  • 25
0

Here is Kiran's answer from above in PHP, which works great for me. Thanks Kiran.

function isTooLightYIQ($hexcolor)
{
    $hexcolor = ltrim($hexcolor, "#");
    $r = base_convert(substr($hexcolor, 0, 2), 16, 10); 
    $g = base_convert(substr($hexcolor, 2, 2), 16, 10); 
    $b = base_convert(substr($hexcolor, 4, 2), 16, 10); 
    $yiq = (($r * 299) + ($g * 587) + ($b * 114)) / 1000;
    return $yiq >= 128;
}

Usage (using maliayas's adjustBrightness() function):

$adjustPercent = -0.45;  //  45% darker
$darkHexColor = (isTooLightYIQ($hexColor)) ? adjustBrightness($hexColor, $adjustPercent) : $HexColor;