CSSで重なり順を意識する

##はじめに
`z-index`を使うことははよくあると思います。
ですがちゃんと理解してないで使うと思った通りにならないということが多々あります。
実際私もなんとなくで使っていてハマりました…
なので自分でも理解できるようにまとめてみました。

##そもそもz-indexとは？
要素の重なり順（スタックレベル）を指定するCSSのプロパティです。
通常は後に書いた要素の方が上に表示されますが、`z-index`を使用することによって自由に優先順位を設定することができます。
書き方は以下のように記述します。

`z-index: 値;`

```
z-index: 10;
z-index: 20;
z-index: 100;
```
値は整数またはauto（初期値）を指定します。
指定した値が大きい要素ほど上に表示されます。


##どんなときに使う？
`position: absolute`や`position: fixed`で要素を重ねた時などに重なり順を指定するのに使うことが多いです。
`z-index`を使用するには、その要素に`position`プロパティで**static（初期値）以外の値が適用されている**必要があります。
`z-index`は`position`と一緒に使うと覚えればいいですね！

##実際に使ってみよう
<p class="codepen" data-height="265" data-theme-id="light" data-default-tab="css,result" data-<p class="codepen" data-height="265" data-theme-id="light" data-default-tab="css,result" data-user="s_miko" data-slug-hash="GRjvoMK" style="height: 265px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-pen-title="GRjvoMK">
  <span>See the Pen <a href="https://codepen.io/s_miko/pen/GRjvoMK">
  GRjvoMK</a> by mikoshiba (<a href="https://codepen.io/s_miko">@s_miko</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>

```scss:scss
 .wrapper{
   position: relative;
 } 

.box {
  position: absolute;
  width: 100px;
  height: 100px;
  
  &.box1{
    top: 0;
    left: 0;
    background-color: #07bc8c;
  }
  
  &.box2{
    top: 50px;
    left: 50px;
    background-color: #e02f2f;
  }
}
```

`z-index`は特に指定してないですね。
`z-index`を指定しなければ後に書いた要素の方が上に表示されます。
なのでbox2が上に表示されてます。

では`z-index`を指定するとどうなるでしょう？

```scss:scss
 .wrapper {
   position: relative;
 } 

 .box {
   position: absolute;
   width: 100px;
   height: 100px;
  
   &.box1{
     z-index: 1;
     top: 0;
     left: 0;
     background-color: #07bc8c;
   }
  
   &.box2{
     top: 50px;
     left: 50px;
     background-color: #e02f2f;
   }
 }
```

<p class="codepen" data-height="265" data-theme-id="light" data-default-tab="css,result" data-user="s_miko" data-slug-hash="ExgwdZd" style="height: 265px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-pen-title="ExgwdZd">
  <span>See the Pen <a href="https://codepen.io/s_miko/pen/ExgwdZd">
  ExgwdZd</a> by mikoshiba (<a href="https://codepen.io/s_miko">@s_miko</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>

box1に`z-index: 1;`を書き足しました。
先に書いたbox1が上に表示されています。
このように`z-index`を使えば重ね順を指定できます。

##意図した通りに動かない…

<p class="codepen" data-height="265" data-theme-id="light" data-default-tab="css,result" data-user="s_miko" data-slug-hash="VwKMadv" style="height: 265px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-pen-title="VwKMadv">
  <span>See the Pen <a href="https://codepen.io/s_miko/pen/VwKMadv">
  VwKMadv</a> by mikoshiba (<a href="https://codepen.io/s_miko">@s_miko</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>

```html:html
<div class="wrapper"> 
  <div class="box box1">box1</div>
  <div class="box box2">box2
    <div class="box box3">box3</div>
  </div>
</div>
```

```scss:scss
 .wrapper {
   position: relative;
 } 

 .box {
   position: absolute;
   width: 100px;
   height: 100px;
  
   &.box1{
     z-index: 2;
     top: 0;
     left: 0;
     background-color: #07bc8c;
   }
  
   &.box2{
     z-index: 1;
     top: 50px;
     left: 50px;
     background-color: #e02f2f;
   }
  
   &.box3{
     z-index: 100;
     top: 50px;
     left: 50px;
     background-color: #ffcc00;
   }
 }
```
box1、box2、box3それぞれに`z-index`を指定しました。
数値だけで見ると box3 > box1 > box2の順番になりそうですよね。
でも実際はbox1が一番上にきています。
それはなぜでしょう？

ここで出てくるのが**スタックコンテキスト**です。


##スタックコンテキスト
> 重ね合わせコンテキストは、ビューポートまたはウェブページに面していると想定されるユーザーに対する仮想的な Z 軸に沿って並べられた HTML 要素の三次元の概念化です。 HTML 要素は、要素の属性に基づいてこの空間を優先度つきの順序で占有します。

う〜〜〜〜〜ん、わからん！！！


簡単に説明すると、スタックコンテキストとは**特定の条件において作られる要素のグループ**のことです。
特定の条件とは

**`position:relative`または`position:absolute`かつ`z-index:auto`以外の整数を指定すること**

です。
他にもありますが、大体この条件が使われます。

```html:html
<!-- スタックコンテキスト -->
<div class="box1" style="position: relative; z-index: 1;">
  <div class="box1-1"></div>
  <div class="box1-2"></div>
</div>
<!-- /スタックコンテキスト -->
<div class="box2">
  <div class="box2-1"></div>
</div>
```
box1に特定の条件（`position:relative`かつ`z-index:1`）指定しているので、
box1を親とするその子要素（box1-1、box1-2）のグループが作られます。
これがスタックコンテキストです。
上の例でいうとbox1、box2、box3それぞれスタックコンテキストを生成しています。

また、htmlはデフォルトでスタックコンテキストを生成しているので、
何も指定しなくてもbox1〜box3はルートスタックコンテキストに所属しています。

##スタックコンテキストとスタックレベル
スタックレベルとは同一スタックコンテキストのなかの重なり順のことです。
下記でいうとbox1とbox2は兄弟要素、つまり同じスタックレベルです。
`z-index`で指定している順序は、HTML全体のなかの重なり順ではなく、このスタックレベルのことを指しています。

さっきの意図しないコードをもう一回見てみましょう。

```html:html
<div class="wrapper"> 
  <div class="box box1">box1</div>
  <div class="box box2">box2
    <div class="box box3">box3</div>
  </div>
</div>
```

```scss:scss
 .wrapper{
   position: relative;
 } 

 .box {
   position: absolute;
   width: 100px;
   height: 100px;
  
   &.box1{
     z-index: 2;
     top: 0;
     left: 0;
     background-color: #07bc8c;
   }
  
   &.box2{
     z-index: 1;
     top: 50px;
     left: 50px;
     background-color: #e02f2f;
   }
  
   &.box3{
     z-index: 100;
     top: 50px;
     left: 50px;
     background-color: #ffcc00;
   }
 }
```
box1とbox２はスタックレベルが同じです。
box1とbox２だと1の方が数値が大きいのでbox1が上に表示されます。
box3は100という大きい値を設定してるにもかかわらずbox1より下に表示されるのはbox３がbox2のスタックコンテキストに属しているからです。
なのでbox3は親要素box2以外の数値の影響を受ける事はありません。

##まとめ
`z-idnex`が効かないときは`position`に`static`以外が指定されているか確認する、
またはスタックコンテキストとスタックレベルを意識すれば幸せになれそうですね。


##参考文献
- [重ね合わせコンテキスト - CSS: カスケーディングスタイルシート | MDN](https://developer.mozilla.org/ja/docs/Web/Guide/CSS/Understanding_z_index/The_stacking_context)
- [君は真に理解しているか？z-indexとスタッキングコンテキストの関係 - ICS MEDIA](https://ics.media/entry/200609/)
- [【CSS】z-indexの使い方をサンプルで解説！効かない理由は | MDN](https://wunderstand.net/1212/)
- [【CSS】z-indexのルールを理解する！スタックコンテキストとは？](https://egrdc-d.site/rule-of-z-index/)