Code Tutorial

Create Speech Bubbles with Pure CSS

Copy-paste CSS code snippets for speech bubbles, thought clouds, and chat-style messages. No images, no JavaScript — just clean, scalable CSS.

1. Basic Speech Bubble

The foundation of every CSS speech bubble: a rounded box with a triangular tail created using the ::after pseudo-element and CSS borders.

Hello! I'm a CSS speech bubble.
.speech-bubble {
  position: relative;
  background: #ffffff;
  border: 2px solid #111111;
  border-radius: 16px;
  padding: 16px 20px;
  max-width: 300px;
  font-family: sans-serif;
  box-shadow: 3px 3px 0 #111;
}

.speech-bubble::after {
  content: '';
  position: absolute;
  bottom: -12px;
  left: 24px;
  width: 0;
  height: 0;
  border-left: 12px solid transparent;
  border-right: 12px solid transparent;
  border-top: 12px solid #111111;
}

.speech-bubble::before {
  content: '';
  position: absolute;
  bottom: -9px;
  left: 26px;
  width: 0;
  height: 0;
  border-left: 10px solid transparent;
  border-right: 10px solid transparent;
  border-top: 10px solid #ffffff;
  z-index: 1;
}
How it works: The ::after pseudo-element creates a triangle using the CSS border trick — setting transparent left/right borders and a solid top border. The ::before element creates a slightly smaller white triangle on top to make the tail appear hollow.

2. Tail Position Variations

Change the tail position by adjusting the left, right, top, and bottom properties of the pseudo-elements.

/* Tail: Bottom-Right */
.speech-bubble.tail-br::after {
  bottom: -12px;
  right: 24px;
  left: auto;
}

/* Tail: Top-Left */
.speech-bubble.tail-tl::after {
  top: -12px;
  bottom: auto;
  left: 24px;
  border-top: none;
  border-bottom: 12px solid #111111;
}

/* Tail: Top-Right */
.speech-bubble.tail-tr::after {
  top: -12px;
  bottom: auto;
  right: 24px;
  left: auto;
  border-top: none;
  border-bottom: 12px solid #111111;
}

3. Thought Bubble (Cloud Style)

Thought bubbles use a cloud-like shape with circular "dots" trailing from the thinker. We achieve this with border-radius: 50% on the pseudo-elements.

I'm thinking about CSS...
.thought-bubble {
  position: relative;
  background: #ffffff;
  border: 2px solid #111;
  border-radius: 30px;
  padding: 18px 24px;
  max-width: 280px;
  box-shadow: 3px 3px 0 #111;
}

.thought-bubble::before {
  content: '';
  position: absolute;
  bottom: -18px;
  left: 28px;
  width: 14px;
  height: 14px;
  background: #fff;
  border: 2px solid #111;
  border-radius: 50%;
}

.thought-bubble::after {
  content: '';
  position: absolute;
  bottom: -30px;
  left: 20px;
  width: 8px;
  height: 8px;
  background: #fff;
  border: 2px solid #111;
  border-radius: 50%;
}

4. Chat / Messaging Bubble

Recreate the iMessage/WhatsApp look with colored rounded rectangles and a small curved tail.

Hey, how are you?
I'm great, thanks!
.chat-bubble {
  padding: 10px 16px;
  max-width: 280px;
  font-family: -apple-system, sans-serif;
  font-size: 14px;
  line-height: 1.4;
}

.chat-bubble.sent {
  background: #007aff;
  color: #fff;
  border-radius: 18px 18px 4px 18px;
  align-self: flex-end;
}

.chat-bubble.received {
  background: #e9e9eb;
  color: #111;
  border-radius: 18px 18px 18px 4px;
  align-self: flex-start;
}

5. Shout / Exclamation Bubble

Shout bubbles are trickier in pure CSS. One approach uses clip-path: polygon() to create the spiky starburst shape.

.shout-bubble {
  position: relative;
  background: #ffeb3b;
  padding: 30px 40px;
  text-align: center;
  font-weight: bold;
  font-family: 'Comic Sans MS', cursive;
  clip-path: polygon(
    50% 0%, 61% 15%, 78% 5%,
    75% 22%, 95% 25%, 82% 38%,
    100% 50%, 82% 62%, 95% 75%,
    75% 78%, 78% 95%, 61% 85%,
    50% 100%, 39% 85%, 22% 95%,
    25% 78%, 5% 75%, 18% 62%,
    0% 50%, 18% 38%, 5% 25%,
    25% 22%, 22% 5%, 39% 15%
  );
}
Tip: Adjust the polygon coordinates to create more or fewer spikes. More points = smoother spikes, fewer points = more dramatic spikes.

6. Pixel / Retro Bubble

Create a pixelated look using box-shadow to simulate stepped edges, or use a stepped border-image.

Press START
.pixel-bubble {
  position: relative;
  background: #fff;
  border: 3px solid #111;
  padding: 12px 18px;
  font-family: 'Press Start 2P', 'Courier New', monospace;
  font-size: 12px;
  image-rendering: pixelated;
  /* No border-radius — sharp corners only */
}

/* Stepped pixel tail */
.pixel-bubble::before {
  content: '';
  position: absolute;
  bottom: -9px;
  left: 14px;
  width: 12px;
  height: 3px;
  background: #111;
}

.pixel-bubble::after {
  content: '';
  position: absolute;
  bottom: -12px;
  left: 17px;
  width: 6px;
  height: 3px;
  background: #111;
}

7. Animated Typing Bubble

A popular UI pattern — the "someone is typing..." indicator with bouncing dots inside a chat bubble.

.typing-bubble {
  background: #e9e9eb;
  border-radius: 18px;
  padding: 12px 18px;
  display: inline-flex;
  gap: 5px;
  align-items: center;
}

.typing-bubble span {
  width: 8px;
  height: 8px;
  background: #999;
  border-radius: 50%;
  animation: typing-bounce 1.4s infinite ease-in-out;
}

.typing-bubble span:nth-child(2) { animation-delay: 0.2s; }
.typing-bubble span:nth-child(3) { animation-delay: 0.4s; }

@keyframes typing-bounce {
  0%, 60%, 100% { transform: translateY(0); }
  30% { transform: translateY(-6px); }
}

Need Image-Based Speech Bubbles?

Our generator creates speech bubble PNGs instantly — no CSS required. Choose from classic, thought, shout, pixel, chat, and more styles.

Related articles:

Related tools: