SPB Git

spb/svgarden Public

SVGarden — searchable bank of 74 self-contained SVG+CSS animation snippets (svgarden.dev)

HTML 79.2% Astro 10.3% JavaScript 6% CSS 3.7% Shell 0.8%
4.1 KB · 107 lines html
Raw Blame History
1<!--2  ============================================================3  SVGarden — https://www.svgarden.dev4  Author : Simon-Pierre Boucher5  Contact: contact@spboucher.ai6  File   : snippets/scroll/scroll-reveal-mask.html7  Desc   : Items unclip themselves as they enter the scroll viewport8  ============================================================9-->10<!--svgarden11title: Scroll reveal mask12slug: scroll-reveal-mask13category: scroll14tags: [scroll, reveal, clip-path, view-timeline]15difficulty: advanced16techniques: ["animation-timeline: view()", animation-range, "clip-path: inset()", "@supports"]17how_it_works: >18  Where scroll() tracks how far a container has scrolled, view() tracks how far19  a specific element has traveled across the visible viewport of that20  container — every item below owns its own timeline. animation-range: entry21  0% cover 40% confines the clip-path animation to the moment the item enters22  until it is 40% across, so each row wipes open exactly as you meet it and23  plays in reverse when you scroll back. The inset() clip is animatable24  because only its numbers change. Without scroll-driven animation support the25  @supports block is skipped and the rows are simply visible.26support: "view() timelines need Chrome/Edge 115+; other browsers show all rows unmasked."27customizable:28  - { var: "--sg-color", label: "Accent",     type: color, default: "#7F77DD" }29  - { var: "--sg-size",  label: "Box height", type: range, min: 180, max: 400, default: 260, unit: px }30created: 2026-08-1031-->32<div class="sg-scroll-reveal-mask" style="--sg-color:#7F77DD; --sg-size:260px;">33  <p class="sg-scroll-reveal-mask-hint">scroll ↓ to reveal</p>34  <div class="sg-scroll-reveal-mask-item">35    <svg viewBox="0 0 24 24" aria-hidden="true" focusable="false"><circle cx="12" cy="12" r="9" /><path d="M8 12.5 L11 15 L16 9" /></svg>36    <span class="sg-scroll-reveal-mask-bar" style="width: 72%;"></span>37  </div>38  <div class="sg-scroll-reveal-mask-item">39    <svg viewBox="0 0 24 24" aria-hidden="true" focusable="false"><circle cx="12" cy="12" r="9" /><path d="M8 12.5 L11 15 L16 9" /></svg>40    <span class="sg-scroll-reveal-mask-bar" style="width: 55%;"></span>41  </div>42  <div class="sg-scroll-reveal-mask-item">43    <svg viewBox="0 0 24 24" aria-hidden="true" focusable="false"><circle cx="12" cy="12" r="9" /><path d="M8 12.5 L11 15 L16 9" /></svg>44    <span class="sg-scroll-reveal-mask-bar" style="width: 80%;"></span>45  </div>46  <div class="sg-scroll-reveal-mask-item">47    <svg viewBox="0 0 24 24" aria-hidden="true" focusable="false"><circle cx="12" cy="12" r="9" /><path d="M8 12.5 L11 15 L16 9" /></svg>48    <span class="sg-scroll-reveal-mask-bar" style="width: 63%;"></span>49  </div>50</div>51<style>52  .sg-scroll-reveal-mask {53    width: 100%;54    min-width: 220px;55    height: var(--sg-size);56    overflow-y: scroll;57    border: 1px solid rgba(128, 128, 128, 0.3);58    border-radius: 10px;59    padding: 0 14px;60  }61  .sg-scroll-reveal-mask-hint {62    margin: 12px 2px calc(var(--sg-size) * 0.55);63    font-size: 13px;64    opacity: 0.6;65  }66  .sg-scroll-reveal-mask-item {67    display: flex;68    align-items: center;69    gap: 12px;70    padding: 14px;71    margin-bottom: calc(var(--sg-size) * 0.5);72    border: 1px solid rgba(128, 128, 128, 0.3);73    border-radius: 10px;74  }75  .sg-scroll-reveal-mask-item:last-of-type {76    margin-bottom: calc(var(--sg-size) * 0.35);77  }78  .sg-scroll-reveal-mask-item svg {79    width: 26px;80    height: 26px;81    flex: none;82    fill: none;83    stroke: var(--sg-color);84    stroke-width: 2;85    stroke-linecap: round;86    stroke-linejoin: round;87  }88  .sg-scroll-reveal-mask-bar {89    height: 8px;90    border-radius: 4px;91    background: var(--sg-color);92    opacity: 0.55;93  }94  @supports (animation-timeline: view()) {95    .sg-scroll-reveal-mask-item {96      animation: sg-scroll-reveal-mask-wipe linear both;97      animation-duration: auto;98      animation-timeline: view();99      animation-range: entry 0% cover 40%;100    }101  }102  @keyframes sg-scroll-reveal-mask-wipe {103    from { clip-path: inset(0 100% 0 0 round 10px); opacity: 0.2; }104    to   { clip-path: inset(0 0 0 0 round 10px); opacity: 1; }105  }106</style>107