Skip to content
animorio
IT
Back to the library

Greetings while it loads

Transitions, TextGSAP, CSS onlyEasyCompressed weight: Demo 5.3 KBGSAP + CustomEase 31 KBFreeDownload the zip

A loader that says hello in nine languages, one word at a time, while a counter climbs in bursts; at a hundred the word lights up, the curtain lifts with its edge bowing and the page underneath rises line by line.

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>Greetings while it loads</title>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource/instrument-serif@5.3.0/index.css">
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource/noto-sans-tifinagh@5.3.0/index.css">
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/mona-sans@5.3.0/standard.css">
  <link rel="stylesheet" href="style.css">
</head>
<body>
  <!-- the curtain: one greeting at a time and a counter; at a hundred it lifts -->
  <div class="curtain" data-curtain aria-hidden="true">
    <div class="curtain__inner" data-inner>
      <p class="curtain__say" data-say><span class="curtain__word" data-word>Bonjour.</span></p>
      <p class="curtain__count"><span data-count>00</span><small>%</small></p>
      <p class="curtain__label">Preparing the experience</p>
    </div>
  </div>

  <main class="page">
    <header class="top">
      <p class="brand">Mirage</p>
      <p class="top__line">Digital studio</p>
    </header>
    <h1 class="title">
      <span class="title__line"><span data-line>We build for people</span></span>
      <span class="title__line"><span data-line>who say hello</span></span>
      <span class="title__line"><span data-line>in nine languages.</span></span>
    </h1>
    <p class="text" data-rise>Interfaces, apps and brands that feel at home wherever they land.</p>
    <div class="actions" data-rise>
      <button class="replay" type="button" data-replay data-autoclic>
        <span class="replay__text" data-text="Replay the curtain">Replay the curtain</span>
        <svg class="replay__icon" viewBox="0 0 24 24" aria-hidden="true"><path d="M4.5 12a7.5 7.5 0 1 0 2.2-5.3" /><path d="M4.5 4.5v4.2h4.2" /></svg>
      </button>
    </div>
  </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/CustomEase.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.

39 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 “Greetings while it loads” from Animorio and fit it into my site

What it does

The page arrives covered by a very dark green curtain. In the middle, one word at a time: Bonjour., ⴰⵣⵓⵍ in Tamazight, Hola., Ciao., مرحبا, やあ, Hallå., Olá. and last Hello., the page’s language. Latin words are set in a serif, the others in a typeface made for their own script; each takes the place of the last by rising a few pixels out of a slight blur, and meanwhile it breathes softly. Below, a two-digit counter with a small % climbs in bursts, with short stops, and below that sits Preparing the experience. At a hundred the word lights up, everything holds still for half a second and the curtain flies up: its bottom edge bows with the speed, the words lag a little behind and the page underneath rises line by line. The Replay button drops the curtain again and starts over.

How it works

The words

The words sit in a list and change every 0.3 seconds, called by the timeline: so the replay button stops everything with a single kill. A regular expression, /[A-Za-zÀ-ÿ]/, picks the typeface: Latin letters get Instrument Serif, the others Noto Sans Tifinagh, Geeza Pro, Hiragino, and Arabic gets dir="rtl". The line has a fixed height of 1.3 em, so the counter never moves. Each new word rises 16% out of a 5 px blur over 0.26 seconds of expo.out.

The breath and the counter

While it waits, the word breathes: opacity between 0.72 and 0.9, half a breath every 0.45 seconds with sine.inOut, back and forth; at a hundred it rises to 1. The counter jumps towards five uneven stops, 26, 37, 61, 83 and 100: each burst takes 72% of its fifth of the time with power2.out and the rest is a pause. It shows two digits and stays at 99 until the value reaches 99.5.

The curtain

After half a second’s pause the curtain rises by 100% of its height over 1.1 seconds, on a curve steep at both ends, cubic-bezier(0.76, 0, 0.24, 1), made with CustomEase. Meanwhile its content moves down by 35%: against the screen it rises more slowly, and the words seem to lag behind without ever crossing the edge.

The bowing edge

Under the curtain there is half an ellipse of the same colour, 12 vh tall and squashed to zero with scaleY. During the lift a CSS variable, --bow, goes from 0 to 1 and back to 0 in two stretches of sine.inOut: the peak falls halfway, when the curtain is fastest, and the edge bends down like a pulled sheet.

The page and the button

The title’s three lines each wait in their own mask, moved down by 130% so the tallest letters don’t peek out, and rise with expo.out, 0.08 seconds apart, when the curtain is halfway. The button is an elastic pill: with the pointer over it the words widen along Mona Sans’s width axis, from 100% to 125%, and the fill swells with cubic-bezier(0.34, 1.9, 0.45, 1); the room for the wide words is already kept by an invisible zero-height copy, so nothing around it moves.

Values to change

NameFileDefaultWhat it changes
WORDSscript.js9The greetings, in order: the last one stays lit when the curtain lifts.
EACHscript.js0.3How many seconds each greeting stays; the counter reaches a hundred in this time times the number of words.
STOPSscript.js26, 37, 61, 83, 100Where the counter pauses between bursts.
BREATHscript.js0.72, 0.9Between which opacities the word breathes while it waits.
HOLD, LIFTscript.js0.5, 1.1The pause at a hundred and the curtain’s lift, in seconds.
LAGscript.js35How far the words lag behind as the curtain lifts, in percent of the screen.

Try them in the Playground

When to use it

For the loader of a site that speaks to several countries, or of a studio that wants to introduce itself before showing any work. Here the counter follows a fixed time: on a real site tie it to what is really loading, with a minimum duration.

On phones

The words shrink to 64 px and the page title to 46; the curtain’s curve stays 12% of the screen tall, and on a narrow screen it looks rounder.

With reduced motion

No movement: only Hello. stays, the counter climbs to a hundred in 0.8 seconds and the curtain fades away; the page’s lines are already in place and the rest fades in. The button repeats the same.

Pitfalls

  • Words in different scripts have different heights: without a fixed-height line, the counter below jumps at every change.
  • The Tamazight typeface arrives the first time it is needed, that is once loading has started: the curtain waits for its typefaces, at most a second, or a word shows up as boxes or in the wrong face.
  • With a line-height below 1 tall letters stick out of their line: hidden in the mask with a 110% shift, their tips peek out. It takes at least 130%.
  • The replay button drops the curtain before putting the page back down: if the lines went back into their masks straight away, you would see them vanish.

Libraries

GSAP 3.15.0, CustomEase (GSAP) 3.15.0, Instrument Serif 5.3.0, Noto Sans Tifinagh 5.3.0, Mona Sans (font variabile) 5.3.0.

Compressed with gzip, the three demo files weigh 5.3 KB; the libraries: GSAP + CustomEase 31 KB.

Testing

Tested on 28 September 2026

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

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