1. Qiita
  2. 投稿
  3. CSS

CSS影付き吹き出し位置12パターン

  • 20
    いいね
  • 1
    コメント

影付き吹き出しの作り方を毎回調べている気がするのでメモっておく。

サイズゼロ要素のborderを太くする方法だと影つきのものに対応できないので,transformrotate()skew()を活用する方法を使います。

内側にdiv要素を設けてもいい場合

スクリーンショット 2017-02-06 10.22.28.png

このはみ出た部分を

スクリーンショット 2017-02-06 10.22.43.png

これで塗りつぶします。

スクリーンショット 2017-02-06 4.22.58.png

ブラウザのアドレスバーにコピペして確認
data:text/html;charset=utf8;base64,PCFET0NUWVBFIGh0bWw+Cgo8bWV0YSBjaGFyc2V0PSJVVEYtOCI+Cjx0aXRsZT5DU1PlvbHku5jjgY3lkLnjgY3lh7rjgZfkvY3nva4xMuODkeOCv+ODvOODszwvdGl0bGU+Cgo8c3R5bGU+CgovKiDooajnpLrnlKggKi8KaHRtbCxib2R5IHsKICAgIGhlaWdodDogMTAwJTsKICAgIGRpc3BsYXk6IGZsZXg7CiAgICBmbGV4LWRpcmVjdGlvbjogY29sdW1uOwogICAganVzdGlmeS1jb250ZW50OiBjZW50ZXI7CiAgICBhbGlnbi1pdGVtczogY2VudGVyOwp9Ci5yb3cgewogICAgZGlzcGxheTogZmxleDsKfQoKLyog5a6a55+zICovCi5iYWxsb29uIHsKICAgIHBvc2l0aW9uOiByZWxhdGl2ZTsKfQouYmFsbG9vbjo6YmVmb3JlIHsKICAgIGNvbnRlbnQ6ICcnOwogICAgei1pbmRleDogMTsKICAgIHBvc2l0aW9uOiBhYnNvbHV0ZTsKfQouYmFsbG9vbjo6YWZ0ZXIgewogICAgY29udGVudDogJyc7CiAgICB6LWluZGV4OiAyOwogICAgcG9zaXRpb246IGFic29sdXRlOwogICAgdG9wOiAwOwogICAgbGVmdDogMDsKICAgIHdpZHRoOiAxMDAlOwogICAgaGVpZ2h0OiAxMDAlOwp9Ci5iYWxsb29uX19pbm5lciB7CiAgICB6LWluZGV4OiAzOwogICAgcG9zaXRpb246IHJlbGF0aXZlOwp9CgovKiDoqK3lrprpoIXnm64gKi8KLmJhbGxvb24gewogICAgd2lkdGg6IDIwMHB4OyAvKiDluYUgKi8KICAgIG1pbi1oZWlnaHQ6IDYwcHg7IC8qIOacgOWwj+OBrumrmOOBlSAqLwogICAgbWFyZ2luOiAyMHB4OyAvKiDlpJblgbTjga7kvZnnmb0gKi8KICAgIHBhZGRpbmc6IDEwcHg7IC8qIOWGheWBtOOBruS9meeZvSAqLwp9Ci5iYWxsb29uLAouYmFsbG9vbjo6YWZ0ZXIgewogICAgYm9yZGVyLXJhZGl1czogNXB4OyAvKiDop5Ljga7kuLjjgoHmlrkgKi8KfQouYmFsbG9vbiwKLmJhbGxvb246OmJlZm9yZSB7CiAgICBib3gtc2hhZG93OiAwcHggMHB4IDEwcHggMHB4IHJnYmEoMTYzLDE2MywxNjMsMC41MCk7IC8qIOW9seOBruiJsuOBqOS7mOOBkeaWuSAqLwp9Ci5iYWxsb29uLAouYmFsbG9vbjo6YmVmb3JlLAouYmFsbG9vbjo6YWZ0ZXIsCi5iYWxsb29uX19pbm5lciB7CiAgICBiYWNrZ3JvdW5kOiAjZmZmZWQ2OyAvKiDloZfjgorjgaTjgbbjgZfoibIgKi8KfQoKLyoqIAogKiDjgZPjgZPjgYvjgonlhYjjga7jgoLjga7jgpIx44Gk6YG444Gz44G+44GZCiAqIOS9jee9ruiqv+aVtOOChOW8leOBjeS8uOOBsOOBl+OBruiqv+aVtOOBquOBqeOCguOBp+OBjeOBvuOBmQogKi8KCi8qIOS4iui+uuW3puWBtCAqLwouYmFsbG9vbi0tdG9wX2xlZnQ6OmJlZm9yZSB7CiAgICBsZWZ0OiAxMHB4OwogICAgdG9wOiAtMTBweDsKICAgIHRyYW5zZm9ybTogcm90YXRlKDQ1ZGVnKSBza2V3KDIwZGVnLCAyMGRlZyk7CiAgICB3aWR0aDogMjBweDsKICAgIGhlaWdodDogMjBweDsKfQovKiDkuIrovrrkuK3lpK4gKi8KLmJhbGxvb24tLXRvcF9jZW50ZXI6OmJlZm9yZSB7CiAgICBsZWZ0OiA0NSU7CiAgICB0b3A6IC0xMHB4OwogICAgdHJhbnNmb3JtOiByb3RhdGUoNDVkZWcpIHNrZXcoMjBkZWcsIDIwZGVnKTsKICAgIHdpZHRoOiAyMHB4OwogICAgaGVpZ2h0OiAyMHB4Owp9Ci8qIOS4iui+uuWPs+WBtCAqLwouYmFsbG9vbi0tdG9wX3JpZ2h0OjpiZWZvcmUgewogICAgcmlnaHQ6IDEwcHg7CiAgICB0b3A6IC0xMHB4OwogICAgdHJhbnNmb3JtOiByb3RhdGUoNDVkZWcpIHNrZXcoMjBkZWcsIDIwZGVnKTsKICAgIHdpZHRoOiAyMHB4OwogICAgaGVpZ2h0OiAyMHB4Owp9CgovKiDlj7PovrrkuIrlgbQgKi8KLmJhbGxvb24tLXJpZ2h0X3RvcDo6YmVmb3JlIHsKICAgIHJpZ2h0OiAtMTBweDsKICAgIHRvcDogMTBweDsKICAgIHRyYW5zZm9ybTogcm90YXRlKDQ1ZGVnKSBza2V3KC0yMGRlZywgLTIwZGVnKTsKICAgIHdpZHRoOiAyMHB4OwogICAgaGVpZ2h0OiAyMHB4Owp9Ci8qIOWPs+i+uuS4reWkriAqLwouYmFsbG9vbi0tcmlnaHRfbWlkZGxlOjpiZWZvcmUgewogICAgcmlnaHQ6IC0xMHB4OwogICAgdG9wOiAzNiU7CiAgICB0cmFuc2Zvcm06IHJvdGF0ZSg0NWRlZykgc2tldygtMjBkZWcsIC0yMGRlZyk7CiAgICB3aWR0aDogMjBweDsKICAgIGhlaWdodDogMjBweDsKfQovKiDlj7PovrrkuIvlgbQgKi8KLmJhbGxvb24tLXJpZ2h0X2JvdHRvbTo6YmVmb3JlIHsKICAgIHJpZ2h0OiAtMTBweDsKICAgIGJvdHRvbTogMTBweDsKICAgIHRyYW5zZm9ybTogcm90YXRlKDQ1ZGVnKSBza2V3KC0yMGRlZywgLTIwZGVnKTsKICAgIHdpZHRoOiAyMHB4OwogICAgaGVpZ2h0OiAyMHB4Owp9CgovKiDkuIvovrrlt6blgbQgKi8KLmJhbGxvb24tLWJvdHRvbV9sZWZ0OjpiZWZvcmUgewogICAgbGVmdDogMTBweDsKICAgIGJvdHRvbTogLTEwcHg7CiAgICB0cmFuc2Zvcm06IHJvdGF0ZSg0NWRlZykgc2tldygyMGRlZywgMjBkZWcpOwogICAgd2lkdGg6IDIwcHg7CiAgICBoZWlnaHQ6IDIwcHg7Cn0KLyog5LiL6L665Lit5aSuICovCi5iYWxsb29uLS1ib3R0b21fY2VudGVyOjpiZWZvcmUgewogICAgbGVmdDogNDUlOwogICAgYm90dG9tOiAtMTBweDsKICAgIHRyYW5zZm9ybTogcm90YXRlKDQ1ZGVnKSBza2V3KDIwZGVnLCAyMGRlZyk7CiAgICB3aWR0aDogMjBweDsKICAgIGhlaWdodDogMjBweDsKfQovKiDkuIvovrrlj7PlgbQgKi8KLmJhbGxvb24tLWJvdHRvbV9yaWdodDo6YmVmb3JlIHsKICAgIHJpZ2h0OiAxMHB4OwogICAgYm90dG9tOiAtMTBweDsKICAgIHRyYW5zZm9ybTogcm90YXRlKDQ1ZGVnKSBza2V3KDIwZGVnLCAyMGRlZyk7CiAgICB3aWR0aDogMjBweDsKICAgIGhlaWdodDogMjBweDsKfQoKLyog5bem6L665LiK5YG0ICovCi5iYWxsb29uLS1sZWZ0X3RvcDo6YmVmb3JlIHsKICAgIGxlZnQ6IC0xMHB4OwogICAgdG9wOiAxMHB4OwogICAgdHJhbnNmb3JtOiByb3RhdGUoNDVkZWcpIHNrZXcoLTIwZGVnLCAtMjBkZWcpOwogICAgd2lkdGg6IDIwcHg7CiAgICBoZWlnaHQ6IDIwcHg7Cn0KLyog5bem6L665Lit5aSuICovCi5iYWxsb29uLS1sZWZ0X21pZGRsZTo6YmVmb3JlIHsKICAgIGxlZnQ6IC0xMHB4OwogICAgdG9wOiAzNiU7CiAgICB0cmFuc2Zvcm06IHJvdGF0ZSg0NWRlZykgc2tldygtMjBkZWcsIC0yMGRlZyk7CiAgICB3aWR0aDogMjBweDsKICAgIGhlaWdodDogMjBweDsKfQovKiDlt6bovrrkuIvlgbQgKi8KLmJhbGxvb24tLWxlZnRfYm90dG9tOjpiZWZvcmUgewogICAgbGVmdDogLTEwcHg7CiAgICBib3R0b206IDEwcHg7CiAgICB0cmFuc2Zvcm06IHJvdGF0ZSg0NWRlZykgc2tldygtMjBkZWcsIC0yMGRlZyk7CiAgICB3aWR0aDogMjBweDsKICAgIGhlaWdodDogMjBweDsKfQoKPC9zdHlsZT4KCjxkaXYgY2xhc3M9InJvdyI+CiAgICA8ZGl2IGNsYXNzPSJiYWxsb29uIGJhbGxvb24tLXRvcF9sZWZ0Ij4KICAgICAgICA8ZGl2IGNsYXNzPSJiYWxsb29uX19pbm5lciI+CiAgICAgICAgICAgIOS4iui+uuW3puWBtAogICAgICAgIDwvZGl2PgogICAgPC9kaXY+CiAgICA8ZGl2IGNsYXNzPSJiYWxsb29uIGJhbGxvb24tLXRvcF9jZW50ZXIiPgogICAgICAgIDxkaXYgY2xhc3M9ImJhbGxvb25fX2lubmVyIj4KICAgICAgICAgICAg5LiK6L665Lit5aSuCiAgICAgICAgPC9kaXY+CiAgICA8L2Rpdj4KICAgIDxkaXYgY2xhc3M9ImJhbGxvb24gYmFsbG9vbi0tdG9wX3JpZ2h0Ij4KICAgICAgICA8ZGl2IGNsYXNzPSJiYWxsb29uX19pbm5lciI+CiAgICAgICAgICAgIOS4iui+uuWPs+WBtAogICAgICAgIDwvZGl2PgogICAgPC9kaXY+CjwvZGl2PgoKPGRpdiBjbGFzcz0icm93Ij4KICAgIDxkaXYgY2xhc3M9ImJhbGxvb24gYmFsbG9vbi0tcmlnaHRfdG9wIj4KICAgICAgICA8ZGl2IGNsYXNzPSJiYWxsb29uX19pbm5lciI+CiAgICAgICAgICAgIOWPs+i+uuS4iuWBtAogICAgICAgIDwvZGl2PgogICAgPC9kaXY+CiAgICA8ZGl2IGNsYXNzPSJiYWxsb29uIGJhbGxvb24tLXJpZ2h0X21pZGRsZSI+CiAgICAgICAgPGRpdiBjbGFzcz0iYmFsbG9vbl9faW5uZXIiPgogICAgICAgICAgICDlj7PovrrkuK3lpK4KICAgICAgICA8L2Rpdj4KICAgIDwvZGl2PgogICAgPGRpdiBjbGFzcz0iYmFsbG9vbiBiYWxsb29uLS1yaWdodF9ib3R0b20iPgogICAgICAgIDxkaXYgY2xhc3M9ImJhbGxvb25fX2lubmVyIj4KICAgICAgICAgICAg5Y+z6L665LiL5YG0CiAgICAgICAgPC9kaXY+CiAgICA8L2Rpdj4KPC9kaXY+Cgo8ZGl2IGNsYXNzPSJyb3ciPgogICAgPGRpdiBjbGFzcz0iYmFsbG9vbiBiYWxsb29uLS1ib3R0b21fbGVmdCI+CiAgICAgICAgPGRpdiBjbGFzcz0iYmFsbG9vbl9faW5uZXIiPgogICAgICAgICAgICDkuIvovrrlt6blgbQKICAgICAgICA8L2Rpdj4KICAgIDwvZGl2PgogICAgPGRpdiBjbGFzcz0iYmFsbG9vbiBiYWxsb29uLS1ib3R0b21fY2VudGVyIj4KICAgICAgICA8ZGl2IGNsYXNzPSJiYWxsb29uX19pbm5lciI+CiAgICAgICAgICAgIOS4i+i+uuS4reWkrgogICAgICAgIDwvZGl2PgogICAgPC9kaXY+CiAgICA8ZGl2IGNsYXNzPSJiYWxsb29uIGJhbGxvb24tLWJvdHRvbV9yaWdodCI+CiAgICAgICAgPGRpdiBjbGFzcz0iYmFsbG9vbl9faW5uZXIiPgogICAgICAgICAgICDkuIvovrrlj7PlgbQKICAgICAgICA8L2Rpdj4KICAgIDwvZGl2Pgo8L2Rpdj4KCjxkaXYgY2xhc3M9InJvdyI+CiAgICA8ZGl2IGNsYXNzPSJiYWxsb29uIGJhbGxvb24tLWxlZnRfdG9wIj4KICAgICAgICA8ZGl2IGNsYXNzPSJiYWxsb29uX19pbm5lciI+CiAgICAgICAgICAgIOW3pui+uuS4iuWBtAogICAgICAgIDwvZGl2PgogICAgPC9kaXY+CiAgICA8ZGl2IGNsYXNzPSJiYWxsb29uIGJhbGxvb24tLWxlZnRfbWlkZGxlIj4KICAgICAgICA8ZGl2IGNsYXNzPSJiYWxsb29uX19pbm5lciI+CiAgICAgICAgICAgIOW3pui+uuS4reWkrgogICAgICAgIDwvZGl2PgogICAgPC9kaXY+CiAgICA8ZGl2IGNsYXNzPSJiYWxsb29uIGJhbGxvb24tLWxlZnRfYm90dG9tIj4KICAgICAgICA8ZGl2IGNsYXNzPSJiYWxsb29uX19pbm5lciI+CiAgICAgICAgICAgIOW3pui+uuS4i+WBtAogICAgICAgIDwvZGl2PgogICAgPC9kaXY+CjwvZGl2Pgo
ソースコード
<!DOCTYPE html>

<meta charset="UTF-8">
<title>CSS影付き吹き出し位置12パターン</title>

<style>

/* 表示用 */
html,body {
    height: 100%;
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
}
.row {
    display: flex;
}

/* 定石 */
.balloon {
    position: relative;
}
.balloon::before {
    content: '';
    z-index: 1;
    position: absolute;
}
.balloon::after {
    content: '';
    z-index: 2;
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
}
.balloon__inner {
    z-index: 3;
    position: relative;
}

/* 設定項目 */
.balloon {
    width: 200px; /* 幅 */
    min-height: 60px; /* 最小の高さ */
    margin: 20px; /* 外側の余白 */
    padding: 10px; /* 内側の余白 */
}
.balloon,
.balloon::after {
    border-radius: 5px; /* 角の丸め方 */
}
.balloon,
.balloon::before {
    box-shadow: 0px 0px 10px 0px rgba(163,163,163,0.50); /* 影の色と付け方 */
}
.balloon,
.balloon::before,
.balloon::after,
.balloon__inner {
    background: #fffed6; /* 塗りつぶし色 */
}

/** 
 * ここから先のものを1つ選びます
 * 位置調整や引き伸ばしの調整などもできます
 */

/* 上辺左側 */
.balloon--top_left::before {
    left: 10px;
    top: -10px;
    transform: rotate(45deg) skew(20deg, 20deg);
    width: 20px;
    height: 20px;
}
/* 上辺中央 */
.balloon--top_center::before {
    left: 45%;
    top: -10px;
    transform: rotate(45deg) skew(20deg, 20deg);
    width: 20px;
    height: 20px;
}
/* 上辺右側 */
.balloon--top_right::before {
    right: 10px;
    top: -10px;
    transform: rotate(45deg) skew(20deg, 20deg);
    width: 20px;
    height: 20px;
}

