Skip to content
animorio
IT
Back to the library

The sentence that fills with water on scroll

Scroll, TextGSAP, CSS onlyMediumCompressed weight: Demo 6.9 KBGSAP + ScrollTrigger 45 KBLenis 5.3 KBFreeDownload the zip

Scroll inside the preview

A minimal-style scroll animation on warm white: a sentence drawn in thin outlines, like glass letters, fills with blue water as you scroll down, from the bottom line to the top. The surface sways on its own, sloshes when you scroll fast, leans towards the pointer and takes a drop where you tap; small bubbles climb and a thin gauge on the side reads the millilitres.

The code

A folder that runs on its own: index.html, style.css, script.js and the libraries from a CDN. The React and Vue tabs hold the same demo as a ready component, which switches its animations off when it leaves the page.

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Brimvale Glass</title>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/fraunces@5.3.0/index.css">
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/archivo@5.3.0/index.css">
  <link rel="stylesheet" href="style.css">
</head>
<body>
  <!-- a made-up maker of glass carafes, Brimvale. The stage sticks while you scroll: the sentence is drawn as thin glass
       outlines and water rises inside the letters as you scroll, with a surface that sways, sloshes when you scroll
       fast, leans towards the pointer and takes a drop where you tap. A thin gauge on the side reads the millilitres.
       The water, the surface and the bubbles are drawn by the script -->
  <main>
    <section class="corsa" data-corsa>
      <div class="palco" data-palco>
        <header class="testa">
          <a class="marchio" href="#" data-entra>Brimvale</a>
          <p class="testa__nota" data-entra>Glass carafes, blown by hand</p>
        </header>

        <svg class="tela" data-tela viewBox="0 0 1000 640" role="img" aria-label="Slowly, then all at once.">
          <defs>
            <clipPath id="lettere" data-lettere>
              <text class="riga" x="470" y="190" text-anchor="middle">Slowly,</text>
              <text class="riga" x="470" y="360" text-anchor="middle">then all</text>
              <text class="riga" x="470" y="530" text-anchor="middle">at once.</text>
            </clipPath>
            <linearGradient id="acqua-grad" x1="0" y1="0" x2="0" y2="1">
              <stop offset="0" class="acqua__alto"/>
              <stop offset="1" class="acqua__basso"/>
            </linearGradient>
          </defs>


          <!-- the glass: a thick outline with the paper colour laid over its inner half, so only the outer edge shows
               and the overlapping parts inside the letters stay hidden; the water goes on top -->
          <g class="contorni" data-contorni>
            <g class="contorni__bordo">
              <text class="riga" x="470" y="190" text-anchor="middle">Slowly,</text>
              <text class="riga" x="470" y="360" text-anchor="middle">then all</text>
              <text class="riga" x="470" y="530" text-anchor="middle">at once.</text>
            </g>
            <g class="contorni__vetro">
              <text class="riga" x="470" y="190" text-anchor="middle">Slowly,</text>
              <text class="riga" x="470" y="360" text-anchor="middle">then all</text>
              <text class="riga" x="470" y="530" text-anchor="middle">at once.</text>
            </g>
          </g>
          <g clip-path="url(#lettere)">
            <path class="acqua" data-acqua d="M0 640 H1000 V640 Z"/>
            <path class="acqua__riflesso" data-riflesso d="M0 0"/>
            <g data-bolle></g>
            <path class="acqua__pelo" data-pelo d="M0 0"/>
          </g>

          <circle class="goccia" data-goccia r="7" cx="0" cy="-20"/>

          <g class="scala" data-scala>
            <path class="scala__asta" d="M944 80 V560"/>
            <g data-tacche></g>
            <g class="scala__indice" data-indice>
              <path d="M926 0 H962"/>
              <text class="scala__numero" data-numero x="914" y="5" text-anchor="end">0 ml</text>
            </g>
          </g>
        </svg>

        <p class="cenno" data-entra>Scroll to pour, tap for a drop</p>
        <p class="stato" data-entra>Carafe <span class="stato__parola" data-stato>empty</span></p>
      </div>
    </section>

    <footer class="piede">
      <p>Each Brimvale carafe holds 500 ml and is blown, cooled and polished in one small workshop.</p>
    </footer>
  </main>

  <script src="https://cdn.jsdelivr.net/npm/gsap@3.15.0/dist/gsap.min.js"></script>
  <script src="https://cdn.jsdelivr.net/npm/gsap@3.15.0/dist/ScrollTrigger.min.js"></script>
  <script src="https://cdn.jsdelivr.net/npm/lenis@1.3.26/dist/lenis.min.js"></script>
  <script src="script.js"></script>
