FooterMega Footer
Uitgebreide donkere footer met accent featured-strip, merk-kolom met socials + nieuwsbrief en meerdere link-kolommen.
src/components/footer/FooterMega.astro
---
/**
* FooterMega — uitgebreide donkere footer: accent featured-strip bovenaan, een
* merk-kolom met socials + nieuwsbrief, meerdere link-kolommen, en een
* copyright-band onderaan.
*
* Props:
* - featured?: { label: string; desc: string; cta: { label: string; href: string } } | null
* - logo?: string
* - logoHref?: string
* - tagline?: string
* - socials?: { network: 'instagram'|'linkedin'|'twitter'; href: string }[]
* - newsletterLabel?: string
* - newsletterPlaceholder?: string
* - columns?: { title: string; links: { label: string; href: string }[] }[]
* - copyright?: string (default: "© {jaar}")
* - bottomLinks?: { label: string; href: string }[]
* - background?: string
* - accent?: string
*/
interface FooterColumn { title: string; links: { label: string; href: string }[] }
interface Social { network: 'instagram' | 'linkedin' | 'twitter'; href: string }
interface Featured { label: string; desc: string; cta: { label: string; href: string } }
interface Props {
featured?: Featured | null;
logo?: string;
logoHref?: string;
tagline?: string;
socials?: Social[];
newsletterLabel?: string;
newsletterPlaceholder?: string;
columns?: FooterColumn[];
copyright?: string;
bottomLinks?: { label: string; href: string }[];
background?: string;
accent?: string;
}
const {
featured = { label: 'Nieuw: AI Automations', desc: 'Automatiseer je marketing met onze nieuwe AI agents.', cta: { label: 'Meer weten →', href: '#' } },
logo = 'Merk',
logoHref = '/',
tagline = 'Online marketing die werkt voor ambitieuze bedrijven.',
socials = [
{ network: 'instagram', href: '#' },
{ network: 'linkedin', href: '#' },
{ network: 'twitter', href: '#' },
],
newsletterLabel = 'Nieuwsbrief',
newsletterPlaceholder = 'Jouw e-mailadres',
columns = [
{ title: 'Diensten', links: [
{ label: 'Google Ads', href: '#' },
{ label: 'Meta Ads', href: '#' },
{ label: 'SEO', href: '#' },
{ label: 'Webdesign', href: '#' },
] },
{ title: 'Bedrijf', links: [
{ label: 'Over ons', href: '#' },
{ label: 'Cases', href: '#' },
{ label: 'Blog', href: '#' },
{ label: 'Vacatures', href: '#' },
] },
{ title: 'Contact', links: [
{ label: 'Gratis gesprek', href: '#' },
{ label: 'Mail ons', href: '#' },
{ label: 'Bel ons', href: '#' },
] },
],
copyright,
bottomLinks = [
{ label: 'Privacybeleid', href: '#' },
{ label: 'Algemene voorwaarden', href: '#' },
],
background = 'var(--color-primary, #0a0a0a)',
accent = 'var(--color-accent, #6366f1)',
} = Astro.props;
const year = new Date().getFullYear();
const copyrightText = copyright ?? `© ${year}`;
const ICONS: Record<Social['network'], string> = {
instagram: 'M12 2.163c3.204 0 3.584.012 4.85.07 3.252.148 4.771 1.691 4.919 4.919.058 1.265.069 1.645.069 4.849 0 3.205-.012 3.584-.069 4.849-.149 3.225-1.664 4.771-4.919 4.919-1.266.058-1.644.07-4.85.07-3.204 0-3.584-.012-4.849-.07-3.26-.149-4.771-1.699-4.919-4.92-.058-1.265-.07-1.644-.07-4.849 0-3.204.013-3.583.07-4.849.149-3.227 1.664-4.771 4.919-4.919 1.266-.057 1.645-.069 4.849-.069zm0-2.163c-3.259 0-3.667.014-4.947.072-4.358.2-6.78 2.618-6.98 6.98-.059 1.281-.073 1.689-.073 4.948 0 3.259.014 3.668.072 4.948.2 4.358 2.618 6.78 6.98 6.98 1.281.058 1.689.072 4.948.072 3.259 0 3.668-.014 4.948-.072 4.354-.2 6.782-2.618 6.979-6.98.059-1.28.073-1.689.073-4.948 0-3.259-.014-3.667-.072-4.947-.196-4.354-2.617-6.78-6.979-6.98-1.281-.059-1.69-.073-4.949-.073zm0 5.838c-3.403 0-6.162 2.759-6.162 6.162s2.759 6.163 6.162 6.163 6.162-2.759 6.162-6.163c0-3.403-2.759-6.162-6.162-6.162zm0 10.162c-2.209 0-4-1.79-4-4 0-2.209 1.791-4 4-4s4 1.791 4 4c0 2.21-1.791 4-4 4zm6.406-11.845c-.796 0-1.441.645-1.441 1.44s.645 1.44 1.441 1.44c.795 0 1.439-.645 1.439-1.44s-.644-1.44-1.439-1.44z',
linkedin: 'M20.447 20.452h-3.554v-5.569c0-1.328-.027-3.037-1.852-3.037-1.853 0-2.136 1.445-2.136 2.939v5.667H9.351V9h3.414v1.561h.046c.477-.9 1.637-1.85 3.37-1.85 3.601 0 4.267 2.37 4.267 5.455v6.286zM5.337 7.433c-1.144 0-2.063-.926-2.063-2.065 0-1.138.92-2.063 2.063-2.063 1.14 0 2.064.925 2.064 2.063 0 1.139-.925 2.065-2.064 2.065zm1.782 13.019H3.555V9h3.564v11.452zM22.225 0H1.771C.792 0 0 .774 0 1.729v20.542C0 23.227.792 24 1.771 24h20.451C23.2 24 24 23.227 24 22.271V1.729C24 .774 23.2 0 22.222 0h.003z',
twitter: 'M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-4.714-6.231-5.401 6.231H2.744l7.737-8.835L1.254 2.25H8.08l4.259 5.633 5.905-5.633zm-1.161 17.52h1.833L7.084 4.126H5.117z',
};
---
<footer class="bl-section fm" style={`--fm-bg:${background};--fm-ac:${accent}`}>
{featured && (
<div class="fm__featured">
<div class="bl-inner fm__featured-inner">
<div class="fm__featured-text">
<p class="fm__featured-label"><span aria-hidden="true">→ </span>{featured.label}</p>
<p class="fm__featured-desc">{featured.desc}</p>
</div>
<a href={featured.cta.href} class="fm__featured-cta">{featured.cta.label}</a>
</div>
</div>
)}
<div class="fm__body">
<div class="bl-inner fm__inner">
<div class="fm__brand">
<a href={logoHref} class="fm__logo"><span class="fm__logo-text">{logo}</span></a>
{tagline && <p class="fm__tagline">{tagline}</p>}
{socials.length > 0 && (
<div class="fm__socials">
{socials.map(s => (
<a href={s.href} class="fm__social" target="_blank" rel="noopener" aria-label={s.network}>
<svg width="18" height="18" viewBox="0 0 24 24" fill="currentColor"><path d={ICONS[s.network]}></path></svg>
</a>
))}
</div>
)}
{newsletterLabel && (
<div class="fm__newsletter">
<p class="fm__newsletter-label">{newsletterLabel}</p>
<form class="fm__newsletter-form">
<input type="email" placeholder={newsletterPlaceholder} class="fm__newsletter-input" aria-label={newsletterLabel} />
<button type="submit" class="fm__newsletter-btn" aria-label="Inschrijven">→</button>
</form>
</div>
)}
</div>
{columns.map(col => (
<div class="fm__col">
<h3 class="fm__col-heading">{col.title}</h3>
<ul class="fm__col-links">
{col.links.map(l => <li><a href={l.href} class="fm__col-link">{l.label}</a></li>)}
</ul>
</div>
))}
</div>
</div>
<div class="fm__bottom">
<div class="bl-inner fm__bottom-inner">
<p class="fm__copyright">{copyrightText}</p>
{bottomLinks.length > 0 && (
<div class="fm__bottom-links">
{bottomLinks.map(l => <a href={l.href} class="fm__bottom-link">{l.label}</a>)}
</div>
)}
</div>
</div>
</footer>
<style>
.fm{background:var(--fm-bg);color:#aaa;padding-block:0}
.fm__featured{background:var(--fm-ac)}
.fm__featured-inner{padding-block:1.25rem;display:flex;align-items:center;justify-content:space-between;gap:1rem;flex-wrap:wrap}
.fm__featured-label{font-weight:700;color:#fff;font-size:.9375rem;margin:0}
.fm__featured-desc{font-size:.875rem;color:#ffffffe6;margin:.15rem 0 0}
.fm__featured-cta{display:inline-block;background:#ffffff29;color:#fff;padding:.5rem 1.25rem;border-radius:.5rem;text-decoration:none;font-weight:700;font-size:.875rem;white-space:nowrap;transition:background .2s}
.fm__featured-cta:hover{background:#ffffff40}
.fm__body{border-bottom:1px solid rgba(255,255,255,.08)}
.fm__inner{padding-block:4rem;display:grid;grid-template-columns:1.75fr 1fr 1fr 1fr;gap:3rem}
.fm__logo{text-decoration:none;display:inline-block;margin-bottom:1rem}
.fm__logo-text{font-size:1.25rem;font-weight:800;color:#fff;letter-spacing:-.03em}
.fm__tagline{font-size:1rem;line-height:1.65;margin-bottom:1.5rem;max-width:28ch;color:#aaa}
.fm__socials{display:flex;gap:.625rem;margin-bottom:1.75rem}
.fm__social{width:36px;height:36px;background:#ffffff1f;border-radius:.5rem;display:flex;align-items:center;justify-content:center;color:#e8e8e8;text-decoration:none;transition:background .15s,color .15s}
.fm__social:hover{background:var(--fm-ac);color:#fff}
.fm__newsletter-label{font-size:.8125rem;font-weight:600;color:#999;margin-bottom:.625rem;text-transform:uppercase;letter-spacing:.06em}
.fm__newsletter-form{display:flex;gap:0;border:1px solid rgba(255,255,255,.18);border-radius:.5rem;overflow:hidden}
.fm__newsletter-input{flex:1;background:#ffffff14;border:none;padding:.625rem .875rem;color:#fff;font-size:.9375rem;outline:none}
.fm__newsletter-input::placeholder{color:#999}
.fm__newsletter-btn{background:var(--fm-ac);border:none;color:#fff;padding:.625rem 1rem;cursor:pointer;font-size:1rem;transition:filter .15s}
.fm__newsletter-btn:hover{filter:brightness(1.15)}
.fm__col-heading{font-size:.75rem;font-weight:700;letter-spacing:.08em;text-transform:uppercase;color:#999;margin-bottom:1rem}
.fm__col-links{list-style:none;padding:0;margin:0;display:flex;flex-direction:column;gap:.5rem}
.fm__col-link{font-size:.9375rem;color:#aaa;text-decoration:none;transition:color .15s}
.fm__col-link:hover{color:#fff}
.fm__bottom-inner{padding-block:1.25rem;display:flex;align-items:center;justify-content:space-between;gap:1rem;flex-wrap:wrap}
.fm__copyright{font-size:.8125rem;color:#999;margin:0}
.fm__bottom-links{display:flex;gap:1.5rem}
.fm__bottom-link{font-size:.8125rem;color:#999;text-decoration:none;transition:color .15s}
.fm__bottom-link:hover{color:#fff}
@media(max-width:860px){.fm__inner{grid-template-columns:1fr 1fr}.fm__brand{grid-column:1 / -1}}
@media(max-width:520px){.fm__inner{grid-template-columns:1fr}.fm__bottom-inner{flex-direction:column;align-items:flex-start}}
</style>
Props
| Prop | Type | Default | Beschrijving |
|---|---|---|---|
featured | { label; desc; cta: { label; href } } | null | - | Accent featured-strip bovenaan |
logo | string | 'Merk' | Merknaam |
tagline | string | - | Korte omschrijving |
socials | { network: 'instagram'|'linkedin'|'twitter'; href }[] | - | Social-media links met SVG-icoon |
newsletterLabel | string | 'Nieuwsbrief' | Label boven het nieuwsbrief-formulier |
newsletterPlaceholder | string | - | Placeholder e-mailveld |
columns | { title; links: { label; href }[] }[] | - | Link-kolommen |
bottomLinks | { label; href }[] | - | Secundaire links onderaan |
copyright | string | '© {jaar}' | Copyright-regel |
background | string | - | Achtergrondkleur |
accent | string | - | Accent-kleur (strip, hover, knop) |
* = verplicht