← Back to gallery
CSS

Segmented Control Radio Tab Group

A native radio-group segmented control that slides a pill indicator with translateX while keeping radios as the source of truth for keyboard and screen reader selection.

Duration
1s
Resolution
1440×900
Format
CSS
segmented-controlradio-grouppill-slidetranslateXaccessibility

Interaction / radio-group / segmented

Segmented control radio tab group

Reimplements a segmented control by layering a sliding pill indicator on top of a real radio group, so keyboard, screen reader, and touch users all get the single-choice semantics.

view modegrid
Layout

Two-option layout toggle

View Mode

Two-option segmented control that swaps between grid and list views. The indicator slides across a fixed track width.

  • grid vs list
  • toolbar
  • fixed width
Plan

Three-tier pricing segmented

Plan Tier

Three-option plan picker where the pill indicator slides to mark the chosen tier and a price label updates alongside.

  • 3 tier
  • pricing
  • radio group
Period

Four-option analytics range

Time Period

Four-option analytics period picker with a slimmer underline indicator, tuned for tight labels like 1D / 1W / 1M / 1Y.

  • 4 options
  • analytics
  • dense

Segmented inspector

View Mode

Layout

Click or use arrow keys to move the indicator.

Options
2
Slide
0.22s

Short label sets keep the indicator target wide, which reads well at tight toolbar sizes and mobile widths.

css
.segmented {
  position: relative;
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  padding: 4px;
  background: rgba(15, 23, 42, 0.6);
  border-radius: 999px;
  --active-index: 0;
}

.segmented input {
  position: absolute;
  opacity: 0;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

.segmented label {
  position: relative;
  z-index: 1;
  padding: 8px 16px;
  border-radius: 999px;
  text-align: center;
  cursor: pointer;
  transition: color 0.22s ease;
}

.segmented::before {
  content: '';
  position: absolute;
  inset: 4px;
  width: calc(100% / 2 - 8px);
  border-radius: 999px;
  background: #7dd3fc;
  transform: translateX(calc(100% * var(--active-index)));
  transition: transform 0.22s cubic-bezier(0.2, 0.8, 0.2, 1);
}

.segmented input:checked + label { color: #0f172a; }

.segmented:has(input:nth-of-type(2):checked) { --active-index: 1; }
.segmented:has(input:nth-of-type(3):checked) { --active-index: 2; }
.segmented:has(input:nth-of-type(4):checked) { --active-index: 3; }

@media (prefers-reduced-motion: reduce) {
  .segmented::before, .segmented label { transition: none; }
}