Color of stacked semi-transparent boxes depends on order?

  • A+
Category:Languages

Why does the final color of two stacked semi-translucent boxes depend on the order?

How could I make it so that I get the same color in both cases?

.a {   background-color: rgba(255, 0, 0, 0.5) }  .b {   background-color: rgba(0, 0, 255, 0.5) }
<span class="a"><span class="b">          Color 1</span></span> <span class="b"><span class="a">Different Color 2</span></span>


Simply because they aren't 100% transparent but they are having opacity less than 1 and for both cases the combination of the color is not the same.

For the first case, you have 50% of blue then 50% of transparent. Through this transparent part you have 50% of red color (so we have only 25% of red in total). Same logic for the second case (50% of red and 25% of blue); thus you will see different colors because for both cases we don't have the same proportion.

To avoid this you need to have the same proportion for both your colors.

Here is an example to better illustrate and show how we can obtain same color:

In the top layer (the inner span) we have 0.25 of opacity (so we have 25% of the first color and 75% of transparent) then for the bottom layer (the outer span) we have 0.333 opacity (so we have 1/3 of 75% = 25% of the color and the remaining is transparent). We have the same proportion in both layers (25%) so we see the same color even if we reverse the order of layers.

.a {   background-color: rgba(255, 0, 0, 0.333) }  .b {   background-color: rgba(0, 0, 255, 0.333) }  .a > .b {   background-color: rgba(0, 0, 255, 0.25) } .b > .a {   background-color: rgba(255, 0, 0, 0.25) }
<span class="a"><span class="b">          Color 1</span></span> <span class="b"><span class="a">Different Color 2</span></span>

As a side note, the white background is also affecting the rendering of the colors. Its proportion is 50% which will make the logical result of 100% (25% + 25% + 50%).

You may also notice that it won't be possible to have same proportion for our both colors if the top layer is having an opacity bigger than 0.5 because the first one will have more than 50% and it will remain less than 50% for the second one:

.a {   background-color: rgba(255, 0, 0, 1) }  .b {   background-color: rgba(0, 0, 255, 1) }  .a > .b {   background-color: rgba(0, 0, 255, 0.6) } .b > .a {   background-color: rgba(255, 0, 0, 0.6) }
<span class="a"><span class="b">          Color 1</span></span> <span class="b"><span class="a">Different Color 2</span></span>

UPDATE

For a more accurate and precise explanation here is the formula used to calculate the color we see after the combination of both (it apply to each pixel)ref:

ColorF = ((ColorT * opacityT) + ColorB*OpacityB*(1 - OpacityT)) / factor 

ColorF is our final color. ColorT/ColorB are respectively the top and bottom color. opacityT/opacityB are respectively the top and bottom opacity defined for each color:

The factor is defined by this formula OpacityT + OpacityB*(1 - OpacityT).

It's clear that if we switch the two layers the factor won't change (it will remain a constant) but we can clearly see that the proportion for each color will change since we don't have the same multiplier.

For our initial case, both opacities are 0.5 so we will have:

ColorF = ((ColorT * 0.5) + ColorB*0.5*(1 - 0.5)) / factor 

Like explained above, the top color is having a proportion of 50% (0.5) and the bottom one is having a proportion of 25% (0.5*(1-0.5)) so switching the layer will also switch these proportion; thus we see a different final color.

Now if we consider the second example we will have:

ColorF = ((ColorT * 0.25) + ColorB*0.333*(1 - 0.25)) / factor 

In this case we have 0.25 = 0.333*(1 - 0.25) so switching the two layers will have no effect; thus the color will remain the same.

This answer intend to provide a very simplifed explanation about this behavior and not to provide a fix.

Comment

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: