web-dev-qa-db-fra.com

La couleur des boîtes empilées semi-transparentes dépend de la commande.

Pourquoi la couleur finale de deux boîtes semi-translucides empilées dépend-elle de la commande?

Comment pourrais-je faire pour que je reçois la même couleur dans les deux cas?

.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>
74
rmv

Tout simplement parce que, dans les deux cas, la combinaison de couleurs n’est pas la même en raison de l’opacité du calque top qui affecte la couleur du calque bottom.

Dans le premier cas, vous voyez 50% de ble et 50% de transparent dans la couche supérieure. À travers la partie transparente, vous voyez 50% de couleur rouge dans la couche inférieure (nous ne voyons donc que 25% de rouge au total). Même logique pour le deuxième cas (50% de rouge et 25% de ble); ainsi, vous verrez des couleurs différentes car dans les deux cas, nous n’avons pas la même proportion.

Pour éviter cela, vous devez avoir la même proportion pour vos deux couleurs.

Voici un exemple pour mieux illustrer et montrer comment obtenir la même couleur:

Dans la couche supérieure (la portée intérieure), nous avons 0.25 D'opacité (nous avons donc 25% de la première couleur et 75% de la transparence), puis pour la couche inférieure (la portée extérieure), nous avons 0.333 Opacité (nous avons donc 1/3 de 75% = 25% de la couleur et le reste est transparent). Nous avons la même proportion dans les deux couches (25%) donc nous voyons le même couleur même si nous inversons l'ordre des couches.

.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>

En remarque, le fond blanc affecte également le rendu des couleurs. Sa proportion est de 50%, ce qui donnera un résultat logique de 100% (25% + 25% + 50%).

Vous remarquerez peut-être également qu'il ne sera pas possible d'avoir la même proportion pour nos deux couleurs si le calque supérieur a une opacité supérieure à 0.5, Car le premier aura plus de 50% et il restera inférieur à 50% pour le second:

.a {
  background-color: rgba(255, 0, 0, 1) /*taking 40% even with opacity:1*/
}

.b {
  background-color: rgba(0, 0, 255, 1) /*taking 40% even with opacity:1*/
}

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

Le cas trivial courant est lorsque la couche supérieure contient opacity:1, Ce qui donne la couleur de dessus avec une proportion de 100%; c'est donc une couleur opaque.


Pour une explication plus précise, voici la formule utilisée pour calculer la couleur que nous voyons après la combinaison des deux couches.ref:

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

ColorF est notre couleur finale. ColorT/ColorB sont respectivement les couleurs supérieure et inférieure. opacityT/opacityB sont respectivement les opacités supérieure et inférieure définies pour chaque couleur:

Le factor est défini par cette formule OpacityT + OpacityB*(1 - OpacityT).

Il est clair que si nous commutons les deux couches, la factor ne changera pas (elle restera constante), mais nous pouvons voir clairement que la proportion de chaque couleur changera car nous n'avons pas le même multiplicateur.

Pour notre cas initial, les deux opacités sont 0.5. Nous aurons donc:

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

Comme expliqué ci-dessus, la couleur du haut a une proportion de 50% (0.5) Et celle du bas a une proportion de 25% (0.5*(1-0.5)), de sorte que la commutation des calques changera également les proportions; nous voyons donc une couleur différente finale.

Maintenant, si nous considérons le deuxième exemple, nous aurons:

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

Dans ce cas, nous avons 0.25 = 0.333*(1 - 0.25) donc la commutation des deux couches n'aura aucun effet; ainsi la couleur restera la même.

Nous pouvons également identifier clairement les cas triviaux:

  • Lorsque la couche supérieure a opacity:0, La formule est égale à ColorF = ColorB
  • Lorsque la couche supérieure a opacity:1, La formule est égale à ColorF = ColorT
82
Temani Afif

Vous pouvez utiliser la propriété css, mix-blend-mode : multiply (limité support du navigateur )

.a {
  background-color: rgba(255, 0, 0, 0.5);
  mix-blend-mode: multiply;
}

.b {
  background-color: rgba(0, 0, 255, 0.5);
  mix-blend-mode: multiply;
}

