Zoeken...  ⌘K GitHub

HeroAsymmetric Hero

Drie-koloms hero: twee staande beelden met badge flankeren een gecentreerde tekstkolom met overline, kop, sub en twee CTA's.

/hero-asymmetric
src/components/hero/HeroAsymmetric.astro
---
/**
 * HeroAsymmetric
 * Drie-koloms hero: twee staande beelden flankeren een gecentreerde tekstkolom
 * met overline, kop (cursief accent-woord), sub en twee CTA's. Beelden dragen
 * een badge (social proof).
 *
 * Props: zie interface hieronder. Alle copy is prop-driven.
 */
interface ImageSlide {
  src: string;
  alt?: string;
  badge?: string;
}
interface Props {
  overline?: string;
  headline: string;
  accent?: string;
  sub?: string;
  primaryCta?: { label: string; href: string };
  linkCta?: { label: string; href: string };
  imageLeft?: ImageSlide;
  imageRight?: ImageSlide;
}

const {
  overline,
  headline,
  accent,
  sub,
  primaryCta,
  linkCta,
  imageLeft,
  imageRight,
} = Astro.props;
---

<section class:list={['bl-section', 'has']} data-component="hero-asymmetric">
  <div class="bl-inner has__inner">
    {imageLeft && (
      <div class="has__col has__col--img1">
        <div class="has__img-wrap">
          <img data-allow-img src={imageLeft.src} alt={imageLeft.alt ?? ''} class="has__img" loading="eager" fetchpriority="high" decoding="async" />
          {imageLeft.badge && <span class="has__badge has__badge--tl">{imageLeft.badge}</span>}
        </div>
      </div>
    )}
    <div class="has__col has__col--text">
      {overline && <p class="has__overline">{overline}</p>}
      <h1 class="has__headline">{headline}{accent && <em> {accent}</em>}</h1>
      {sub && <p class="has__sub">{sub}</p>}
      {(primaryCta || linkCta) && (
        <div class="has__ctas">
          {primaryCta && <a href={primaryCta.href} class="has__cta has__cta--primary">{primaryCta.label}</a>}
          {linkCta && (
            <a href={linkCta.href} class="has__cta has__cta--link">
              {linkCta.label}
              <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"></path></svg>
            </a>
          )}
        </div>
      )}
    </div>
    {imageRight && (
      <div class="has__col has__col--img2">
        <div class="has__img-wrap">
          <img data-allow-img src={imageRight.src} alt={imageRight.alt ?? ''} class="has__img" loading="eager" fetchpriority="high" decoding="async" />
          {imageRight.badge && <span class="has__badge has__badge--br">{imageRight.badge}</span>}
        </div>
      </div>
    )}
  </div>
</section>

<style>
.has{background:var(--color-bg, #fff);overflow:hidden}
.has__inner{display:grid;grid-template-columns:1fr 1.2fr 1fr;gap:1.5rem;align-items:center;min-height:560px}
.has__col--img1 .has__img-wrap,.has__col--img2 .has__img-wrap{position:relative;border-radius:calc(var(--radius, .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 .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:.75rem;font-weight:700;padding:.4rem .875rem;border-radius:100px;white-space:nowrap}
.has__badge--tl{top:1rem;left:1rem}
.has__badge--br{bottom:1rem;right:1rem}
.has__col--text{padding:1rem;text-align:center}
.has__overline{font-size:.8125rem;font-weight:700;letter-spacing:.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:-.03em;color:var(--color-primary, #0a0a0a);margin-bottom:1.25rem}
.has__headline 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:.9375rem;transition: opacity, transform, background-color, color, border-color, box-shadow, filter .2s}
.has__cta--primary{display:inline-block;background:var(--color-primary, #0a0a0a);color:#fff;padding:.8125rem 1.75rem;border-radius:var(--radius, .5rem)}
.has__cta--primary:hover{background:var(--color-accent, #6366f1);transform:translateY(-1px)}
.has__cta--link{display:inline-flex;align-items:center;gap:.35rem;color:var(--color-primary, #0a0a0a);padding:.8125rem 0;opacity:.7}
.has__cta--link:hover{opacity:1;color:var(--color-accent, #6366f1)}
@media (max-width:768px){
  .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
overline string - Kleine overline boven de kop
headline * string - H1-kop
accent string - Accent-woord direct na de kop
sub string - Ondertitel
primaryCta { label: string; href: string } - Primaire knop
linkCta { label: string; href: string } - Secundaire tekstlink met pijl
imageLeft { src: string; alt?: string; badge?: string } - Linker beeld + optionele badge
imageRight { src: string; alt?: string; badge?: string } - Rechter beeld + optionele badge

* = verplicht