吹き出し会話のスタイルを作ってみる

f:id:c-miya:20170805134951p:plain
あまり自分で使うこともないのですが、cssで作る吹き出し会話について考えてみました。


この手のcssは、はてなブログでもよく取り上げられていて、誰かのをコピペしているようです。そういう系の記事を見かけることはよくあるのですが、中身までしっかり読んでないので具体的にはよくわかってません。なので、まぁ自分で作ってみようと、そういうわけです。

基本の形

基本は右や左にアイコンがあって、その隣に吹き出しがあるというもの。交互になってるのもポイントですね。ということは…

<div class="fuki-box">
<img src="画像URL" />
<div class="fuki">セリフ内容</div>
</div>

こんな感じかな?

セリフ部分のスタイル

セリフ部分はdivにボーダーなり付けて角丸にして調整。問題はツノ部分。これはたぶんボーダーで作ってるんだろうな。これ、わたしあまり理解してないんだよな…。


borderでツノ

試しに。

Test

<div style="width:50%;border:10px solid #999;">Test</div>

ふむ。

Test

<div style="width:50%;border:10px solid;border-top-color:#999;border-right-color:#f90;border-bottom-color:#f0f;border-left-color:#9f9;">Test</div>

うんうん。

<div style="width:40px;border:20px solid;border-top-color:#999;border-right-color:#f90;border-bottom-color:#f0f;border-left-color:#9f9;"></div>

ほうほう。

<div style="width:40px;border-top:10px solid #999;border-right:40px solid #f90;border-bottom:30px solid #f0f;"></div>

なるほどね。

<div style="width:40px;border:20px solid transparent;border-right-color:#f90;"></div>

本体とくっつけてみる

これはテスト。

