BeAct Co., Ltd.

BLOG
社員ブログ

CSSの重ね順とz-indexを「レイヤー」で考える・1

こんにちは! 今日もプログラミングを楽しんでいますか?

さてこんかいは、Webの画面設計をする人の悩みのタネ、CSSの「重ね順」と「z-index」と仲良くなるコツを、複数回にわたって一緒に学んでいきたいとおもいます。.cssファイルで{z-index: 1001}などと書いている例も見かけますが、コツさえ掴めばもっとシンプルに重なりを設計できるので、ぜひ覚えていってくださいね!


ペイントアプリの「レイヤー」

まずはこの画像を見てください。これは Paint.net という Windows 用のペイントアプリケーションの一部を切り取ったスクリーンショットです。

ところで、右下に「レイヤー」と書かれた UI がありますね。ひとまずこれを、便宜的に「レイヤーコンテナ」と呼ぶことにしましょう。さて、これは一体なんでしょう?

レイヤーの例
※画像は Paint.net(© dotPDN LLC)のスクリーンショットを引用しています。

この手のアプリケーションに慣れた方ならおわかりと思いますが、これは絵の要素をバラバラに書いて、あとで位置や色を簡単に変えるための仕組みです。層(レイヤー)の言葉通り、各レイヤーはレイヤーコンテナ内に積み重なっており、画面には奥から手前に配置されます。もちろんレイヤーの順番を変えれば、手前と奥を入れ替えるのも簡単です。

これと同じくらい簡単に、CSSの重なりも制御できたらいいのに……と思う方もいらっしゃるのではないでしょうか? 実は、ずっと以前からあるのです

重ね合わせコンテキスト=レイヤーコンテナ!

以前、重ね合わせコンテキストについてお話したことがあると思います。実はこれが、CSSにおける「レイヤーコンテナ」です!

<body>タグは、明示しなくても「ルートコンテキスト」という重ね合わせコンテキストを持っています。そう、すでにレイヤーコンテナなのです。なので、その直近の子孫が {position: absolute;} を持てば、それは「<body>左上隅を原点とした座標系を持つレイヤー」となります。

後ろに書いたほうが手前!

同じコンテキスト内にある「きょうだい」レイヤーが重なったときは、後ろに書いたほうが手前に来ます。上のコードサンプルで「赤いレイヤー」が手前に来ているのは、その要素が後ろに書かれているからです。

ルートコンテキスト

<!-- こっちが先に書かれているから、奥! -->
<div class="layer blue">
  青いレイヤー
</div>

<!-- こっちが後ろに書かれているから、手前! -->
<div class="layer red">
  赤いレイヤー
</div>

でも、HTML は書き換えたくないけど、重なりの順番は変えたいな……というご要望もあることでしょう。もちろんその手段もあります。それはみなさんもよくご存知のはずです

z-index

はい、ここで初めて z-index の登場です! この指定は、「同じレイヤーコンテナ(重ね合わせコンテキスト)にある、きょうだいレイヤーの重ね順を決める」ためのものです(ここであえて、強調して書いていることを覚えておいてくださいね)。

See the Pen StackingAsLayer_02 by isobeact (@rmzpacpm-the-builder) on CodePen.

z-index に整数を与えることで、重ね順を制御できます。数字が大きいほど手前になります。逆にz-index を省略すると auto という値を設定したとみなされ、先の例の通り「HTML要素が書かれた順番に」重なります。

.blue {
  top: 10%;
  left: 20%;
  width: 40%;
  height: 50%;
  background: #88f;
  /* z-index を auto 以外の整数にすると、その手前になる! */
  z-index: 1;
}
.red {
  top: 20%;
  left: 40%;
  width: 40%;
  height: 50%;
  background: #f88;
  /* z-index を省くと、 auto とみなされる */
}

「同じ」レイヤーコンテナとは?

上で、「ここであえて、強調して書いていることを覚えておいてくださいね」と注釈をつけましたが、同じレイヤーコンテナとは、何が「同じ」なのでしょうか? 以下の例を見てみましょう。

さっきと同じように見えますね。でも、HTML部分をごらんください。

ルートコンテキスト

<!-- ぼくは「コンテキスト」じゃないよ -->
<div>
  <!-- ぼくは .red のきょうだい! -->
  <div class="layer blue">
    青いレイヤー
  </div>
</div>

<!-- ぼくは .blue のきょうだい! -->
<div class="layer red">
  赤いレイヤー
</div>

<div class="layer blue"> が、別の <div> に囲われています! これでは「同じレイヤーコンテナを持つきょうだい」とは呼べなくなってしまう……と思いがちですが、実はそんなことはないのです。なぜでしょうか?

実は、レイヤーの外側の要素がコンテキストでなければ、レイヤーコンテナへの参照を妨げないというルールがあるためです。……言葉だとわかりにくいので、図にしてみましょう。

青と赤のレイヤーが「きょうだい」になる理屈

レイヤーコンテナは、最も近い子孫レイヤー同士を「きょうだい」とみなします。逆に言えば、レイヤーは、最も近い祖先の重ね合わせコンテキストを「レイヤーコンテナ」とみなします。その間に「コンテキストではない要素」があっても、それは論理構造としては無視されてしまうのです!

このルールが、重ね合わせコンテキストの理解が難しいと思われている原因の一つかもしれません。

こんかいのまとめ

こんかいは、重ね合わせコンテキストを「レイヤーコンテナ」、その最も近い子孫の {position:absolute} 要素を「レイヤー」に見立てることで、「きょうだいレイヤー同士の重なりのルール」をおさらいしました。

また、z-indexは「きょうだい同士の重なり順の指定」であること、さらに「コンテキストではない要素は、レイヤーとレイヤーコンテナの参照を妨げない」という意外なルールがあることもご紹介しました。

次回は、「ルートコンテキストよりも上位にあるコンテキスト」と、その便利な使い方について学んでいく予定です。お楽しみに!