CSS Comic Book Style Speech Bubble
Tags: webdev, css, programming, tutorial
Published: 2023-10-05 05:08:58

## Speech Bubble CSS

Creating speech bubbles with CSS is a simple job, but I made it simpler with this gist. Find the HTML & CSS code for it below. 
For more explanations on how it works check out my extended [CSS Speech Bubbles](https://www.coding-dude.com/wp/css/css-speech-bubbles/) post on my [CodingDude](https://www.coding-dude.com/) blog.

[![CSS Speech Bubbles](https://www.coding-dude.com/wp/wp-content/uploads/2023/09/css-speech-bubble.jpg)](https://www.coding-dude.com/wp/css/css-speech-bubbles/)

inspired by [Comic Strip Template](https://www.psd-dude.com/tutorials/resources/comic-strip-template.aspx) by [PSDDude](https://www.psd-dude.com/)

## Speech Bubble HTML Code:

```html
<div class="speech-bubble">CSS IS AWESOME!!! 💥 DON'T YOU THINK?</div>
```

## Speech Bubble CSS Code:

```css
.speech-bubble{
  --arrow-w:0.5em;
  --arrow-h:1em;
  --bubble-corners:0;
  --w:12em;
  --border-size:3px;
  --text-color:black;
  --bubble-color:white;
  --border-color:black;
}
.speech-bubble{
  text-align:center;
  font-family:cursive;
  font-size:20px;
  font-weight:bold;
  color:var(--text-color);
  background:var(--bubble-color);
  padding:1em;
  position:relative;
  border-radius:var(--bubble-corners);
  max-width:var(--w);
  box-shadow:0 0 0 var(--border-size) var(--border-color);
}

.speech-bubble.round{
  --bubble-corners:1em;
}

.speech-bubble.circle{
  --bubble-corners:100%;
  padding:2em;
}

.speech-bubble:before,.speech-bubble:after{
  content:"";
  position:absolute;
  bottom:calc(-1 * var(--arrow-h) * 2 + 0.5px);
  left:50%;
  border-style:solid;
  border-width:var(--arrow-h) var(--arrow-w);
  border-color:var(--bubble-color) transparent transparent;
}

.speech-bubble:before{
  border-width:calc(var(--arrow-h) + var(--border-size)) calc(var(--arrow-w) + var(--border-size));
  border-color:var(--border-color) transparent transparent;
  bottom:calc(-1 * var(--arrow-h) * 2 - 2.5*var(--border-size)); 
  left:calc(50% - var(--border-size));
}

.speech-bubble.t:after{
  border-color:transparent transparent var(--bubble-color);
  bottom:auto;
  top:calc(-1 * var(--arrow-h) * 2 + 0.5px);
}

.speech-bubble.t:before{
  border-width:calc(var(--arrow-h) + var(--border-size)) calc(var(--arrow-w) + var(--border-size));
  border-color:transparent transparent var(--border-color);
  bottom:auto;
  top:calc(-1 * var(--arrow-h) * 2 - 2.5*var(--border-size)); 
}

.speech-bubble.l:after{
  border-color:transparent var(--bubble-color) transparent transparent;
  bottom:auto;
  border-width:var(--arrow-w) var(--arrow-h);
  top:calc(50% - var(--arrow-w));
  left:calc(-1 * var(--arrow-h) * 2 + 0.5px);
}

.speech-bubble.l:before{
  border-width:calc(var(--arrow-w) + var(--border-size)) calc(var(--arrow-h) + var(--border-size));
  border-color:transparent var(--border-color) transparent transparent;
  bottom:auto;  
  top:calc(50% - var(--arrow-w) - var(--border-size));
  left:calc(-1 * var(--arrow-h) * 2 - 2.5*var(--border-size)); 
}

.speech-bubble.r:after{
  border-color:transparent transparent transparent var(--bubble-color);
  bottom:auto;
  left:auto;
  border-width:var(--arrow-w) var(--arrow-h);
  top:calc(50% - var(--arrow-w));
  right:calc(-1 * var(--arrow-h) * 2 + 0.5px);
}

.speech-bubble.r:before{
  border-width:calc(var(--arrow-w) + var(--border-size)) calc(var(--arrow-h) + var(--border-size));
  border-color:transparent transparent transparent var(--border-color);
  bottom:auto;
  left:auto;
  top:calc(50% - var(--arrow-w) - var(--border-size));
  right:calc(-1 * var(--arrow-h) * 2 - 2.5*var(--border-size)); 
}

.speech-bubble.pop{
  animation-name: pop;
  animation-duration: 0.5s;
  animation-timing-function:cubic-bezier(0.755, 0.050, 0.855, 0.060);
}

.speech-bubble.float{
  animation-name: float-up;
  animation-duration: 2s;
  animation-iteration-count: infinite;
  animation-timing-function:ease;
}

.speech-bubble.r.float{
  animation-name: float-left;
}

.speech-bubble.l.float{
  animation-name: float-right;
}

.speech-bubble.t.float{
  animation-name: float-down;
}

@keyframes pop {
  0% {transform: scale(0.8);}
  80% {transform: scale(1.1);}
  90% {transform: scale(0.9);}
  100% {transform: scale(1);}
}

@keyframes float-up {
  0% {transform: translateY(0);}
  50% {transform: translateY(calc(-1 * var(--arrow-h)));}
}

@keyframes float-left {
  0% {transform: translateX(0);}
  50% {transform: translateX(calc(-1 * var(--arrow-h)));}
}

@keyframes float-right {
  0% {transform: translateX(0);}
  50% {transform: translateX(var(--arrow-h));}
}

@keyframes float-down {
  0% {transform: translateY(0);}
  50% {transform: translateY(var(--arrow-h));}
}
```

## Speech Bubble CSS Classes & Customization

Customize the Speech Bubble Design with Provided CSS Classes
Use the following CSS classes together with the base .speech-bubble class:

- `t`, `l`, `r` or `b` for placing the arrow top, left, right or bottom (by default the speech bubble arrow points downwards)
- `round` or `circle` for bubble shape (by default the dialog box has square corners); TIP: Circle works best for dialog bubbles, because in old comic books and newspaper doodle drawings, that’s how they were drawn.
- `pop` or `float` for animation (by default the text bubble is static)

### Additional Customization via CSS Variables

1. `--arrow-w`: This variable sets the width of the arrow of the speech bubble to 0.5em.
1. `--arrow-h`: This variable sets the height of the arrow of the speech bubble to 1em.
1. `--bubble-corners`: This variable determines the roundness of the bubble’s corners. A value of 0 indicates sharp corners (so a square text bubble) while something like 50% would make a circle or elliptical talking bubble.
1. `--w`: This variable sets the maximum width of the speech bubble, which is 12em in this case.
1. `--border-size`: It defines the size or thickness of the border around the speech bubble, which is set to 3px.
1. `--text-color`: This variable sets the color of the text inside the speech bubble to black.
1. `--bubble-color`: It determines the background color of the speech bubble itself, which is set to white.
1. `--border-color`: This variable determines the color of the border around the speech bubble, also set to black.

## Codepen Demo

{% codepen https://codepen.io/inegoita/pen/gOZXPvX %}

## You can follow me

My blog: [coding-dude.com](https://www.coding-dude.com/)
Twitter: [@codingdudecom](https://twitter.com/codingdudecom)