Zoeken...  ⌘K GitHub

HeroAsymmetric Hero

Drie-koloms asymmetrisch grid: afbeeldingen links+rechts, tekst gecentreerd. Badges op afbeeldingen.

/hero-asymmetric
src/components/hero/HeroAsymmetric.astro
---
/**
 * HeroAsymmetric
 * 3-koloms asymmetrisch grid: tekst + 2 afbeeldingen met badge overlays.
 * Editorial / Modern Retail mix — gedurfd layout, typografisch sterk.
 */
interface Props {
  overline?: string;
  headline: string;
  sub: string;
  ctaLabel?: string;
  ctaHref?: string;
  ctaSecondary?: string;
  ctaSecondaryHref?: string;
  image1: string;
  image2: string;
  badge1?: string;
  badge2?: string;
}

const {
  overline,
  headline,
  sub,
  ctaLabel = 'Lees meer',
  ctaHref = '#',
  ctaSecondary,
  ctaSecondaryHref = '#',
  image1,
  image2,
  badge1,
  badge2,
} = Astro.props;
---

<section class="has" data-component="hero-asymmetric">
  <div class="has__inner">
    <!-- Col 1: image tall -->
    <div class="has__col has__col--img1">
      <div class="has__img-wrap">
        <img src={image1} alt="" class="has__img" loading="eager" />
        {badge1 && <span class="has__badge has__badge--tl">{badge1}</span>}
      </div>
    </div>

    <!-- Col 2: text centered -->
    <div class="has__col has__col--text">
      {overline && <p class="has__overline">{overline}</p>}
      <h1 class="has__headline" set:html={headline} />
      <p class="has__sub">{sub}</p>
      <div class="has__ctas">
        <a href={ctaHref} class="has__cta has__cta--primary">{ctaLabel}</a>
        {ctaSecondary && (
          <a href={ctaSecondaryHref} class="has__cta has__cta--link">
            {ctaSecondary}
            <svg width="14" height="14" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2"><path d="M3 8h10M9 4l4 4-4 4"/></svg>
          </a>
        )}
      </div>
    </div>

    <!-- Col 3: image shorter + badge -->
    <div class="has__col has__col--img2">
      <div class="has__img-wrap">
        <img src={image2} alt="" class="has__img" loading="eager" />
        {badge2 && <span class="has__badge has__badge--br">{badge2}</span>}
      </div>
    </div>
  </div>
</section>

<style>
  .has {
    background: var(--color-bg, #fff);
    padding: 4rem 1.5rem;
    overflow: hidden;
  }

  .has__inner {
    max-width: 1200px;
    margin: 0 auto;
    display: grid;
    grid-template-columns: 1fr 1.2fr 1fr;
    gap: 1.5rem;
    align-items: center;
    min-height: 560px;
  }

  /* Images */
  .has__col--img1 .has__img-wrap,
  .has__col--img2 .has__img-wrap {
    position: relative;
    border-radius: calc(var(--radius, 0.5rem) * 2);
    overflow: hidden;
  }

  .has__col--img1 {
    align-self: stretch;
  }

  .has__col--img2 {
    align-self: end;
  }

  .has__img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
    min-height: 320px;
    transition: transform 0.6s ease;
  }

  .has__col--img1 .has__img { height: 520px; }
  .has__col--img2 .has__img { height: 360px; }

  .has__img-wrap:hover .has__img {
    transform: scale(1.03);
  }

  .has__badge {
    position: absolute;
    background: var(--color-accent, #6366f1);
    color: #fff;
    font-size: 0.75rem;
    font-weight: 700;
    padding: 0.4rem 0.875rem;
    border-radius: 100px;
    white-space: nowrap;
  }

  .has__badge--tl { top: 1rem; left: 1rem; }
  .has__badge--br { bottom: 1rem; right: 1rem; }

  /* Text */
  .has__col--text {
    padding: 1rem;
    text-align: center;
  }

  .has__overline {
    font-size: 0.75rem;
    font-weight: 700;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--color-accent, #6366f1);
    margin-bottom: 1rem;
  }

  .has__headline {
    font-size: clamp(2rem, 3.5vw, 3.25rem);
    font-weight: 800;
    line-height: 1.1;
    letter-spacing: -0.03em;
    color: var(--color-primary, #0a0a0a);
    margin-bottom: 1.25rem;
  }

  .has__headline :global(em) {
    font-style: normal;
    color: var(--color-accent, #6366f1);
  }

  .has__sub {
    font-size: 1rem;
    line-height: 1.7;
    color: var(--color-muted, #6b7280);
    margin-bottom: 2rem;
  }

  .has__ctas {
    display: flex;
    gap: 1rem;
    justify-content: center;
    flex-wrap: wrap;
  }

  .has__cta {
    text-decoration: none;
    font-weight: 700;
    font-size: 0.9375rem;
    transition: all 0.2s;
  }

  .has__cta--primary {
    display: inline-block;
    background: var(--color-primary, #0a0a0a);
    color: #fff;
    padding: 0.8125rem 1.75rem;
    border-radius: var(--radius, 0.5rem);
  }

  .has__cta--primary:hover {
    background: var(--color-accent, #6366f1);
    transform: translateY(-1px);
  }

  .has__cta--link {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    color: var(--color-primary, #0a0a0a);
    padding: 0.8125rem 0;
    opacity: 0.7;
  }

  .has__cta--link:hover {
    opacity: 1;
    color: var(--color-accent, #6366f1);
  }

  @media (max-width: 900px) {
    .has__inner {
      grid-template-columns: 1fr;
      min-height: auto;
    }

    .has__col--img1 { order: 1; }
    .has__col--text { order: 2; }
    .has__col--img2 { order: 3; }

    .has__col--img1 .has__img,
    .has__col--img2 .has__img { height: 280px; }
  }
</style>

Props

Prop Type Default Beschrijving
headline * string H1 — gebruik <em> voor accent
sub * string Subtitel
image1 * string Hoge afbeelding links
image2 * string Kortere afbeelding rechts
overline string Kleine tekst boven headline
badge1 string Badge op linker afbeelding
badge2 string Badge op rechter afbeelding

* = verplicht