Skip to content
animorio
IT
All components

The campsite calendar

Calendars, Physics, SVG, TransitionsGSAP, CanvasAdvancedCompressed weight: Demo 16 KBGSAP 28 KBFreeDownload the zip

A campsite’s booking calendar, drawn like the illustrated map of a meadow: every day is a pitch. Choosing the arrival, a rolled tent drops onto its pitch; choosing the departure, the tent is pitched and stretches over the nights, one hoop after the other on springs, then night falls on the pitches of the stay with its stars and the tent lights up from inside.

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>The campsite calendar</title>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/bricolage-grotesque@5.3.0/index.css">
  <link rel="stylesheet" href="style.css">
</head>
<body>
  <main class="stage">
    <!-- the picker: a month of pitches on a meadow seen from above. Choosing the arrival rolls a tent onto its pitch,
         choosing the departure pitches it: the tent stretches over the nights, hoop after hoop, and the night falls on
         them with its stars. The pitches, the tent and the trees are drawn by the script -->
    <div class="camp" data-picker>
      <div class="camp__head">
        <button class="camp__nav" type="button" aria-label="Previous month" data-prev><svg viewBox="0 0 24 24" aria-hidden="true"><path d="M14.5 6 8.5 12l6 6"/></svg></button>
        <h2 class="camp__month" data-month-name></h2>
        <button class="camp__nav" type="button" aria-label="Next month" data-next><svg viewBox="0 0 24 24" aria-hidden="true"><path d="M9.5 6l6 6-6 6"/></svg></button>
      </div>
      <div class="camp__week" aria-hidden="true" data-week></div>
      <div class="camp__meadow" data-meadow>
        <canvas class="camp__grass" aria-hidden="true" data-grass></canvas>
        <div class="camp__grid" data-grid></div>
      </div>
      <div class="camp__foot">
        <p class="camp__sum" aria-hidden="true" data-sum></p>
        <button class="camp__clear" type="button" data-clear>Clear dates</button>
      </div>
      <p class="sr" role="status" aria-live="polite" data-said></p>
    </div>
  </main>

  <script src="https://cdn.jsdelivr.net/npm/gsap@3.15.0/dist/gsap.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.

37 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 campsite calendar” from Animorio and fit it into my site

What it does

On a white background a canvas-coloured card with the month, the arrows and, below, a meadow seen from above with tracks between the rows. Every day is a pitch mown in stripes with its wooden plaque and number; the pitches already booked have someone else’s dome tent on them and can’t be chosen, the gone days are dry grass, the days outside the month are trees. The first click chooses the arrival: a rolled tent drops onto the pitch with a bounce and a few blades of grass fly. Then, with a mouse, a dashed guy rope runs from the tent to the pitch under the pointer and the pitches of the stay are marked with a light edge. The second click chooses the departure: the bag opens, the tent rises on its first hoop and its tail is pulled to the departure; the hoops follow it on springs, bunched up at first (the fabric bulges between one hoop and the next), then taut, until every night has its hoop. Where a week ends the tent goes on in the row below. When it gets there the guy ropes and pegs appear, and night falls on the pitches of the nights, one after the other, with its stars; the tent lights up from inside and spills a little light on the grass. Below are the dates, and the nights and the total counting up to their numbers. A new arrival, or Clear dates, takes the tent down: it folds back to the arrival, sinks and is gone, and the day comes back. When the page opens a four-night stay is pitched in front of you.

How it works

The meadow

The month is a grid of six weeks of buttons, so every month is equally tall. Under the grid a canvas draws the grass once (a few thousand short blades from a number generator that always gives the same numbers) and the tracks in the gaps between the rows. The booked pitches, the prices, the trees and the stars come from a number worked out from the date, so they are always the same.

Hoops on springs

The tent is a chain of hoops, one per day, with their positions in days. The first stays on the arrival; the last one, the tail, goes to the departure on a stiff spring (PITCH); the ones in between chase their share of the tail on softer springs (FABRIC). Four small steps per frame, with the step capped at 1/30 of a second, and a hoop never passes the one before it.

