HP.
HP.

Reputation: 19896

How to generate a CSS color that is some specific percentage lighter/darker using JavaScript

Let's say I have a color of #404040. How can I generate a new color hex code which is either lighter or darker by 20% (or another given percentage)? I need this for generating a color to apply on hover.

The color being applied changes based on the chosen theme, therefore it is not possible to use another class or :hover with a predefined color value.

Upvotes: 36

Views: 31542

Answers (11)

Jan Schaefer
Jan Schaefer

Reputation: 1932

For this solution you need two elements the outer one defines your color, the inner one is used for the highlighting. In my case I have something like this:

<div class="button"><a href="#">Hi Color</a></div>

Then you define in CSS:

.button {
   display: inline-block;
   background-color: blue;
}

.button a {
   display: inline-block;
}

.button a:hover {
   background-color: rgba(255,255,255,0.5);
}

JSFiddle

Upvotes: 1

SGFX
SGFX

Reputation: 11

Here is my way of doing it using replace and split.

var CO='';

$('#HoverMe').hover(function(){  
    CO=$(this).css('backgroundColor');
 
    var CC= $(this).css('backgroundColor').replace('rgb(','').replace(')','').split(',');

    var Change=0.2;

    var CR=Math.floor((CC[0]*Change)+parseInt(CC[0]));

    var CG=Math.floor((CC[1]*Change)+parseInt(CC[1]));

    var CB=Math.floor((CC[2]*Change)+parseInt(CC[2]));

    $(this).css('background','rgb('+CR+','+CG+','+CB+')');
},

function(){
    $(this).css('background',CO);
});

Upvotes: 1

user989840
user989840

Reputation: 188

From How to Calculate Lighter or Darker Hex Colors in JavaScript by Craig Buckler, September 6, 2011:

function ColorLuminance(hex, lum) {
  // validate hex string
  hex = String(hex).replace(/[^0-9a-f]/gi, '');
  if (hex.length < 6) {
      hex = hex[0]+hex[0]+hex[1]+hex[1]+hex[2]+hex[2];
  }
  lum = lum || 0;
  // convert to decimal and change luminosity
  var rgb = "#", c, i;
  for (i = 0; i < 3; i++) {
      c = parseInt(hex.substr(i*2,2), 16);
      c = Math.round(Math.min(Math.max(0, c + (c * lum)), 255)).toString(16);
      rgb += ("00"+c).substr(c.length);
  }
  return rgb;
}

Upvotes: 3

Radek
Radek

Reputation: 3931

If you mean server side JS then you can use Stylus which is a CSS preprocessor with built-in functions for making colors lighter/darker etc.

Upvotes: 0

Scott Mermelstein
Scott Mermelstein

Reputation: 15397

I found a way just using CSS, similar to Wander Nauta's solution, but without using an image. If you can change the html, simply put a div behind the area you want to change with the original color set as the background. Then, you can set the area you're concerned about with a semi-transparent white or black background, and you'll lighten or darken your element.

I'm guessing it has its limitations, but it works great for me.

Upvotes: 0

Simone Gianni
Simone Gianni

Reputation: 11662

Probably you missed http://www.safalra.com/web-design/javascript/colour-handling-and-processing/ . It supports HSV and HSL colors and convert between them and between RGB values.

HSV and HSL are much more "human friendly" representations of colors, so using them making a lighter color, a darker one, a more or less intense one, or finding the color with the best contrast is extremely simple.

Upvotes: 0

ericslaw
ericslaw

Reputation: 921

perhaps jquery.colorhelpers.js functions for scale and add would help? I'm trying to find better examples than are found in-line for the flot source code, however.

Upvotes: 0

Justin Johnson
Justin Johnson

Reputation: 31300

This is just a modification of eyelidlessness' answer, since I saw the same function twice

var pad = function(num, totalChars) {
    var pad = '0';
    num = num + '';
    while (num.length < totalChars) {
        num = pad + num;
    }
    return num;
};

// Ratio is between 0 and 1
var changeColor = function(color, ratio, darker) {
    var difference = Math.round(ratio * 255) * (darker ? -1 : 1),
        minmax     = darker ? Math.max : Math.min,
        decimal    = color.replace(
            /^#?([a-z0-9][a-z0-9])([a-z0-9][a-z0-9])([a-z0-9][a-z0-9])/i,
            function() {
                return parseInt(arguments[1], 16) + ',' +
                    parseInt(arguments[2], 16) + ',' +
                    parseInt(arguments[3], 16);
            }
        ).split(/,/);
    return [
        '#',
        pad(minmax(parseInt(decimal[0], 10) + difference, 0).toString(16), 2),
        pad(minmax(parseInt(decimal[1], 10) + difference, 0).toString(16), 2),
        pad(minmax(parseInt(decimal[2], 10) + difference, 0).toString(16), 2)
    ].join('');
};
var lighterColor = function(color, ratio) {
    return changeColor(color, ratio, false);
};
var darkerColor = function(color, ratio) {
    return changeColor(color, ratio, true);
};

