Color Operations in Less

Color operations in less

Has A Few Challenges and Caveats

Normally, people do not use a function like darken() to get a color that they already know they want to end up at (they just put the color value they already know they want). However, I will assume there is more behind this question than that.

The darken() Function

The darken() function of LESS affects the "brightness" or "lightness" portion of a color considered from the viewpoint of its hsl settings (hue, saturation, lightness). Here's your two colors considered from that view (based on this site, I have noticed some variations between sites--some are probably more accurate than others):

#952262 = hsl(327, 63%, 36%)
#681744 = hsl(327, 64%, 25%)

So the darkness value you seek can be hand calculated from that site, by just a subtraction, 36% - 25% = 11%. Plugging that into your function:

darken(@base_color, 11%);

Yields

#671844 /* not 681744! */ 

Hey! That Didn't Match My Target!

Notice that the s (saturation) value above shows as different by 1% from your base to your target, which means that technically you cannot get from your base color to the target color purely through the darken() function. Instead, you either need to use another function to tweak the s value also, or your target should be adjusted slightly to the following (which keeps s at 63%):

#681844 = hsl(327, 63%, 25%)

But that number (#681844) still does not match the LESS output (#671844). The website shows the LESS output as being hsl(327, 62%, 25%) (notice the saturation value dropped to 62%). I suspect what this means is a difference in rounding calculations between the website calculations and the LESS function calculations. This may well be why your original number was off by 1% on saturation as well, whatever program you used rounded differently than the website also. This is probably not a big issue, as it gets you close to your target value.

Using LESS to Calculate It

Now, depending on what your actually doing, you can use LESS to calculate that percentage, instead of hand calculating it, using the lightness() function. Assume you had adjusted your target to #681844 based off the website. Then this is an example of getting the percentage you want (I use a fake property color-calc to show the calcuation:

@base_color: #952262;  /* Base #952262 = hsl(327, 63%, 36%) */
@real_target_color: #681844; /* Real Target #681844 = hsl(327, 63%, 25%) */
@color_calc: (lightness(@base_color) - lightness(@real_target_color));

.test {
color-calc: @color_calc;
color: darken(@base_color, 11%);
}

Outputs:

.test {
color-calc: 11%;
color: #671844;
}

Notice that it calculated the 11% difference in darkness. Also, notice that it still ends up with a value slightly different than target because of that (I suppose) rounding issue. Plugging in the final value LESS generates (#671844) as the target still yields the same 11% value for darken().

LESS CSS - Adding a percentage to a hex color - How does this work?

See Language Features > Overview > Operations.

Assuming it's actually @new-color: @primary-color + 10%; (and = is just a typo in your Q) it goes like this:

  • if the first operand of an arithmetic expression is a color any subsequent operands are converted to colors too.
  • scalar numeric values (e.g. 10%) are converted to a color as value -> rgb(value, value, value). I.e. 10% is converted to rgb(10, 10, 10) color value (% is irrelevant in this case and it will be the same for 10, 10px, 10whatever etc.)
  • arithmetic operations apply to color operands on a per-RGB-channel basis.

So in summary it's:

#0070b8 -> rgb(0, 112, 184)
10% -> rgb(10, 10, 10)

rgb(0, 112, 184) + rgb(10, 10, 10) ->
rgb(0 + 10, 112 + 10, 184 + 10) ->
rgb(10, 122, 194)

rgb(10, 122, 194) -> #0a7ac2

Or yet in other words, #0070B8 + 10 is a just shorthand for #0070b8 + #0a0a0a hence the #0a7aC2 result. (And yet again % unit has no effect there and should be removed to make it less confusing).


To answer:

It looks like it added an absolute value of 10 to the R/G/B component of the hex color, but that seems counter-intuitive.

See Strict Units.
Basically it is the same as 10px + 10% for example, it will result in 20px (and not in 10px + 10px * 0.1). Same way CSS calc(10px + 10%) is not equal to (10px + 10px * 0.1) though Less arithmetic expressions are not equal to those of calc too since the compiler has no all that information about current element state a browser has.

Yes, % arithmetic is a typical confusion in Less, but note that percentage values in CSS always refer to a value set elsewhere and are never considered to be some kind of "ratio value" on their own. E.g. width: 50% -> 50% of the container width and it's not equal to width: 0.5 or something. So in Less you never assume 10% in an arithmetic expression can refer to some previous value of the same expression and/or being implicitly converted to a unitless ratio (e.g. it's never 10% -> 0.1).

LESS contrast() function

The square brackets denote optional arguments and shouldn't appear in your code. Check out the LESS function reference and its documentation on contrast, it has an example on how to use contrast correctly:

Example:

contrast(#aaaaaa)
contrast(#222222, #101010)
contrast(#222222, #101010, #dddddd)

Output:

#000000 // black
#ffffff // white
#dddddd

So your code should read:

color: contrast(@popupBg, black, white, 43%);

On the other hand, are you sure that @popupBg is defined?

Check out this jsfiddle for a demo.

LESS: Darken whatever color is already set on the element

You could try:

.active{
background:lighten(-10%);
}

Not sure if that'd work though so what might be better is using:

.active{
filter: brightness(0.1);
-webkit-filter: brightness(0.1);
-moz-filter: brightness(0.1);
-o-filter: brightness(0.1);
-ms-filter: brightness(0.1);
}

(play around with the 0.1 value to get your desired effect)

What’s the difference between the LESS color functions lighten and tint?

From this thread that was asking for tint comes this comment:

Tint/shade is not the same thing as lighten/darken. Tint and shade are
effectively mixing with white and black respectively, whereas
lighten/darken are manuipulating the luminance channel independently
of hue and saturation. The former can produce hue shifts, whereas the
latter does not. That's not to say it's not useful, just that it's not
the same thing. Mathematically it's that linear changes in RGB space
do not necessarily correspond with linear changes in HSL space, though
in practice they will produce fairly similar results.

There is a slight difference in the math behind the two.

less mixin name is evaluated to colour/color

This is a legacy feature of Less. For the time being, one of the below work-around solutions could be used to overcome this color name to hex code conversion.

.completeColour(~"Orange",1);

or

.completeColour(e("Orange"),1);

Both the options explicitly tell the compiler that the value being passed is a String and not a Color and hence Less compiler would not convert it to the corresponding hex code.

Sources:

  1. Less GitHub - how to avoid color name be translated into color value?
  2. Less GitHub - Compilation of named colors results in hex values being used incorrectly in interpolations

Update: Starting from version 2.0.0, this color name to hex code conversion would not happen if the color is mentioned explicitly as a name and has no other color based operations on it. Version 2.0.0 is currently in beta mode.

(Official Update: V2 Upgrade Guide | Original Source: More consistent named color variables).



Related Topics



Leave a reply



Submit