Skip to content
animorio
IT
All components

The mat card

Cards, Hover, PhysicsGSAP, CSS onlyAdvancedCompressed weight: Demo 9.8 KBGSAP 28 KBFreeDownload the zip

In the minimal style: the card of a print for sale in a small gallery, hanging framed on a pale wall and drawn to scale. On hover the white mat widens on a spring, as when the framer tries a wider mat, and its width is written inside in vermilion like a dimension; title, artist and price take weight. On click the format goes from A3 to A2 to A4 and the print and frame grow or shrink to their real size, while the dimensions count the centimetres.

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 mat card</title>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/fraunces@5.3.0/full.css">
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/instrument-sans@5.3.0/wdth.css">
  <link rel="stylesheet" href="style.css">
</head>
<body>
  <main class="stage">
    <!-- the card of a print for sale in a small gallery. On the wall the print hangs framed, drawn to scale: around
         it a white mat, and around the mat a thin black frame. With the pointer over the card (or a tap, or the
         keyboard) the mat widens on a spring, as when a framer lays a wider mat on the print, and its width is
         written in the mat like a dimension on a drawing. Choosing another format (a click on the print, or the three
         sizes below) the print and its frame grow or shrink to the new size on their springs, while the overall size
         of the frame counts along its two dimension lines. The frame, the mat, the dimensions and the print are drawn
         by the script and the CSS -->
    <article class="print" aria-labelledby="print-title" data-print>
      <button class="wall" type="button" data-wall data-autoclic>
        <span class="frame" data-frame>
          <span class="window" data-window>
            <!-- the print: a black half disc resting on a line, and a vermilion square balanced on top -->
            <svg class="art" viewBox="0 0 210 297" preserveAspectRatio="xMidYMid slice" aria-hidden="true">
              <rect class="art__paper" width="210" height="297" />
              <path class="art__dome" d="M47 200a58 58 0 0 1 116 0z" />
              <path class="art__line" d="M30 200.5h150" />
              <rect class="art__weight" x="95" y="122" width="20" height="20" />
            </svg>
          </span>
        </span>
        <svg class="quotes" aria-hidden="true" data-quotes>
          <path class="quotes__size" data-size-lines />
          <path class="quotes__size" data-size-ticks />
          <text class="quotes__label" data-size-w>0 cm</text>
          <text class="quotes__label" data-size-h>0 cm</text>
          <path class="quotes__mat" data-mat-line />
          <text class="quotes__mat-label" data-mat-label>Mat 5 cm</text>
        </svg>
        <span class="sr" data-wall-label>Resting Weight, framed. Show the next format</span>
      </button>

      <div class="info">
        <p class="kind">Gicl&eacute;e print &middot; Edition of 50</p>
        <div class="head">
          <h2 class="title" id="print-title" data-title>Resting Weight</h2>
          <p class="price" data-price>&euro;190</p>
        </div>
        <p class="artist" data-artist>Ada Velloso, 2026</p>
        <div class="foot">
          <div class="formats" role="radiogroup" aria-label="Format" data-formats></div>
          <p class="note" data-note>Black ash frame</p>
        </div>
      </div>
      <p class="sr" aria-live="polite" data-live></p>
    </article>
  </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.

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 “The mat card” from Animorio and fit it into my site

What it does

On a white background a card 340 pixels wide. At the top a warm grey wall and, hanging in the middle, a framed print drawn to scale: the thin black frame, the white mat with its cream bevelled cut around the work, and the work itself, a black half dome resting on a thin line with a small vermilion square balanced on top. Around the frame two thin grey dimensions, as in a technical drawing, with extension lines and oblique slashes at the ends: the width below and the height beside it, rotated, in centimetres. Inside the mat, under the work, a vermilion dimension says how wide it is: Mat 5 cm. Under the wall the kind of print, the title and the price in Fraunces, the artist’s name and three little sheets drawn to scale, A4, A3 and A2, with the chosen one showing its mat inside. With the pointer over the card the mat widens to 8 cm on a spring, goes a pixel past and settles: the frame grows, its shadow lifts off the wall while it moves and the dimension counts 5, 6, 7, 8; title, artist and price take weight one after the other and the letters of Fraunces go from soft to crisp. A click on the print, or on one of the three sheets, changes the format: print and frame grow or shrink to the new size, the mat gives a little under the push and opens again, the dimensions count the centimetres along their lines and the price counts to the new one. Every format hangs with its centre at the same height, as in a gallery.

How it works

Everything in centimetres

