# Room 101

> Drag, throw or press the web's pet hates into Room 101: a heavy door eases ajar as they near it, pulls them into the dark and slams shut with a rattle.

Canonical: https://gsapvault.com/effects/room-101
Live demo: https://gsapvault.com/demos/room-101/index.html

| Property | Value |
|----------|-------|
| Type | effect |
| Tier | paid |
| Price | £5 |
| Difficulty | advanced |
| Plugins | Draggable, InertiaPlugin |
| Techniques | draggable, momentum, 3d-transforms, keyboard-navigation |
| Uses Lenis | No |

## Lighthouse, as measured

Google Lighthouse on the demo, 15 September 2026. A measurement of the demo as shipped, not a promise for your page.

| Category | Score |
|----------|-------|
| Accessibility | 100 |
| Best practices | 100 |

No performance score is published: it depends on the deployment (server compression, caching, CDN, connection and device) rather than on the code, so measure it where it will live.

## Overview

Effect number 101 is Room 101, in the spirit of the British TV panel show where guests banish their pet hates. The web's own pet hates sit beside a heavy painted door: a cookie banner, an autoplay video, lorem ipsum, a newsletter popup, a spinner that never stops, a Click here link, a CAPTCHA and a layout shift.

Drag one towards the door and the door eases ajar in 3D, further the closer you get, with darkness behind it. Drop it in the doorway or throw it hard enough and the room takes it: the item accelerates into the gap, stretches along its path, spins and shrinks into the dark, then the door slams with an overshoot, the frame and the brass 101 plate rattle and a line of dust settles. A weak throw thuds off the closed door instead. A tally rolls up with every banishment, and when everything is gone one button lets them all back out.

## Features

- A door that answers proximity: the leaf eases ajar in CSS 3D as a dragged item approaches and swings back as it leaves
- Drop in the doorway or throw with enough speed: InertiaPlugin release velocity decides between banish, thud and glide
- The pull stretches each item along its own path of travel, whatever its tilt, then spins and shrinks it into the dark
- A heavy slam with overshoot, a rattling frame and number plate, settling dust and a floor that makes nearby items hop
- Weak throws bounce off the closed door with a thud and a shudder; items never leave the stage
- Fast repeated banishes queue: the door stays open for the next item and slams once at the end
- Items are native buttons: Enter, Space, click and tap run the same door sequence
- A rolling tally, an aria-live status line and a Let them out button that tumbles everything back out
- A small API on the element: banish(), restore(), count() and revert()
- Reduced motion swaps the swing, pull and slam for fades; without JavaScript the room is a still composition

## Use Cases

- An easter egg or 404 page that turns frustration into play
- A playful way to dismiss notifications, tags or filters on a portfolio or campaign site
- Onboarding or survey pages where visitors throw away the options they do not want
- Conference, podcast or agency pages about bad web practice, with the offenders as the content
- A drag-to-delete pattern for a to-do or moodboard that needs more character than a bin icon

## Vibe-Code Ready Setup

This effect includes `START-HERE-AI.md`, a product-specific copy-paste setup prompt for Cursor, Claude Code, ChatGPT, GitHub Copilot, Windsurf, and other coding assistants. It tells the assistant to inspect the existing stack, integrate the supplied files, preserve the design, scope selectors, retain accessibility and responsive behaviour, add framework-appropriate GSAP cleanup, and report what it tested.