<div class="fuki1">これはテスト。</div>
.fuki1{background:#ccc;padding:1em;margin:0 0 0 15px;border-radius:6px;position:relative;}
.fuki1::before{content:'';position:absolute;top:calc(50% - 10px);left:-16px;font-size:0;border-top:10px solid transparent;border-right:16px solid #f90;border-bottom:10px solid transparent;}

単色塗りつぶしなら、これで色を揃えればOKなんでしょうな。

ボーダーを付けてみる

ツノはセリフ本文のdivの::beforeで作成して付けるとたぶんいい感じ。で、そのまま本体にボーダーをつけると…

これはテスト。

まぁこうなるわな。なので、ツノ部分に白抜きを与えるために、少し位置をずらしたもう1個のツノを::afterで作ってかぶせる。

これはテスト。

被せたのを白にすれば…

これはテスト。

疑似ボーダーのできあがり。

<div class="fuki4">これはテスト。</div>
.fuki4{padding:1em;margin:0 0 0 15px;border:3px solid #333;border-radius:6px;position:relative;}
.fuki4::before{content:'';position:absolute;top:calc(50% - 10px);left:-16px;font-size:0;border-top:10px solid transparent;border-right:16px solid #333;border-bottom:10px solid transparent;}
.fuki4::after{content:'';position:absolute;top:calc(50% - 10px);left:-12px;font-size:0;border-top:10px solid transparent;border-right:16px solid #fff;border-bottom:10px solid transparent;}

画像と並べる

喋っている人を表すアイコン画像と並べる方法は、まぁいろいろあるのですが、最近はflexboxが好きなのでこれで。


意識高すぎワロタ。

<div class="fuki-box5">
<div class="fukimg5"><img src="https://cdn1.www.st-hatena.com/users/c-/c-miya/profile.gif" /></div>
<div class="fuki5">意識高すぎワロタ。</div>
</div>
.fuki-box5{display:-webkit-flex;display:flex;}
.fukimg5{width:64px;height:auto;-webkit-flex-shrink:0;flex-shrink:0;}
.fuki5{padding:1em;margin:0 0 0 15px;border:3px solid #333;border-radius:6px;position:relative;}
.fuki5::before{content:'';position:absolute;top:calc(50% - 10px);left:-16px;font-size:0;border-top:10px solid transparent;border-right:16px solid #333;border-bottom:10px solid transparent;}
.fuki5::after{content:'';position:absolute;top:calc(50% - 10px);left:-12px;font-size:0;border-top:10px solid transparent;border-right:16px solid #fff;border-bottom:10px solid transparent;}

ただ、このままだとセリフの量が多くなるとツノの位置が合わなくなる。


親譲りの無鉄砲で小供の時から損ばかりしている。小学校に居る時分学校の二階から飛び降りて一週間ほど腰を抜かした事がある。なぜそんな無闇をしたと聞く人があるかも知れぬ。別段深い理由でもない。新築の二階から首を出していたら、同級生の一人が冗談に、いくら威張っても、そこから飛び降りる事は出来まい。

ツノの位置をセリフ本文の縦中央にしていたけど、画像に合わせたほうが良いか…?


親譲りの無鉄砲で小供の時から損ばかりしている。小学校に居る時分学校の二階から飛び降りて一週間ほど腰を抜かした事がある。なぜそんな無闇をしたと聞く人があるかも知れぬ。別段深い理由でもない。新築の二階から首を出していたら、同級生の一人が冗談に、いくら威張っても、そこから飛び降りる事は出来まい。

左右に分けて会話形式に

左右に分けると起こることは「アイコン画像が右になる」「ツノの位置も逆になる」ということ。

  1. 会話全体をdivで囲んで、その中の奇数と偶数でcssを切り替える
  2. それぞれ別のクラス名をつける

1.のほうがなんとなく記述量が少なくなる気がしないでもない。ただ必ず左に画像がある方から話し始めなければならなくなりそう。それは面倒そうなので2.を採用。



あのイーハトヴォのすきとおった風、夏でも底に冷たさをもつ青いそら、うつくしい森で飾られたモーリオ市、郊外のぎらぎら光る草の波。

誰だこのグラサン

flexbox使うと並びの方向を変えるだけで済むのがめっちゃ楽。ツノ部分は単に回転させても良かったかも。

まとめ

んー…、まぁこんなものですか。よく使われているのをみると、吹き出しにシャドウつけたりアイコンを丸にしてるのも見かけますが、あまり好みではないのでやらない。

最終的なhtmlとcssは以下の通り。

<div class="fuki-box">
<!-- 左アイコン -->
<div class="fuki fukiL">
<div class="fukimg"><img src="画像URL-1" /></div>
<div class="fukitxt">テキスト1</div>
</div>

<!-- 右アイコン -->
<div class="fuki fukiR">
<div class="fukimg"><img src="画像URL-2" /></div>
<div class="fukitxt">テキスト2</div>
</div>

</div>
.fuki{
  display: -webkit-flex;
  display: flex;
  margin: 0 0 1.5em 0;
}
.fukiR{
  -webkit-flex-direction: row-reverse;
  flex-direction: row-reverse;
}
.fukimg{
  width: 64px;
  height: auto;
  -webkit-flex-shrink: 0;
  flex-shrink: 0;
}
.fukitxt{
  padding: 1em;
  border: 3px solid #333;
  border-radius: 6px;
  position: relative;
}
.fukiL .fukitxt{
  margin: 0 0 0 15px;
}
.fukiR .fukitxt{
  margin: 0 15px 0;
}
.fukitxt::before,.fukitxt::after{
  content: '';
  position: absolute;
  top: 19px;
  font-size: 0;
  border-top: 10px solid transparent;
  border-bottom: 10px solid transparent;
}
.fukiL .fukitxt::before{
  left: -16px;
  border-right: 16px solid #333;
}
.fukiL .fukitxt::after{
  left: -12px;
  border-right: 16px solid #fff;
}
.fukiR .fukitxt::before{
  right: -16px;
  border-left: 16px solid #333;
}
.fukiR .fukitxt::after{
  right: -12px;
  border-left: 16px solid #fff;
}

もっと記述を少なくするだとかスマートにするだとか、いろいろありそうですが、まぁ練習的なものなのでこんなところで。個人的にはボーダーではなくベタ塗りにするのも好きなんですけどね。