[css] Dynamically change color to lighter or darker by percentage CSS (Javascript)

We have a big application on the site and we have a few links which are, let's say blue color like the blue links on this site. Now I want to make some other links, but with lighter color. Obviously I can just do simply by the hex code adding in the CSS file, but our site lets user decide what colors they want for their customized profile/site (like Twitter).

So, my question is: can we reduce the color by percentage?

Let's say the following code is CSS:

a {
  color: blue;
}

a.lighter {
  color: -50%; // obviously not correct way, but just an idea
}

OR

a.lighter {
  color: blue -50%;  // again not correct, but another example of setting color and then reducing it
}

Is there a way to reduce a color by a percentage?

This question is related to css

The answer is


There is "opacity" which will make the background shine through:

opacity: 0.5;

but I'm not sure this is what you mean. Define "reduce color": Make transparent? Or add white?


This is an old question, but most of the answers require the use of a preprocessor or JavaScript to operate, or they not only affect the color of the element but also the color of the elements contained within it. I am going to add a kind-of-complicated CSS-only way of doing the same thing. Probably in the future, with the more advanced CSS functions, it will be easier to do.

The idea is based on using:

  • RGB colors, so you have separate values for red, green, and blue;
  • CSS variables, to store the color values and the darkness; and
  • The calc function, to apply the change.

By default darkness will be 1 (for 100%, the regular color), and if you multiply by a number between 0 and 1, you'll be making the color darker. For example, if you multiply by 0.85 each of the values, you'll be making the colors 15% darker (100% - 15% = 85% = 0.85).

Here is an example, I created three classes: .dark, .darker, and .darkest that will make the original color 25%, 50%, and 75% darker respectively:

_x000D_
_x000D_
html {_x000D_
  --clarity: 1;_x000D_
}_x000D_
_x000D_
div {_x000D_
  display: inline-block;_x000D_
  height: 100px;_x000D_
  width: 100px;_x000D_
  line-height: 100px;_x000D_
  color: white;_x000D_
  text-align: center;_x000D_
  font-family: arial, sans-serif;_x000D_
  font-size: 20px;_x000D_
  background: rgba(_x000D_
                  calc(var(--r) * var(--clarity)), _x000D_
                  calc(var(--g) * var(--clarity)), _x000D_
                  calc(var(--b) * var(--clarity))_x000D_
                );_x000D_
}_x000D_
_x000D_
.dark    { --clarity: 0.75; }_x000D_
.darker  { --clarity: 0.50; }_x000D_
.darkest { --clarity: 0.25; }_x000D_
_x000D_
.red {_x000D_
  --r: 255;_x000D_
  --g: 0;_x000D_
  --b: 0;_x000D_
}_x000D_
_x000D_
.purple {_x000D_
  --r: 205;_x000D_
  --g: 30;_x000D_
  --b: 205;_x000D_
}
_x000D_
<div class="red">0%</div>_x000D_
<div class="red dark">25%</div>_x000D_
<div class="red darker">50%</div>_x000D_
<div class="red darkest">75%</div>_x000D_
_x000D_
<br/><br/>_x000D_
_x000D_
<div class="purple">0%</div>_x000D_
<div class="purple dark">25%</div>_x000D_
<div class="purple darker">50%</div>_x000D_
<div class="purple darkest">75%</div>
_x000D_
_x000D_
_x000D_


if you decide to use http://compass-style.org/, a sass-based css framework, it provides very useful darken() and lighten() sass functions to dynamically generate css. it's very clean:

@import compass/utilities

$link_color: #bb8f8f
a
  color: $link_color
a:visited
  color: $link_color
a:hover
  color: darken($link_color,10)

generates

a {
  color: #bb8f8f;
}

a:visited {
  color: #bb8f8f;
}

a:hover {
  color: #a86f6f;
}

As far as I know, there's no way you can do this in CSS.

But I think that a little server-side logic could easily do as you suggest. CSS stylesheets are normally static assets, but there is no reason they couldn't be dynamically generated by server-side code. Your server-side script would:

  1. Check a URL parameter to determine the user and therefore the user's chosen colour. Use a URL parameter rather than a session variable so that you can still cache the CSS.
  2. Break up the colour into its red, green and blue components
  3. Increment each of the three components by a set amount. Experiment with this to get the results you are after.
  4. Generate CSS incorporating the new colour