.c {
  position: relative;
  left: 0px;
  width: 50px;
  height: 50px;
}

.d {
  position: relative;
  left: 25px;
  top: -50px;
  width: 50px;
  height: 50px;
}
<span class="a"><span class="b">          Color 1</span></span>
<span class="b"><span class="a">Different Color 2</span></span>

<div class="c a"></div>
<div class="d b"></div>

<div class="c b"></div>
<div class="d a"></div>
35
Moffen

Vous mélangez trois couleurs dans l'ordre suivant:

  • rgba(0, 0, 255, 0.5) over (rgba(255, 0, 0, 0.5) over rgba(255, 255, 255, 1))
  • rgba(255, 0, 0, 0.5) over (rgba(0, 0, 255, 0.5) over rgba(255, 255, 255, 1))

Et vous obtenez des résultats différents. En effet, la couleur de premier plan est mélangée à la couleur d’arrière-plan à l’aide de mode de fusion normal1 qui n'est pas commutatif . Et comme il n’est pas commutatif, l’échange des couleurs d’avant-plan et d’arrière-plan produira un résultat différent.

1 Le mode de fusion est une fonction qui accepte une couleur de premier plan et d'arrière-plan, applique une formule et renvoie la couleur résultante.

La solution consiste à utiliser un mode de fusion commutatif: un mode qui renvoie la même couleur pour la même paire de couleurs dans n'importe quel ordre (par exemple, le mode de fusion multiplié, qui multiplie les deux couleurs et renvoie la couleur résultante; ou le mode de fusion assombri, qui renvoie la couleur plus foncée des deux).

$(function() {
  $("#mode").on("change", function() {
    var mode = $(this).val();
    $("#demo").find(".a, .b").css({
      "mix-blend-mode": mode
    });
  });
});
#demo > div {
  width: 12em;
  height: 5em;
  margin: 1em 0;
}

#demo > div > div {
  width: 12em;
  height: 4em;
  position: relative;
  top: .5em;
  left: 4em;
}

.a {
  background-color: rgba(255, 0, 0, 0.5);
}

.b {
  background-color: rgba(0, 0, 255, 0.5);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>

<select id="mode">
  <optgroup label="commutative">
    <option>multiply</option>
    <option>screen</option>
    <option>darken</option>
    <option>lighten</option>
    <option>difference</option>
    <option>exclusion</option>
  </optgroup>
  <optgroup label="non-commutative">
    <option selected>normal</option>
    <option>overlay</option>
    <option>color-dodge</option>
    <option>color-burn</option>
    <option>hard-light</option>
    <option>soft-light</option>
    <option>hue</option>
    <option>saturation</option>
    <option>color</option>
    <option>luminosity</option>
  </optgroup>
</select>

<div id="demo">
  <div class="a">
    <div class="b"></div>
  </div>
  <div class="b">
    <div class="a"></div>
  </div>
</div>

Pour être complet, voici la formule permettant de calculer la couleur composée:

αs x (1 - αb) x Cs + αs x αb x B(Cb, Cs) + (1 - αs) x αb x Cb

avec:

Cs: la valeur de la couleur de premier plan
αs: la valeur alpha de la couleur de premier plan
Cb: la valeur de couleur de la couleur de fond
αb: la valeur alpha de la couleur de fond B: la fonction de fusion

18
Salman A

Pour une explication de ce qui se passe, voir la réponse de Temani Afif.
Comme solution alternative, vous pouvez prendre un intervalle, a par exemple, le positionner et lui donner un indice z inférieur s'il est à l'intérieur de b. Ensuite, l'empilement sera toujours le même: b est dessiné au-dessus de a dans la première ligne, et a est dessiné au-dessous de b dans la seconde .

.a {
  background-color: rgba(255, 0, 0, 0.5);
}

.b {
  background-color: rgba(0, 0, 255, 0.5);
}

.b .a {position:relative; z-index:-1;}
<span class="a"><span class="b">     Color 1</span></span>
<span class="b"><span class="a">Same Color 2</span></span>
7
Mr Lister