Aurora Hero

A full-bleed hero with a slow aurora of blurred colour blobs drifting behind balanced display type. Pure CSS — no canvas, no JS.

  • conic-gradient
  • filter: blur
  • text-wrap: balance

Source

A single self-contained .astro component. It uses Prism's design tokens (--spectrum-*, --ink…) with sensible fallbacks, so it renders even outside this site.

heroes/aurora-hero.astro
---
export const meta = {
  title: "Aurora Hero",
  tags: ["hero", "gradient", "css-only"],
  description:
    "A full-bleed hero with a slow aurora of blurred colour blobs drifting behind balanced display type. Pure CSS — no canvas, no JS.",
  tech: ["conic-gradient", "filter: blur", "text-wrap: balance"],
  height: 560,
};
---

<section class="aurora-hero">
  <div class="aurora" aria-hidden="true">
    <span class="blob b1"></span>
    <span class="blob b2"></span>
    <span class="blob b3"></span>
  </div>
  <div class="aurora-hero__content">
    <p class="kicker">Now in private beta</p>
    <h1>Ship interfaces that feel <em>alive.</em></h1>
    <p class="sub">A design engine for teams who care about the last 10%. Motion, colour and type that respond to every interaction.</p>
    <div class="actions">
      <a href="#" class="a-btn a-btn--solid">Get early access</a>
      <a href="#" class="a-btn a-btn--ghost">Watch the film →</a>
    </div>
  </div>
</section>

<style>
  .aurora-hero {
    position: relative; min-height: 560px; display: grid; place-items: center;
    padding: 4rem 1.5rem; overflow: hidden; isolation: isolate;
    background: var(--bg, #0e0f1a); color: var(--ink, #f2f2f7); text-align: center;
  }
  .aurora { position: absolute; inset: -20%; z-index: -1; filter: blur(70px) saturate(1.3); }
  .blob { position: absolute; width: 45vmax; height: 45vmax; border-radius: 50%; opacity: 0.7; mix-blend-mode: screen; }
  .b1 { background: var(--spectrum-1, #8b5cf6); top: -10%; left: -5%; animation: drift1 18s ease-in-out infinite; }
  .b2 { background: var(--spectrum-3, #45d3e8); top: 10%; right: -10%; animation: drift2 22s ease-in-out infinite; }
  .b3 { background: var(--spectrum-5, #fbbf24); bottom: -20%; left: 30%; animation: drift3 26s ease-in-out infinite; }
  @keyframes drift1 { 50% { transform: translate(20%, 15%) scale(1.2); } }
  @keyframes drift2 { 50% { transform: translate(-15%, 20%) scale(1.1); } }
  @keyframes drift3 { 50% { transform: translate(10%, -20%) scale(1.25); } }

  .aurora-hero__content { max-width: 44rem; display: grid; gap: 1.1rem; justify-items: center; }
  .kicker {
    font-size: 0.8rem; font-weight: 600; letter-spacing: 0.12em; text-transform: uppercase;
    padding: 0.4rem 0.9rem; border-radius: 999px; color: var(--ink, #fff);
    border: 1px solid color-mix(in oklab, currentColor 25%, transparent);
    background: color-mix(in oklab, currentColor 8%, transparent);
  }
  .aurora-hero h1 {
    font-size: clamp(2.4rem, 1.6rem + 4vw, 4.6rem); line-height: 1.02;
    letter-spacing: -0.03em; text-wrap: balance; margin: 0;
  }
  .aurora-hero h1 em {
    font-style: normal;
    background: linear-gradient(100deg, var(--spectrum-1, #8b5cf6), var(--spectrum-3, #45d3e8), var(--spectrum-5, #fbbf24));
    -webkit-background-clip: text; background-clip: text; color: transparent;
  }
  .sub { font-size: 1.15rem; line-height: 1.5; color: var(--ink-muted, #b7b9c9); max-width: 40ch; }
  .actions { display: flex; flex-wrap: wrap; gap: 0.8rem; justify-content: center; margin-top: 0.5rem; }
  .a-btn { padding: 0.8rem 1.4rem; border-radius: 999px; font-weight: 600; text-decoration: none; transition: transform 0.2s cubic-bezier(0.34,1.56,0.64,1); }
  .a-btn:hover { transform: translateY(-2px); }
  .a-btn--solid { background: #fff; color: #111; }
  .a-btn--ghost { color: var(--ink, #fff); border: 1px solid color-mix(in oklab, currentColor 30%, transparent); }

  @media (prefers-reduced-motion: reduce) { .blob { animation: none; } }
</style>