Links to this CSS-generating page would look something like:

<link rel="stylesheet" href="http://yoursite.com/custom.ashx?user=1231">

If you don't use the .css extension be sure to set the MIME-type correctly so that the browser knows to interpret the file as CSS.

(Note that to make colours lighter you have to raise each of the RGB values)


If you only need to change background color, this is a great approach that is futureproof - Use linear-gradient method on background image!

Check out the example below:

_x000D_
_x000D_
document_x000D_
  .getElementById('colorpicker')_x000D_
  .addEventListener('change', function(event) {_x000D_
    document_x000D_
      .documentElement_x000D_
      .style.setProperty('--color', event.target.value);_x000D_
  });
_x000D_
span {_x000D_
  display: inline-block;_x000D_
  border-radius: 20px;_x000D_
  height: 40px;_x000D_
  width: 40px;_x000D_
  vertical-align: middle;_x000D_
}_x000D_
_x000D_
.red {_x000D_
  background-color: red;_x000D_
}_x000D_
_x000D_
.red-darker {_x000D_
  background: linear-gradient(_x000D_
    to top,_x000D_
    rgba(0, 0, 0, 0.25),_x000D_
    rgba(0, 0, 0, 0.25)_x000D_
  ) red;_x000D_
}_x000D_
_x000D_
:root {_x000D_
  --color: lime;_x000D_
}_x000D_
_x000D_
.dynamic-color {_x000D_
  background-color: var(--color);_x000D_
}_x000D_
_x000D_
.dynamic-color-darker {_x000D_
  background: linear-gradient(_x000D_
    to top,_x000D_
    rgba(0, 0, 0, 0.25),_x000D_
    rgba(0, 0, 0, 0.25)_x000D_
  ) var(--color);_x000D_
}
_x000D_
<table>_x000D_
  <tr>_x000D_
    <td><strong>Static Color</strong></td>_x000D_
    <td><span class="red"></span></td>_x000D_
    <td><span class="red-darker"></span></td>_x000D_
  </tr>_x000D_
  <tr>_x000D_
    <td><strong>Dynamic Color</strong></td>_x000D_
    <td><span class="dynamic-color"></span></td>_x000D_
    <td><span class="dynamic-color-darker"></span></td>_x000D_
  </tr>_x000D_
</table>_x000D_
<br/>_x000D_
Change the dynamic color: <input id="colorpicker" value="#00ff00" type="color"/>
_x000D_
_x000D_
_x000D_

Credits: https://css-tricks.com/css-custom-properties-theming/


At the time of writing, here's the best pure CSS implementation for color manipulation I found:

Use CSS variables to define your colors in HSL instead of HEX/RGB format, then use calc() to manipulate them.

Here's a basic example:

_x000D_
_x000D_
:root {_x000D_
  --link-color-h: 211;_x000D_
  --link-color-s: 100%;_x000D_
  --link-color-l: 50%;_x000D_
  --link-color-hsl: var(--link-color-h), var(--link-color-s), var(--link-color-l);_x000D_
_x000D_
  --link-color: hsl(var(--link-color-hsl));_x000D_
  --link-color-10: hsla(var(--link-color-hsl), .1);_x000D_
  --link-color-20: hsla(var(--link-color-hsl), .2);_x000D_
  --link-color-30: hsla(var(--link-color-hsl), .3);_x000D_
  --link-color-40: hsla(var(--link-color-hsl), .4);_x000D_
  --link-color-50: hsla(var(--link-color-hsl), .5);_x000D_
  --link-color-60: hsla(var(--link-color-hsl), .6);_x000D_
  --link-color-70: hsla(var(--link-color-hsl), .7);_x000D_
  --link-color-80: hsla(var(--link-color-hsl), .8);_x000D_
  --link-color-90: hsla(var(--link-color-hsl), .9);_x000D_
_x000D_
  --link-color-warm: hsl(calc(var(--link-color-h) + 80), var(--link-color-s), var(--link-color-l));_x000D_
  --link-color-cold: hsl(calc(var(--link-color-h) - 80), var(--link-color-s), var(--link-color-l));_x000D_
_x000D_
  --link-color-low: hsl(var(--link-color-h), calc(var(--link-color-s) / 2), var(--link-color-l));_x000D_
  --link-color-lowest: hsl(var(--link-color-h), calc(var(--link-color-s) / 4), var(--link-color-l));_x000D_
_x000D_
  --link-color-light: hsl(var(--link-color-h), var(--link-color-s), calc(var(--link-color-l) / .9));_x000D_
  --link-color-dark: hsl(var(--link-color-h), var(--link-color-s), calc(var(--link-color-l) * .9));_x000D_
}_x000D_
_x000D_
.flex {_x000D_
  display: flex;_x000D_
}_x000D_
_x000D_
.flex > div {_x000D_
  flex: 1;_x000D_
  height: calc(100vw / 10);_x000D_
}
_x000D_
<h3>Color Manipulation (alpha)</h3>_x000D_
_x000D_
<div class="flex">_x000D_
  <div style="background-color: var(--link-color-10)"></div>_x000D_
  <div style="background-color: var(--link-color-20)"></div>_x000D_
  <div style="background-color: var(--link-color-30)"></div>_x000D_
  <div style="background-color: var(--link-color-40)"></div>_x000D_
  <div style="background-color: var(--link-color-50)"></div>_x000D_
  <div style="background-color: var(--link-color-60)"></div>_x000D_
  <div style="background-color: var(--link-color-70)"></div>_x000D_
  <div style="background-color: var(--link-color-80)"></div>_x000D_
  <div style="background-color: var(--link-color-90)"></div>_x000D_
  <div style="background-color: var(--link-color)"></div>_x000D_
</div>_x000D_
_x000D_
<h3>Color Manipulation (Hue)</h3>_x000D_
_x000D_
<div class="flex">_x000D_
  <div style="background-color: var(--link-color-warm)"></div>_x000D_
  <div style="background-color: var(--link-color)"></div>_x000D_
  <div style="background-color: var(--link-color-cold)"></div>_x000D_
</div>_x000D_
_x000D_
<h3>Color Manipulation (Saturation)</h3>_x000D_
_x000D_
<div class="flex">_x000D_
  <div style="background-color: var(--link-color)"></div>_x000D_
  <div style="background-color: var(--link-color-low)"></div>_x000D_
  <div style="background-color: var(--link-color-lowest)"></div>_x000D_
</div>_x000D_
_x000D_
<h3>Color Manipulation (Lightness)</h3>_x000D_
_x000D_
<div class="flex">_x000D_
  <div style="background-color: var(--link-color-light)"></div>_x000D_
  <div style="background-color: var(--link-color)"></div>_x000D_
  <div style="background-color: var(--link-color-dark)"></div>_x000D_
</div>
_x000D_
_x000D_
_x000D_

I also created a CSS framework (still in early stage) to provide basic CSS variables support called root-variables.


You can do this with CSS filters in all modern browsers (see the caniuse compatibility table).

_x000D_
_x000D_
.button {_x000D_
  color: #ff0000;_x000D_
}_x000D_
_x000D_
/* note: 100% is baseline so 85% is slightly darker, _x000D_
   20% would be significantly darker */_x000D_
.button:hover {_x000D_
  filter: brightness(85%);_x000D_
}
_x000D_
<button class="button">Foo lorem ipsum</button>
_x000D_
_x000D_
_x000D_

Here's more reading from CSS Tricks about the various filters you can use: https://css-tricks.com/almanac/properties/f/filter/


I am adding an answer using raw CSS3 and SVG without requiring LESS or SASS.

Basically, if the question is to make a colour 10%,25%,50% ligher or darker for the sakes of a global hover effect you can create an SVG data call like this

:root{
--lighten-bg: url('data:image/svg+xml;utf8,<svg version="1.1" id="cssLighten" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="50px" height="50px" viewBox="0 0 50 50" enable-background="new 0 0 50 50" xml:space="preserve"><rect opacity="0.2" fill="white" width="50" height="50"/></svg>') !important;
--darken-bg: url('data:image/svg+xml;utf8,<svg version="1.1" id="cssDarken" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="50px" height="50px" viewBox="0 0 50 50" enable-background="new 0 0 50 50" xml:space="preserve"><rect opacity="0.2" fill="black" width="50" height="50"/></svg>') !important;

}

