31 CSS Hero Sections06 / 31

Pure CSSMIT licensed

Video Loop Hero

Memphis-modern video-pretender — geometric SVG shapes oscillating like a video loop, pinned behind cobalt-on-bone copy with a lemon CTA. No real video, no licensing.

Published

Live Demo
Try it

The code

<section class="hs-06" aria-label="Hero">
  <div class="hs-06__shapes" aria-hidden="true">
    <span class="hs-06__s1"></span>
    <span class="hs-06__s2"></span>
    <span class="hs-06__s3"></span>
    <span class="hs-06__s4"></span>
  </div>
  <div class="hs-06__content">
    <span class="hs-06__eye">▸ NOW PLAYING</span>
    <h2>Your portfolio, <em>animated.</em></h2>
    <p>Drop in your projects. We turn them into the kind of motion reel that gets the call back.</p>
    <a class="hs-06__cta" href="#start">Play with it</a>
  </div>
</section>
.hs-06 {
  position: relative;
  overflow: hidden;
  display: grid;
  place-items: center;
  width: 100%;
  min-height: 100vh;
  padding: clamp(28px, 5vw, 64px) clamp(20px, 5vw, 56px);
  background: #f4f1ea;
  font-family: 'Inter', system-ui, sans-serif;
  color: #0b1f4a;
  box-sizing: border-box;
  contain: layout paint;
}

.hs-06__shapes {
  position: absolute;
  inset: 0;
  pointer-events: none;
}

.hs-06__shapes span {
  position: absolute;
  animation: hs-06-bounce 8s ease-in-out infinite alternate;
}

.hs-06__s1 {
  top: 8%;
  left: 6%;
  width: 110px;
  height: 110px;
  background: #0b1f4a;
  border-radius: 50%;
}

.hs-06__s2 {
  top: 12%;
  right: 10%;
  width: 0;
  height: 0;
  border-left: 70px solid transparent;
  border-right: 70px solid transparent;
  border-bottom: 120px solid #f5d028;
  animation-delay: -3s;
}

.hs-06__s3 {
  bottom: 10%;
  left: 12%;
  width: 140px;
  height: 50px;
  background: #ee5253;
  border-radius: 999px;
  animation-delay: -5s;
  transform: rotate(-12deg);
}

.hs-06__s4 {
  bottom: 8%;
  right: 8%;
  width: 90px;
  height: 90px;
  background: #0b1f4a;
  border-radius: 12px;
  animation-delay: -7s;
  transform: rotate(15deg);
}

@keyframes hs-06-bounce {
  0% {
    transform: translate(0,0) rotate(0deg);
  }

  100% {
    transform: translate(20px,-15px) rotate(8deg);
  }
}

.hs-06__s2 {
  animation-name: hs-06-bounce-tri;
}

@keyframes hs-06-bounce-tri {
  0% {
    transform: translate(0,0);
  }

  100% {
    transform: translate(-15px,20px);
  }
}

.hs-06__content {
  position: relative;
  z-index: 1;
  max-width: 600px;
  text-align: center;
}

.hs-06__eye {
  display: inline-block;
  padding: 4px 12px;
  background: #0b1f4a;
  color: #f5d028;
  font-family: 'JetBrains Mono', monospace;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.18em;
  margin-bottom: 22px;
}

.hs-06 h2 {
  margin: 0 0 16px;
  font-family: 'Inter', sans-serif;
  font-size: clamp(38px, 6vw, 64px);
  font-weight: 900;
  letter-spacing: -0.03em;
  line-height: 1;
}

.hs-06 h2 em {
  color: #ee5253;
  font-style: italic;
  font-weight: 900;
}

.hs-06 p {
  margin: 0 auto 28px;
  font-size: 16px;
  line-height: 1.55;
  color: #4a5878;
  max-width: 460px;
}

.hs-06__cta {
  display: inline-block;
  padding: 14px 28px;
  background: #f5d028;
  color: #0b1f4a;
  font-weight: 800;
  font-size: 14.5px;
  text-decoration: none;
  border-radius: 4px;
  border: 3px solid #0b1f4a;
  box-shadow: 6px 6px 0 #0b1f4a;
  transition: transform 0.15s, box-shadow 0.15s;
}

.hs-06__cta:hover {
  transform: translate(2px,2px);
  box-shadow: 4px 4px 0 #0b1f4a;
}

@media (prefers-reduced-motion: reduce) {
  .hs-06__shapes span {
    animation: none;
  }

  .hs-06__cta {
    transition: none;
  }
}
Paste this into ChatGPT, Claude, Cursor, or any coding assistant. The block below is pre-framed with everything the AI needs to integrate this demo into your project — markup, styles, scoping notes, and the source URL. Hit Copy and paste straight into your chat.
Here's a working CSS Hero Section from CodeFronts. Use it as-is or adapt to your framework. All classes are scoped under a unique prefix so the code won't collide with your existing styles. MIT licensed.
Demo: Video Loop Hero
Source: https://codefronts.com/layouts/css-hero-sections/video-loop-hero/

