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.
JavaScript

Avatar of undefined
Last Comment
drunken_elf

8/22/2022 - Mon
RobPal

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
hankknight


<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

ASKER
drunken_elf

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.
Experts Exchange has (a) saved my job multiple times, (b) saved me hours, days, and even weeks of work, and often (c) makes me look like a superhero! This place is MAGIC!
Walt Forbes
RobPal

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
hankknight

Log in or sign up to see answer
Become an EE member today7-DAY FREE TRIAL
Members can start a 7-Day Free trial then enjoy unlimited access to the platform
Sign up - Free for 7 days
or
Learn why we charge membership fees
We get it - no one likes a content blocker. Take one extra minute and find out why we block content.
See how we're fighting big data
Not exactly the question you had in mind?
Sign up for an EE membership and get your own personalized solution. With an EE membership, you can ask unlimited troubleshooting, research, or opinion questions.
ask a question
ASKER
drunken_elf

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