.myButton{
    color: white;
    background-color:blue;
}
.myButton:hover{
    background-image: var(--lighten-bg);
}

For some reason, unknown to me, the SVG won't allow me to enter a hex value in the "fill" attribute but "white" and "black" satisfy my need.

Food for thought: If you didn't mind using images, just use a 50% transparent PNG as the background image. If you wanted to be fancy, call a PHP script as the background image and pass it the HEX and OPACITY values and let it spit out the SVG code above.


I found a PHP class that let me do this server side. I just output an inline CSS color style for whatever I need to be lighter/darker. Works great.

http://www.barelyfitz.com/projects/csscolor/

(note that the class uses PEAR for throwing errors, but I didn't want to include PEAR just to modify colors, so I just removed all the PEAR references)

I turned it into a static class with static methods so I can call "lighten" & "darken" functions directly without creating a new object.

Sample usage:

$original_color = 'E58D8D';  
$lighter_color = Css::lighten($original_color, .7);  
$darker_color = Css::darken($original_color, .7);

If you want darker color, you can use rgba black with low opacity:

rgba(0,0,0,0.3)

For lighter use white:

rgba(255,255,255,0.3).

In LESS, you would use the following variables:

@primary-color: #999;
@primary-color-lighter: lighten(@primary-color, 20%);

This would take the 1st variable and lighten it by 20% (or any other percentage). In this example, you'd end up with your lighter color being: #ccc


You could use a little javascript to calculate the darker and lighter color using the rgb().

Fiddle : Not really nice, but it is just for illustration.

What it essentially does is sets a color and selects 20 colors with the same amount (compared to one another) of rgb only with 10 apart.

for (var i=-10; i < $('.row:eq(0) .block').length/2 ; i++) {
 var r = 91;
 var g = 192;
 var b = 222;
 $('.row:eq(1) .block:eq('+(i+10)+')').css('background' , color(r+(i*10),g+(i*10),b+   (i*10))      );
};

Use the filter pure CSS property. for a complete description of the filter property functions read this awesome article.

I had a same issue like yours, and I fixed it by using the brightness function of filter property:

.my-class {
  background-color: #18d176;
  filter: brightness(90%);
}

See my comment on Ctford's reply.

I'd think the easy way to lighten a color would be to take each of the RGB components, add to 0xff and divide by 2. If that doesn't give the exact results you want, take 0xff minus the current value times some constant and then add back to the current value. For example if you want to shift 1/3 of the way toward white, take (0xff - current)/3+current.

You'd have to play with it to see what results you got. I would worry that with this simple a formula, a factor big enough to make dark colors fade nicely might make light colors turn completely white, while a factor small enough to make light colors only lighten a little might make dark colors not lighten enough.

Still, I think going by a fraction of the distance to white is more promising than a fixed number of steps.


Not directly, no. But you could use a site, such as colorschemedesigner.com, that will give you your base color and then give you the hex and rgb codes for different ranges of your base color.

Once I find my color schemes for my site, I put the hex codes for the colors and name them inside a comment section at the top of my stylesheet.

Some other color scheme generators include:


You could use RGBa ('a' being alpha transparency), but it's not widely supported yet. It will be, though, so you could use it now and add a fallback:

a:link { 
    color: rgb(0,0,255); 
    }
a:link.lighter {
    color: rgb(128,128,255); /* This gets applied only in browsers that don't apply the rgba line */
    }
a:link.lighter { /* This comes after the previous line, so has priority in supporting browsers */
    color: rgba(0,0,255,0.5); /* last value is transparency */
    }

One outdated simple answer (in 2013) was to use a 50% transparent white PNG over the color:

div {
    background-color:red;
}

div:hover {
    background-image:url('lighten.png');
}

Where lighten.png is a PNG of a white fill with 50% transparency.

There's much better ways to do this today. I hope people stop commenting now.


Try:

a {
  color: hsl(240, 100%, 50%);
}

a:hover {
  color: hsl(240, 100%, 70%);
}

Bringing it all together, a table solution done purely with DIV and CSS, try it ;) The browser should support RGBA colors though....

