Motion Lab / FAQ / svg morph toggle / playful
Meestal binnen 10 werkdagen. We werken in vaste sprints, jij weet wat je krijgt en wanneer.
Vanaf 2.450 euro, alles inbegrepen. Hosting via Cloudflare blijft gratis. Geen verrassingen.
Ja. Eenvoudige editor + uitlegvideo. Liever niet zelf? Wij doen het in een onderhoudspakket.
Zeker. Stuur logo, kleuren en fonts mee — wij vertalen het 1:1 naar een snelle site.
// Mechanisme: faq-svg-morph-toggle-playful (techniek #33 — SVG morphing) // Per item morphen we het "+" path naar "×" via GSAP attr-tween (path-d interpolation). // Bouncy back.out(1.7), auto-loop opent items 1..4 met 1.2s tussenpoos, dan reset. import gsap from 'https://esm.sh/[email protected]'; const PLUS = 'M12 5 L12 19 M5 12 L19 12'; const CROSS = 'M6 6 L18 18 M18 6 L6 18'; const reduce = window.matchMedia('(prefers-reduced-motion: reduce)').matches; const root = document.querySelector('.faq-morph-play'); if (root) { const items = Array.from(root.querySelectorAll('[data-faq]')); const setOpen = (item, open) => { const path = item.querySelector('.morph-icon'); const body = item.querySelector('.faq-body'); item.classList.toggle('is-open', open); if (reduce) { path.setAttribute('d', open ? CROSS : PLUS); body.style.height = 'auto'; body.style.opacity = '1'; return; } gsap.to(path, { attr: { d: open ? CROSS : PLUS }, duration: 0.45, ease: 'back.out(1.7)' }); if (open) { const h = body.scrollHeight || 80; gsap.fromTo(body, { height: 0, opacity: 0 }, { height: h, opacity: 1, duration: 0.5, ease: 'back.out(1.4)', onComplete: () => { body.style.height = 'auto'; } }); } else { gsap.to(body, { height: 0, opacity: 0, duration: 0.35, ease: 'power2.in' }); } }; items.forEach((it) => it.querySelector('.faq-trigger').addEventListener('click', () => setOpen(it, !it.classList.contains('is-open')))); // Auto-loop bij viewport-enter const start = () => { items.forEach((it, i) => setTimeout(() => setOpen(it, true), 400 + i * 1200)); setTimeout(() => items.forEach((it) => setOpen(it, false)), 400 + items.length * 1200 + 1500); }; start(); }
<!-- Skeleton: faq-svg-morph-toggle-playful -->
<section class="faq-morph-play">
<h2>Veelgestelde vragen.</h2>
<ul class="faq-list">
<li data-faq class="faq-card">
<button class="faq-trigger" type="button">
<span class="faq-q">Vraag?</span>
<svg class="faq-icon" viewBox="0 0 24 24" width="22" height="22"><path class="morph-icon" d="M12 5 L12 19 M5 12 L19 12" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" fill="none"/></svg>
</button>
<div class="faq-body"><p>Antwoord.</p></div>
</li>
<!-- 4 items totaal -->
</ul>
</section> /* Styling: faq-svg-morph-toggle-playful */
:root {
--block-bg: #FFE3EE;
--block-fg: #2A1530;
--block-card: #FFFFFF;
--block-mint: #A8E0BE;
--block-sky: #B5E3FF;
}
.faq-morph-play { background: var(--block-bg); color: var(--block-fg); font-family: 'Quicksand', system-ui, sans-serif; padding: clamp(3rem,8vw,7rem) clamp(1.5rem,5vw,4rem); }
.faq-morph-play h2 { font-weight: 700; font-size: clamp(2.25rem,5vw,3.5rem); letter-spacing: -0.01em; margin: 0 0 2.5rem 0; }
.faq-morph-play .faq-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 1rem; max-width: 720px; }
.faq-morph-play .faq-card { background: var(--block-card); border-radius: 24px; padding: 0.5rem 1.5rem; box-shadow: 0 6px 0 rgba(42,21,48,.08); transition: box-shadow .25s ease; }
.faq-morph-play .faq-card.is-open { box-shadow: 0 10px 0 var(--block-mint); }
.faq-morph-play .faq-trigger { width: 100%; appearance: none; background: transparent; border: 0; cursor: pointer; padding: 1.25rem 0; display: flex; justify-content: space-between; align-items: center; font: 600 1.05rem/1.3 'Quicksand', sans-serif; color: var(--block-fg); }
.faq-morph-play .faq-icon { background: var(--block-sky); border-radius: 999px; width: 36px; height: 36px; padding: 7px; flex: none; }
.faq-morph-play .faq-card.is-open .faq-icon { background: var(--block-mint); }
.faq-morph-play .faq-body { height: 0; opacity: 0; overflow: hidden; }
.faq-morph-play .faq-body p { margin: 0 0 1.25rem 0; font: 400 0.95rem/1.55 'Quicksand', sans-serif; color: rgba(42,21,48,.78); }
@media (prefers-reduced-motion: reduce) { .faq-morph-play .faq-body { height: auto; opacity: 1; } }