Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I get the color halfway between two colors?

Tags:

html

css

People also ask

How do you combine two Colours together?

If you combine two primary colors with each other, you get a so-called secondary color. If you mix red and blue, you get violet, yellow and red become orange, blue and yellow become green. If you mix all the primary colors together, you get black.

How do I make colors with RGB?

To start mixing in RGB, think of each channel as a bucket of red, green, or blue paint. With 8 bits per channel, you have 256 levels of granularity for how much of that color you want to mix in; 255 is the whole bucket, 192 = three quarters, 128 = half bucket, 64 = quarter bucket, and so on.


As Mr Lister just said, it is easy to automate the calculation with any programming language :

  1. Separate your two colors into their 3 color numbers for Red, Green, Blue : (r1,g1,b1) and (r2,g2,b2).
    • For example #15293E, #012549 become ("15", "29", "3E"), ("01", "25", "49")

  2. Convert each color string into an integer, specifying explicitly that you are parsing a hexadecimal-based representation of a number.
    • For example ("15", "29", "3E") becomes (21, 41, 62)

  3. Calculate the average (r',g',b') = ( (r1+r2)/2, (g1+g2)/2, (b1+b2)/2 ).
    • For example ( (21+1)/2, (41+37)/2, (62+73)/2) = (11, 39, 67)

  4. Convert them again to strings , specifying explicitly that you are generating two-digit hexadecimal representations (pad with a zero when necessary).
    • For example (11, 39, 67) -> ("0B", "27", "43")

  5. Concatenate a hash character followed by the 3 strings
    • For example ("0B", "27", "43") -> "#0B2743"

Edit : Implementation is not "very easy" as I initially stated. I took the time to write the code in several languages on Programming-Idioms .


I use this website to do this task for me: ColorBlender.

The mid-color will be #0B2744.


With LESS

If you use the latest LESS CSS preprocessor then you'll notice there is a function (mix()) that does this:

mix(#15293E, #012549, 50%)

Outputs: #0b2744.


If you need to do this generically, and expect the middle colour to be visually accurate in more cases (i.e. the visual colour and tone of the mid point should "look right" to a human viewer), then as suggested above you may want to convert from RGB to HSV or HSL before calculating the mid point, and then convert back afterwards. This may differ significantly from averaging RGB values directly.

Here is some JavaScript code for the conversion to/from HSL that I found on a brief search, and that on a brief check appears to do the right thing:

github.com/mjackson/mjijackson.github.com/blob/master/2008/02/rgb-to-hsl-and-rgb-to-hsv-color-model-conversion-algorithms-in-javascript.txt

https://web.archive.org/web/20170919064926/https://github.com/mjackson/mjijackson.github.com/blob/master/2008/02/rgb-to-hsl-and-rgb-to-hsv-color-model-conversion-algorithms-in-javascript.txt

Just apply the rgbToHsl function to your two r,g,b colour vectors, average the two resulting vectors, and apply hslToRgb to that . . .


Handy-Dandy Function

function padToTwo(numberString) {
    if (numberString.length < 2) {
        numberString = '0' + numberString;
    }
    return numberString;
}

function hexAverage() {
    var args = Array.prototype.slice.call(arguments);
    return args.reduce(function (previousValue, currentValue) {
        return currentValue
            .replace(/^#/, '')
            .match(/.{2}/g)
            .map(function (value, index) {
                return previousValue[index] + parseInt(value, 16);
            });
    }, [0, 0, 0])
    .reduce(function (previousValue, currentValue) {
        return previousValue + padToTwo(Math.floor(currentValue / args.length).toString(16));
    }, '#');
}

console.log(hexAverage('#111111', '#333333')); // => #222222
console.log(hexAverage('#111111', '#222222')); // => #191919
console.log(hexAverage('#111111', '#222222', '#333333')); // => #222222
console.log(hexAverage('#000483', '#004B39')); // => #00275e