nathanziarek nathanziarek - 3 years ago 180
Less Question

Given two colors, both in HSV(B), how can I convert one to another using LESS CSS?

I'm designing some colored blocks, where the text is one color and the background is a lighter / desaturated shade of that same color (think warning text, where the words is red and it has a light pinkish background).

The text color is #990000. The background color is #f2dede. In Photoshop HSV, that equates to hsv( 0, 100%, 60%) & hsv(0, 8%, 95%).

With this color set, I'd like to be able to toss in other colors -- a nice green or yellow -- and have the background automatically calculated.

Using LESSCSS, I've tried:

@color: desaturate( lighten( hsv(0, 100%, 60%), 35%), 92% );

But I can't get it to render the color I generate by performing the same changes in Photoshop.

The color theory of this is beyond my comprehension, but my question is: How do I convert one color to another color, given the Photoshop HSB values?


I get it a little better -- the L and the B in HSB and HSL are not at all compatible, so lightening the color the "B" delta is never going to work.

It's sloppy, but something like this works:

@foreground: #990000;
@background: hsv(hsvhue(@foreground),

Lacking a "value" command similar to lighten/darken, I'm thinking this is the best I'm going to get. (If I don't get any other responses, I'll mark this the answer).

Thanks much...Nate

Answer Source

Note: my answer here discusses some issues with color theory and LESS functions that you may find useful also.

For LESS 1.4 (which has some new built in functions)


@color: hsv(0, 100%, 60%);
@bkg: hsv(hsvhue(@color), (hsvsaturation(@color) - 92%), (hsvvalue(@color) + 34.75%));

.test {
  color: @color;
  background-color: @bkg;

CSS Output

.test {
  color: #990000;
  background-color: #f2dede;

The link I posted above may explain why my value is 34.75% and not 35% more like your numbers were expecting.

UPDATE: I just noticed that you had essentially posted a similar answer in your question. I'm not certain exactly what issue you are still facing with that method of calculation.

UPDATE 2: If you desire it to generally always "contrast" then something like this may work better:

@color: hsv(0, 100%, 60%);
@darkerBkg: hsv(hsvhue(@color), (hsvsaturation(@color) - 92%), (hsvvalue(@color) + 34.75%));
@lighterBkg: hsv(hsvhue(@color), (hsvsaturation(@color) + 92%), (hsvvalue(@color) - 34.75%));
@bkg: contrast(@color, @darkerBkg, @lighterBkg, 43%);

.test {
  color: @color;
  background-color: @bkg;

Using the contrast function with the default 43% threshold value will cause a "flip" to the @lighterBkg in this case at a 35% saturation value (hsv(0,35%,60%)).

The calculation numbers you have set are going to work best with colors in the initial saturation range of 92-100 (or with the contrast feature also 0-8), and initial value range of 0-65 (or with contrast you would probably be covered in any value range). In the contrast version, any saturation between 9-91 will begin to "equalize" to either 0% or 100%. You would need to decide on a new "calculation" and add some other math logic in if that was an issue, but I think with the contrast version it may not be a problem.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download