// Use
var darker = darkerColor('#404040', .2);
var lighter = lighterColor('#404040', .2);

Upvotes: 0

eyelidlessness
eyelidlessness

Reputation: 63519

var pad = function(num, totalChars) {
    var pad = '0';
    num = num + '';
    while (num.length < totalChars) {
        num = pad + num;
    }
    return num;
};

// Ratio is between 0 and 1
var changeColor = function(color, ratio, darker) {
    // Trim trailing/leading whitespace
    color = color.replace(/^\s*|\s*$/, '');

    // Expand three-digit hex
    color = color.replace(
        /^#?([a-f0-9])([a-f0-9])([a-f0-9])$/i,
        '#$1$1$2$2$3$3'
    );

    // Calculate ratio
    var difference = Math.round(ratio * 256) * (darker ? -1 : 1),
        // Determine if input is RGB(A)
        rgb = color.match(new RegExp('^rgba?\\(\\s*' +
            '(\\d|[1-9]\\d|1\\d{2}|2[0-4][0-9]|25[0-5])' +
            '\\s*,\\s*' +
            '(\\d|[1-9]\\d|1\\d{2}|2[0-4][0-9]|25[0-5])' +
            '\\s*,\\s*' +
            '(\\d|[1-9]\\d|1\\d{2}|2[0-4][0-9]|25[0-5])' +
            '(?:\\s*,\\s*' +
            '(0|1|0?\\.\\d+))?' +
            '\\s*\\)$'
        , 'i')),
        alpha = !!rgb && rgb[4] != null ? rgb[4] : null,

        // Convert hex to decimal
        decimal = !!rgb? [rgb[1], rgb[2], rgb[3]] : color.replace(
            /^#?([a-f0-9][a-f0-9])([a-f0-9][a-f0-9])([a-f0-9][a-f0-9])/i,
            function() {
                return parseInt(arguments[1], 16) + ',' +
                    parseInt(arguments[2], 16) + ',' +
                    parseInt(arguments[3], 16);
            }
        ).split(/,/),
        returnValue;

    // Return RGB(A)
    return !!rgb ?
        'rgb' + (alpha !== null ? 'a' : '') + '(' +
            Math[darker ? 'max' : 'min'](
                parseInt(decimal[0], 10) + difference, darker ? 0 : 255
            ) + ', ' +
            Math[darker ? 'max' : 'min'](
                parseInt(decimal[1], 10) + difference, darker ? 0 : 255
            ) + ', ' +
            Math[darker ? 'max' : 'min'](
                parseInt(decimal[2], 10) + difference, darker ? 0 : 255
            ) +
            (alpha !== null ? ', ' + alpha : '') +
            ')' :
        // Return hex
        [
            '#',
            pad(Math[darker ? 'max' : 'min'](
                parseInt(decimal[0], 10) + difference, darker ? 0 : 255
            ).toString(16), 2),
            pad(Math[darker ? 'max' : 'min'](
                parseInt(decimal[1], 10) + difference, darker ? 0 : 255
            ).toString(16), 2),
            pad(Math[darker ? 'max' : 'min'](
                parseInt(decimal[2], 10) + difference, darker ? 0 : 255
            ).toString(16), 2)
        ].join('');
};
var lighterColor = function(color, ratio) {
    return changeColor(color, ratio, false);
};
var darkerColor = function(color, ratio) {
    return changeColor(color, ratio, true);
};

// Use
var darker = darkerColor('rgba(80, 75, 52, .5)', .2);
var lighter = lighterColor('rgba(80, 75, 52, .5)', .2);

Now handles RGB(A) input, as well as hex (3 digit or 6).

Upvotes: 67

Wander Nauta
Wander Nauta

Reputation: 19615

You could make a partially-transparent white or black PNG and overlay (underlay?) it on hover:

div.button {
  background-color: #404040;
}
body>div.button:hover {
  background-image: url('blackpixel.png');
}

No JS required.

Upvotes: 8

ChssPly76
ChssPly76

Reputation: 100686

You basically just need to add (for lighter) or subtract (for darker) equal amounts from each of R, G, B components.

Take a look at Domino 2.0 which is a small javascript library that does just that.

Upvotes: 1

Related Questions