CSS bubble generator
Build speech-bubble tooltips with pure CSS triangles: direction, size, radius, border width and colours, triangle size and offset — with a live preview plus ready-to-copy CSS (::before/::after) and HTML.
Runs in your browserEvery computation happens in your browser — your data never leaves this device.
Distance from the bubble’s left (top) edge to the arrow centre; clamped to stay inside
Live preview
CSS
.bubble {
position: relative;
box-sizing: border-box;
width: 240px;
min-height: 72px;
padding: 12px 16px;
background: #FFFFFF;
border: 2px solid #D6D9DE;
border-radius: 12px;
}
.bubble::before,
.bubble::after {
content: "";
position: absolute;
width: 0;
height: 0;
border-style: solid;
pointer-events: none;
}
.bubble::before {
position: absolute;
width: 0;
height: 0;
border-style: solid;
pointer-events: none;
top: 100%;
left: 118px;
margin-left: -14.8px;
border-width: 14.8px 14.8px 0 14.8px;
border-color: #D6D9DE transparent transparent transparent;
}
.bubble::after {
position: absolute;
width: 0;
height: 0;
border-style: solid;
pointer-events: none;
top: 100%;
left: 118px;
margin-left: -12px;
border-width: 12px 12px 0 12px;
border-color: #FFFFFF transparent transparent transparent;
}
HTML
<div class="bubble">A sample bubble message used to show the layout.</div>
What this tool does
- Build a tooltip, chat bubble or callout without hand-rolling CSS triangles: pick the arrow side and size, then copy the ready-made CSS and HTML.
- The part that usually breaks — the border opening where the arrow meets the bubble — is handled by the two-layer ::before / ::after triangles, so changing colors or radius does not expose a gap.
- Reposition the arrow freely: the offset is clamped inside the bubble so it never floats off the edge, whether you want it near a corner or centered.
- Ask for a shadow and it uses filter: drop-shadow, so the shadow follows the bubble plus arrow outline instead of tracing a rectangle.
Example
Input
Default rounded-bubble preset: arrow at the bottom, width 240px, min height 72px, radius 12px, 2px border in #D6D9DE, #FFFFFF background, 12px triangle, offset 120px
Output
.bubble declares position: relative, width: 240px, border: 2px solid #D6D9DE, border-radius: 12px; .bubble::before draws the border-colored triangle with 14.8px border-width, top: 100%, left: 118px and margin-left: -14.8px; .bubble::after draws the background triangle at 12px with left: 118px and margin-left: -12px
The outer triangle is 2px × √2 ≈ 2.8px taller than the inner one, which makes the perpendicular gap between the two hypotenuses exactly the 2px border width — that is why the border looks continuous around the arrow.
Frequently asked questions
Why are two pseudo-element triangles needed?
A single triangle only works for a flat-colored bubble. With a border you need a border-colored triangle underneath and a background-colored one on top so the border can wrap around the arrow. Their offsets differ by exactly the border width, so the inner one hides the middle of the outer one.
What if the arrow offset is very large or very small?
It is clamped into [H, span − H], where H is half the outer triangle’s width and span is the bubble width or min height, so the arrow can never hang past the edge. If the bubble is too small for any valid range it simply centers. A negative value reports an invalid offset.
Why drop-shadow instead of box-shadow?
box-shadow only follows the element’s rectangle, so the pseudo-element triangle gets no shadow and the result looks like a floating right-angled shadow. drop-shadow applies to the rendered silhouette including the pseudo-elements, keeping the shadow in step with the bubble shape.
What if a color or size is invalid?
Colors accept 3, 4, 6 or 8 hex digits (#fff, #FFFFFF, #FF000080); color names or rgb() report an invalid color. Sizes outside their ranges are clamped rather than rejected — width 40–800, radius 0–200, border 0–20, triangle 2–80.
Can I edit the generated HTML?
Yes, it is simply <div class="bubble">text</div>, and the text is escaped (& < > " become entities) so it cannot break the markup. If you rename the class, update the selectors in the CSS too.
Keywords:cssbubbletooltipspeech bubblearrowtriangle气泡对话框提示框三角气泡生成器