/* 右辺上側 */
.balloon--right_top::before {
    right: -10px;
    top: 10px;
    transform: rotate(45deg) skew(-20deg, -20deg);
    width: 20px;
    height: 20px;
}
/* 右辺中央 */
.balloon--right_middle::before {
    right: -10px;
    top: 36%;
    transform: rotate(45deg) skew(-20deg, -20deg);
    width: 20px;
    height: 20px;
}
/* 右辺下側 */
.balloon--right_bottom::before {
    right: -10px;
    bottom: 10px;
    transform: rotate(45deg) skew(-20deg, -20deg);
    width: 20px;
    height: 20px;
}

/* 下辺左側 */
.balloon--bottom_left::before {
    left: 10px;
    bottom: -10px;
    transform: rotate(45deg) skew(20deg, 20deg);
    width: 20px;
    height: 20px;
}
/* 下辺中央 */
.balloon--bottom_center::before {
    left: 45%;
    bottom: -10px;
    transform: rotate(45deg) skew(20deg, 20deg);
    width: 20px;
    height: 20px;
}
/* 下辺右側 */
.balloon--bottom_right::before {
    right: 10px;
    bottom: -10px;
    transform: rotate(45deg) skew(20deg, 20deg);
    width: 20px;
    height: 20px;
}

