影付き吹き出しの作り方を毎回調べている気がするのでメモっておく。
内側にも要素を設ける方法
概要
一番無難な方法です。特に事情が無ければこれを選択してください。
- サイズゼロ要素の
border
を太くする方法だと影つきのものに対応できないので,transform
のrotate()
とskew()
を活用する方法を使います。 -
z-index
を使うことで,前後関係を定義しています。 - ひし形の内側部分がテキストと被らないように,四角形の疑似要素を上から被せています。テキストはさらにその上に来るようにします。
長所
- 位置の微調整をしやすい
- 倍率によらず表示が安定している
- 基本的にアニメーションを併用できる
短所
- HTMLがやや冗長
実装
ブラウザのアドレスバーにコピペして確認
data:text/html;charset=utf-8;base64,PCFET0NUWVBFIGh0bWw+Cgo8bWV0YSBjaGFyc2V0PSJVVEYtOCI+Cjx0aXRsZT5DU1PlvbHku5jjgY3lkLnjgY3lh7rjgZfkvY3nva4xMuODkeOCv+ODvOODszwvdGl0bGU+Cgo8c3R5bGU+CgovKiDooajnpLrnlKggKi8KaHRtbCxib2R5IHsKICBoZWlnaHQ6IDEwMCU7CiAgZGlzcGxheTogZmxleDsKICBmbGV4LWRpcmVjdGlvbjogY29sdW1uOwogIGp1c3RpZnktY29udGVudDogY2VudGVyOwogIGFsaWduLWl0ZW1zOiBjZW50ZXI7Cn0KLnJvdyB7CiAgZGlzcGxheTogZmxleDsKfQoKLyog5ZC544GN5Ye644GX44O75YWo5YWx6YCaICovCi5iYWxsb29uIHsKICBwb3NpdGlvbjogcmVsYXRpdmU7CiAgd2lkdGg6IDIwMHB4OyAvKiDluYUgKi8KICBtaW4taGVpZ2h0OiA2MHB4OyAvKiDmnIDlsI/jga7pq5jjgZUgKi8KICBtYXJnaW46IDIwcHg7IC8qIOWkluWBtOOBruS9meeZvSAqLwogIHBhZGRpbmc6IDEwcHg7IC8qIOWGheWBtOOBruS9meeZvSAqLwp9Ci5iYWxsb29uOjpiZWZvcmUgewogIGNvbnRlbnQ6ICcnOwogIHBvc2l0aW9uOiBhYnNvbHV0ZTsKICB6LWluZGV4OiAxOwogIHdpZHRoOiAyMHB4OyBoZWlnaHQ6IDIwcHg7IC8qIOWQueOBjeWHuuOBl+OCteOCpOOCuiAqLwp9Ci5iYWxsb29uOjphZnRlciB7CiAgY29udGVudDogJyc7CiAgcG9zaXRpb246IGFic29sdXRlOwogIHotaW5kZXg6IDI7CiAgdG9wOiAwOyBsZWZ0OiAwOwogIHdpZHRoOiAxMDAlOyBoZWlnaHQ6IDEwMCU7Cn0KLmJhbGxvb24+KiB7CiAgcG9zaXRpb246IHJlbGF0aXZlOwogIHotaW5kZXg6IDM7Cn0KLmJhbGxvb24sCi5iYWxsb29uOjphZnRlciB7CiAgYm9yZGVyLXJhZGl1czogNXB4OyAvKiDop5Ljga7kuLjjgoHmlrkgKi8KfQouYmFsbG9vbiwKLmJhbGxvb246OmJlZm9yZSB7CiAgYm94LXNoYWRvdzogMCAwIDEwcHggMCByZ2JhKDE2MywxNjMsMTYzLDAuNTApOyAvKiDjgbzjgYvjgZfot53pm6Io56ysM+W8leaVsCnvvIzmi6HmlaPot53pm6Io56ysNOW8leaVsCnvvIzoibIo56ysNeW8leaVsCkgKi8KfQouYmFsbG9vbiwKLmJhbGxvb246OmJlZm9yZSwKLmJhbGxvb246OmFmdGVyIHsKICBiYWNrZ3JvdW5kOiAjZmZmZWQ2OyAvKiDog4zmma/oibIgKi8KfQoKLyog5ZC544GN5Ye644GX44O75LiK6L665bem5YG0ICovCi5iYWxsb29uLS10b3BfbGVmdDo6YmVmb3JlIHsKICB0b3A6IC0xMHB4OyBsZWZ0OiAxMHB4OyAvKiDkvY3nva4gKi8KICB0cmFuc2Zvcm06IHJvdGF0ZSg0NWRlZykgc2tldygyMGRlZywyMGRlZyk7IC8qIOWCvuaWnOinkihza2V3KSAqLwp9Ci8qIOWQueOBjeWHuuOBl+ODu+S4iui+uuS4reWkriAqLwouYmFsbG9vbi0tdG9wX2NlbnRlcjo6YmVmb3JlIHsKICB0b3A6IC0xMHB4OyBsZWZ0OiA1MCU7IC8qIOS9jee9riAqLwogIHRyYW5zZm9ybTogdHJhbnNsYXRlWCgtNTAlKSByb3RhdGUoNDVkZWcpIHNrZXcoMjBkZWcsMjBkZWcpOyAvKiDlgr7mlpzop5Ioc2tldykgKi8KfQovKiDlkLnjgY3lh7rjgZfjg7vkuIrovrrlj7PlgbQgKi8KLmJhbGxvb24tLXRvcF9yaWdodDo6YmVmb3JlIHsKICB0b3A6IC0xMHB4OyByaWdodDogMTBweDsgLyog5L2N572uICovCiAgdHJhbnNmb3JtOiByb3RhdGUoNDVkZWcpIHNrZXcoMjBkZWcsMjBkZWcpOyAvKiDlgr7mlpzop5Ioc2tldykgKi8KfQoKLyog5ZC544GN5Ye644GX44O75Y+z6L665LiK5YG0ICovCi5iYWxsb29uLS1yaWdodF90b3A6OmJlZm9yZSB7CiAgcmlnaHQ6IC0xMHB4OyB0b3A6IDEwcHg7IC8qIOS9jee9riAqLwogIHRyYW5zZm9ybTogcm90YXRlKDQ1ZGVnKSBza2V3KC0yMGRlZywtMjBkZWcpOyAvKiDlgr7mlpzop5Ioc2tldykgKi8KfQovKiDlkLnjgY3lh7rjgZfjg7vlj7PovrrkuK3lpK4gKi8KLmJhbGxvb24tLXJpZ2h0X21pZGRsZTo6YmVmb3JlIHsKICByaWdodDogLTEwcHg7IHRvcDogNTAlOyAvKiDkvY3nva4gKi8KICB0cmFuc2Zvcm06IHRyYW5zbGF0ZVkoLTUwJSkgcm90YXRlKDQ1ZGVnKSBza2V3KC0yMGRlZywtMjBkZWcpOyAvKiDlgr7mlpzop5Ioc2tldykgKi8KfQovKiDlkLnjgY3lh7rjgZfjg7vlj7PovrrkuIvlgbQgKi8KLmJhbGxvb24tLXJpZ2h0X2JvdHRvbTo6YmVmb3JlIHsKICByaWdodDogLTEwcHg7IGJvdHRvbTogMTBweDsgLyog5L2N572uICovCiAgdHJhbnNmb3JtOiByb3RhdGUoNDVkZWcpIHNrZXcoLTIwZGVnLC0yMGRlZyk7IC8qIOWCvuaWnOinkihza2V3KSAqLwp9CgovKiDlkLnjgY3lh7rjgZfjg7vkuIvovrrlt6blgbQgKi8KLmJhbGxvb24tLWJvdHRvbV9sZWZ0OjpiZWZvcmUgewogIGJvdHRvbTogLTEwcHg7IGxlZnQ6IDEwcHg7IC8qIOS9jee9riAqLwogIHRyYW5zZm9ybTogcm90YXRlKDQ1ZGVnKSBza2V3KDIwZGVnLDIwZGVnKTsgLyog5YK+5pac6KeSKHNrZXcpICovCn0KLyog5ZC544GN5Ye644GX44O75LiL6L665Lit5aSuICovCi5iYWxsb29uLS1ib3R0b21fY2VudGVyOjpiZWZvcmUgewogIGJvdHRvbTogLTEwcHg7IGxlZnQ6IDUwJTsgLyog5L2N572uICovCiAgdHJhbnNmb3JtOiB0cmFuc2xhdGVYKC01MCUpIHJvdGF0ZSg0NWRlZykgc2tldygyMGRlZywyMGRlZyk7IC8qIOWCvuaWnOinkihza2V3KSAqLwp9Ci8qIOWQueOBjeWHuuOBl+ODu+S4i+i+uuWPs+WBtCAqLwouYmFsbG9vbi0tYm90dG9tX3JpZ2h0OjpiZWZvcmUgewogIGJvdHRvbTogLTEwcHg7IHJpZ2h0OiAxMHB4OyAvKiDkvY3nva4gKi8KICB0cmFuc2Zvcm06IHJvdGF0ZSg0NWRlZykgc2tldygyMGRlZywyMGRlZyk7IC8qIOWCvuaWnOinkihza2V3KSAqLwp9CgovKiDlkLnjgY3lh7rjgZfjg7vlt6bovrrkuIrlgbQgKi8KLmJhbGxvb24tLWxlZnRfdG9wOjpiZWZvcmUgewogIGxlZnQ6IC0xMHB4OyB0b3A6IDEwcHg7IC8qIOS9jee9riAqLwogIHRyYW5zZm9ybTogcm90YXRlKDQ1ZGVnKSBza2V3KC0yMGRlZywtMjBkZWcpOyAvKiDlgr7mlpzop5Ioc2tldykgKi8KfQovKiDlkLnjgY3lh7rjgZfjg7vlt6bovrrkuK3lpK4gKi8KLmJhbGxvb24tLWxlZnRfbWlkZGxlOjpiZWZvcmUgewogIGxlZnQ6IC0xMHB4OyB0b3A6IDUwJTsgLyog5L2N572uICovCiAgdHJhbnNmb3JtOiB0cmFuc2xhdGVZKC01MCUpIHJvdGF0ZSg0NWRlZykgc2tldygtMjBkZWcsLTIwZGVnKTsgLyog5YK+5pac6KeSKHNrZXcpICovCn0KLyog5ZC544GN5Ye644GX44O75bem6L665LiL5YG0ICovCi5iYWxsb29uLS1sZWZ0X2JvdHRvbTo6YmVmb3JlIHsKICBsZWZ0OiAtMTBweDsgYm90dG9tOiAxMHB4OyAvKiDkvY3nva4gKi8KICB0cmFuc2Zvcm06IHJvdGF0ZSg0NWRlZykgc2tldygtMjBkZWcsLTIwZGVnKTsgLyog5YK+5pac6KeSKHNrZXcpICovCn0KCjwvc3R5bGU+Cgo8ZGl2IGNsYXNzPSJyb3ciPgogIDxkaXYgY2xhc3M9ImJhbGxvb24gYmFsbG9vbi0tdG9wX2xlZnQiPjxkaXY+5LiK6L665bem5YG0PC9kaXY+PC9kaXY+CiAgPGRpdiBjbGFzcz0iYmFsbG9vbiBiYWxsb29uLS10b3BfY2VudGVyIj48ZGl2PuS4iui+uuS4reWkrjwvZGl2PjwvZGl2PgogIDxkaXYgY2xhc3M9ImJhbGxvb24gYmFsbG9vbi0tdG9wX3JpZ2h0Ij48ZGl2PuS4iui+uuWPs+WBtDwvZGl2PjwvZGl2Pgo8L2Rpdj4KCjxkaXYgY2xhc3M9InJvdyI+CiAgPGRpdiBjbGFzcz0iYmFsbG9vbiBiYWxsb29uLS1yaWdodF90b3AiPjxkaXY+5Y+z6L665LiK5YG0PC9kaXY+PC9kaXY+CiAgPGRpdiBjbGFzcz0iYmFsbG9vbiBiYWxsb29uLS1yaWdodF9taWRkbGUiPjxkaXY+5Y+z6L665Lit5aSuPC9kaXY+PC9kaXY+CiAgPGRpdiBjbGFzcz0iYmFsbG9vbiBiYWxsb29uLS1yaWdodF9ib3R0b20iPjxkaXY+5Y+z6L665LiL5YG0PC9kaXY+PC9kaXY+CjwvZGl2PgoKPGRpdiBjbGFzcz0icm93Ij4KICA8ZGl2IGNsYXNzPSJiYWxsb29uIGJhbGxvb24tLWJvdHRvbV9sZWZ0Ij48ZGl2PuS4i+i+uuW3puWBtDwvZGl2PjwvZGl2PgogIDxkaXYgY2xhc3M9ImJhbGxvb24gYmFsbG9vbi0tYm90dG9tX2NlbnRlciI+PGRpdj7kuIvovrrkuK3lpK48L2Rpdj48L2Rpdj4KICA8ZGl2IGNsYXNzPSJiYWxsb29uIGJhbGxvb24tLWJvdHRvbV9yaWdodCI+PGRpdj7kuIvovrrlj7PlgbQ8L2Rpdj48L2Rpdj4KPC9kaXY+Cgo8ZGl2IGNsYXNzPSJyb3ciPgogIDxkaXYgY2xhc3M9ImJhbGxvb24gYmFsbG9vbi0tbGVmdF90b3AiPjxkaXY+5bem6L665LiK5YG0PC9kaXY+PC9kaXY+CiAgPGRpdiBjbGFzcz0iYmFsbG9vbiBiYWxsb29uLS1sZWZ0X21pZGRsZSI+PGRpdj7lt6bovrrkuK3lpK48L2Rpdj48L2Rpdj4KICA8ZGl2IGNsYXNzPSJiYWxsb29uIGJhbGxvb24tLWxlZnRfYm90dG9tIj48ZGl2PuW3pui+uuS4i+WBtDwvZGl2PjwvZGl2Pgo8L2Rpdj4
ソースコード
<!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;
width: 200px; /* 幅 */
min-height: 60px; /* 最小の高さ */
margin: 20px; /* 外側の余白 */
padding: 10px; /* 内側の余白 */
}
.balloon::before {
content: '';
position: absolute;
z-index: 1;
width: 20px; height: 20px; /* 吹き出しサイズ */
}
.balloon::after {
content: '';
position: absolute;
z-index: 2;
top: 0; left: 0;
width: 100%; height: 100%;
}
.balloon>* {
position: relative;
z-index: 3;
}
.balloon,
.balloon::after {
border-radius: 5px; /* 角の丸め方 */
}
.balloon,
.balloon::before {
box-shadow: 0 0 10px 0 rgba(163,163,163,0.50); /* ぼかし距離(第3引数),拡散距離(第4引数),色(第5引数) */
}
.balloon,
.balloon::before,
.balloon::after {
background: #fffed6; /* 背景色 */
}
/* 吹き出し・上辺左側 */
.balloon--top_left::before {
top: -10px; left: 10px; /* 位置 */
transform: rotate(45deg) skew(20deg,20deg); /* 傾斜角(skew) */
}
/* 吹き出し・上辺中央 */
.balloon--top_center::before {
top: -10px; left: 50%; /* 位置 */
transform: translateX(-50%) rotate(45deg) skew(20deg,20deg); /* 傾斜角(skew) */
}
/* 吹き出し・上辺右側 */
.balloon--top_right::before {
top: -10px; right: 10px; /* 位置 */
transform: rotate(45deg) skew(20deg,20deg); /* 傾斜角(skew) */
}
/* 吹き出し・右辺上側 */
.balloon--right_top::before {
right: -10px; top: 10px; /* 位置 */
transform: rotate(45deg) skew(-20deg,-20deg); /* 傾斜角(skew) */
}
/* 吹き出し・右辺中央 */
.balloon--right_middle::before {
right: -10px; top: 50%; /* 位置 */
transform: translateY(-50%) rotate(45deg) skew(-20deg,-20deg); /* 傾斜角(skew) */
}
/* 吹き出し・右辺下側 */
.balloon--right_bottom::before {
right: -10px; bottom: 10px; /* 位置 */
transform: rotate(45deg) skew(-20deg,-20deg); /* 傾斜角(skew) */
}
/* 吹き出し・下辺左側 */
.balloon--bottom_left::before {
bottom: -10px; left: 10px; /* 位置 */
transform: rotate(45deg) skew(20deg,20deg); /* 傾斜角(skew) */
}
/* 吹き出し・下辺中央 */
.balloon--bottom_center::before {
bottom: -10px; left: 50%; /* 位置 */
transform: translateX(-50%) rotate(45deg) skew(20deg,20deg); /* 傾斜角(skew) */
}
/* 吹き出し・下辺右側 */
.balloon--bottom_right::before {
bottom: -10px; right: 10px; /* 位置 */
transform: rotate(45deg) skew(20deg,20deg); /* 傾斜角(skew) */
}
/* 吹き出し・左辺上側 */
.balloon--left_top::before {
left: -10px; top: 10px; /* 位置 */
transform: rotate(45deg) skew(-20deg,-20deg); /* 傾斜角(skew) */
}
/* 吹き出し・左辺中央 */
.balloon--left_middle::before {
left: -10px; top: 50%; /* 位置 */
transform: translateY(-50%) rotate(45deg) skew(-20deg,-20deg); /* 傾斜角(skew) */
}
/* 吹き出し・左辺下側 */
.balloon--left_bottom::before {
left: -10px; bottom: 10px; /* 位置 */
transform: rotate(45deg) skew(-20deg,-20deg); /* 傾斜角(skew) */
}
</style>
<div class="row">
<div class="balloon balloon--top_left"><div>上辺左側</div></div>
<div class="balloon balloon--top_center"><div>上辺中央</div></div>
<div class="balloon balloon--top_right"><div>上辺右側</div></div>
</div>
<div class="row">
<div class="balloon balloon--right_top"><div>右辺上側</div></div>
<div class="balloon balloon--right_middle"><div>右辺中央</div></div>
<div class="balloon balloon--right_bottom"><div>右辺下側</div></div>
</div>
<div class="row">
<div class="balloon balloon--bottom_left"><div>下辺左側</div></div>
<div class="balloon balloon--bottom_center"><div>下辺中央</div></div>
<div class="balloon balloon--bottom_right"><div>下辺右側</div></div>
</div>
<div class="row">
<div class="balloon balloon--left_top"><div>左辺上側</div></div>
<div class="balloon balloon--left_middle"><div>左辺中央</div></div>
<div class="balloon balloon--left_bottom"><div>左辺下側</div></div>
</div>
div
要素1個だけで作る方法
概要
CSS職人の @junya さんにご紹介していただいた方法です。アニメーションを使わない,静的な表示しか行わないという前提なら,これを選択してもいいかもしれません。
-
translateZ
を使うことで,前後関係を定義しています。 - ひし形の内側部分がテキストと被らないように,グラデーションで透明色にして,実質的な三角形を描画しています。
長所
- HTMLが美しい
短所
- Webkitの仕様(?)で,表示倍率によっては分断する線が見えてしまう
- IE10+以外ではアニメーションを併用した実装が内容によっては不可能になる
実装
ブラウザのアドレスバーにコピペして確認
data:text/html;charset=utf-8;base64,PCFET0NUWVBFIGh0bWw+Cgo8bWV0YSBjaGFyc2V0PSJVVEYtOCI+Cjx0aXRsZT5DU1PlvbHku5jjgY3lkLnjgY3lh7rjgZfkvY3nva4xMuODkeOCv+ODvOODszwvdGl0bGU+Cgo8c3R5bGU+CgovKiDooajnpLrnlKggKi8KaHRtbCxib2R5IHsKICBoZWlnaHQ6IDEwMCU7CiAgZGlzcGxheTogZmxleDsKICBmbGV4LWRpcmVjdGlvbjogY29sdW1uOwogIGp1c3RpZnktY29udGVudDogY2VudGVyOwogIGFsaWduLWl0ZW1zOiBjZW50ZXI7Cn0KLnJvdyB7CiAgZGlzcGxheTogZmxleDsKfQoKLyog5ZC544GN5Ye644GX44O75YWo5YWx6YCaICovCi5iYWxsb29uIHsKICBwb3NpdGlvbjogcmVsYXRpdmU7CiAgdHJhbnNmb3JtLXN0eWxlOiBwcmVzZXJ2ZS0zZDsKICB3aWR0aDogMjAwcHg7IC8qIOW5hSAqLwogIG1pbi1oZWlnaHQ6IDYwcHg7IC8qIOacgOWwj+OBrumrmOOBlSAqLwogIG1hcmdpbjogMjBweDsgLyog5aSW5YG044Gu5L2Z55m9ICovCiAgcGFkZGluZzogMTBweDsgLyog5YaF5YG044Gu5L2Z55m9ICovCiAgYm9yZGVyLXJhZGl1czogNXB4OyAvKiDop5Ljga7kuLjjgoHmlrnjgIAqLwp9Ci5iYWxsb29uOjpiZWZvcmUsCi5iYWxsb29uOjphZnRlciB7CiAgY29udGVudDogJyc7CiAgcG9zaXRpb246IGFic29sdXRlOwogIHdpZHRoOiAyMHB4OyBoZWlnaHQ6IDIwcHg7IC8qIOWQueOBjeWHuuOBl+OCteOCpOOCuiAqLyAKfQouYmFsbG9vbiwKLmJhbGxvb246OmJlZm9yZSB7CiAgYmFja2dyb3VuZDogI2ZmZmVkNjsgLyog6IOM5pmv6Imy77yIbGluZWFyLWdyYWRpZW5044KC44GT44Gu6Imy44Go57Wx5LiA44GZ44KL5b+F6KaB44GM44GC44KL77yJKi8KICBib3gtc2hhZG93OiAwIDAgMTBweCAwIHJnYmEoMTYzLDE2MywxNjMsMC41MCk7IC8qIOOBvOOBi+OBl+i3nemboijnrKwz5byV5pWwKe+8jOaLoeaVo+i3nemboijnrKw05byV5pWwKe+8jOiJsijnrKw15byV5pWwKSAqLwp9CgovKiDlkLnjgY3lh7rjgZfjg7vkuIrovrrlhbHpgJogKi8KLmJhbGxvb24tLXRvcF9sZWZ0OjphZnRlciwKLmJhbGxvb24tLXRvcF9jZW50ZXI6OmFmdGVyLAouYmFsbG9vbi0tdG9wX3JpZ2h0OjphZnRlciB7CiAgYmFja2dyb3VuZDogbGluZWFyLWdyYWRpZW50KDEzNWRlZywgI2ZmZmVkNiA1MSUsIHRyYW5zcGFyZW50IDUxJSk7IC8qIOesrDLlvJXmlbDjgatiYWNrZ3JvdW5k44Go5YWx6YCa44Gu6IOM5pmv6Imy44KS5oyH5a6aICovCn0KLyog5ZC544GN5Ye644GX44O75Y+z6L665YWx6YCaICovCi5iYWxsb29uLS1yaWdodF90b3A6OmFmdGVyLAouYmFsbG9vbi0tcmlnaHRfbWlkZGxlOjphZnRlciwKLmJhbGxvb24tLXJpZ2h0X2JvdHRvbTo6YWZ0ZXIgewogIGJhY2tncm91bmQ6IGxpbmVhci1ncmFkaWVudCgtMTM1ZGVnLCAjZmZmZWQ2IDUxJSwgdHJhbnNwYXJlbnQgNTElKTsgLyog56ysMuW8leaVsOOBq2JhY2tncm91bmTjgajlhbHpgJrjga7og4zmma/oibLjgpLmjIflrpogKi8KfQovKiDlkLnjgY3lh7rjgZfjg7vkuIvovrrlhbHpgJogKi8KLmJhbGxvb24tLWJvdHRvbV9sZWZ0OjphZnRlciwKLmJhbGxvb24tLWJvdHRvbV9jZW50ZXI6OmFmdGVyLAouYmFsbG9vbi0tYm90dG9tX3JpZ2h0OjphZnRlciB7CiAgYmFja2dyb3VuZDogbGluZWFyLWdyYWRpZW50KC00NWRlZywgI2ZmZmVkNiA1MSUsIHRyYW5zcGFyZW50IDUxJSk7IC8qIOesrDLlvJXmlbDjgatiYWNrZ3JvdW5k44Go5YWx6YCa44Gu6IOM5pmv6Imy44KS5oyH5a6aICovCn0KLyog5ZC544GN5Ye644GX44O75bem6L665YWx6YCaICovCi5iYWxsb29uLS1sZWZ0X3RvcDo6YWZ0ZXIsCi5iYWxsb29uLS1sZWZ0X21pZGRsZTo6YWZ0ZXIsCi5iYWxsb29uLS1sZWZ0X2JvdHRvbTo6YWZ0ZXIgewogIGJhY2tncm91bmQ6IGxpbmVhci1ncmFkaWVudCg0NWRlZywgI2ZmZmVkNiA1MSUsIHRyYW5zcGFyZW50IDUxJSk7IC8qIOesrDLlvJXmlbDjgatiYWNrZ3JvdW5k44Go5YWx6YCa44Gu6IOM5pmv6Imy44KS5oyH5a6aICovCn0KCi8qIOWQueOBjeWHuuOBl+ODu+S4iui+uuW3puWBtCAqLwouYmFsbG9vbi0tdG9wX2xlZnQ6OmJlZm9yZSwuYmFsbG9vbi0tdG9wX2xlZnQ6OmFmdGVyIHsKICB0b3A6IC0xMHB4OyBsZWZ0OiAxMHB4OyAvKiDkvY3nva4gKi8KICB0cmFuc2Zvcm06IHJvdGF0ZSg0NWRlZykgc2tldygyMGRlZywyMGRlZykgdHJhbnNsYXRlWigtMXB4KTsgLyog5YK+5pac6KeSKHNrZXcpICovCn0KLmJhbGxvb24tLXRvcF9sZWZ0OjphZnRlciB7CiAgdHJhbnNmb3JtOiByb3RhdGUoNDVkZWcpIHNrZXcoMjBkZWcsMjBkZWcpIHRyYW5zbGF0ZVooMXB4KTsgLyog5YK+5pac6KeSKHNrZXcpICovCn0KCi8qIOWQueOBjeWHuuOBl+ODu+S4iui+uuS4reWkriAqLwouYmFsbG9vbi0tdG9wX2NlbnRlcjo6YmVmb3JlLC5iYWxsb29uLS10b3BfY2VudGVyOjphZnRlciB7CiAgdG9wOiAtMTBweDsgbGVmdDogNTAlOyAvKiDkvY3nva4gKi8KICB0cmFuc2Zvcm06IHRyYW5zbGF0ZVgoLTUwJSkgcm90YXRlKDQ1ZGVnKSBza2V3KDIwZGVnLDIwZGVnKSB0cmFuc2xhdGVaKC0xcHgpOyAvKiDlgr7mlpzop5Ioc2tldykgKi8KfQouYmFsbG9vbi0tdG9wX2NlbnRlcjo6YWZ0ZXIgewogIHRyYW5zZm9ybTogdHJhbnNsYXRlWCgtNTAlKSByb3RhdGUoNDVkZWcpIHNrZXcoMjBkZWcsMjBkZWcpIHRyYW5zbGF0ZVooMXB4KTsgLyog5YK+5pac6KeSKHNrZXcpICovCn0KCi8qIOWQueOBjeWHuuOBl+ODu+S4iui+uuWPs+WBtCAqLwouYmFsbG9vbi0tdG9wX3JpZ2h0OjpiZWZvcmUsLmJhbGxvb24tLXRvcF9yaWdodDo6YWZ0ZXIgewogIHRvcDogLTEwcHg7IHJpZ2h0OiAxMHB4OyAvKiDkvY3nva4gKi8KICB0cmFuc2Zvcm06IHJvdGF0ZSg0NWRlZykgc2tldygyMGRlZywyMGRlZykgdHJhbnNsYXRlWigtMXB4KTsgLyog5YK+5pac6KeSKHNrZXcpICovCn0KLmJhbGxvb24tLXRvcF9yaWdodDo6YWZ0ZXIgewogIHRyYW5zZm9ybTogcm90YXRlKDQ1ZGVnKSBza2V3KDIwZGVnLDIwZGVnKSB0cmFuc2xhdGVaKDFweCk7IC8qIOWCvuaWnOinkihza2V3KSAqLwp9CgovKiDlkLnjgY3lh7rjgZfjg7vlj7PovrrkuIrlgbQgKi8KLmJhbGxvb24tLXJpZ2h0X3RvcDo6YmVmb3JlLC5iYWxsb29uLS1yaWdodF90b3A6OmFmdGVyIHsKICByaWdodDogLTEwcHg7IHRvcDogMTBweDsgLyog5L2N572uICovCiAgdHJhbnNmb3JtOiByb3RhdGUoNDVkZWcpIHNrZXcoLTIwZGVnLC0yMGRlZykgdHJhbnNsYXRlWigtMXB4KTsgLyog5YK+5pac6KeSKHNrZXcpICovCn0KLmJhbGxvb24tLXJpZ2h0X3RvcDo6YWZ0ZXIgewogIHRyYW5zZm9ybTogcm90YXRlKDQ1ZGVnKSBza2V3KC0yMGRlZywtMjBkZWcpIHRyYW5zbGF0ZVooMXB4KTsgLyog5YK+5pac6KeSKHNrZXcpICovCn0KCi8qIOWQueOBjeWHuuOBl+ODu+WPs+i+uuS4reWkriAqLwouYmFsbG9vbi0tcmlnaHRfbWlkZGxlOjpiZWZvcmUsLmJhbGxvb24tLXJpZ2h0X21pZGRsZTo6YWZ0ZXIgewogIHJpZ2h0OiAtMTBweDsgdG9wOiA1MCU7IC8qIOS9jee9riAqLwogIHRyYW5zZm9ybTogdHJhbnNsYXRlWSgtNTAlKSByb3RhdGUoNDVkZWcpIHNrZXcoLTIwZGVnLC0yMGRlZykgdHJhbnNsYXRlWigtMXB4KTsgLyog5YK+5pac6KeSKHNrZXcpICovCn0KLmJhbGxvb24tLXJpZ2h0X21pZGRsZTo6YWZ0ZXIgewogIHRyYW5zZm9ybTogdHJhbnNsYXRlWSgtNTAlKSByb3RhdGUoNDVkZWcpIHNrZXcoLTIwZGVnLC0yMGRlZykgdHJhbnNsYXRlWigxcHgpOyAvKiDlgr7mlpzop5Ioc2tldykgKi8KfQoKLyog5ZC544GN5Ye644GX44O75Y+z6L665LiL5YG0ICovCi5iYWxsb29uLS1yaWdodF9ib3R0b206OmJlZm9yZSwuYmFsbG9vbi0tcmlnaHRfYm90dG9tOjphZnRlciB7CiAgcmlnaHQ6IC0xMHB4OyBib3R0b206IDEwcHg7IC8qIOS9jee9riAqLwogIHRyYW5zZm9ybTogcm90YXRlKDQ1ZGVnKSBza2V3KC0yMGRlZywtMjBkZWcpIHRyYW5zbGF0ZVooLTFweCk7IC8qIOWCvuaWnOinkihza2V3KSAqLwp9Ci5iYWxsb29uLS1yaWdodF9ib3R0b206OmFmdGVyIHsKICB0cmFuc2Zvcm06IHJvdGF0ZSg0NWRlZykgc2tldygtMjBkZWcsLTIwZGVnKSB0cmFuc2xhdGVaKDFweCk7IC8qIOWCvuaWnOinkihza2V3KSAqLwp9CgovKiDlkLnjgY3lh7rjgZfjg7vkuIvovrrlt6blgbQgKi8KLmJhbGxvb24tLWJvdHRvbV9sZWZ0OjpiZWZvcmUsLmJhbGxvb24tLWJvdHRvbV9sZWZ0OjphZnRlciB7CiAgYm90dG9tOiAtMTBweDsgbGVmdDogMTBweDsgLyog5L2N572uICovCiAgdHJhbnNmb3JtOiByb3RhdGUoNDVkZWcpIHNrZXcoMjBkZWcsMjBkZWcpIHRyYW5zbGF0ZVooLTFweCk7IC8qIOWCvuaWnOinkihza2V3KSAqLwp9Ci5iYWxsb29uLS1ib3R0b21fbGVmdDo6YWZ0ZXIgewogIHRyYW5zZm9ybTogcm90YXRlKDQ1ZGVnKSBza2V3KDIwZGVnLDIwZGVnKSB0cmFuc2xhdGVaKDFweCk7IC8qIOWCvuaWnOinkihza2V3KSAqLwp9CgovKiDlkLnjgY3lh7rjgZfjg7vkuIvovrrkuK3lpK4gKi8KLmJhbGxvb24tLWJvdHRvbV9jZW50ZXI6OmJlZm9yZSwuYmFsbG9vbi0tYm90dG9tX2NlbnRlcjo6YWZ0ZXIgewogIGJvdHRvbTogLTEwcHg7IGxlZnQ6IDUwJTsgLyog5L2N572uICovCiAgdHJhbnNmb3JtOiB0cmFuc2xhdGVYKC01MCUpIHJvdGF0ZSg0NWRlZykgc2tldygyMGRlZywyMGRlZykgdHJhbnNsYXRlWigtMXB4KTsgLyog5YK+5pac6KeSKHNrZXcpICovCn0KLmJhbGxvb24tLWJvdHRvbV9jZW50ZXI6OmFmdGVyIHsKICB0cmFuc2Zvcm06IHRyYW5zbGF0ZVgoLTUwJSkgcm90YXRlKDQ1ZGVnKSBza2V3KDIwZGVnLDIwZGVnKSB0cmFuc2xhdGVaKDFweCk7IC8qIOWCvuaWnOinkihza2V3KSAqLwp9CgovKiDlkLnjgY3lh7rjgZfjg7vkuIvovrrlj7PlgbQgKi8KLmJhbGxvb24tLWJvdHRvbV9yaWdodDo6YmVmb3JlLC5iYWxsb29uLS1ib3R0b21fcmlnaHQ6OmFmdGVyIHsKICBib3R0b206IC0xMHB4OyByaWdodDogMTBweDsgLyog5L2N572uICovCiAgdHJhbnNmb3JtOiByb3RhdGUoNDVkZWcpIHNrZXcoMjBkZWcsMjBkZWcpIHRyYW5zbGF0ZVooLTFweCk7IC8qIOWCvuaWnOinkihza2V3KSAqLwp9Ci5iYWxsb29uLS1ib3R0b21fcmlnaHQ6OmFmdGVyIHsKICB0cmFuc2Zvcm06IHJvdGF0ZSg0NWRlZykgc2tldygyMGRlZywyMGRlZykgdHJhbnNsYXRlWigxcHgpOyAvKiDlgr7mlpzop5Ioc2tldykgKi8KfQoKLyog5ZC544GN5Ye644GX44O75bem6L665LiK5YG0ICovCi5iYWxsb29uLS1sZWZ0X3RvcDo6YmVmb3JlLC5iYWxsb29uLS1sZWZ0X3RvcDo6YWZ0ZXIgewogIGxlZnQ6IC0xMHB4OyB0b3A6IDEwcHg7IC8qIOS9jee9riAqLwogIHRyYW5zZm9ybTogcm90YXRlKDQ1ZGVnKSBza2V3KC0yMGRlZywtMjBkZWcpIHRyYW5zbGF0ZVooLTFweCk7IC8qIOWCvuaWnOinkihza2V3KSAqLwp9Ci5iYWxsb29uLS1sZWZ0X3RvcDo6YWZ0ZXIgewogIHRyYW5zZm9ybTogcm90YXRlKDQ1ZGVnKSBza2V3KC0yMGRlZywtMjBkZWcpIHRyYW5zbGF0ZVooMXB4KTsgLyog5YK+5pac6KeSKHNrZXcpICovCn0KCi8qIOWQueOBjeWHuuOBl+ODu+W3pui+uuS4reWkriAqLwouYmFsbG9vbi0tbGVmdF9taWRkbGU6OmJlZm9yZSwuYmFsbG9vbi0tbGVmdF9taWRkbGU6OmFmdGVyIHsKICBsZWZ0OiAtMTBweDsgdG9wOiA1MCU7IC8qIOS9jee9riAqLwogIHRyYW5zZm9ybTogdHJhbnNsYXRlWSgtNTAlKSByb3RhdGUoNDVkZWcpIHNrZXcoLTIwZGVnLC0yMGRlZykgdHJhbnNsYXRlWigtMXB4KTsgLyog5YK+5pac6KeSKHNrZXcpICovCn0KLmJhbGxvb24tLWxlZnRfbWlkZGxlOjphZnRlciB7CiAgdHJhbnNmb3JtOiB0cmFuc2xhdGVZKC01MCUpIHJvdGF0ZSg0NWRlZykgc2tldygtMjBkZWcsLTIwZGVnKSB0cmFuc2xhdGVaKDFweCk7IC8qIOWCvuaWnOinkihza2V3KSAqLwp9CgovKiDlkLnjgY3lh7rjgZfjg7vlt6bovrrkuIvlgbQgKi8KLmJhbGxvb24tLWxlZnRfYm90dG9tOjpiZWZvcmUsLmJhbGxvb24tLWxlZnRfYm90dG9tOjphZnRlciB7CiAgbGVmdDogLTEwcHg7IGJvdHRvbTogMTBweDsgLyog5L2N572uICovCiAgdHJhbnNmb3JtOiByb3RhdGUoNDVkZWcpIHNrZXcoLTIwZGVnLC0yMGRlZykgdHJhbnNsYXRlWigtMXB4KTsgLyog5YK+5pac6KeSKHNrZXcpICovCn0KLmJhbGxvb24tLWxlZnRfYm90dG9tOjphZnRlciB7CiAgdHJhbnNmb3JtOiByb3RhdGUoNDVkZWcpIHNrZXcoLTIwZGVnLC0yMGRlZykgdHJhbnNsYXRlWigxcHgpOyAvKiDlgr7mlpzop5Ioc2tldykgKi8KfQoKPC9zdHlsZT4KCjxkaXYgY2xhc3M9InJvdyI+CiAgPGRpdiBjbGFzcz0iYmFsbG9vbiBiYWxsb29uLS10b3BfbGVmdCI+5LiK6L665bem5YG0PC9kaXY+CiAgPGRpdiBjbGFzcz0iYmFsbG9vbiBiYWxsb29uLS10b3BfY2VudGVyIj7kuIrovrrkuK3lpK48L2Rpdj4KICA8ZGl2IGNsYXNzPSJiYWxsb29uIGJhbGxvb24tLXRvcF9yaWdodCI+5LiK6L665Y+z5YG0PC9kaXY+CjwvZGl2PgoKPGRpdiBjbGFzcz0icm93Ij4KICA8ZGl2IGNsYXNzPSJiYWxsb29uIGJhbGxvb24tLXJpZ2h0X3RvcCI+5Y+z6L665LiK5YG0PC9kaXY+CiAgPGRpdiBjbGFzcz0iYmFsbG9vbiBiYWxsb29uLS1yaWdodF9taWRkbGUiPuWPs+i+uuS4reWkrjwvZGl2PgogIDxkaXYgY2xhc3M9ImJhbGxvb24gYmFsbG9vbi0tcmlnaHRfYm90dG9tIj7lj7PovrrkuIvlgbQ8L2Rpdj4KPC9kaXY+Cgo8ZGl2IGNsYXNzPSJyb3ciPgogIDxkaXYgY2xhc3M9ImJhbGxvb24gYmFsbG9vbi0tYm90dG9tX2xlZnQiPuS4i+i+uuW3puWBtDwvZGl2PgogIDxkaXYgY2xhc3M9ImJhbGxvb24gYmFsbG9vbi0tYm90dG9tX2NlbnRlciI+5LiL6L665Lit5aSuPC9kaXY+CiAgPGRpdiBjbGFzcz0iYmFsbG9vbiBiYWxsb29uLS1ib3R0b21fcmlnaHQiPuS4i+i+uuWPs+WBtDwvZGl2Pgo8L2Rpdj4KCjxkaXYgY2xhc3M9InJvdyI+CiAgPGRpdiBjbGFzcz0iYmFsbG9vbiBiYWxsb29uLS1sZWZ0X3RvcCI+5bem6L665LiK5YG0PC9kaXY+CiAgPGRpdiBjbGFzcz0iYmFsbG9vbiBiYWxsb29uLS1sZWZ0X21pZGRsZSI+5bem6L665Lit5aSuPC9kaXY+CiAgPGRpdiBjbGFzcz0iYmFsbG9vbiBiYWxsb29uLS1sZWZ0X2JvdHRvbSI+5bem6L665LiL5YG0PC9kaXY+CjwvZGl2Pg
ソースコード
<!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;
transform-style: preserve-3d;
width: 200px; /* 幅 */
min-height: 60px; /* 最小の高さ */
margin: 20px; /* 外側の余白 */
padding: 10px; /* 内側の余白 */
border-radius: 5px; /* 角の丸め方 */
}
.balloon::before,
.balloon::after {
content: '';
position: absolute;
width: 20px; height: 20px; /* 吹き出しサイズ */
}
.balloon,
.balloon::before {
background: #fffed6; /* 背景色(linear-gradientもこの色と統一する必要がある)*/
box-shadow: 0 0 10px 0 rgba(163,163,163,0.50); /* ぼかし距離(第3引数),拡散距離(第4引数),色(第5引数) */
}
/* 吹き出し・上辺共通 */
.balloon--top_left::after,
.balloon--top_center::after,
.balloon--top_right::after {
background: linear-gradient(135deg, #fffed6 51%, transparent 51%); /* 第2引数にbackgroundと共通の背景色を指定 */
}
/* 吹き出し・右辺共通 */
.balloon--right_top::after,
.balloon--right_middle::after,
.balloon--right_bottom::after {
background: linear-gradient(-135deg, #fffed6 51%, transparent 51%); /* 第2引数にbackgroundと共通の背景色を指定 */
}
/* 吹き出し・下辺共通 */
.balloon--bottom_left::after,
.balloon--bottom_center::after,
.balloon--bottom_right::after {
background: linear-gradient(-45deg, #fffed6 51%, transparent 51%); /* 第2引数にbackgroundと共通の背景色を指定 */
}
/* 吹き出し・左辺共通 */
.balloon--left_top::after,
.balloon--left_middle::after,
.balloon--left_bottom::after {
background: linear-gradient(45deg, #fffed6 51%, transparent 51%); /* 第2引数にbackgroundと共通の背景色を指定 */
}
/* 吹き出し・上辺左側 */
.balloon--top_left::before,.balloon--top_left::after {
top: -10px; left: 10px; /* 位置 */
transform: rotate(45deg) skew(20deg,20deg) translateZ(-1px); /* 傾斜角(skew) */
}
.balloon--top_left::after {
transform: rotate(45deg) skew(20deg,20deg) translateZ(1px); /* 傾斜角(skew) */
}
/* 吹き出し・上辺中央 */
.balloon--top_center::before,.balloon--top_center::after {
top: -10px; left: 50%; /* 位置 */
transform: translateX(-50%) rotate(45deg) skew(20deg,20deg) translateZ(-1px); /* 傾斜角(skew) */
}
.balloon--top_center::after {
transform: translateX(-50%) rotate(45deg) skew(20deg,20deg) translateZ(1px); /* 傾斜角(skew) */
}
/* 吹き出し・上辺右側 */
.balloon--top_right::before,.balloon--top_right::after {
top: -10px; right: 10px; /* 位置 */
transform: rotate(45deg) skew(20deg,20deg) translateZ(-1px); /* 傾斜角(skew) */
}
.balloon--top_right::after {
transform: rotate(45deg) skew(20deg,20deg) translateZ(1px); /* 傾斜角(skew) */
}
/* 吹き出し・右辺上側 */
.balloon--right_top::before,.balloon--right_top::after {
right: -10px; top: 10px; /* 位置 */
transform: rotate(45deg) skew(-20deg,-20deg) translateZ(-1px); /* 傾斜角(skew) */
}
.balloon--right_top::after {
transform: rotate(45deg) skew(-20deg,-20deg) translateZ(1px); /* 傾斜角(skew) */
}
/* 吹き出し・右辺中央 */
.balloon--right_middle::before,.balloon--right_middle::after {
right: -10px; top: 50%; /* 位置 */
transform: translateY(-50%) rotate(45deg) skew(-20deg,-20deg) translateZ(-1px); /* 傾斜角(skew) */
}
.balloon--right_middle::after {
transform: translateY(-50%) rotate(45deg) skew(-20deg,-20deg) translateZ(1px); /* 傾斜角(skew) */
}
/* 吹き出し・右辺下側 */
.balloon--right_bottom::before,.balloon--right_bottom::after {
right: -10px; bottom: 10px; /* 位置 */
transform: rotate(45deg) skew(-20deg,-20deg) translateZ(-1px); /* 傾斜角(skew) */
}
.balloon--right_bottom::after {
transform: rotate(45deg) skew(-20deg,-20deg) translateZ(1px); /* 傾斜角(skew) */
}
/* 吹き出し・下辺左側 */
.balloon--bottom_left::before,.balloon--bottom_left::after {
bottom: -10px; left: 10px; /* 位置 */
transform: rotate(45deg) skew(20deg,20deg) translateZ(-1px); /* 傾斜角(skew) */
}
.balloon--bottom_left::after {
transform: rotate(45deg) skew(20deg,20deg) translateZ(1px); /* 傾斜角(skew) */
}
/* 吹き出し・下辺中央 */
.balloon--bottom_center::before,.balloon--bottom_center::after {
bottom: -10px; left: 50%; /* 位置 */
transform: translateX(-50%) rotate(45deg) skew(20deg,20deg) translateZ(-1px); /* 傾斜角(skew) */
}
.balloon--bottom_center::after {
transform: translateX(-50%) rotate(45deg) skew(20deg,20deg) translateZ(1px); /* 傾斜角(skew) */
}
/* 吹き出し・下辺右側 */
.balloon--bottom_right::before,.balloon--bottom_right::after {
bottom: -10px; right: 10px; /* 位置 */
transform: rotate(45deg) skew(20deg,20deg) translateZ(-1px); /* 傾斜角(skew) */
}
.balloon--bottom_right::after {
transform: rotate(45deg) skew(20deg,20deg) translateZ(1px); /* 傾斜角(skew) */
}
/* 吹き出し・左辺上側 */
.balloon--left_top::before,.balloon--left_top::after {
left: -10px; top: 10px; /* 位置 */
transform: rotate(45deg) skew(-20deg,-20deg) translateZ(-1px); /* 傾斜角(skew) */
}
.balloon--left_top::after {
transform: rotate(45deg) skew(-20deg,-20deg) translateZ(1px); /* 傾斜角(skew) */
}
/* 吹き出し・左辺中央 */
.balloon--left_middle::before,.balloon--left_middle::after {
left: -10px; top: 50%; /* 位置 */
transform: translateY(-50%) rotate(45deg) skew(-20deg,-20deg) translateZ(-1px); /* 傾斜角(skew) */
}
.balloon--left_middle::after {
transform: translateY(-50%) rotate(45deg) skew(-20deg,-20deg) translateZ(1px); /* 傾斜角(skew) */
}
/* 吹き出し・左辺下側 */
.balloon--left_bottom::before,.balloon--left_bottom::after {
left: -10px; bottom: 10px; /* 位置 */
transform: rotate(45deg) skew(-20deg,-20deg) translateZ(-1px); /* 傾斜角(skew) */
}
.balloon--left_bottom::after {
transform: rotate(45deg) skew(-20deg,-20deg) translateZ(1px); /* 傾斜角(skew) */
}
</style>
<div class="row">
<div class="balloon balloon--top_left">上辺左側</div>
<div class="balloon balloon--top_center">上辺中央</div>
<div class="balloon balloon--top_right">上辺右側</div>
</div>
<div class="row">
<div class="balloon balloon--right_top">右辺上側</div>
<div class="balloon balloon--right_middle">右辺中央</div>
<div class="balloon balloon--right_bottom">右辺下側</div>
</div>
<div class="row">
<div class="balloon balloon--bottom_left">下辺左側</div>
<div class="balloon balloon--bottom_center">下辺中央</div>
<div class="balloon balloon--bottom_right">下辺右側</div>
</div>
<div class="row">
<div class="balloon balloon--left_top">左辺上側</div>
<div class="balloon balloon--left_middle">左辺中央</div>
<div class="balloon balloon--left_bottom">左辺下側</div>
</div>
番外編: 吹き出し部分を「▲」の文字で表現する
高度な微調整が必要であり,傾斜角も固定なので実用性は薄めですが,
- どうしても
<div>
1個で実現したい - どうしても
opacity
を変化させるアニメーションを使いたい
という縛りつきで @junya さんによって生み出されたトリッキーな方法です。
(コメント欄参照)