</body>
</html>

Playground

Change values, colours and text with the controls and watch the animation respond live. Or write in the code yourself. Then download the folder with your changes.

25 values to change

Or ask Claude Code for it

With the Animorio connector, Claude Code takes it from here, guide included, and fits it into your project. Paste this request:

Take “The sentence that fills with water on scroll” from Animorio and fit it into my site

What it does

A warm white page with the name of an invented workshop of blown glass carafes, Brimvale, at the top and, in the middle, the sentence «Slowly, then all at once.» on three lines, in Fraunces, drawn only in a thin outline, as if every letter were made of glass. As you scroll the stage stays still and water rises inside the letters: first it fills «at once.», then «then all», then «Slowly,». The water is blue, the only colour, lighter just under the surface, and the surface is a line that sways gently on its own, with a pale glint running just under it. Scroll fast and the water sloshes, then settles on a spring; the pointer makes it lean towards itself, like a carafe being moved. A tap lets a drop fall: it falls, stretches as it speeds up and opens two ripples that run out to the edges of the letters. Small bubbles climb through the water and pop at the surface. On the right a thin gauge reads from 0 to 500 ml, with the blue marker and number rising with the water, and at the bottom the label goes from empty to pouring to full; once the carafe is full the surface calms down and the marker gives a little jump.

How it works

The letters as a mask

The sentence is in the SVG twice: once inside a clipPath, which masks the water, and once on top, with no fill and only a one-and-a-half pixel outline. The water is a path as wide as the drawing, from the surface down to the bottom: the mask only shows it inside the letters, so it rises line by line by itself.

The surface

Every frame the surface is redrawn every ten units: two waves running opposite ways, a third longer one for the slosh, the lean towards the pointer and the ripples of the drops, each a wave train that spreads and fades. The level comes from the scroll, eased a little.

Two springs

The slosh follows the scroll speed on a spring, so it grows when you scroll fast and dies down when you stop; the lean follows the pointer on another spring, with a small overshoot. When nobody moves, a fake pointer sways on its own and now and then a drop falls.

The gauge and the word

The gauge has a tick every 25 ml and numbers every 100; the marker is a group that moves with the level. The word at the bottom changes with a small bounce, and once the carafe is full the waves calm down and the marker jumps.

Values to change

NameFileDefaultWhat it changes
RIDEscript.js1How much scroll the pour takes: 2 is twice as long.
FULL_ATscript.js0.9How far down the page the water reaches the top (0 to 1).
WAVESscript.js1How much the surface sways on its own.
SLOSHscript.js1How much a fast scroll makes the water slosh.
TILTscript.js1How much the surface leans towards the pointer.
BUBBLESscript.js12How many bubbles climb in the water.

Try them in the Playground

When to use it

For the opening of a glassworks, a mineral water, a bar or a spa: a sentence that fills up as you read it, scrolling.

On phones

The same animation with adapted sizes: the drawing shrinks to the width and height of the page, the note at the top right is hidden and the drop falls where you tap.

With reduced motion

Nothing moves and the scroll is not smoothed: the sentence is already full of water, the surface is still, no bubbles or drops, and the page fades in.

Pitfalls

  • The mask needs the same letters as the outline, in the same face: it waits for document.fonts.ready before starting, otherwise the water spills out of the letters for a moment.
  • The slosh sits on a spring rather than on the speed itself: taken raw it shakes at every mouse wheel tick.
  • The bubbles are only born under the surface: born above it, they showed up outside the water for a frame.

Libraries

GSAP 3.15.0, ScrollTrigger 3.15.0, Lenis 1.3.26, Fraunces (font variabile) 5.3.0, Archivo (font variabile) 5.3.0.

Compressed with gzip, the three demo files weigh 6.9 KB; the libraries: GSAP + ScrollTrigger 45 KB, Lenis 5.3 KB.

Testing

Tested on 24 October 2026

  • Desktop: Done
  • Phone: Done
  • Reduced motion: Done
  • Safari on iPhone: To do

License

Use it in your own projects and in your clients’ projects. Do not resell it or redistribute it as is. GSAP stays under its own Standard license. Full license.

All animations