[How AI-assisted setup works](https://gsapvault.com/vibe-coding)

## How It Works

Every item is a native button made draggable with Draggable inside the room's bounds, while InertiaPlugin tracks its velocity. During a drag the distance from the item to the doorway sets how far the door leaf rotates about its hinge, inside a perspective on the doorway. On release the item's path is projected forward from its velocity: a drop in the doorway or a fast enough path into the door commits it, a slow path into the door bounces off with a thud, and anything else glides to a stop. A committed item joins a queue; the door opens fully, the item is pulled into the gap along a bowed path while a stretch along its direction of travel is combined with its spin and shrink, and it fades into the dark. The door slams once the queue is empty. Keyboard activation calls the same banish routine, so every input sees identical motion.

## Documentation

How this effect works and how it goes into a page. The reference you use once you own the files (worked examples, events, the programmatic API, the class list) ships with the download.

### Quick Start

**1. Add to your HTML `<head>`:**

_Code snippet omitted: it ships with the download._

**2. Add before the closing `</body>` tag:**

_Code snippet omitted: it ships with the download._

**3. Add the room anywhere in your `<body>`:**

_Code snippet omitted: it ships with the download._

The demo's `index.html` has the full door (panels, push plate, handle, kick plate, hinges) and all eight pet hates.

### Using It With Your Own Design

**What the effect needs from your markup:**

- `[data-room-101]` is the room: the positioning context, the drag bounds and the scope for everything below. Several rooms on one page work independently.
- `[data-room-doorway]` is the drop zone and the dark opening. Its rectangle decides where a drop counts, and the pull aims at its latch side.
- `[data-room-leaf]` is the door leaf the script rotates on its hinge. Put anything you like on it.
- `[data-room-item]` elements are the things you banish. Use native `<button>`s so Enter, Space and screen readers work; `data-name` is what the status line announces.
- Optional hooks: `[data-room-door]` (rattles on the slam and is what a weak throw bounces off), `[data-room-plate]` (rattles harder), `[data-room-shade]` (darkens as the leaf turns away), `[data-room-tally]` and `[data-room-count]` (the rolling tally), `[data-room-status]` (the live region) and `[data-room-restore]` (appears when everything is gone).

**What is only the demo's styling:** the painted panels, the brass plate, the fittings, the floor and skirting, the wall colour, Mona Sans, the accent blue and every `.pet--*` card design. Replace the pet hates with any content: product cards, tags, emoji, images. Reposition them with `--x`, `--y` and `--r` (and `--mx`, `--my`, `--mr` below 640px).

**CSS the effect depends on:**

- The room needs `position: relative`, a size and `overflow: hidden`.
- The doorway needs `overflow: hidden` and a `perspective`; the leaf needs `position: absolute; inset: 0; transform-origin: 0 50%` (hinged on the left, so the gap opens on the right, where the pull aims).
- Items need `position: absolute` inside the room and `touch-action: none` under `.has-js`, so a touch drag moves the item rather than scrolling the page. Nothing else on the page blocks scrolling.
- Each item's resting tilt comes from its CSS `transform: rotate(...)`. The script reads it on load and on resize, so keep other transforms off the item itself.
- `.room__tally-window` clips the number while it rolls; keep its `overflow: hidden` if you keep the roll.
- `.room__restore[hidden] { display: none; }` if your button styles set `display`.

### Options

Set these on the `[data-room-101]` element.

| Attribute | Values | Default | Description |
|-----------|--------|---------|-------------|
| `data-commit-speed` | px per second | `650` | How fast a throw has to be to carry an item through the door. Slower throws that reach the door thud off it. |
| `data-open-angle` | degrees | `76` | How wide the door swings open for the pull. |
| `data-ajar-angle` | degrees | `40` | How far the door eases ajar while an item is dragged right up to it. |
| `data-reach` | doorway widths | `1.3` | How far from the doorway the door starts to respond to a dragged item. |
| `data-throw-time` | seconds | `0.3` | How far ahead a release is projected to decide where it lands. Larger values make throws travel further. |

### How items are judged on release

- **Dropped in the doorway:** banished.
- **Thrown into the door fast enough:** banished, even from across the room.
- **Pushed or thrown weakly into the door:** the door shuts if it was ajar, the item thuds off it and the door shudders.
- **Anything else:** the item glides to a stop and stays inside the room.

Banishes queue. While the room is pulling one item, anything else you drop in or press waits its turn; the door stays open between them and slams once, at the end.

### Accessibility

- **Keyboard:** every item is a native button. Enter or Space banishes it through the same door sequence, and focus moves to the next remaining item (or to Let them out when the room is empty).
- **Pointer and touch:** drag and throw; a click or tap without dragging also banishes.
- **Screen readers:** the visual tally is `aria-hidden`; a polite live region announces each banishment (using `data-name`) and the restore. Each item's visible text is its accessible name, so voice-control users can say what they see; avoid an `aria-label` that leaves visible text out.
- **Reduced motion:** no swing, pull, spin, shake or dust. A banished item fades out and the tally updates; Let them out fades them back. Dragging still works, with the doorway outlined as the drop zone. The CSS loops in the demo cards (spinner, sound bars) stop.
- **Without JavaScript:** the room is a still composition with the door closed and every item visible.
- **Focus visible:** items and the restore button have a clear focus ring.

### Dependencies

**Required:**
- GSAP 3.12+ (the demo is pinned to 3.15.0)
- Draggable plugin
- InertiaPlugin (release velocity)

## What You Get

- `index.html`: working demo page
- `assets/script.js`: commented, readable source
- `assets/style.css`: effect styles
- `README.md`: full documentation with examples and framework integration notes
- `START-HERE-AI.md`: product-specific copy-paste prompt for AI-assisted setup
- `LICENSE.txt`: standard license terms
- Lifetime updates: re-download anytime from your library

## Get the Code

This is a premium effect. The standard license costs £5 one-time and covers unlimited personal and commercial projects with no attribution required for our code. Bundled third-party assets retain their own licences and attribution requirements. The only restrictions: no redistribution of the code itself and no competing effect libraries.

- [Buy Room 101](https://gsapvault.com/effects/room-101)
- [The Vault (£99 one-time, best value): every collection in the Vault library, plus future items added to those collections](https://gsapvault.com/effects)

## Judge the Code Quality First

These related effects are free with complete source published, written to the same production standard (cleanup functions, reduced-motion support, framework-agnostic):

- [Hover Underline](https://gsapvault.com/effects/hover-underline.md): Four material link underlines (an exit-through line, marker sweep, hand-drawn wave, and an endlessly travelling wave) with coordinated type and active-index responses.
- [3D Card Flip Gallery](https://gsapvault.com/effects/3d-card-flip.md): Tactile GSAP 3D cards with deep perspective, reactive edge lighting and shifting shadows. Flip on hover, keyboard focus or tap, with grouped auto-close.
- [Tailwind Component Remixer](https://gsapvault.com/effects/tailwind-class-playground.md): Generate fresh Tailwind component recipes with procedural SVG artwork, coordinated colour palettes and animated GSAP layout transitions.

---

From [GSAP Vault](https://gsapvault.com): production-ready GSAP animation effects. Full catalog for agents: https://gsapvault.com/llms-full.txt
