z-indexとHTML階層、positionの関係

#  コード
<p class="codepen" data-height="300" data-default-tab="html,result" data-slug-hash="KKoodBo" data-user="malle9876" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/malle9876/pen/KKoodBo">
  z-index_pre</a> by malle9876 (<a href="https://codepen.io/malle9876">@malle9876</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

[^1]:ふたつめの CodePen と同じものになっているため、以下のコードと一致しません。
```html
<div class="top">トップ</div>
<div class="one">要素1</div>
<div class="two">
  <span>要素2</span>
  <div class="three">要素3</div>
</div>
```
```css
.top {
  border: 1px solid #000;
}
.one {
  width: 200px;
  height: 50px;
  background-color: red;
  position: absolute;
  z-index: 11;
}

.two {
  width: 200px;
  height: 50px;
  background-color: #00bfff;
  z-index: 12;
  position: absolute;
  top: 80px;
}

.three {
  width: 100px;
  height: 40px;
  background-color: yellow;
  opacity: 0.7;
  position: relative;
  left: 50px;
  top: -40px;
  z-index: 10;
}

```

トップという一番上の要素があり、そこから要素1、要素2と続いています。
また、要素2の中には要素3が定義されていますが、こちらは要素1の方向にはみ出しています。

CSSを見ると、要素1と要素2には```position: absolute```が、要素3には```position: relative```が指定されています。

さらに注目すると、```z-index```の値が**表示順になっていません**。

要素1は```z-index: 11```であるのに対し、上に重なっている要素3は```z-index: 10```です。
## なぜz-indexの値が無視されているのか
まず、要素2と要素3の関係についてみていきます。
要素3は、要素2の子要素として定義されています。
```html
<div class="two">
  <span>要素2</span>
  <div class="three">要素3</div>
</div>
```
このようなとき、何も指定していなくても重なり順は子要素、親要素となり、```z-index```ではこの順番を変えることができません。
要素2も```z-index: 12```と、要素3の```z-index: 10```より大きいですが、このようなルールにより要素3のほうが上に重なり表示されます。

次に要素1と要素2の関係をみていきます。
```html
<div class="one">要素1</div>
<div class="two">
  <span>要素2</span>
  <div class="three">要素3</div>
</div>
```
要素1は```z-index: 11```、要素2は```z-index: 12```を持っています。
特に子要素、親要素の関係ではないため、重なっていないように見えますが、**実は要素2のほうが前に出ていることがわかります**。

ここまでの情報を整理すると、重なり順はそれぞれ
要素3 > 要素2
要素2 > 要素1
となっています。

要素1より、要素3が前に出ている理由は、上記の関係から分かるかと思います。
つまり、要素3の親要素である要素2がもともと要素1よりも前に出ており、子要素は親要素より前に表示されるというルールのため、要素2より要素3のほうが前に出ている、ということです。

# position: absoluteを外す
ここで、何らかの都合で要素2の```position: absolute```を外さなくてはならなくなったとします。
まずないと思いますが。
```position: absolute```を外し、要素1に被らないように```margin-top```をつけます。

<p class="codepen" data-height="300" data-default-tab="html,result" data-slug-hash="zYWRwRR" data-user="malle9876" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/malle9876/pen/zYWRwRR">
  z-index</a> by malle9876 (<a href="https://codepen.io/malle9876">@malle9876</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

要素3が要素1に被ってしまいました。

## 被る理由
こちらのページの説明では、```z-index```は以下のように書かれています。
https://developer.mozilla.org/ja/docs/Web/CSS/z-index

>位置指定されたボックス (つまり、position が static 以外のもの) では、z-index プロパティが以下のことを定義します。
>
>1.現在の重ね合わせコンテキストにおけるボックスの重ね合わせレベル
>2.ボックスがローカルな重ね合わせコンテキストを作るかどうか

```position```を何も指定してない場合、全ての要素は```position: static```を持ちます。
そして、引用文から```position: static```がある要素では```z-index```は効果がないことがわかります。
そのため、先ほどはあった要素2　>　要素1という表示順の関係がなくなってしまったのです。

すると、どうでしょうか。
要素2は```z-index```が意味を持たず、表示順の競争から脱落。
要素1と要素3同士の戦いになります。

要素1と要素3の```z-index```の値はそれぞれ```11```と```10```。
そのため、```z-index```の値が大きい要素1が上に表示されてしまったのでした。

# 教訓
```z-index```の値は、表示するページ全体を見て決めた方がよいですね。
そもそも```position```がついたりつかなかったりしてるのが悪いと思いますが。