CSSのmix-blend-modeは、重なり合う要素のブレンドモードを指定するプロパティです。
このプロパティを使うと、単なる透過だけではなく、乗算などさまざまなブレンドモードで重ねることができるようになるので、デザインの幅もぐっと広がります。どんどん使っていきたいところなのですが、意外と制約が多くままならないことが多いので、実際のコーディング例をもとに気をつけるべきポイントをまとめてみました。
#コーディングするデザイン
画像の上に文字が乗っており、その下に座布団(塗りつぶした長方形)が重なっているという、よくあるデザイン。
座布団だけが乗算で重なっており、その上のテキストは不透明の白で乗っています。
画像は背景ではなく、img要素としてコーディングされる必要があると仮定します。
#コーディングの失敗例その1:文字も乗算になってしまう
まずは以下のようにコーディングしてみます。
HTML
<div class="wrapper">
<div class="image">
<img src="img/lunch.jpg" alt="ランチ">
</div>
<div class="text">
<p class="title">Lunch</p>
</div>
</div>
CSS
.wrapper {
width: 700px;
font-family: Baskerville;
position: relative;
}
.wrapper .text {
position: absolute;
top: 50%;
left: 50%;
-webkit-transform: translate(-50%, -50%);
-ms-transform: translate(-50%, -50%);
transform: translate(-50%, -50%);
background-color: rgba(69, 38, 18, 0.7);
padding: 50px 110px;
}
.wrapper .title {
font-size: 70px;
color: #ffffff;
}
表示
このコーディングの仕方だと、座布団にmix-blend-mode: multiplyを指定すると、その子要素であるテキストも乗算で重ねられてしまいます。
#コーディングの失敗例その2:乗算にならない
それでは、座布団の要素にbefore擬似要素を置いて、テキストとは兄弟関係になるようにしてみましょう。
CSS
.wrapper {
width: 700px;
font-family: Baskerville;
position: relative;
}
.wrapper .text {
position: absolute;
top: 50%;
left: 50%;
-webkit-transform: translate(-50%, -50%);
-ms-transform: translate(-50%, -50%);
transform: translate(-50%, -50%);
padding: 50px 110px;
}
.wrapper .text:before {
content: '';
display: block;
position: absolute;
z-index: 1;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: rgba(69, 38, 18, 0.7);
mix-blend-mode: multiply;
}
.wrapper .title {
font-size: 70px;
color: #ffffff;
position: relative;
z-index: 2;
}
表示
少しわかりにくいかもしれませんが、座布団の要素.text:beforeに設定したmix-blend-mode: multiplyが適用されていないことが分かります。
##なぜmix-blend-modeが適用されないのか?
実は、mix-blend-modeは、同じスタックコンテキスト内にある要素同士のブレンドモードを指定するプロパティです。
このコーディング例では、座布団の要素に
transform: translate(-50%, -50%);
を指定しています。
実は、要素にtransformを指定すると、新しいスタックコンテキストが作られます。すると、その子要素であるbefore擬似要素とp要素は料理の写真のimg要素とは別のスタックコンテキストに属することになり、これらの要素の重なりには、mix-blend-modeが適用されなくなってしまうのです。
#成功例
これをもとに、もう少し考えてみます。
要素の重なりと、画像の中心にテキストを置く配置を別の方法で実装します。
.wrapper {
width: 700px;
font-family: Baskerville;
position: relative;
display: grid;
grid-template-rows: auto;
grid-template-columns: auto;
}
.wrapper .image {
grid-row: 1 / 2;
grid-column: 1 / 2;
}
.wrapper .text {
grid-row: 1 / 2;
grid-column: 1 / 2;
align-self: center;
justify-self: center;
padding: 50px 110px;
position: relative;
}
.wrapper .text:before {
content: '';
display: block;
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: rgba(69, 38, 18, 0.7);
mix-blend-mode: multiply;
z-index: 1;
}
.wrapper .title {
font-size: 70px;
color: #ffffff;
position: relative;
z-index: 2;
}
この例では、ラッパ要素にdisplay: gridを指定しました。
そして、画像とテキストを同じグリッドセル上に配置します。
テキストの中央寄せは、
align-self: center;
justify-self: center;
で指定しました。
この時、画像とテキストの重なり順を指定しようと、z-indexを指定してしまわないように気をつけてください。
positionをstatic以外に設定し、かつz-indexがauto以外の時も、やはりスタックコンテキストが新たに作られてしまうからです。
CSS Gridでは、同じグリッドセル上にある要素は、ソースコード上で後に書かれたものが上に来る仕様になっています。上に置きたい要素を後の方に書くようにしましょう。