Memphis-modern video-pretender — geometric SVG shapes oscillating like a video loop, pinned behind cobalt-on-bone copy with a lemon CTA. No real video, no licensing.
## HTML
```html
<section class="hs-06" aria-label="Hero">
  <div class="hs-06__shapes" aria-hidden="true">
    <span class="hs-06__s1"></span>
    <span class="hs-06__s2"></span>
    <span class="hs-06__s3"></span>
    <span class="hs-06__s4"></span>
  </div>
  <div class="hs-06__content">
    <span class="hs-06__eye">▸ NOW PLAYING</span>
    <h2>Your portfolio, <em>animated.</em></h2>
    <p>Drop in your projects. We turn them into the kind of motion reel that gets the call back.</p>
    <a class="hs-06__cta" href="#start">Play with it</a>
  </div>
</section>
```
## CSS
```css
.hs-06 {
  position: relative;
  overflow: hidden;
  display: grid;
  place-items: center;
  width: 100%;
  min-height: 100vh;
  padding: clamp(28px, 5vw, 64px) clamp(20px, 5vw, 56px);
  background: #f4f1ea;
  font-family: 'Inter', system-ui, sans-serif;
  color: #0b1f4a;
  box-sizing: border-box;
  contain: layout paint;
}

.hs-06__shapes {
  position: absolute;
  inset: 0;
  pointer-events: none;
}

.hs-06__shapes span {
  position: absolute;
  animation: hs-06-bounce 8s ease-in-out infinite alternate;
}

.hs-06__s1 {
  top: 8%;
  left: 6%;
  width: 110px;
  height: 110px;
  background: #0b1f4a;
  border-radius: 50%;
}

.hs-06__s2 {
  top: 12%;
  right: 10%;
  width: 0;
  height: 0;
  border-left: 70px solid transparent;
  border-right: 70px solid transparent;
  border-bottom: 120px solid #f5d028;
  animation-delay: -3s;
}

.hs-06__s3 {
  bottom: 10%;
  left: 12%;
  width: 140px;
  height: 50px;
  background: #ee5253;
  border-radius: 999px;
  animation-delay: -5s;
  transform: rotate(-12deg);
}

.hs-06__s4 {
  bottom: 8%;
  right: 8%;
  width: 90px;
  height: 90px;
  background: #0b1f4a;
  border-radius: 12px;
  animation-delay: -7s;
  transform: rotate(15deg);
}

@keyframes hs-06-bounce {
  0% {
    transform: translate(0,0) rotate(0deg);
  }

  100% {
    transform: translate(20px,-15px) rotate(8deg);
  }
}

.hs-06__s2 {
  animation-name: hs-06-bounce-tri;
}

@keyframes hs-06-bounce-tri {
  0% {
    transform: translate(0,0);
  }

  100% {
    transform: translate(-15px,20px);
  }
}

.hs-06__content {
  position: relative;
  z-index: 1;
  max-width: 600px;
  text-align: center;
}

.hs-06__eye {
  display: inline-block;
  padding: 4px 12px;
  background: #0b1f4a;
  color: #f5d028;
  font-family: 'JetBrains Mono', monospace;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.18em;
  margin-bottom: 22px;
}

.hs-06 h2 {
  margin: 0 0 16px;
  font-family: 'Inter', sans-serif;
  font-size: clamp(38px, 6vw, 64px);
  font-weight: 900;
  letter-spacing: -0.03em;
  line-height: 1;
}

.hs-06 h2 em {
  color: #ee5253;
  font-style: italic;
  font-weight: 900;
}

.hs-06 p {
  margin: 0 auto 28px;
  font-size: 16px;
  line-height: 1.55;
  color: #4a5878;
  max-width: 460px;
}

.hs-06__cta {
  display: inline-block;
  padding: 14px 28px;
  background: #f5d028;
  color: #0b1f4a;
  font-weight: 800;
  font-size: 14.5px;
  text-decoration: none;
  border-radius: 4px;
  border: 3px solid #0b1f4a;
  box-shadow: 6px 6px 0 #0b1f4a;
  transition: transform 0.15s, box-shadow 0.15s;
}

.hs-06__cta:hover {
  transform: translate(2px,2px);
  box-shadow: 4px 4px 0 #0b1f4a;
}

@media (prefers-reduced-motion: reduce) {
  .hs-06__shapes span {
    animation: none;
  }

  .hs-06__cta {
    transition: none;
  }
}
```

How this works

