AI CSS Animations

Video Chapter Scrubber Hover

A video player whose progress bar is split into chapters: hovering one thickens it and pops its title and timestamp above. Each chapter's width is a flex-grow value set inline.

Also known as: youtube chapters hover css, video progress bar hover, chapter markers timeline.

2:31 / 9:48

HTML

<div class="hfx-video-chapters">
  <div class="hfx-video-chapters-bar">
    <button aria-label="Intro, 0:00" data-tip="Intro · 0:00" style="--g: 2"></button>
    <button aria-label="Setup, 1:12" data-tip="Setup · 1:12" style="--g: 3"></button>
    <button aria-label="Build, 3:40" data-tip="Build · 3:40" style="--g: 4"></button>
    <button aria-label="Ship it, 7:05" data-tip="Ship it · 7:05" style="--g: 2.5"></button>
  </div>
  <div class="hfx-video-chapters-controls">
    <svg viewBox="0 0 24 24" aria-hidden="true"><path fill="currentColor" d="M7.5 5.2v13.6a.8.8 0 0 0 1.2.7l10.6-6.8a.8.8 0 0 0 0-1.4L8.7 4.5a.8.8 0 0 0-1.2.7z"/></svg><span>2:31 / 9:48</span><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M4 9V5.5A1.5 1.5 0 0 1 5.5 4H9M15 4h3.5A1.5 1.5 0 0 1 20 5.5V9M20 15v3.5a1.5 1.5 0 0 1-1.5 1.5H15M9 20H5.5A1.5 1.5 0 0 1 4 18.5V15"/></svg>
  </div>
</div>

CSS

.hfx-video-chapters {
  --c: var(--hfx-color, #3b82f6);
  font-size: var(--hfx-size, 16px);
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  width: 20em;
  height: 10.5em;
  padding: 0 0.9em 0.55em;
  border-radius: 0.8em;
  background:
    linear-gradient(to top, rgba(0, 0, 0, 0.6), transparent 48%),
    radial-gradient(circle at 74% 30%, rgba(255, 255, 255, 0.85) 0 7%, transparent 7.5%),
    radial-gradient(ellipse 62% 42% at 18% 100%, color-mix(in srgb, var(--c) 60%, #000) 0 98%, transparent 100%),
    radial-gradient(ellipse 72% 48% at 88% 106%, color-mix(in srgb, var(--c) 78%, #000) 0 98%, transparent 100%),
    linear-gradient(180deg, color-mix(in srgb, var(--c) 35%, #fff), var(--c));
  color: #fff;
  font-family: system-ui, sans-serif;
}
.hfx-video-chapters-bar {
  display: flex;
  gap: 0.2em;
}
.hfx-video-chapters-bar button {
  --bar: rgba(255, 255, 255, 0.35);
  position: relative;
  flex: var(--g) 1 0;
  height: 1.1em;
  padding: 0;
  border: 0;
  background: none;
  cursor: pointer;
}
.hfx-video-chapters-bar button:nth-child(1) { --bar: #fff; }
.hfx-video-chapters-bar button:nth-child(2) { --bar: linear-gradient(90deg, #fff 45%, rgba(255, 255, 255, 0.35) 45%); }
/* the visible segment, thinner than the hit area */
.hfx-video-chapters-bar button::before {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  top: 50%;
  height: 0.3em;
  margin-top: -0.15em;
  border-radius: 0.15em;
  background: var(--bar);
  transition: transform 0.2s ease;
}
.hfx-video-chapters-bar button::after {
  content: attr(data-tip);
  position: absolute;
  bottom: calc(100% + 0.5em);
  left: 50%;
  padding: 0.35em 0.65em;
  border-radius: 0.4em;
  background: rgba(15, 23, 42, 0.85);
  color: #fff;
  font-size: 0.75em;
  font-weight: 600;
  white-space: nowrap;
  opacity: 0;
  pointer-events: none;
  transform: translate(-50%, 0.4em);
  transition: opacity 0.2s ease, transform 0.25s cubic-bezier(0.3, 0.7, 0.4, 1);
}
.hfx-video-chapters-bar button:is(:hover, :focus-visible)::before { transform: scaleY(2); }
.hfx-video-chapters-bar button:is(:hover, :focus-visible)::after {
  opacity: 1;
  transform: translate(-50%, 0);
}
.hfx-video-chapters-controls {
  display: flex;
  align-items: center;
  gap: 0.6em;
  font-size: 0.8em;
  font-variant-numeric: tabular-nums;
}
.hfx-video-chapters-controls svg { width: 1.35em; height: 1.35em; }
.hfx-video-chapters-controls svg:last-child { margin-left: auto; }

@media (prefers-reduced-motion: reduce) {
  .hfx-video-chapters, .hfx-video-chapters *, .hfx-video-chapters::before, .hfx-video-chapters::after, .hfx-video-chapters *::before, .hfx-video-chapters *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}

Customizing this snippet

  • Color: set --hfx-color on the element or a parent. Currently previewing #3b82f6.
  • Base size: set --hfx-size. Every other dimension is in em, so the whole thing scales together. Currently previewing 16px.
  • Speed: change the duration on the transition or animation shorthand. Staggered delays are relative, so they keep their rhythm.
  • Reduced motion: the rule at the end of the CSS turns the motion off for people who asked their OS for less of it. Keep it.

Similar hover effects

Sliding Pill Nav Hover Effect
Directional Underline Nav Hover Effect
Dot Indicator Nav Hover Effect
Vertical Nav Indicator Hover Effect