Skip to content
animorio
IT
All components

The button under a cover

Buttons, 3D, TransitionsGSAP, CSS onlyAdvancedCompressed weight: Demo 8.3 KBGSAP 28 KBFreeDownload the zip

A deploy button that can't be pressed by mistake: it sits under a glass cover hinged at the top, lifted with a click or pulled up by hand. Pressed, it stays down, counts down while the striped ring turns, deploys with an arc filling up, comes back up green, and the cover slams shut by itself.

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 button under a cover</title>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/martian-mono@5.3.0/index.css">
  <link rel="stylesheet" href="style.css">
</head>
<body>
  <!-- the whole device: the plate in its 3D scene, and the flat areas where the hand goes -->
  <div class="device" data-device data-autoclic>
  <main class="stage">
    <!-- the button under a cover: the red button can't be pressed until its glass cover is lifted (a click, or a
         drag upwards); pressed, it counts down, deploys, turns green, and the cover slams shut by itself -->
    <div class="console" data-console>
      <div class="console__head" aria-hidden="true"><span>Deploy</span><span>v2.4.0</span></div>
      <div class="well" data-well>
        <span class="well__ring" aria-hidden="true" data-ring></span>
        <span class="well__hole" aria-hidden="true"></span>
        <svg class="well__arc" viewBox="0 0 140 140" aria-hidden="true"><circle cx="70" cy="70" r="65" pathLength="1" data-arc/></svg>
        <button class="big" type="button" disabled aria-label="Deploy to production" data-big>
          <span class="big__top" data-top>
            <span class="big__show" aria-hidden="true" data-show></span>
          </span>
        </button>
        <div class="lid" data-lid>
          <button class="lid__cover" type="button" aria-label="Lift the cover" aria-expanded="false" data-cover>
            <span class="lid__glass" aria-hidden="true"><span class="lid__shine" data-shine></span></span>
            <span class="lid__tab" aria-hidden="true"><span>Lift</span></span>
          </button>
        </div>
      </div>
      <p class="console__status" aria-live="polite"><span data-status>Lift the cover to arm</span></p>
    </div>
  </main>
  <!-- where the hand goes: two flat, invisible areas over the cover and the button, kept on them by the script. Over
       the 3D of the tilted plate Safari on iPhone can lose the touches: flat areas outside the scene always get them -->
  <div class="hits" aria-hidden="true">
    <span class="hit hit--big is-off" data-hit-big></span>
    <span class="hit hit--lid" data-hit-lid></span>
  </div>
  </div>

  <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.

17 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 button under a cover” from Animorio and fit it into my site

What it does

On a black background a plate of dark metal tilted back like a device on a desk, with the words Deploy and v2.4.0 at the top; in the middle a big red button in a well, inside a ring of yellow and black stripes, under a reddish glass cover with a Lift tab; below, the line Lift the cover to arm. With the mouse over it, the cover lifts a little. Clicking it, or pulling it up by hand past 45 degrees, the cover swings open on its top hinge, goes past its stop and comes back with a bounce, with a reflection sliding across the glass; the line says Armed. Press to deploy. Pressed, the button stays down, the striped ring starts to turn and the numbers 3, 2 and 1 come up on the button, with the line Deploying in 3, in 2, in 1; then an arrow keeps rising while a white arc fills round the button (Deploying to production). Done, the button comes back up with a bounce, turns green with a tick that draws itself and the line says Live on production; after a moment the cover closes by itself: it falls fast, bounces once and the plate jolts under the blow, and then the button turns red again. Pressed again during the countdown, it stops and says Deploy cancelled. If nobody presses, after a few seconds the cover closes by itself and the line says Cover closed.

How it works

The tilted plate

The plate is turned back by 22 degrees (rotationX with GSAP) and the stage gives it depth (perspective 1000px); plate, well and cover have transform-style preserve-3d, so the cover turns in the same space as the plate and, open, is seen from the front instead of edge-on.

The cover on its hinge

The cover is a button turning with rotateX round its top edge (transform-origin 50% 0) up to LIFT degrees: past 90 it leans back and its underside shows. The word Lift has backface-visibility hidden, so it is never read backwards. The reflection on the glass slides and brightens with the angle.

The hand on the cover

The hand does not touch the real cover but a flat, invisible area over it, outside the 3D scene, which the script keeps in place (shut, the well with a 12 pixel margin and the tab; open, the part above the hinge); the same for the button. A click opens or closes it; a drag follows it (1.1 degrees for every pixel pulled upwards) and, let go, past 45 degrees it flies open with elastic.out, before that it falls back. If nobody presses the button for RELOCK seconds, the cover closes by itself.

The countdown and the deploy

The button's face sits 8 pixels above its side; pressed it stays 5 pixels lower, and a timeline shows COUNT numbers, one every TICK seconds, while the ring turns; then the SVG arc fills with stroke-dashoffset in 1.3 seconds. The green at the end is a second layer over the red that comes on with opacity, because two gradients do not blend into each other.

The blow, the keys and the preview

Closing, the cover falls with power3.in, comes back up 6 degrees and falls again, and the plate jolts by 3 pixels. With the keyboard the cover opens with Enter and the focus moves to the button; Escape stops the countdown or closes the cover. A click from a script (the library's preview) lifts the cover, and the next click presses the button.

Values to change

NameFileDefaultWhat it changes
LIFTscript.js108How far the cover opens, in degrees.
COUNTscript.js3The number the countdown starts from.
TICKscript.js0.6The seconds of each number of the countdown.
RELOCKscript.js6The seconds the cover stays open if nobody presses, before it closes itself.

Try them in the Playground

When to use it

For the important actions of a dashboard that can't be undone: publishing, going live, launching a campaign, shutting down a service, emptying a queue. Also as a playful button on the page of a product for developers.

On phones

The plate is 280 pixels wide, or the screen minus 48; the finger pulls the cover up without scrolling the page (touch-action none on the cover's area), and the cover lifts by itself only for the mouse arriving, not for the finger.

With reduced motion

The cover opens and closes in a fifth of a second, without bounces or jolts; the ring does not turn, the numbers change without rising and the arrow stays still; the arc still fills, because it tells how long is left.

Pitfalls

  • A cover turned past 90 degrees, seen from the front, is a thin strip: for the opening to read, the plate must be tilted, with the whole chain of elements in preserve-3d.
  • Words on the back of something turned read backwards: backface-visibility hidden on the words, with their parent in preserve-3d.
  • Over a 3D scene with several levels in preserve-3d Safari on iPhone may not deliver the touches, and measures elements turned past 90 degrees wrongly: the hand goes to flat areas outside the scene, placed starting from an element that measures right (the well).
  • A stroke with round ends and zero length still shows as a speck: the empty arc is hidden with opacity until it starts to fill.
  • GSAP's transform wipes out the CSS one: the plate's tilt is given with GSAP (rotationX), so the entrance and the jolt, made with y, keep it.

Libraries

GSAP 3.15.0, Martian Mono (font variabile) 5.3.0.

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

Testing

Tested on 4 October 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 components