Dynamically change color to lighter or darker by percentage CSS

Css

Css Problem Overview


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?

Css Solutions


Solution 1 - Css

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

.button {
  color: #ff0000;
}

/* note: 100% is baseline so 85% is slightly darker, 
   20% would be significantly darker */
.button:hover {
  filter: brightness(85%);
}

<button class="button">Foo lorem ipsum</button>

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

Solution 2 - Css

All modern browsers have had 100% filter support since January 2020. Even UC Browser for Android (instead of Chrome, on the $80 phones) supports it.

a {
    /* a nice, modern blue for links */
    color: #118bee;
}
a:active {
    /* Darken on click by 15% (down to 85%) */
    filter: brightness(0.85);
}

Additionally, you can control this dynamically with CSS variables, which have been supported by most browsers since October 2017 (excluding QQ):

:root {
    --color: #118bee;
    --hover-brightness: 1.2;
}
a {
    color: var(--color);
}
a:active {
    /* Darken on click */
    filter: brightness(var(--hover-brightness));
}

Not my project, but one that's great to look at for a real-world example of how great modern CSS can be, check out: MVP.css


Original Answer

If you're using a stack which lets you use Sass or Less, you can use the lighten function:

$linkcolour: #0000FF;

a {
  color: $linkcolour;
}

a.lighter {
  color: lighten($linkcolour, 50%);
}

There's also darken which does the same, but in the opposite direction.

Solution 3 - Css

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?

Solution 4 - Css

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%);
}

Solution 5 - Css

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:

:root {
  --link-color-h: 211;
  --link-color-s: 100%;
  --link-color-l: 50%;
  --link-color-hsl: var(--link-color-h), var(--link-color-s), var(--link-color-l);

  --link-color: hsl(var(--link-color-hsl));
  --link-color-10: hsla(var(--link-color-hsl), .1);
  --link-color-20: hsla(var(--link-color-hsl), .2);
  --link-color-30: hsla(var(--link-color-hsl), .3);
  --link-color-40: hsla(var(--link-color-hsl), .4);
  --link-color-50: hsla(var(--link-color-hsl), .5);
  --link-color-60: hsla(var(--link-color-hsl), .6);
  --link-color-70: hsla(var(--link-color-hsl), .7);
  --link-color-80: hsla(var(--link-color-hsl), .8);
  --link-color-90: hsla(var(--link-color-hsl), .9);

  --link-color-warm: hsl(calc(var(--link-color-h) + 80), var(--link-color-s), var(--link-color-l));
  --link-color-cold: hsl(calc(var(--link-color-h) - 80), var(--link-color-s), var(--link-color-l));

  --link-color-low: hsl(var(--link-color-h), calc(var(--link-color-s) / 2), var(--link-color-l));
  --link-color-lowest: hsl(var(--link-color-h), calc(var(--link-color-s) / 4), var(--link-color-l));

  --link-color-light: hsl(var(--link-color-h), var(--link-color-s), calc(var(--link-color-l) / .9));
  --link-color-dark: hsl(var(--link-color-h), var(--link-color-s), calc(var(--link-color-l) * .9));
}

.flex {
  display: flex;
}

.flex > div {
  flex: 1;
  height: calc(100vw / 10);
}

<h3>Color Manipulation (alpha)</h3>

<div class="flex">
  <div style="background-color: var(--link-color-10)"></div>
  <div style="background-color: var(--link-color-20)"></div>
  <div style="background-color: var(--link-color-30)"></div>
  <div style="background-color: var(--link-color-40)"></div>
  <div style="background-color: var(--link-color-50)"></div>
  <div style="background-color: var(--link-color-60)"></div>
  <div style="background-color: var(--link-color-70)"></div>
  <div style="background-color: var(--link-color-80)"></div>
  <div style="background-color: var(--link-color-90)"></div>
  <div style="background-color: var(--link-color)"></div>
</div>

<h3>Color Manipulation (Hue)</h3>

<div class="flex">
  <div style="background-color: var(--link-color-warm)"></div>
  <div style="background-color: var(--link-color)"></div>
  <div style="background-color: var(--link-color-cold)"></div>
</div>

<h3>Color Manipulation (Saturation)</h3>

<div class="flex">
  <div style="background-color: var(--link-color)"></div>
  <div style="background-color: var(--link-color-low)"></div>
  <div style="background-color: var(--link-color-lowest)"></div>
</div>

<h3>Color Manipulation (Lightness)</h3>

<div class="flex">
  <div style="background-color: var(--link-color-light)"></div>
  <div style="background-color: var(--link-color)"></div>
  <div style="background-color: var(--link-color-dark)"></div>
</div>

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

Solution 6 - Css

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%);
}

Solution 7 - Css

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);

Solution 8 - Css

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

Solution 9 - Css

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:

html {
  --clarity: 1;
}

