Link to home
Start Free TrialLog in
Avatar of drunken_elf
drunken_elf

asked on

How do I automatically set a foreground colour based upon a background colour?

I need a function that will automatically choose white or black text based upon a background colour, so its readable (white on yellow is not, for example). It is for a member profile option I am creating on a website, where users can choose a base colour for their profile and depending on that colour it will set white or black text.

Any help would be great, thanks.
Avatar of RobPal
RobPal
Flag of United Kingdom of Great Britain and Northern Ireland image

Hi there, this will all depend on how many colours you are using, but we can set a rule using the hex code for colours to help determine whether black or white is the best text colour to overlay the background.

Firstly I'm assuming you will have some kind of html form dropdown menu for the user to pick their background colour.  When this value is chosen and the button clicked then you need a javascript function that will not only use the value of the option to set the background colour but also evaluate the middle two characters of the hex code to determine whether balc or white text should be used.

So your html form might look like this:


<form name="form1" onsubmit="chng_cols()">
  <select size="1" name="bgCol">
  <option value="#FF00FF">#FF00FF</option>
  <option value="#FFCCFF">#FFCCFF</option>
  <option value="#FF33FF">#FF33FF</option>
  <option value="#FF66FF">#FF66FF</option>
  <option value="#FF99FF">#FF99FF</option>
  <option value="#CC00CC">#CC00CC</option>
  <option value="#CC66CC">#CC66CC</option>
  <option value="#CC99CC">#CC99CC</option>
  <option value="#CCCCCC">#CCCCCC</option>
  </select>
  <p><input type="submit" value="Submit"></p>
</form>

and your script would look like this:-

function chng_cols() {

var colhex=document.form1.bgCol.value.slice(3,5);

  if (colhex=="FF") {
var txtCol = '#000000';
}
else if (colhex=="CC"){
var txtCol = '#000000';
}
else if (colhex=="99"){
var txtCol = '#000000';
}
else if (colhex=="66"){
var txtCol = '#FFFFFF';
}
else if (colhex=="33"){
var txtCol = '#FFFFFF';
}
else if (colhex=="00"){
var txtCol = '#FFFFFF';
}

  var bgCol=document.form1.bgCol.value
 
}


I hope that helps, let me know if not.

Rob

<html>
<head> 
<title>Demo</title>
 
<script type="text/javascript">
 
function inverse(theString)
{
 
var bodyBG = document.getElementsByTagName('BODY')[0];
bodyBG.style.background = bgColor = '#'+theString;
 
	if(theString.length<6||theString.length>6){
	window.alert('You Must Enter a six digit color code')
	document.rin.reset();
	return false;
	}
	a=theString.slice(0,2);
	b=theString.slice(2,4);
	c=theString.slice(4,6);
	a1=16*giveHex(a.slice(0,1));
	a2=giveHex(a.slice(1,2));
	a=a1+a2;
	b1=16*giveHex(b.slice(0,1));
	b2=giveHex(b.slice(1,2));
	b=b1+b2;
	c1=16*giveHex(c.slice(0,1));
	c2=giveHex(c.slice(1,2));
	c=c1+c2;
	newColor=DecToHex(255-a)+""+DecToHex(255-b)+""+DecToHex(255-c);
 
 
var fColor = document.getElementById('foreground');
fColor.style.color = newColor;
 
}
var hexbase="0123456789ABCDEF";
function DecToHex(number) {
          return( hexbase.charAt((number>> 4)& 0xf)+ hexbase.charAt(number& 0xf));
        }
function giveHex(s){
	s=s.toUpperCase();
	return parseInt(s,16);
}
 
 
</script>
 
</head>
<body>
 
 
<form>
#<input type="text" name="bgColor" id='bgColor'/>
<input type="button" value="Change Color" onclick="inverse(bgColor.value);" />
</form>
 
<div id="foreground">
<p>
This is a a test! It is for a member profile option I am creating on a website, where users can choose a base colour for their profile and depending on that colour it will set white or black text.
</p>
</div>
 
 
</body>
</html>

Open in new window

Avatar of drunken_elf
drunken_elf

ASKER

Hi guys,

Thanks for your comments.

RobPal, unfortunately your solution is not what I am after. I am using a HSV based colour picker to select the colours, so the possible colours a millions not just a drop down menu with a select few.

Hankknight, your solution was good but still not quite what I was looking for. Notice that if you try 808080 in the text box, the text is still not readable. Rather than an inversion, I would just like to provide the either black or white text.

I believe there are some guidelines from w3 our there, but I don't know where, and from memory they do not provide an answer, only a guide algorithm that I have no idea how to implement.

Any other ideas?

The jscolor control does it, but I cannot figure it out through their code?

Thanks for all your help so far.
Hi there.

It should be possible to adapt my code to suit your specific circumstances.  Just alter the way the hex colour code is passed to the script, ie not using a select dropdown.  The rules remain the same and you can add more if needed just by copying the patterm already in place

e.g.

else if (colhex=="80"){
var txtCol = '#FFFFFF';
}

I hope that helps but if not, maybe it might be useful for someone else looking for a similar solution.

Cheers,

Rob
ASKER CERTIFIED SOLUTION
Avatar of hankknight
hankknight
Flag of Canada image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Hankknight, that's just about what I was after. Just one thing...

Why do you define a and b but then use only c to measure brightness?

I've modified it so that c actually equals (c+b+a / 3) so its an average amongst the three. This seems to perform in the way I was looking for.

Thanks for your help guys.
Scott