CSSの:before :afterでz-indexがうまく機能しない現象に対処
最近はHTMLのコーディング作業での装飾にスタイルシートを使うことが多くなりました。
以前は画像を使って背景に当てていましたが、最近は線や模様などをCSSで直接描くことができます。
ただ複雑な模様にすると、タグをたくさん設置しなければならず、少々おっくうです。
そこで、:befor、:afterを使います。なぜならこの方法で、一つのタグに最大3つの要素を設定でき、タグ設置数を減らせるからです。
今回、:before、:afterを使用して、見出しに背景模様を設定しようとしたところ、妙な現象が起きました。何をやっても背景が前面に出てきます。
なぜ?と思いながらググって調べてみたところ、解決できましたので忘備録として記録いたします。
今回やりたかったこと
H1タグだけで以下のような背景模様を設置します。
1色だけならば、通常の背景設定だけでOKですが、2色になると少々むつかしいです。
そこで、:beforeと:afterを使って実現しようと考えました。
まずやってみたところこんな感じになりました。
半分で色を変えるのだから、absolute設定を使います。
でもそれだけだと、文字部分が後ろになるので、z-indexを使い文字が最前面になるようにすればよい。
そう考え、以下のような記述をしました。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 |
<!doctype html> <html> <head> <meta charset="shift_jis"> <title></title> <style type="text/css"> h1 { text-align: center; position: relative; padding-top: 20px; padding-bottom: 20px; z-index: 999; } h1:before { content: ""; background-color: #3CF; display: block; height: 100%; width: 50%; position: absolute; top: 0px; left: 0px; z-index: 0; } h1:after { content: ""; background-color: #F66; display: block; height: 100%; width: 50%; position: absolute; top: 0px; right: 0px; z-index: 0; } </style> </head> <body> <h1>見出しテスト</h1> </body> </html> |
案外簡単!
そう思って確認したところ、次のような表示になりました。
背景のほうが最前面になり、文字が後ろに隠れています。
z-indexで表示順番を指定したのになぜ?
:beforeと:afterのz-indexをマイナスにすれば解決します
なぜz-indexが効かないのか?
ググって調べてみたところ、「:beforeと:afterの場合はz-indexにマイナス値を設定する」というものがありました。
そこで、z-indexに-1を設定してみました。
コーディング
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
<!doctype html> <html> <head> <meta charset="shift_jis"> <title></title> <style type="text/css"> h1 { text-align: center; position: relative; padding-top: 20px; padding-bottom: 20px; } h1:before { content: ""; background-color: #3CF; display: block; height: 100%; width: 50%; position: absolute; top: 0px; left: 0px; z-index: -1; } h1:after { content: ""; background-color: #F66; display: block; height: 100%; width: 50%; position: absolute; top: 0px; right: 0px; z-index: -1; } </style> </head> <body> <h1>見出しテスト</h1> </body> </html> |
結果
ちゃんと背景が後ろになりました。
しかしここで疑問がわきました。
通常は最初のやり方でうまくいくのに、:befoe、:afterだとなぜうまくいかないのでしょうか?
というわけでその理由を調べてみました。
:before、:afterは子要素のため親要素のz-indexを引き継ぎます
:before、:afterのz-indexで調べると、疑似要素に関する要因という回答がありました。
ただ、何かしっくりきませんでした。
なぜならば、以下のようなコーディングでも同じ現象になるためです。
背景が前に来ないのは疑似要素だからではなく、親子関係によるもの
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 |
<!doctype html> <html> <head> <meta charset="shift_jis"> <title></title> <style type="text/css"> .main { text-align: center; position: relative; padding-top: 20px; padding-bottom: 20px; z-index: 999; } .sub01 { content: ""; background-color: #3CF; display: block; height: 100%; width: 50%; position: absolute; z-index: 0; top: 0px; left: 0px; } .sub02 { content: ""; background-color: #F66; display: block; height: 100%; width: 50%; position: absolute; z-index: 0; top: 0px; right: 0px; } </style> </head> <body> <div class="main"> 見出しテスト <div class="sub01"></div> <div class="sub02"></div> </div> </body> </html> |
疑似要素を使っていませんが、背景が前になり文字が表示されません。
つまりこの現象は背景指定した要素と、文字の要素が親子関係になっているため発生しているのです。
子要素は親要素のz-indexを引き継ぐ
HTMLでは、後から記述したほうが前面になります。
つまりz-index値が同じならば、後から記述したほうが前面になるということです。
親子関係の記述の場合は、親が必ず先に記述されます。
終了タグは一番最後に記述されますが、開始タグが先に書かれたほうが後ろになります。
1 2 3 4 5 6 |
<div class="oya"> // ← 親要素が必ず先に記述されます。 <div class="ko01"></div> <div class="ko02"></div> </div> |
子要素は必ず親要素の後に書かれるため、親要素より前面になります。
そして親要素のz-indexは子要素に引き継がれます。
だから子要素のz-indexを小さくしても親要素の前に出てしまうのです。
親要素のz-index 999
子要素のz-index 0
この場合、子要素はz-index999の土台の上にz-index0で構築されます。
子要素のz-index を-1にすると、親要素の後ろになる理由
親要素の土台の上でz-indexを親要素より小さく設定しても、土台の後ろになることはない。
それは理解できましたが、子要素のz-indexに-1を設定すると、親要素の後ろになります。
この理屈について調べてみました。
以下の設定は子要素は事実上 z-index 999になります。
親要素のz-index 999
子要素のz-index 0(事実上 z-index 999)
では子要素のz-indexを1にした場合は次のような意味になります。
親要素のz-index 999
子要素のz-index 1(事実上 z-index 1000)
ということになります。
ということは、-1を設定するとこのようになります。
親要素のz-index 999
子要素のz-index -1(事実上 z-index 998)
-1を設定することで、事実上親要素よりz-indexの値が小さくなるため、後ろに表示されるというわけです。
※注意点
親要素と同系列のタグAが、親要素よりz-indexの値が大きい場合、子要素のz-indexがタグAより大きくてもタグAのほうが前面に表示されます。
z-indexは同系列要素同士で比較されるためです。
わかるようなわからないような話ですが
z-indexは、タグの階層で比較される、されないが決まります。
階層が同じ場合しか比較されないためです。
ただ親子関係の場合は、子要素のz-indexにマイナス値を指定すると階層の異なる親要素より後ろに配置されます。
このことがわかりにくさを倍増している感じがしました。
:beforeと:afterは本体タグから見れば、子要素になります。
階層が異なるため、プラス値では比較されないのです。
それが理解できて、なんとなく理屈がわかった感じがしました。
よく知っているつもりでも、落とし穴ってあるものです。