The print, the mat and the frame have their real size in centimetres (FORMATS, MAT, MOULDING). The scale of the wall, in pixels per centimetre, is worked out from the largest frame that has to fit (the largest format with the wide mat and some room for the dimensions) and worked out again with a ResizeObserver when the card changes size, even halfway through a movement.

Three springs

The width and height of the print and the width of the mat are three springs in centimetres, integrated on the GSAP ticker in four sub-steps with the step capped at 1/30 of a second; stiffness STIFFNESS and damping DAMPING. The mat’s spring is a little quicker than the print’s, and at every change of format it gets a push of GIVE centimetres against the growth: it gives and opens again. When all three are still the ticker lets them go.

The frame drawn at every frame

At every step of the springs the real frame is laid out again, not a scaled copy of it: the border of the box is the black frame (border-width), the background is the mat and the window inside has its size in pixels. So the frame and the bevelled cut stay thin and sharp at every size. The speed of the print lifts the frame’s shadow off the wall through a CSS variable.

The dimensions

An SVG over the wall draws the dimensions as paths on half coordinates: dimension lines broken in the middle for the number, extension lines set three pixels off the frame and oblique slashes at the ends. The numbers are the size of the spring in that frame, with one decimal and tabular figures, so they count while the frame moves; the mat’s counts in whole centimetres towards its goal.

The weight of the words

Title and price are in variable Fraunces: on hover the wght goes from WEIGHT[0] to WEIGHT[1] with a small overshoot (back.out) and the SOFT axis from 50 to 0, so the letters turn crisp; the artist, in Instrument Sans, takes weight and a hair of width. The three lines start 60 milliseconds apart, and go back in the reverse order.

Keyboard and touch

The print is a button that moves to the next format; the three sheets are a radiogroup with the arrows, Home and End, and each sheet is drawn by the script in the proportion of its format. Keyboard focus does what the mouse passing over does; on a phone the finger holds the mat wide and lets it go a second and a half later, so the change can be seen.

Values to change

NameFileDefaultWhat it changes
FORMATSscript.js[{ name: 'A4', width: 21, height: 29.7, price: 140 }, …]The formats on sale, in order: the name, the width and height of the print in centimetres and the price. The wall fits the largest format; five at most.
STARTscript.js'A3'The format shown at the start (its name, as in FORMATS).
MATscript.js[5, 8]How wide the mat is at rest and with the pointer over it, in centimetres.
MOULDINGscript.js1.6How wide the black frame is, in centimetres.
STIFFNESSscript.js150How quickly the frame changes size (the stiffness of the springs).
DAMPINGscript.js0.72The damping of the springs: at 1 they land without going past, lower they go past more.
GIVEscript.js0.7How much the mat gives when the print grows or shrinks, in centimetres.
WEIGHTscript.js[340, 580]The weight of the title and the price, at rest and with the pointer over the card.
CURRENCYscript.js'€'The sign before the price.

Try them in the Playground

When to use it

For the card of a print, a poster or a photograph for sale: the shop of a gallery, an illustrator, a photographer, an art printer. It works wherever size matters and there are several formats to choose from, because it shows how big what you buy really is, frame included.

On phones

The card is 340 pixels wide, or the screen minus 32, and the wall’s scale is worked out again on the real size. There is no mouse passing over: a finger on the card widens the mat like the pointer, a tap on the print or on a sheet changes the format, and the wide mat stays a second and a half after the tap, so the frame can be seen changing. The springs and timings are the same as on a computer.

With reduced motion

No springs and no growing: the frame changes size at once, hidden by a fade, and the dimensions are the new ones straight away. The mat widens the same way, the weight of the words changes without animating and when the page opens everything is already in place.

Pitfalls

  • A FLIP made with scale would also enlarge the black frame and the bevelled cut, which would thicken during the change: the frame is laid out at its real size at every step of the springs, with width, height and border in pixels.
  • The mat’s number taken from the spring would read «Mat 4 cm» for a moment, as the mat gives at a change of format: the number counts towards the goal with a tween of its own, the spring only moves the line.
  • At the start the dimensions grow out of the middle: with the line shorter than the break for the number the path turned back and drew a dash in the middle, and the extension lines at almost zero length made dots. They are drawn only once longer than the break, and the slashes come in with a fade.
  • Enter and Space on the button make a click with no detail, like the preview’s: a key pressed marks it, so from the keyboard the format changes and the demonstration tour does not start.
  • The scale of the wall comes from the largest frame, with the wide mat, the push of the change and a margin: otherwise A2 with the wide mat would go off the wall and the dimensions would end up outside.

Libraries

GSAP 3.15.0, Fraunces (font variabile) 5.3.0, Instrument Sans (font variabile) 5.3.0.

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

Testing

Tested on 16 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