<head>
<style>
    .colored-div-table {
        display: table;
        table-layout: fixed;
    }
    .colored-div-table #col {
        display: table-column;
    }
    .colored-div-table #col:nth-child(odd) {
    }
    .colored-div-table #col:nth-child(even) {
    }
    .colored-div-table #col:nth-child(1){
        background-color: lightblue;
        width: 50px !important;
    }
    .colored-div-table #col:nth-child(2){
        background-color: lightyellow;
        width: 200px !important;
    }
    .colored-div-table #col:nth-child(3){
        background-color: lightcyan;
        width: 50px !important;
    }
    .colored-div-table #row {
        display: table-row;
    }
    .colored-div-table #row div {
        display: table-cell;
    }
    .colored-div-table #row div:nth-child(1) {

    }
    .colored-div-table #row div:nth-child(2) {
    }
    .colored-div-table #row div:nth-child(3) {
    }
    .colored-div-table #row:nth-child(odd) {
        background-color: rgba(0,0,0,0.1)
    }
    .colored-div-table #row:nth-child(even) {
    }
</style>
</head>
<body>

<div id="divtable" class="colored-div-table">
    <div id="col"></div>
    <div id="col"></div>
    <div id="col"></div>  

    <div id="row">
        <div>First Line</div><div>FL C2</div><div>FL C3></div>
    </div>

    <div id="row">
        <div>Second Line</div><div>SL C2</div><div>SL C3></div>
    </div>

    <div id="row">
        <div>Third Line</div><div>TL C2</div><div>TL C3></div>
    </div>

    <div id="row">
        <div>Forth Line</div><div>FL C2</div><div>FL C3></div>
    </div>
    <div id="row">
        <div>Fifth Line</div><div>FL C2</div><div>FL C3></div>
    </div>
    <div id="row">
        <div>Sixth Line</div><div>SL C2</div><div>SL C3></div>
    </div>
    <div id="row">
        <div>Seventh Line</div><div>SL C2</div><div>SL C3></div>
    </div>
    <div id="row">
        <div>Eight Line</div><div>EL C2</div><div>EL C3></div>
    </div>
    <div id="row">
        <div>Nineth Line</div><div>NL C2</div><div>NL C3></div>
    </div>
    <div id="row">
        <div>Tenth Line</div><div>TL C2</div><div>TL C3></div>
    </div>

</div>
</body>

You can use a JavaScript library such as JXtension which gives the user the ability to make a color lighter or darker. If you would like to find documentation for this brand new library, click here. You can also use JXtension to combine one color with another.


I know it's late but, you could use a wrapper to your buttons and change a rgba color function opacity level, as said in other answers but with no explicit example.

Here's a pen:

https://codepen.io/aronkof/pen/WzGmjR

_x000D_
_x000D_
#wrapper {_x000D_
  width: 50vw;_x000D_
  height: 50vh;_x000D_
  background-color: #AAA;_x000D_
  margin: 20px auto;_x000D_
  border-radius: 5px;_x000D_
  display: grid;_x000D_
  place-items: center;_x000D_
} _x000D_
_x000D_
.btn-wrap {_x000D_
  background-color: #000;_x000D_
  display: inline-block;_x000D_
}_x000D_
_x000D_
button {_x000D_
  transition: all 0.6s linear;_x000D_
  background-color: rgba(0, 255, 0, 1);_x000D_
  border: none;_x000D_
  outline: none;_x000D_
  color: #fff;_x000D_
  padding: 50px;_x000D_
  font-weight: 700;_x000D_
  font-size: 2em;_x000D_
}_x000D_
_x000D_
button:hover {_x000D_
  background-color: rgba(0, 255, 0, .5);_x000D_
}
_x000D_
<div id="wrapper">_x000D_
  <div class="btn-wrap">_x000D_
    <button class="btn">HEY!</buutton>_x000D_
  </div>_x000D_
</div>
_x000D_
_x000D_
_x000D_


HSL Colors provide an answer, a HSL color value is specified with: hsl(hue [0,255], saturation %, lightness %).

HSL is supported in IE9+, Firefox, Chrome, Safari, and in Opera 10+

a
{
color:hsl(240,65%,50%);
}
a.lighter 
{
color:hsl(240,65%,75%);
}

If you need to brute force it for older browser compatibility, you can use Colllor to automatically select similar color variations.

Example (color: #a9dbb4):

enter image description here