Motion Lab / process / lottie step icons / playful
In 30 minuten begrijpen we je doel, doelgroep en de stem van je merk.
Eerste flow + huisstijl in 5 werkdagen, jij geeft één rondje feedback.
Snelle, schaalbare site op Astro. Jij volgt mee in een live preview.
Domein live, analytics aan, korte overdracht en je bent zelfstandig.
Optioneel maandelijks: nieuwe pagina’s, A/B-testjes, SEO-finetuning.
// Mechanisme: process-lottie-step-icons-playful (techniek #28 — Lottie iconography) // Lottie-web via esm.sh laadt inline animation-data per step. Bij viewport-enter spelen icons // na elkaar af (stagger 0.5s) + GSAP card-reveal (back.out(1.7)). Fallback: SVG SMIL pulse. import lottie from 'https://esm.sh/[email protected]'; import gsap from 'https://esm.sh/[email protected]'; const reduce = window.matchMedia('(prefers-reduced-motion: reduce)').matches; const root = document.querySelector('.proc-lottie-play'); if (root) { const steps = Array.from(root.querySelectorAll('[data-step]')); const players = steps.map((s) => { const mount = s.querySelector('.lottie-mount'); try { return lottie.loadAnimation({ container: mount, renderer: 'svg', loop: true, autoplay: false, animationData: buildPulseLottie() }); } catch (_) { return null; } }); const start = () => { if (reduce) { players.forEach((p) => { try { p && p.goToAndStop(0, true); } catch (_) {} }); return; } players.forEach((p, i) => setTimeout(() => { try { p && p.play(); } catch (_) {} }, i * 500)); gsap.from(steps, { y: 24, autoAlpha: 0, duration: 0.7, ease: 'back.out(1.7)', stagger: 0.12 }); }; const io = new IntersectionObserver((es) => es.forEach((e) => { if (e.isIntersecting) { io.disconnect(); start(); } }), { threshold: 0.25 }); io.observe(root); }
<!-- Skeleton: process-lottie-step-icons-playful -->
<section class="proc-lottie-play">
<h2>Hoe we werken.</h2>
<ol class="step-row">
<li data-step class="step-card">
<div class="lottie-mount" aria-hidden="true"></div>
<span class="step-num">01</span>
<h3>Stap-titel</h3>
<p>Stap-omschrijving.</p>
</li>
<!-- 4-5 steps totaal -->
</ol>
</section> /* Styling: process-lottie-step-icons-playful */
:root {
--block-bg: #FFE3EE;
--block-fg: #2A1530;
--block-card: #FFFFFF;
--block-mint: #A8E0BE;
--block-sky: #B5E3FF;
--block-sun: #FFE08A;
--block-rose: #FFB7C9;
}
.proc-lottie-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); }
.proc-lottie-play h2 { font-weight: 700; font-size: clamp(2.25rem,5vw,3.5rem); letter-spacing: -0.01em; margin: 0 0 3rem 0; }
.proc-lottie-play .step-row { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: 1.25rem; }
.proc-lottie-play .step-card { background: var(--block-card); border-radius: 24px; padding: 1.75rem 1.5rem; position: relative; box-shadow: 0 8px 0 rgba(42,21,48,.08); transition: transform .3s ease; }
.proc-lottie-play .step-card:nth-child(4n+1) .lottie-mount { background: var(--block-mint); }
.proc-lottie-play .step-card:nth-child(4n+2) .lottie-mount { background: var(--block-sky); }
.proc-lottie-play .step-card:nth-child(4n+3) .lottie-mount { background: var(--block-sun); }
.proc-lottie-play .step-card:nth-child(4n) .lottie-mount { background: var(--block-rose); }
.proc-lottie-play .lottie-mount { width: 72px; height: 72px; border-radius: 999px; padding: 12px; display: grid; place-items: center; margin-bottom: 1rem; }
.proc-lottie-play .lottie-mount svg { width: 100%; height: 100%; }
.proc-lottie-play .step-num { font: 700 0.7rem/1 'Quicksand', sans-serif; letter-spacing: 0.18em; background: var(--block-bg); color: var(--block-fg); padding: 0.4rem 0.7rem; border-radius: 999px; display: inline-block; margin-bottom: 0.5rem; }
.proc-lottie-play .step-card h3 { margin: 0.25rem 0 0.5rem 0; font: 700 1.05rem/1.3 'Quicksand', sans-serif; }
.proc-lottie-play .step-card p { margin: 0; font: 400 0.9rem/1.5 'Quicksand', sans-serif; color: rgba(42,21,48,.72); }