In this piece I will show you how you can calculate esthetic colors using Javascript. In this particular case the result will be a glossy button, but this technique can be used for anything.
Background: At cSupport we have a very different idea of how to work with design. While most of our competitors use fixed templates, or have a huge palette where you need to decide every single color, we believe that it should be much more straight forward, and elegant. Give us one color, and we will calculate everything else needed for delivering a gorgeous layout. We have used this setup for more than 2 years now, and I think it is time for us to reveal how!
JSFiddle (source code): http://jsfiddle.net/danschultzer/BQHHR/
Gist (source code): https://gist.github.com/danschultzer/5289717
This will be our final version (click it to update the color):
Let’s get down to it!
1. Starting from just one base color!
Let’s start off with just one HEX color as our base color. You can use any color yourself, and replicate the following steps! Or just click on the buttons to change the color randomly.
Sometimes you might use hex colors of just 3 values such as #000. We have to fix that by using the following function.
// HEX digits
function correctHex(color){
color = String(color).replace(/#[^0-9a-fA-F]/gi, "");
if (color.length<6) {
color='#' + color[1] + color[1] + color[2] + color[2] + color[3] + color[3];
}
return color;
}
Of course you might also want to make sure that it is a valid color, but for the simplicity of this blog post we do not check for that.
2. What is a readable contrast?
We want to use the chosen color as a background color. The text color has to be readable thus light background with light text, and dark background with dark text is no-go!
The following function will decide if we need a black or a white text color. This is not an exact science, and there will be cases where the composition doesn’t look visually appealing (you can adjust the threshold values). In almost all cases we keep good esthetics though!
// Text Color
function textColor(color){
var treshold = 105;
var delta = parseInt(color.substr(1, 2), 16) * 0.299 + parseInt(color.substr(3, 2), 16) * 0.587 + parseInt(color.substr(5, 2), 16) * 0.114;
return ((255 - delta) < treshold) ? "#000000" : "#ffffff";
}
This function gives us the following text color:
Great, now we are able to find the right contrast so the text can be read easily!
3. Time for the glossy color!
We are well on our way to create amazing automated esthetic coloring! Now, I wish to add a glossy look (basically a gradient). To do this we have to calculate the color darker/lighter than it is. Usually you do this by converting to HSL, but this is tedious, and I believe ultimately a waste of energy. I found a much smarter solution from Craig Buckler.
This function calculates lighter/darker shades of a color in a very simple way.
// Color Luminance
function colorLuminance(color, lum) {
color = color.replace(/^\s*#|\s*$/g, "");
lum=lum||0;
// convert to decimal and change luminosity
var color2="#",c,i;
for (i=0;i<3;i++){
c = parseInt(color.substr(i*2, 2), 16);
if(c<50)c=50;
c = Math.round(Math.min(Math.max(0,c + (c*lum)), 255)).toString(16);
color2 += ("00" + c).substr(c.length);
}
return color2;
}
Let’s say we want a glossy reflection, top to down. We go for 20% glossiness. In this case we have to make sure that the lighter color always will be on top.
This function takes care of the luminance on darker/lighter colors, and will output the darker and ligher color in correct order, based on the text color. To make it more clear, we don’t want a more light white color, or a more dark black color.
// Glossy Color
function calculateGlossyColors(color, textColor, shine)
{
if (textColor == "#000000") {
var color2 = color;
color = colorLuminance(color, -shine);
} else {
var color2 = colorLuminance(color, shine);
}
return {color: color, color2: color2}
}
Here is 20% difference in the colors:
color2 will always be the lighter one (glossy), so we can safely use it as the top color
4. Now it get’s interesting, gradients!
Now let’s build a simple CSS3 gradient generator. We are just using a linear top-down gradient.
// Gradient Builder
function gradientBuilder(color, color2, start, middle1, middle2, end){
return "background-image: -moz-linear-gradient( top, " + color2 + " " + start + ", " + color2 + " " + middle1 + ", " + color + " " + middle2 + ", " + color + " " + end + ");" /* FF3.6+ */
+"background-image: -webkit-gradient( linear, left top, left bottom, color-stop(" + start + "," + color2 + "), color-stop(" + middle2 + "," + color2 + "), color-stop(" + middle2 + "," + color + "), color-stop(" + end + "," + color + "));" /* Chrome,Safari4+ */
+"background-image: -webkit-linear-gradient( top, " + color2 + " " + start + ", " + color2 + " " + middle1 + ", " + color + " " + middle2 + ", " + color + " " + end + ");" /* Chrome10+,Safari5.1+ */
+"background-image: -o-linear-gradient( top, " + color2 + " " + start + ", " + color2 + " " + middle1 + ", " + color + " " + middle2 + ", " + color + " " + end + "));" /* Opera 11.10+ */
+"background-image: -ms-linear-gradient( top, " + color2 + " " + start + ", " + color2 + " " + middle1 + ", " + color + " " + middle2 + ", " + color + " " + end + "));" /* IE10+ */
+"background: linear-gradient(to bottom, " + color2 + " " + start + ", " + color2 + " " + middle1 + ", " + color + " " + middle2 + ", " + color + " " + end + ");" /* W3C */
// IE gradient is disabled because it makes tooltip's not being displayed!
+"filter: progid: DXImageTransform." + "Microsoft" + ".gradient(" + "startColorstr=\'" + color2 + "\',endColorstr=\'" + color +"\',GradientType=0" + ");zoom:1;" /* IE6-9, careful, they always mess up */
}
We can now add the gradient to our button! With a stop around half-way we will make the glossy effect powerful. It’s really shaping up with all functions together now:
5. Conclusion
From here on all the heavy work is done. Now we can add all the extra (subtle) stuff. I have added an indent text shadow for better readability, and done a more sharp and fluid look.
You can move forward from here, and build pretty much anything that uses an unpredictable random color. With this technique, you will stay highly flexible, and the output will almost always be esthetically pleasing for the eyes! Of course this is in no way meant for any permanent design. This is for situations where colors can, and will change easily, and you need the ultimate flexibility, while keeping everything looking sharp.
CSS3 Speech Bubble dcCSS3 iOS IconCSS3 Arrow Pattern
Let me know if you do something awesome with this, I would love to hear from you!
Sources: Contrast text color method, Luminance calculation method, CSS3 Speech Bubble, CSS3 iOS Icon, CSS3 Arrow Pattern