The Dinner
The story behind The Dinner
Inspired by Dinner party on Wikipedia
Built with Pure HTML/CSS · Fraunces variable serif · Caveat handwriting · IntersectionObserver · Scroll-driven state · SVG feTurbulence stain filters · CSS transitions + mix-blend-mode
Techniques Three-state scroll observer (hidden → revealed → passed) · Randomized stain placement (position, rotation, size per course) · Pencil-line strikethrough keyframe on dish names · Inline margin asides as overheard conversation · IntersectionObserver-triggered “coffee pause” on course VII
Direction You are a guest arriving late to a dinner party. The menu is the evening. As you scroll, you consume each course and it decays — crossed out, stained, finished. The conversation in the margin grows more honest as the wine runs down.
Result An aged cardstock menu card floating on a dark table, seven courses from Martini to Coffee, with handwritten margin notes from guests whose evening is unraveling in real time
The Story
A dinner party is one of the oldest social technologies. You gather people around a sequence of dishes, and the sequence does the work — arrival loosens coats, the first course loosens tongues, the main course is where people say what they came to say, and the coffee is where everyone pretends they didn’t hear it. The form dates back at least to the Greek symposium. The word “companion” comes from com-panis: the person you share bread with.
This experience is a menu card for a Tuesday supper at someone’s home. Seven courses, from a cold Martini to a black coffee. You scroll to eat. Each course appears as you approach it — the dish name, a brief note about how it was made, and a scrawled aside in the margin: a fragment of overheard conversation from someone at the table, written in a different hand.
As you scroll past a course, it decays. The dish name gets a pencil line through it. A stain bleeds through the paper — wine, gravy, oil, coffee, depending on what was served. The conversation in the margin, which started with a polite “Come in, come in,” arrives by course five at “I don’t think we like each other very much any more.”
You only attend this dinner once. Reload to attend again.
The Take
The cover reads “Tuesday Supper” in a large variable-weight Fraunces serif — optical size cranked up to 120 for the display heading, then dropped back to 14 for body text. Below it: “at the home of E. and C.” and a date. It looks like a real printed menu card, the kind you might find in a box of someone’s things decades later.
Scroll past the cover and the courses begin. Course I: a Vesper martini. The margin aside fades in — “You made it. Come in, come in.” — written in Caveat, a handwriting face that looks like someone scrawled it with a ballpoint during the meal. The two-column layout (dish on the left, margin on the right) mimics the layout of an annotated manuscript: the main text is what was planned, the margin is what actually happened.
By course IV (roast duck), the margin conversation has turned: “I think she doesn’t talk to him any more. Since the — you know — the thing with her brother.” The stains are accumulating. The earlier courses have pencil lines through their names. The card looks used.
Course VII is just “Coffee. Alone. Black.” The dish name is set smaller and plainer — the optical size drops, the font weight stays neutral. The margin note is from “the clock”: “11:47 p.m. Coats are on the back of the sofa. Nobody wants to go home yet.” A brief coffee-pause class applies to the body when this course hits center-screen, darkening the table edges for 1.8 seconds. The room gets quiet.
The Tech
No canvas, no WebGL, no JavaScript animation loop
This is the first experience in the archive built entirely with HTML, CSS, and a scroll observer. There is no <canvas>, no requestAnimationFrame loop, no shader, no Three.js. The visual richness comes from CSS: variable fonts, mix-blend-mode stain overlays, keyframed strikethrough animations, and transition timing that makes each course’s decay feel organic rather than switched.
Scroll state machine
Each .course element progresses through three states: hidden (default), revealed (margin aside fades in), and passed (dish crossed out, stain bleeds). A single scroll listener checks whether the viewport midpoint has crossed two thresholds per course: 15% into the course triggers reveal, 55% triggers passed. The listener is passive: true and throttled through requestAnimationFrame — but since nothing animates continuously, the RAF exists only as a scroll debounce.
Stain overlays
Each course gets 1–2 <div class="stain"> elements injected by JavaScript at load time with randomized position, rotation, and size. The stain type (wine, gravy, oil, coffee) comes from a data-stain attribute on the course element. Each stain is a radial-gradient colored to match its source, with mix-blend-mode: multiply so it darkens the paper rather than sitting on top of it. The stains start at opacity: 0; transform: scale(0.6) and transition to opacity: 0.78; transform: scale(1) when the course gets the .passed class — a 2.4-second ease that makes the stain appear to bleed outward.
The strikethrough
When a course is passed, its .dish element gets a ::after pseudo-element: a repeating linear gradient that draws a dashed line across the dish name, animated from scaleX(0) to scaleX(1) over 1.6 seconds with ease-out. The dashes are 14px strokes with 3px gaps, angled at -1 degree to look hand-drawn rather than mechanical. It reads as someone drawing a line through the item with a pencil — the kind of mark you’d make on a real menu card as each course is cleared.
Typography as architecture
The Fraunces variable font does heavy lifting. The cover title uses optical size 120 (display weight, high contrast, sharp serifs). Course numbers use optical size 72. Body text uses optical size 14 (text weight, lower contrast, softer). Course VII’s dish name drops to optical size 14 even for the heading — “Coffee” is set plainly, like a postscript, not a course. The font’s variable axis makes these feel like one typeface used by a typographer, not four fonts bolted together.
The margin asides use Caveat — a handwriting face — in a muted wine-ink color. The visual hierarchy (printed menu text vs. handwritten margin notes) maps directly to the narrative hierarchy (what was planned vs. what actually happened).
Responsive
On mobile (≤ 680px), the two-column grid collapses to a single column. Margin asides move below the dish note, separated by a thin rule instead of a left border. The cover title scales down via clamp(). The experience reads comfortably as a long scroll on a phone — which is arguably the more natural reading posture for a menu card.
This blog post was AI generated with Claude Code. Authored by Artificial Noodles.