【CSS】 重なり順を指定するz-indexの使い方!効かないときの対処法と注意点も

「z-indexプロパティ」と聞くと、面倒くさいと顔をしかめる人もいるのではないでしょうか?「要素の順位を決めるプロパティであることはわかっている。でも、思い通りの順位にならないじゃないか」と感じたことはありませんか?

CSSの「z-index」は癖の強いプロパティです。単純な設定は問題なくても、複雑な設定になった途端、思い通りの挙動にはなりません。positionプロパティを使う人であれば、頻度高く使用するのが「z-indexプロパティ」ですが、理屈を知る必要があります。ここでは、その理屈を勉強しましょう。読み終わったら、「z-index」の使い方が理解できていることでしょう。

【初心者向け】CSS(スタイルシート)の書き方を丁寧に解説



CSSの「z-indexプロパティ」とは

例えば、「positionプロパティ」を使用して、要素同士が重なった時に、その要素の順番を指定するCSSプロパティです。

数値の箇所に指定できる値は、以下の2つです。

説明
auto これは要素の重なりを作らない値です。親要素と同じレベルで配置されるのみです。
整数値 最小値で「-2147483647」から「最大値:2147483647」までの整数のみが設定できます。小数点の設定はできません。

z-indexプロパティの基本的な使い方

では、早速、z-indexを使って、挙動の確認を行っていきましょう。サンプルとして、以下のhtmlを設定します。

<div class="sample">
 <div class="z-index-1">
    これは、z-index-1要素です。
 </div>
 <div class="z-index-2">
    これは、z-index-2要素です。
 </div>
</div>

次に、以下のCSSを設定します。

.sample{
    position: relative;
}

.z-index-1{
    position: absolute;
    top: 30px;
    left: 30px;
    background-color: red;
    width: 100px;
    height: 100px;
}

.z-index-2{
    position: absolute;
    top: 50px;
    left: 50px;
    background-color: blue;
    width: 100px;
    height: 100px;
}

「positionプロパティ」を設定していますので、「z-index-1」と「z-index-2」は「sample要素」から距離が取られており、以下のように表示されます。「z-index-1」要素が上にきていることがわかりますね。

「z-indexプロパティ」は、このように要素同士が重なった場合、その重なりの順番を指定することで、表示を変える効果が出せます。例えば、「z-index-2」要素を最前面に持って来たいと考えたとします。その場合は、「z-index-2」に「z-index: 2;」と設定してみましょう。

.sample{
    position: relative;
}

.z-index-1{
    position: absolute;
    top: 30px;
    left: 30px;
    background-color: red;
    width: 100px;
    height: 100px;
}

.z-index-2{
    position: absolute;
    top: 50px;
    left: 50px;
    background-color: blue;
    width: 100px;
    height: 100px;
    z-index: 2;
}

すると、要素同士の順番が変わります。以下では、「z-index-2」の要素が最前面にきていますね。

「z-index」の効果がわかりましたね。このように、要素同士の重なりを制御します。

必ず陥るz-indexの罠:指定したのに効かない

上記の設定のように、簡単なケースばかりではありません。みなさんの中には、「z-index」の順序指定が効かない経験をした人もいるでしょう。例えば、次のように書くと、途端に指定が効かなくなります。「z-index-3」要素を用意し、その中に子要素として「z-index-3-1」を配置します。

<div class="sample">
    <div class="z-index-1">
      これは、z-index-1要素です。
    </div>
    <div class="z-index-2">
      これは、z-index-2要素です。
    </div>
    <div class="z-index-3">
      これは、z-index-3要素です。
      <div class="z-index-3-1">
        これは、z-index-3-1要素です。
      </div>
    </div>
  </div>

CSSは、以下のように前回と同じように設定します。

.sample{
    position: relative;
}

.z-index-1{
    position: absolute;
    top: 30px;
    left: 30px;
    background-color: red;
    width: 100px;
    height: 100px;
}

.z-index-2{
    position: absolute;
    top: 50px;
    left: 50px;
    background-color: blue;
    width: 100px;
    height: 100px;
}

.z-index-3{
    position: absolute;
    top: 80px;
    left: 80px;
    background-color: yellow;
    width: 100px;
    height: 100px;
}

.z-index-3-1{
    background-color: green;
    width: 100px;
    height: 100px;
}

結果、「z-indexプロパティ」を指定していない場合の表示は以下のようになります。上から順に要素が積み重なっていくことがわかります。

次に、CSSでこの順番が逆転するように「z-indexプロパティ」の順番を変えて、「z-indexプロパティ」の指定した順番通りになれば良いのです。

.sample{
    position: relative;
}

.z-index-1{
    position: absolute;
    top: 30px;
    left: 30px;
    background-color: red;
    width: 100px;
    height: 100px;
    z-index: 3;
}

.z-index-2{
    position: absolute;
    top: 50px;
    left: 50px;
    background-color: blue;
    width: 100px;
    height: 100px;
    z-index: 2;
}

.z-index-3{
    position: absolute;
    top: 80px;
    left: 80px;
    background-color: yellow;
    width: 100px;
    height: 100px;
    z-index: 1;
}

.z-index-3-1{
    background-color: green;
    width: 100px;
    height: 100px;
    z-index: 0;
}

結果は想定に反して、思い通りの結果になっていないことがわかります。「z-index-3-1」要素が最も下に来るはずが、親要素の「z-index-3」が最も下に来ていますね。「z-index-3-1」要素の「z-indexプロパティ」は「0」、「z-index-3」要素の「z-indexプロパティ」は「1」で「z-index-3」要素が上に来るはずでした。どうしてこのようなことが起こるのでしょうか?

