← Visual Library / Carousels

Dot-to-pill indicator

A row of small circle indicators where the active one stretches into a pill shape. The dot you're on is unmistakable.

Carousels Captured JS-free
Use when — any carousel that needs an indicator row. The stretched-pill approach reads more confident than dimming/brightening dots, and at a glance shows exactly which slide you're viewing.

Live demo

Click a dot — watch the active dot expand into a pill.

The trick

Each dot is a label with background-clip: content-box + extra padding — the touch target is 32×32px (good for fingers), but only the inner 8×8px area shows as the colored dot. On the active state, the inner area expands to 26px wide and the border-radius drops to 6px — the circle stretches into a pill. The animation is smooth because we're animating width, border-radius, and background-color all on the same easing curve.

HTML — label as wrapper, inner span as the dot

<div class="dots">
  <label for="c1"><span class="dot"></span></label>
  <label for="c2"><span class="dot"></span></label>
  ...
</div>

CSS

/* label = touch target (44×44px), invisible */
.dots label {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  cursor: pointer;
}

/* inner span = the visible dot, animated */
.dots label .dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: rgba(20,20,20,0.22);
  transition:
    background 320ms var(--ease-out-quart),
    width 320ms var(--ease-out-quart),
    border-radius 320ms var(--ease-out-quart);
}

/* active dot → red pill */
.carousel-host:has(#c1:checked) label[for="c1"] .dot {
  background: var(--red);
  width: 28px;
  border-radius: 6px;
}

Gotcha to avoid — don't try to animate the label itself with background-clip: content-box and padding. With box-sizing: border-box a small width will make the content box go negative and the dot disappears. The inner-span approach is bulletproof.

Variants worth considering

Active dot grows but stays round — instead of border-radius: 6px, keep it 50% and just make it slightly larger (12px). Less distinctive but a calmer feel.

Animated travel — for 5+ slides where the pill needs to "travel" between positions, you'd need JS to manage offsets. The pure-CSS pattern only works when each dot's :checked state is independently styleable.

Vertical variant — rotate the dots row 90° via flex-direction: column. Position right-edge for desktop-side-rail carousels.

Source: Chevy 55 reviews carousel (user-uploaded HTML, 2026-05-18).