I'm wondering if there is a way to blend two transparent colours laid over eachother, to achieve a predetermined colour.
I have a menu bar. The background colour of the bar is rgb(0, 0, 0, 0.75)
. The logo on the top-left has a solid red background of #9B0506
. You can check it out live at http://www.phoenixwebdev.com.au/about-our-services/ecommerce/. The site is a work in progress.
I want to make this red partially transparent, but achieve the exact same red, visually, when there is white behind the menu bar. The transparent black is behind the red and will affect the colour.
Is there a way to calculate the hex value of the red to achieve this? I don't even know how to achieve this with a single transparent item against a solid background let alone with the black complicating things. I can't eyeball it, as I'm colourblind. Even if I could a mathematical solution would nag at me.
So for my situation I'm looking for a method to solve mystery transparent red colour
stacked on rgb(0, 0, 0, 0.75)
stacked on white
= #9B0506
I had a read about css blending at https://css-tricks.com/basics-css-blend-modes/. However this doesn't do what I'm talking about.
First of all, it's easier to work with colors in rgba than in hexa.
So, your requested result is 9b0506 -> rgb(155, 5, 6)
Next, the formula for any channel is
(f * a) + (b * (1-a))
where f is the foreground value, b the background value for the channel
Applying this formula for the first 2 layers, white and the black with opacity of 0.75, gives
0 * 0.75 + (255 * 0.25) = 63
Thus the base is rgb (63, 63, 63)
Now, the upper layer can have any alpha that you want ... But for the green channel, the expected result is 5, and the contribution of the base layer alone will be 63 * ( 1 - a). Thus, a value of (1 -a ) greater than 0.08 will contribute to the green chanel more than 5, exceding the total result.
Since the values can not be negative, the minimum alpha for the result is (1 - 0.08) = 0.92.
Now, we can calculate the r g b values:
r = (155 - (63 * 0.08)) / 0.92 = 163
b = (6 - (63 * 0.08)) / 0.92 = 1
(the green channel, as dicussed before, is 0)
So the result is rgba (163, 0, 1, 0.92).
If you want higher transparencies, you need to lower the green channel restrictions (or the green channel result goes higher, or the base color goes lower.. this would be achieved making the black layer have higher opacity)
Based on experimentation, I managed to get the exact color using rgba(163,0,2,.92)
. The below demo renders a box filled with the colours stacked on each other, giving #9B0506
as the overall color.
Also, you don't need to rely on your eyesight to test theoretical values, free applications such as ColorPic and many others allow you to inspect pixels on your screen real time, and get their HEX/RGB color values directly.
I understand that this does not provide any means of calculating it programmatically, but it could serve as a reference point if someone's trying to test an algorithm for this.
.a { z-index: 1; background: white }
.b { z-index: 2; background: rgba(0,0,0,.75) }
.c { z-index: 3; background: rgba(163,0,2,.92) }
.a, .b, .c {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
<div class="a"></div>
<div class="b"></div>
<div class="c"></div>
As per your request, I've tried reproducing the color with a lower opacity value. I've found that rgba(171,0,0,.85)
is very close to the target color and it has slightly more opacity as well. At this point I'm fairly certain the exact color can't be achieved at any other value than that mentioned before, but this should be a close enough approximation that there won't be much of a difference. The demo below has the old color and the new one next to each other, with the color code they produce written on each half.
.a { z-index: 1; background: white }
.b { z-index: 2; background: rgba(0,0,0,.75) }
.c { z-index: 3; background: rgba(163,0,2,.92) }
.d { z-index: 3; background: rgba(171,0,0,.85) }
.a, .b, .c, .d {
position: absolute;
top: 0;
height: 100%;
}
.a, .b {
left: 0;
width: 100%;
}
.c, .d {
color: #fff;
font-size: 3em;
font-family: "Consolas", monospace;
display: flex;
justify-content: center;
align-items: center;
width: 50%;
}
.c { left: 0 }
.d { right: 0 }
<div class="a"></div>
<div class="b"></div>
<div class="c"><span>#9B0506</span></div>
<div class="d"><span>#9B0A0A</span></div>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With