これこそが、「z-indexプロパティ」の使い方を難しくしている点です。この理屈の理解には、「スタック文脈」というキーワードの理解が欠かせません。実は、この「スタック文脈」を理解し、頭に入れておくことで、「z-indexプロパティ」の難解さがあっという間に解けるのです。

スタック文脈を理解しよう。

スタック文脈とは、いわゆる「階層構造」です。例えば、以下のhtmlファイルですが、土台部分には、html文があります。その上に、「sample」要素(親)があり、その上に、「z-index-1」と「z-index-2」という子要素が乗っているイメージです。

<!DOCTYPE html>
<html lang="ja">

<head>
  <meta charset="UTF-8">
  <title>サンプル-position</title>
  <link rel="stylesheet" type="text/css" href="style.css">
</head>

<body>
 <div class="sample">
    <div class="z-index-1">
      これは、z-index-1要素です。
    </div>
    <div class="z-index-2">
      これは、z-index-2要素です。
    </div>
 </div>
</body>
</html>

絵にすると、以下のようなイメージですね。

「z-indexプロパティ」を指定しなくても、要素は積み重なります。まとめると、下から次の順で重なる傾向があります。

この階層構造を強く意識するのが「z-indexプロパティ」の特徴なのです。つまり、「z-indexプロパティ」が効力を発揮する順序とは、「同じ階層内での順序」であり、設定された「z-indexプロパティ」の値(数値)は、階層を超えて影響を及ぼしません。

つまり、以下のhtml文であれば、「z-index-1」と「z-index-2」と「z-index-3」の順序は「z-indexプロパティ」の値で順序を変更できますが、「z-index-3-1」の順番には、影響しません。「z-index-3-1」は、「z-index-3」の子要素ですので、の 「z-indexプロパティ」の値は、その親要素をベースとしての順序となります。仮に、「z-index-3-2」を新たに作成し、そこに「z-indexプロパティ」を設定したら、「z-index-3」要素内での順序が反映されるということです。これで、「z-indexプロパティ」の値の順序とは、全階層を通じた順序ではない、ということが分かったと思います。

次に、「z-indexプロパティ」を指定した場合、同階層でも順番に変化が生じます。基本的には、以下のような順番で配置されるので、覚えておきましょう。

テスト問題

では、「z-indexプロパティ」についてのテストです。以下のhtml文とCSSの指定があった場合、要素の積み重なりの順序はどのようになるでしょうか?

<div class="sample">
    <div class="z-index-1">
      A要素
    </div>
    <div class="z-index-2">
      B要素
    </div>
    <div class="z-index-3">
      C要素
      <div class="z-index-3-1">
        D要素
      </div>
      <div class="z-index-3-2">
        E要素
      </div>
      <div class="z-index-3-3">
        F要素
      </div>
    </div>
  </div>
.sample{
    position: relative;
}

.z-index-1{
    position: absolute;
    top: 30px;
    left: 30px;
    background-color: red;
    width: 100px;
    height: 100px;
    z-index: 3;
}

.z-index-2{
    position: absolute;
    top: 50px;
    left: 50px;
    background-color: blue;
    width: 100px;
    height: 100px;
    z-index: 5;
}

.z-index-3{
    position: absolute;
    top: 80px;
    left: 80px;
    background-color: yellow;
    width: 100px;
    height: 100px;
    z-index: 1;
}

.z-index-3-1{
    position: absolute;
    top: 10px;
    left: 10px;
    background-color: green;
    width: 100px;
    height: 100px;
    z-index: 100;
}

.z-index-3-2{
    position: absolute;
    top: 20px;
    left: 20px;
    background-color: black;
    width: 20px;
    height: 20px;
    width: 100px;
    height: 100px;
    z-index: 10;
}

.z-index-3-3{
    position: absolute;
    top: 40px;
    left: 40px;
    background-color: orange;
    width: 20px;
    height: 20px;
    width: 100px;
    height: 100px;
    z-index: 50;
}

選択肢

上から下へ順番に以下のような順番になります。
①A要素 → B要素 →  C要素 →  D要素 →  E要素 →  F要素
②D要素 → F要素 →  E要素 →  B要素 →  A要素 →  C要素
③B要素 → A要素 →  D要素 →  F要素 →  E要素 →  C要素
④D要素 → A要素 →  B要素 →  F要素 →  C要素 →  E要素
⑤A要素 → B要素 →  F要素 →  D要素 →  E要素 →  C要素

回答

もちろん、答えは、③ですね。以下のような表示になります。まず、A要素、B要素、C要素の順番が決まりますね。次に、C要素を土台として、D要素、E要素、F要素の順番が決まります。値の大きさがどれほど大きく、あるいは、どれほど小さいものでも階層を飛び越えては影響しない、ということが改めて分かったと思います。

まとめ

まとめとして、覚えておいて欲しいことを書きます。

  • 「z-index」は、要素の重なりの順番を指定するプロパティです。
  • 値の大きさによって、順番が決まります。
  • 「z-index」は「positionプロパティ」と一緒に使用することが多いプロパティです。
  • 「z-indexプロパティ」は、階層構造を強く意識するため、同階層での順位の指定ができても、階層を超えての指定はできない。








この記事をかいた人

田中 陽介

ベトナムで起業し、HR関連のコンサルティング業務をやっています。日本を離れて8年が経ちますが、日本ではあり得ないハプニングを楽しんでいます。最近はRuby on RailsでWebサービスを作っています。