Zoeken...  ⌘K GitHub

ClientLogosScroll Social Proof

Dubbele scrollende logo rij voor klanten (marquee-stijl).

/client-logos-scroll
src/components/social-proof/ClientLogosScroll.astro
---
/**
 * ClientLogosScroll
 * Dubbele scrollende logo rij (marquee-stijl) voor klanten/partners.
 */
interface Props {
  eyebrow?: string;
  logos: { name: string; src?: string }[];
  speed?: 'slow' | 'normal' | 'fast';
  bg?: 'white' | 'light' | 'dark';
}
const { eyebrow = 'Vertrouwd door', logos, speed = 'normal', bg = 'white' } = Astro.props;
const duration = speed === 'slow' ? '40s' : speed === 'fast' ? '15s' : '25s';
---
<section class={`cls cls--${bg}`}>
  <div class="cls-inner">
    {eyebrow && <p class="cls-eyebrow">{eyebrow}</p>}
    <div class="cls-track-wrap">
      <div class="cls-track" style={`animation-duration: ${duration}`}>
        {[...logos, ...logos].map((l) => (
          <div class="cls-logo">
            {l.src
              ? <img src={l.src} alt={l.name} class="cls-img" />
              : <span class="cls-name">{l.name}</span>
            }
          </div>
        ))}
      </div>
    </div>
  </div>
</section>
<style>
  .cls { padding: 3.5rem 0; overflow: hidden; }
  .cls--white { background: #fff; border-top: 1px solid #e5e7eb; border-bottom: 1px solid #e5e7eb; }
  .cls--light { background: #f8fafc; border-top: 1px solid #e5e7eb; border-bottom: 1px solid #e5e7eb; }
  .cls--dark { background: #0a0a0a; }
  .cls-inner { }
  .cls-eyebrow { text-align: center; font-size: 0.6875rem; font-weight: 700; letter-spacing: 0.1em; text-transform: uppercase; margin: 0 0 1.75rem; }
  .cls--white .cls-eyebrow, .cls--light .cls-eyebrow { color: #9ca3af; }
  .cls--dark .cls-eyebrow { color: rgba(255,255,255,0.3); }
  .cls-track-wrap { position: relative; }
  .cls-track-wrap::before, .cls-track-wrap::after { content: ''; position: absolute; top: 0; bottom: 0; width: 120px; z-index: 2; pointer-events: none; }
  .cls--white .cls-track-wrap::before, .cls--light .cls-track-wrap::before { background: linear-gradient(90deg, #fff, transparent); }
  .cls--white .cls-track-wrap::after, .cls--light .cls-track-wrap::after { background: linear-gradient(-90deg, #fff, transparent); right: 0; }
  .cls--dark .cls-track-wrap::before { background: linear-gradient(90deg, #0a0a0a, transparent); }
  .cls--dark .cls-track-wrap::after { background: linear-gradient(-90deg, #0a0a0a, transparent); right: 0; }
  .cls--light .cls-track-wrap::before { background: linear-gradient(90deg, #f8fafc, transparent); }
  .cls--light .cls-track-wrap::after { background: linear-gradient(-90deg, #f8fafc, transparent); right: 0; }
  .cls-track { display: flex; gap: 3rem; align-items: center; width: max-content; animation: cls-scroll linear infinite; }
  @keyframes cls-scroll { from { transform: translateX(0); } to { transform: translateX(-50%); } }
  .cls-logo { flex-shrink: 0; display: flex; align-items: center; justify-content: center; padding: 0.5rem 1rem; }
  .cls-img { height: 28px; width: auto; opacity: 0.45; filter: grayscale(1); }
  .cls-name { font-size: 1.0625rem; font-weight: 800; letter-spacing: -0.02em; white-space: nowrap; }
  .cls--white .cls-name, .cls--light .cls-name { color: #d1d5db; }
  .cls--dark .cls-name { color: rgba(255,255,255,0.18); }
</style>

Props

Prop Type Default Beschrijving
logos * { name: string; src?: string }[] Klantlogo items
eyebrow string Eyebrow
speed 'slow' | 'normal' | 'fast' 'normal' Scrollsnelheid
bg 'white' | 'light' | 'dark' Achtergrond variant

* = verplicht