knowledge base

マークアップ/フロントエンドエンジニアのWEB制作における備忘録です。平日はWEB屋、休日は社会人劇団の主宰・劇作家をしています。

スタイルシートのみで吹き出しを実装

borderの特性を利用する

このようなイメージの吹き出しを作ります。

f:id:ShinImae:20151216165853j:plain

問題なのは「角」の作り方ですが、ヒントはborderの描画のされ方にあります。

たとえば、次のようなdivの枠線は下図のように表示されます。

div{
   width: 200px;
   height: 80px;
   border-style: solid;
   border-width: 20px;
   border-top-color: #ccc;
   border-right-color: #aaa;
   border-left-color: #333;
   border-bottom-color: #666
}

f:id:ShinImae:20151216165918j:plain

四辺の色を変えることはほとんどないので気づきにくいのですが、実はborderの角は尖っているのです。

そこで、幅と高さを0にするとこのようになります。

f:id:ShinImae:20151216165936j:plain

「角」に近づいてきましたね。

不要な三辺のborderの色を消しましょう。

div{
   width: 0px;
   height: 0px;
   border-style: solid;
   border-width: 20px;
   border-top-color: #ccc;
   border-right-color: transparent;
   border-left-color: transparent;
   border-bottom-color: transparent;	
}

記述量を減らすために、次のように書き換えます。

div{
   width: 0px;
   height: 0px;
   border-style: solid;
   border-width: 20px;
   border-color: transparent;
   border-top-color: #ccc;
}

f:id:ShinImae:20151216165952j:plain

任意の方向のborder-colorのみ指定にすれば、上下左右すべての方向の「角」を実装できます。

注意すべきなのは、色を透明にすることです。

四辺があるから尖っているため、これをborder:noneにしてしまうと三角形にはならず、ただの直線にしかなりません(しかも今回の場合は幅0pxのため表示すらされません) 。

これを元にして、実装していきます。

極力、古い環境にも対応できるよう(文書構造的には好ましくありませんが)空要素を使用します。

モダンブラウザならば、:after疑似要素を使えばベターです。

<div id="baloon">
   <p>Lorem ipsum</p>
   <span id="angle"></span> 
<div>
#baloon{
  position: relative;
  width: /* 任意の大きさ */
  height: /* 任意の大きさ */
  overflow: visible;
  background: #ccc;
}
  #angle{
    display: inline-block;
    /display: inline;
    /zoom: 1;
    position: absolute;
    bottom: -40px;
    right: 30px; 
    width: 0px;
    height: 0px;
    border-style: solid;
    border-width: 20px;
    border-color: transparent;
    border-top-color: #ccc; 
  }

:after疑似要素は次のように記述します。(空要素はマークアップしません)

#baloon:after{
    content: '';
    display: inline-block;
    position: absolute;
    bottom: -40px;
    right: 30px; 
    width: 0px;
    height: 0px;
    border-style: solid;
    border-width: 20px;
    border-color: transparent;
    border-top-color: #ccc; 
}

すると狙い通りの吹き出しが実装できます。

f:id:ShinImae:20151216165853j:plain

角のサイズを分析してみると、このようになっています。

f:id:ShinImae:20151216170020j:plain

なので、配置する際の座標や角のサイズはborder-widthを基準にして機械的に算出することができます。

ちなみに、この性質を利用すれば次のように変形させることも可能です。

[ex. 左右のborder-widthを半分に]

f:id:ShinImae:20151216170028j:plain

CSS3を使えば、傾いたり歪んだり等、もっと柔軟な表現が可能になります。

IE6では実装できません

IE7は空要素を使うことでギリギリ対応できましたが、IE6での実装は限定的です。

理由は、border-color: transparent に対応していないためです。

どうしても実装したい場合は、透明にした三辺に背景色と同じ色を指定する方法しかありませんが、「角」が別の要素上にかぶってしまうときなどはお手上げです。

良い機会なので、今一度IE6/7で実装不可なものをおさらいしてみます。

IE6未対応

A > B
Aの1階層下の子要素Bを指定するセレクタ
A + B
Aに隣接するBを指定するセレクタ
A:first-child
他の要素内にある最初の子要素Aに対して設定を適用するセレクタ
A[属性名]
属性セレクタのひとつで、指定した属性を持つ要素Aに対して設定を適用する。A[属性名="属性値"], A[属性名|="属性値"], A[属性名~="属性値"]も同様に使用不可です。
a要素以外に対する:hover/:active疑似クラスの指定
マウスカーソルをdivなどにホバーさせてもスタイルを指定できません
max- / min-
max-width / max-height / min-width / min-height 横幅および高さの最大値、最小値を指定
position: fixed
固定表示するためのプロパティです
border-color: transparent
先ほど使用しました、枠線を透明にするためのプロパティです

IE7未対応

A:lang/A:focus疑似クラス
lang属性の値が一致する要素Aを適用先とする。要素Aを選択したときに適用する
:before / :after疑似要素
ソースには書かれませんがCSS上で使用できる要素です
border-spacing
テーブルの隣接するセルの罫線から罫線までの間隔を指定
caption-side
テーブルのキャプションの表示位置を指定

最近の制作現場ではよく使われているものでも、IE6/7では対応できないものが多いようです。