/* 左辺上側 */
.balloon--left_top::before {
    left: -10px;
    top: 10px;
    transform: rotate(45deg) skew(-20deg, -20deg);
    width: 20px;
    height: 20px;
}
/* 左辺中央 */
.balloon--left_middle::before {
    left: -10px;
    top: 36%;
    transform: rotate(45deg) skew(-20deg, -20deg);
    width: 20px;
    height: 20px;
}
/* 左辺下側 */
.balloon--left_bottom::before {
    left: -10px;
    bottom: 10px;
    transform: rotate(45deg) skew(-20deg, -20deg);
    width: 20px;
    height: 20px;
}

</style>

<div class="row">
    <div class="balloon balloon--top_left">
        <div class="balloon__inner">
            上辺左側
        </div>
    </div>
    <div class="balloon balloon--top_center">
        <div class="balloon__inner">
            上辺中央
        </div>
    </div>
    <div class="balloon balloon--top_right">
        <div class="balloon__inner">
            上辺右側
        </div>
    </div>
</div>

<div class="row">
    <div class="balloon balloon--right_top">
        <div class="balloon__inner">
            右辺上側
        </div>
    </div>
    <div class="balloon balloon--right_middle">
        <div class="balloon__inner">
            右辺中央
        </div>
    </div>
    <div class="balloon balloon--right_bottom">
        <div class="balloon__inner">
            右辺下側
        </div>
    </div>
</div>

<div class="row">
    <div class="balloon balloon--bottom_left">
        <div class="balloon__inner">
            下辺左側
        </div>
    </div>
    <div class="balloon balloon--bottom_center">
        <div class="balloon__inner">
            下辺中央
        </div>
    </div>
    <div class="balloon balloon--bottom_right">
        <div class="balloon__inner">
            下辺右側
        </div>
    </div>
</div>

<div class="row">
    <div class="balloon balloon--left_top">
        <div class="balloon__inner">
            左辺上側
        </div>
    </div>
    <div class="balloon balloon--left_middle">
        <div class="balloon__inner">
            左辺中央
        </div>
    </div>
    <div class="balloon balloon--left_bottom">
        <div class="balloon__inner">
            左辺下側
        </div>
    </div>
</div>

内側にdiv要素を作りたくない場合

clip-path使えばできなくもないのですが,ブラウザの対応状況が絶望的なので断念…
何かいい方法あったら教えてください。