FeaturesHorizontal Sections
Alternerende horizontale feature rijen — afbeelding en tekst wisselen per rij.
src/components/sections/FeaturesHorizontal.astro
---
/**
* FeaturesHorizontal
* Alternating horizontale feature rijen: afbeelding + tekst, steeds wisselend.
*/
interface Feature {
label?: string;
headline: string;
body: string;
image: string;
imageAlt?: string;
ctaLabel?: string;
ctaHref?: string;
}
interface Props {
eyebrow?: string;
headline?: string;
features: Feature[];
}
const { eyebrow, headline, features = [] } = Astro.props;
---
<section class="fh" data-component="features-horizontal">
{(eyebrow || headline) && (
<div class="fh__header">
{eyebrow && <p class="fh__eyebrow">{eyebrow}</p>}
{headline && <h2 class="fh__title" set:html={headline} />}
</div>
)}
<div class="fh__rows">
{features.map((f, i) => (
<div class:list={['fh__row', { 'fh__row--reversed': i % 2 !== 0 }]}>
<div class="fh__row-img">
<img src={f.image} alt={f.imageAlt ?? ''} loading="lazy" />
</div>
<div class="fh__row-text">
{f.label && <span class="fh__label">{f.label}</span>}
<h3 class="fh__row-headline" set:html={f.headline} />
<p class="fh__row-body">{f.body}</p>
{f.ctaLabel && (
<a href={f.ctaHref ?? '#'} class="fh__row-cta">
{f.ctaLabel} →
</a>
)}
</div>
</div>
))}
</div>
</section>
<style>
.fh {
background: var(--color-bg, #fff);
padding: 5rem 1.5rem;
}
.fh__header {
max-width: 640px;
margin: 0 auto 4rem;
text-align: center;
}
.fh__eyebrow {
font-size: 0.75rem;
font-weight: 700;
letter-spacing: 0.1em;
text-transform: uppercase;
color: var(--color-accent, #6366f1);
margin-bottom: 0.75rem;
}
.fh__title {
font-size: clamp(1.875rem, 3vw, 2.75rem);
font-weight: 800;
letter-spacing: -0.03em;
color: var(--color-primary, #0a0a0a);
}
.fh__title :global(em) {
font-style: normal;
color: var(--color-accent, #6366f1);
}
.fh__rows {
max-width: 1100px;
margin: 0 auto;
display: flex;
flex-direction: column;
gap: 5rem;
}
.fh__row {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 4rem;
align-items: center;
}
.fh__row--reversed {
direction: rtl;
}
.fh__row--reversed > * {
direction: ltr;
}
.fh__row-img img {
width: 100%;
height: 400px;
object-fit: cover;
border-radius: calc(var(--radius, 0.5rem) * 2);
}
.fh__label {
display: inline-block;
font-size: 0.75rem;
font-weight: 700;
letter-spacing: 0.08em;
text-transform: uppercase;
color: var(--color-accent, #6366f1);
background: color-mix(in srgb, var(--color-accent, #6366f1) 10%, transparent);
padding: 0.3rem 0.75rem;
border-radius: 100px;
margin-bottom: 1rem;
}
.fh__row-headline {
font-size: clamp(1.5rem, 2.5vw, 2.125rem);
font-weight: 800;
letter-spacing: -0.02em;
line-height: 1.2;
color: var(--color-primary, #0a0a0a);
margin-bottom: 1rem;
}
.fh__row-headline :global(em) {
font-style: normal;
color: var(--color-accent, #6366f1);
}
.fh__row-body {
font-size: 1rem;
line-height: 1.7;
color: var(--color-muted, #6b7280);
margin-bottom: 1.5rem;
}
.fh__row-cta {
display: inline-block;
font-weight: 700;
font-size: 0.9375rem;
color: var(--color-accent, #6366f1);
text-decoration: none;
transition: gap 0.15s;
}
.fh__row-cta:hover { opacity: 0.8; }
@media (max-width: 768px) {
.fh__row {
grid-template-columns: 1fr;
gap: 2rem;
}
.fh__row--reversed { direction: ltr; }
.fh__row-img img { height: 260px; }
}
</style>
Props
| Prop | Type | Default | Beschrijving |
|---|---|---|---|
features * | Feature[] | — | Array van features. Elke feature heeft image, headline, body. |
eyebrow | string | — | Label boven sectie headline |
headline | string | — | Sectie headline |
* = verplicht