The fabric

On every frame where something moves the script writes the tent’s SVG again. The top edge is one curve for each stretch between two hoops: if the stretch is shorter than a night the fabric bulges up (BILLOW), if it is taut it sags a little. Each row of the grid has its own piece of tent, cut where the week ends; inside it, clipped by the outline, the folds by the hoops, the curved hoops, the door with its zip and the light along the top. The shadow is the same outline squashed onto the grass with a matrix.

The night

Every pitch has a hidden layer of night and its four-pointed stars. Once the departure is chosen, GSAP turns on the layers of the nights one after the other (DUSK) and makes the stars pop up spinning; meanwhile the tent’s colour goes from orange to the warm light inside, and a blurred glow settles on the grass.

One loop

Springs, flying blades of grass, the rope following the pointer and the GSAP tweens that change the drawing all go through one requestAnimationFrame, which stops by itself when nothing moves any more.

Keyboard, mouse and finger

A single day of the grid takes the Tab key: the arrows move between the days, Home and End go to the start and the end of the week, Page Up and Page Down change month, Enter chooses. With the keyboard the rope follows the focus, with a mouse the pointer; with a finger you tap the arrival and then the departure.

Values to change

NameFileDefaultWhat it changes
WEEK_STARTscript.js1The first day of the week: 1 Monday, 0 Sunday.
PRICEscript.js[28, 34]The price of a pitch for a night, in euros: on weekdays, and on Fridays and Saturdays.
MAX_NIGHTSscript.js14The longest stay, in nights: a departure further away chooses a new arrival.
PITCHscript.js[180, 13]The spring pulling the tent’s tail to the departure: stiffness and damping.
FABRICscript.js[120, 9]The springs of the hoops in between: stiffness and damping.
BILLOWscript.js0.5How much the fabric bulges where the hoops are bunched up.
DUSKscript.js[0.5, 0.08]The night falling: the seconds of each pitch, and the gap between one pitch and the next.
STARSscript.js4The stars on each night.

Try them in the Playground

When to use it

For the booking page of a campsite, a glamping site, a camper stop or a mountain hut: wherever nights outdoors are chosen. The booked pitches and the prices should come from your own system instead of the made-up ones.

On phones

Below 560 pixels the pitches narrow to fit the width of the screen, with slightly smaller plaques; the tent, the ropes and the stars are measured on the pitch, so they stay in proportion. There is no rope under the pointer: you tap the arrival and then the departure.

With reduced motion

No springs, no drops and no flying grass: the tent appears already pitched, the rope goes straight to the pitch, the night and the stars fade in, the months change at once and the nights and the total go straight to their numbers.

Pitfalls

  • The tent must lie over the pitches but under the plaques with the numbers: that is why the tent’s SVG is inside the grid and the buttons create no stacking context of their own (no transform or opacity on the buttons, only on their layers), so the plaque’s z-index counts against the tent.
  • With the springs a hoop could overtake the one before it and the fabric turned inside out: after every step the hoops are put back in order and their backward speed set to zero.
  • A stay crossing from one week to the next must be drawn in two pieces, one per row: the cut ends have no door, no ropes and no sloping part, and the pieces are also cut at the edges of the month so they don’t end up over the trees.
  • The tent’s tail lies on the departure’s pitch: that is why the departure must be free too, not just the nights, or the tent would end up on top of someone else’s.
  • The GSAP tweens that change the drawing (the drop, the light, the taking down) keep the loop running with a counter that goes down both when they end and when they are interrupted: without it the loop either ran for ever or stopped halfway.

Libraries

GSAP 3.15.0, Bricolage Grotesque (font variabile) 5.3.0.

Compressed with gzip, the three demo files weigh 16 KB; the libraries: GSAP 28 KB.

Testing

Tested on 13 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 components