2015.04.11

css3で吹き出し作って、疑似要素がz-indexでどっか行っちゃうの直す

当ブログでは長年?画像で吹き出しを表現していたのですが、retina対応をした時に画像のぼけ具合が気になり出しました。cssで表現出来る部品はなるべくそっちにシフトしたいなーということで!
webでは吹き出しを作るための便利なジェネレーターや沢山の優れたリファレンスが公開されますが、勉強がてら自分なりにまとめてみることにしました。

まずは構成から

どうしてもcssの行数が長ーくなるのが欠点ですな…。それでも画像の方が重いんだろうと気を取り直してやってみます。
疑似要素のbefore afterを使って吹き出し部分を表現します。
ボーダーのある吹き出しにしてみる。

たのしい毒矢入門を読んだんだ。

部品となるのは、

  • 本体の要素p 内容とbackgroundカラーとborder
  • beforeによる前の要素 吹き出しの三角部分(pのボーダー色と同色)
  • afterによる後の要素 吹き出しの三角部分(pのbackgroundと同色)

beforeとafterで三角を作り、二つの三角形の重なりをずらしてボーダーを表現します。
ボーダーが要らなければ、beforeだけでできます。

ベースのp要素にbefore afterの疑似要素を追加する。

たのしい毒矢入門を読んだんだ。

その前に三角の作り方

div#deltaを作り練習してみる。

上下左右はそれぞれ極端に太さをとったボーダー。辺の端っこが斜めになってて隣の辺と合体してるのが分かります。

あ?

widthとheightを0にすることで三角ができる。

残したい辺以外のborder-colorを透明にする。

ボーダーの太さborder-widthを変えることで三角形の角度や長さが調整できる。

これをpのbeforeとafterに応用します。

位置を調整する

三角形は出来たけど、へんな場所にあるのよね。
(解りやすいように三角を赤に変えた)

たのしい毒矢入門を読んだんだ。

beforeとafterの疑似要素をposition: relative;指定のp要素を起点として配置。bottomなどにマイナス値を使って外側に出します。

afterの三角の位置を上側に数pxずらして、下になっているボーダーカラーと同色にしたbeforeの三角をチラ見せしてボーダーを表現する。

たのしい毒矢入門を読んだんだ。

おお!できたよね!

こんなこともできちゃう…はずだった

beforeとafterの配置をうまく使うとカーブの付いた吹き出しも出来るよね。

えっ?毒矢?なにそれこわい。

疑似要素でbeforeとafterで吹き出しと同じ色の円と背景と同じ色の円を重ねてぴよっとした部分を作り、疑似要素の親のdivの後ろへz-index:-1で送る事で実現しています。

z-index:-1が効かないんだ

実は↑このままのソースでは当ブログでは、疑似要素部分がこつ然と姿を消してしまいます。
z-indexが効いてないんじゃなく凄い下の重なりレベルまで潜っていっちゃってて、間にある要素のbackgroundで隠れてちゃってる模様…かといってz-indexの値を大きくしても解決しないわー。
スタックコンテキストとやらを新たに作ることで回避できます。

参考サイト:
CSS3 時代の z-index まとめ | Design Hack and Slash
要素の重なりについて本気出して考えてみた(z-indexとか何とかとか) – No.1026

スタックコンテキストというのはどうも複雑で詳しくは勉強させてもらたブログを見て頂くとして、とりあえずは簡単に

  • スタックレベル レイヤー(重なり)の順番
  • スタックコンテキスト その範囲でだけレイヤーを入れ替えられる結界

だとでも思ってください。

疑似要素を親要素である#ringの下に重ねるには?

疑似要素の親は疑似要素をセットした要素になります。この場合は#ringです。
#ringの直接の親、または新たにdivかなんかでラップして作った#ringの親要素=疑似要素からみて先祖要素(じぃちゃん)を用意します。

この先祖要素(じぃちゃん)を基準とした結界を作ることで、どっかに潜っていった子(疑似要素で作った吹き出し)を親(楕円)と同じ次元に呼び戻し、楕円のすぐ下に配置します。

スタックコンテキストを作るには先祖要素にstatic以外のpositionをセットします。
この場合rerativが適当かと思われます。
positionでz-indexを明示しない場合、autoが割当てられるのですが、autoは0と同じレベルです。しかし、autoはスタッキングコンテキストを作り出しません。
スタッキングコンテキストを作り出すには、z-indexでスタックレベルを明確に0と指定します。他のスタックコンテキストに影響しないなら0でなくとも整数値であれば良いです。

なぜ親がz-index:0ではだめなのさ?

z-index
親のz-indexに0や整数値を指定してしまうと、親を基準としたスタックコンテキストが新たに生まれます。
スタックレベルは所属するスタックコンテキスト内でのみ有効なので、親の下に移動する事が出来なくなります。
子要素である疑似要素のz-index:-1はあくまで親内部でのスタックレベルとなります。
親のz-indexは、一段階外側のスタックコンテキスト内でのスタックレベルを指しているので、親が基準の場合、親と子の重なり順が変更されることがありません。

そんで先祖要素を基準としたスタックコンテキストを作り、親を含めたスタックレベルを設定するわけです。

じぃちゃんを基準としたスタックコンテキストの中では次のように扱われます。
z-index_jj
じぃちゃん(外側の結界であるため内側のレベルに関与しない 0は外側の世界でのレベル)
親(z-index:auto = デフォルト0)
子after(z-index = -1)
子before(z-index =-1 マークアップ順)

意識の片隅に…スタックコンテキスト

この現象はhtml基準のルートスタックコンテキストしか存在しなかったことが原因です。
index:-1でルートの最下層に配置されてしまい、その上にbackgroundが設定された要素がガンガン乗っかっていたのでマスクされてしまいました。
間にある要素にbackgroundが設定されてなければ疑似要素は表示されます。
もし、positionとbackgroundを多用しているなら、ちょっとややこしいけどスタックコンテキストを意識してみるとレイアウトの自由度が上がるような気がします。

コメントをどうぞ



PageTop