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%
5.4 KB · 132 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-scene-day-night.html7  Desc   : Sun sets and moon rises as you scroll the section8  ============================================================9-->10<!--svgarden11title: Day → night scroll scene12slug: scroll-scene-day-night13category: scroll14tags: [scroll, scene, day-night, choreography]15difficulty: advanced16techniques: ["animation-timeline: scroll()", fill-color-keyframes, "color-mix()", translate-property, "@supports"]17how_it_works: >18  Four elements share one scroll(nearest) timeline, each with its own19  keyframes: the sky rect tweens its SVG fill from the day color to the night20  color (fill is a CSS property, so it interpolates like any other), the sun21  translates below the horizon while the moon rises on the mirrored path, and22  the stars hold at opacity 0 until 55% before fading in. Sharing a timeline23  is what keeps the choreography locked to scrubbing — reverse scrolling24  rewinds dawn. The static fallback uses color-mix() to freeze the scene at25  dusk, halfway between the two customizable sky colors.26support: "Scroll-driven animations need Chrome/Edge 115+; other browsers show a static dusk scene (color-mix of the two sky colors)."27customizable:28  - { var: "--sg-sky-day",   label: "Day sky",    type: color, default: "#8FC7EE" }29  - { var: "--sg-sky-night", label: "Night sky",  type: color, default: "#1B2140" }30  - { var: "--sg-size",      label: "Box height", type: range, min: 180, max: 400, default: 260, unit: px }31created: 2026-08-1032-->33<div class="sg-scroll-scene-day-night" style="--sg-sky-day:#8FC7EE; --sg-sky-night:#1B2140; --sg-size:260px;">34  <div class="sg-scroll-scene-day-night-track">35    <div class="sg-scroll-scene-day-night-sticky">36      <svg viewBox="0 0 200 120" preserveAspectRatio="xMidYMid slice" aria-hidden="true" focusable="false">37        <rect class="sg-scroll-scene-day-night-sky" x="0" y="0" width="200" height="120" />38        <g class="sg-scroll-scene-day-night-stars">39          <circle cx="30" cy="22" r="1.3" /><circle cx="70" cy="14" r="1" />40          <circle cx="120" cy="26" r="1.2" /><circle cx="168" cy="16" r="1" />41        </g>42        <circle class="sg-scroll-scene-day-night-sun" cx="52" cy="42" r="14" />43        <g class="sg-scroll-scene-day-night-moon">44          <circle cx="146" cy="38" r="11" />45          <circle class="sg-scroll-scene-day-night-crater" cx="142" cy="35" r="2.6" />46          <circle class="sg-scroll-scene-day-night-crater" cx="150" cy="42" r="1.8" />47        </g>48        <path class="sg-scroll-scene-day-night-hills" d="M0 92 C 40 76, 76 100, 112 88 C 150 76, 176 96, 200 90 V120 H0 Z" />49      </svg>50      <span class="sg-scroll-scene-day-night-hint">scroll ↓</span>51    </div>52  </div>53</div>54<style>55  .sg-scroll-scene-day-night {56    width: 100%;57    min-width: 220px;58    height: var(--sg-size);59    overflow-y: scroll;60    border: 1px solid rgba(128, 128, 128, 0.3);61    border-radius: 10px;62  }63  .sg-scroll-scene-day-night-track { height: calc(var(--sg-size) * 3); }64  .sg-scroll-scene-day-night-sticky {65    position: sticky;66    top: 0;67    height: var(--sg-size);68    /* no overflow:hidden here — it would become the nearest scroll container69       and scroll(nearest) would bind to a box that never scrolls */70  }71  .sg-scroll-scene-day-night-sticky svg {72    display: block;73    width: 100%;74    height: 100%;75  }76  .sg-scroll-scene-day-night-hint {77    position: absolute;78    right: 12px;79    bottom: 8px;80    font-size: 12px;81    color: #ffffff;82    background: rgba(0, 0, 0, 0.35);83    padding: 2px 8px;84    border-radius: 999px;85  }86  /* fallback = frozen dusk, halfway between the two skies */87  .sg-scroll-scene-day-night-sky { fill: color-mix(in srgb, var(--sg-sky-day) 45%, var(--sg-sky-night)); }88  .sg-scroll-scene-day-night-sun { fill: #f6c34a; translate: 0 28px; }89  .sg-scroll-scene-day-night-moon { fill: #e9edf5; translate: 0 30px; }90  .sg-scroll-scene-day-night-crater { fill: rgba(0, 0, 0, 0.15); }91  .sg-scroll-scene-day-night-stars { fill: #ffffff; opacity: 0.45; }92  .sg-scroll-scene-day-night-hills { fill: rgba(18, 22, 34, 0.85); }93  @supports (animation-timeline: scroll()) {94    .sg-scroll-scene-day-night-sky {95      animation: sg-scroll-scene-day-night-dim linear both;96      animation-duration: auto;97      animation-timeline: scroll(nearest);98    }99    .sg-scroll-scene-day-night-sun {100      animation: sg-scroll-scene-day-night-set linear both;101      animation-duration: auto;102      animation-timeline: scroll(nearest);103    }104    .sg-scroll-scene-day-night-moon {105      animation: sg-scroll-scene-day-night-rise linear both;106      animation-duration: auto;107      animation-timeline: scroll(nearest);108    }109    .sg-scroll-scene-day-night-stars {110      animation: sg-scroll-scene-day-night-twinkle linear both;111      animation-duration: auto;112      animation-timeline: scroll(nearest);113    }114  }115  @keyframes sg-scroll-scene-day-night-dim {116    from { fill: var(--sg-sky-day); }117    to   { fill: var(--sg-sky-night); }118  }119  @keyframes sg-scroll-scene-day-night-set {120    from { translate: 0 0; }121    to   { translate: 0 62px; }122  }123  @keyframes sg-scroll-scene-day-night-rise {124    from { translate: 0 68px; }125    to   { translate: 0 0; }126  }127  @keyframes sg-scroll-scene-day-night-twinkle {128    0%, 55% { opacity: 0; }129    100%    { opacity: 1; }130  }131</style>132