The Video Loop Hero fakes a motion reel with pure CSS — no <video> element, no MP4 licensing, no HLS manifest, no autoplay-policy headaches. Four SVG-shape primitives (circle, CSS border-triangle, rotated pill, rotated square) drift on an 8-second ease-in-out keyframe with staggered animation-delay values so the composition never syncs into a static frame. Each shape is absolutely positioned inside a position: relative stage that uses overflow: hidden to clip drift beyond the viewport — the same containment trick production video heroes use, but painted entirely on the compositor thread.

The palette is Memphis-modern deliberately: cobalt #0b1f4a as the deep base, lemon #f5d028 as the dominant CTA hit, coral red #ee5253 as the tension accent, and bone #f4f1ea for the copy field. Cobalt-plus-lemon is the highest-energy safe pairing in the design-system canon (Nike, Bloomberg, Wired have all shipped it) because the contrast ratio comfortably clears WCAG AA while the temperature clash reads as "kinetic." The brutalist CTA — 6px hard box-shadow, black border, no border-radius — signals "creative agency, we take work seriously" without needing a portfolio grid to prove it.

Why it converts: this is a SaaS hero section pattern reworked for creative-agency and portfolio hero positioning, where the visual signals ARE the pitch. Motion primes the visitor to expect a motion reel below the fold, so the CTA click rate rises on "View the reel" copy. Dodging real video sidesteps the biggest INP killer on landing pages — a <video autoplay> element blocks the main thread during decode and adds 200-400ms to Interaction to Next Paint on mid-tier Android, plus CLS if width/height attrs are missing.

Make it yours

  • Recolor by swapping four tokens: base cobalt (#0b1f4a), primary lemon (#f5d028), tension coral (#ee5253), bone copy field (#f4f1ea). Keep base-to-lemon contrast above 7:1 or the CTA loses its animated-headline energy on mobile.
  • Swap shapes to match brand voice: keep the four-primitive count but replace circle with a hexagon, pill with a lozenge, or square with a rhombus. Do NOT exceed four shapes — five is where the composition tips from "kinetic" to "chaotic" and eye-tracking studies show CTA discovery time doubles.
  • Change the CTA shape: current border-radius: 0 is brutalist. For SaaS hero section use, bump to border-radius: 6px and reduce the box-shadow to 3px 3px 0. For pill-style startup hero, use border-radius: 999px and drop the hard shadow entirely — brutalism doesn't survive rounded corners.
  • For dark mode hero inversion: flip base to bone (#f4f1ea), copy to cobalt (#0b1f4a), keep lemon and coral untouched. The shapes need a mix-blend-mode: multiply to prevent them washing out against the light background.
  • For Tailwind: bg-[#0b1f4a] text-[#f4f1ea] overflow-hidden relative on the section, bg-[#f5d028] text-black border-2 border-black shadow-[6px_6px_0_#000] hover:translate-x-1 hover:translate-y-1 hover:shadow-[3px_3px_0_#000] on the CTA. The 8s drift maps to animate-[drift_8s_ease-in-out_infinite] with a custom keyframe.

Gotchas — read before shipping

  • The 8s drift animation runs continuously — without a prefers-reduced-motion guard it violates WCAG 2.3.3 for vestibular-disorder users. The demo already wraps the four shape animation declarations in the media query — never remove it.
  • Real video heroes have three CLS killers this pattern avoids: unset video dimensions, poster-image swap, and autoplay-fail fallback. If you migrate BACK to a real <video> for the reel, set explicit width/height attrs, use poster with matching aspect-ratio, and NEVER rely on JS autoplay — Safari and iOS block it silently and your hero blanks.
  • The lemon CTA (#f5d028) against dark cobalt text (#0b1f4a) gives contrast ~11.5:1 (AAA), but if you re-skin the CTA to white text the ratio drops to 1.6:1 — fails AA catastrophically. Always test the CTA fg/bg pair with a contrast checker before shipping a color variant; it's the #1 landing-page a11y bug.
  • The rotated square and pill use transform: rotate() combined with the drift animation — on Safari < 16, compound transforms in keyframes trigger a subpixel-aliasing bug that makes the shapes shimmer. Add will-change: transform to force GPU compositing and the shimmer disappears.
  • The overflow: hidden on the stage clips shapes that drift beyond edges — critical for the responsive hero section behavior. If you add overflow: visible to debug, the shapes escape the hero and paint over the nav bar, breaking layout on scroll. Never ship without the clip.
  • In React/Next.js, if you server-render this hero and the animation flashes different positions on hydration, that's a CLS red flag — the client picks up the animation-delay mid-cycle. Wrap the shape spans in a useEffect-mounted client component OR accept the flash; do not use animation-play-state: paused on SSR because it forces a paint-blocking style recalc on unpause.

Techniques used in this demo

Search CodeFronts

Loading…