div {
  display: inline-block;
  height: 100px;
  width: 100px;
  line-height: 100px;
  color: white;
  text-align: center;
  font-family: arial, sans-serif;
  font-size: 20px;
  background: rgba(
                  calc(var(--r) * var(--clarity)), 
                  calc(var(--g) * var(--clarity)), 
                  calc(var(--b) * var(--clarity))
                );
}

.dark    { --clarity: 0.75; }
.darker  { --clarity: 0.50; }
.darkest { --clarity: 0.25; }

.red {
  --r: 255;
  --g: 0;
  --b: 0;
}

.purple {
  --r: 205;
  --g: 30;
  --b: 205;
}

<div class="red">0%</div>
<div class="red dark">25%</div>
<div class="red darker">50%</div>
<div class="red darkest">75%</div>

<br/><br/>

<div class="purple">0%</div>
<div class="purple dark">25%</div>
<div class="purple darker">50%</div>
<div class="purple darkest">75%</div>

Solution 10 - Css

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;
}

Solution 11 - Css

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)

Solution 12 - Css

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:

document
  .getElementById('colorpicker')
  .addEventListener('change', function(event) {
    document
      .documentElement
      .style.setProperty('--color', event.target.value);
  });

span {
  display: inline-block;
  border-radius: 20px;
  height: 40px;
  width: 40px;
  vertical-align: middle;
}

.red {
  background-color: red;
}

.red-darker {
  background: linear-gradient(
    to top,
    rgba(0, 0, 0, 0.25),
    rgba(0, 0, 0, 0.25)
  ) red;
}

:root {
  --color: lime;
}

.dynamic-color {
  background-color: var(--color);
}

.dynamic-color-darker {
  background: linear-gradient(
    to top,
    rgba(0, 0, 0, 0.25),
    rgba(0, 0, 0, 0.25)
  ) var(--color);
}

<table>
  <tr>
    <td><strong>Static Color</strong></td>
    <td><span class="red"></span></td>
    <td><span class="red-darker"></span></td>
  </tr>
  <tr>
    <td><strong>Dynamic Color</strong></td>
    <td><span class="dynamic-color"></span></td>
    <td><span class="dynamic-color-darker"></span></td>
  </tr>
</table>
<br/>
Change the dynamic color: <input id="colorpicker" value="#00ff00" type="color"/>

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

Solution 13 - Css

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))      );
};

Solution 14 - Css

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:

Solution 15 - Css

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

Solution 16 - Css

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 */
    }

Solution 17 - Css

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.

Solution 18 - Css

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.

Solution 19 - Css

Try:

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

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

Solution 20 - Css

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>

Solution 21 - Css

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

#wrapper {
  width: 50vw;
  height: 50vh;
  background-color: #AAA;
  margin: 20px auto;
  border-radius: 5px;
  display: grid;
  place-items: center;
} 

.btn-wrap {
  background-color: #000;
  display: inline-block;
}

button {
  transition: all 0.6s linear;
  background-color: rgba(0, 255, 0, 1);
  border: none;
  outline: none;
  color: #fff;
  padding: 50px;
  font-weight: 700;
  font-size: 2em;
}

button:hover {
  background-color: rgba(0, 255, 0, .5);
}

<div id="wrapper">
  <div class="btn-wrap">
    <button class="btn">HEY!</buutton>
  </div>
</div>

Solution 22 - Css

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.

Solution 23 - Css

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);

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionBasitView Question on Stackoverflow
Solution 1 - CssimjaredView Answer on Stackoverflow
Solution 2 - CssGrant CroftonView Answer on Stackoverflow
Solution 3 - CssPekkaView Answer on Stackoverflow
Solution 4 - CssSpliffView Answer on Stackoverflow
Solution 5 - CsssparanoidView Answer on Stackoverflow
Solution 6 - CssAmerllicAView Answer on Stackoverflow
Solution 7 - CssNemanjaLazicView Answer on Stackoverflow
Solution 8 - Csstrebor1979View Answer on Stackoverflow
Solution 9 - CssAlvaro MontoroView Answer on Stackoverflow
Solution 10 - CssJoao TavoraView Answer on Stackoverflow
Solution 11 - CssctfordView Answer on Stackoverflow
Solution 12 - CssYangshun TayView Answer on Stackoverflow
Solution 13 - CsshanwView Answer on Stackoverflow
Solution 14 - Csstahdhaze09View Answer on Stackoverflow
Solution 15 - CssCryptcView Answer on Stackoverflow
Solution 16 - CssstephenhayView Answer on Stackoverflow
Solution 17 - CssAdam WhateversonView Answer on Stackoverflow
Solution 18 - CsssomedevView Answer on Stackoverflow
Solution 19 - CssLordRathanView Answer on Stackoverflow
Solution 20 - CssNA HoijtinkView Answer on Stackoverflow
Solution 21 - CssAron KofflerView Answer on Stackoverflow
Solution 22 - CssJayView Answer on Stackoverflow
Solution 23 - CssCostaView Answer on Stackoverflow