Users can set the background-color of a button through a textbox that accept RGB hexadecimal notation: ff00ff
, ccaa22
, etc. So I need to set the te
var getContrastYIQ = function(color) {
var hex = '#';
var r, g, b;
if (color.indexOf(hex) > -1) {
r = parseInt(color.substr(1, 2), 16);
g = parseInt(color.substr(3, 2), 16);
b = parseInt(color.substr(5, 2), 16);
} else {
color = color.match(/\d+/g);
r = color[0];
g = color[1];
b = color[2];
}
var yiq = ((r * 299) + (g * 587) + (b * 114)) / 1000;
return (yiq >= 128) ? 'black' : 'white';
}
Thanks for the post ZetCoby! Had to adjust your "color.substr(" array position to account for the initial '#'; then it worked great! you could also use a color.replace('#',''); within the if block...
Salaman's code is good but sometimes his inversion is not readable enough. I use YCbCr and just change gray scale.
function invertColor(rgb) {
var yuv = rgb2yuv(rgb);
var factor = 180;
var threshold = 100;
yuv.y = clamp(yuv.y + (yuv.y > threshold ? -factor : factor));
return yuv2rgb(yuv);
}
jsfiddle demo
Here is a very small way to complement the hex value //hex value like "aa00cc"
function complementHex(hexValue){
var reqHex = "";
for(var i=0;i<6;i++){
reqHex = reqHex + (15-parseInt(hexValue[i],16)).toString(16);
}
return reqHex;
}
I linked another Question to this topic in the comments.
JS function to calculate complementary colour?
As Tejasva said you need to need to convert RGB to HSL, complement the Hue and convert it back.
I implemented the linked answer as a sample. Please upvote the original poster if this was helpful for you, because they provided the solution in fact.
Sample
http://jsfiddle.net/pLZ89/2/
You can invert the background color and use it as foreground color. The following algorithm produces results identical to the "Image > Adjustments > Invert" color command in Photoshop:
function invertColor(hexTripletColor) {
var color = hexTripletColor;
color = color.substring(1); // remove #
color = parseInt(color, 16); // convert to integer
color = 0xFFFFFF ^ color; // invert three bytes
color = color.toString(16); // convert to hex
color = ("000000" + color).slice(-6); // pad with leading zeros
color = "#" + color; // prepend #
return color;
}
/*
* Demonstration
*/
function randomColor() {
var color;
color = Math.floor(Math.random() * 0x1000000); // integer between 0x0 and 0xFFFFFF
color = color.toString(16); // convert to hex
color = ("000000" + color).slice(-6); // pad with leading zeros
color = "#" + color; // prepend #
return color;
}
$(function() {
$(".demolist li").each(function() {
var c1 = randomColor();
var c2 = invertColor(c1);
$(this).text(c1 + " " + c2).css({
"color": c1,
"background-color": c2
});
});
});
body { font: bold medium monospace; }
.demolist { margin: 0; padding: 0; list-style-type: none; overflow: hidden; }
.demolist li { float: left; width: 5em; height: 5em; text-align: center; }
<ul class="demolist">
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
</ul>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
Note that this is not a bullet-proof solution. Colors that are close to 50% brightness and/or saturation will not produce sufficient contrast.
Demo on jsFiddle
I had the same issue once, and gathered information all over the internet also using Salman A answer, I came up with this function, it supports hex, rgb and rgba
var invertColor = function (color) {
var hex = '#';
if(color.indexOf(hex) > -1){
color = color.substring(1);
color = parseInt(color, 16);
color = 0xFFFFFF ^ color;
color = color.toString(16);
color = ("000000" + color).slice(-6);
color = "#" + color;
}else{
color = Array.prototype.join.call(arguments).match(/(-?[0-9\.]+)/g);
for (var i = 0; i < color.length; i++) {
color[i] = (i === 3 ? 1 : 255) - color[i];
}
if(color.length === 4){
color = "rgba("+color[0]+","+color[1]+","+color[2]+","+color[3]+")";
}else{
color = "rgb("+color[0]+","+color[1]+","+color[2]+")";
}
}
return color;
}
but I don't think this is what you need, I found something more interesting, the below function will return white or black, it will decide witch one is more readable on the given color.
var getContrastYIQ = function (color){
var hex = '#';
var r,g,b;
if(color.indexOf(hex) > -1){
r = parseInt(color.substr(0,2),16);
g = parseInt(color.substr(2,2),16);
b = parseInt(color.substr(4,2),16);
}else{
color = color.match(/\d+/g);
r = color[0];
g = color[1];
b = color[2];
}
var yiq = ((r*299)+(g*587)+(b*114))/1000;
return (yiq >= 128) ? 'black' : 'white';
}
I don't take credit for any of this, I just got inspired and modified to my needs.
Sources: YIQ function explained