Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

7 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Kitty Cafe

A bakery interior drawn entirely in CSS. No images, no SVG, no canvas — every macaron, whisker and wood grain is a <div> with a border-radius.

The scene: a glass display case packed with cat-themed treats, a chalkboard of drinks, jars on a shelf, and the shop cat asleep on the counter next to somebody's cooling coffee.

The Kitty Cafe scene

What's in the case

Treat
Purrfect Macaron raspberry shells, vanilla bean middle $3.50
Meowcha Cupcake matcha buttercream, ears included $4.25
Fishy Taiyaki custard filled, still warm $3.00
Toe Bean Cookie brown butter shortbread, pink icing $2.75
Choco Cat Donut dark glaze, far too many sprinkles $3.75
Calico Cake Slice three layers, strawberry on top $5.50
Kitten Cake Pop strawberry shell $2.50
Pudding Paws custard cup under burnt caramel $4.00
Whole Kitty Cake on the shelf, 48 hours notice please $28.00

Hover, tap or tab to any treat — in the case or the whole cake up on the shelf — and it lifts with a little price tag.

Click the sleeping cat and she wakes up: eyes open, ears perk, head lifts, and the z's turn into purrs. After about five seconds she settles back down on her own, so you can wake her again.

There's a ball of yarn on the floor too. Click it to pick it up, click the cat to give it to her, and hearts float up while she purrs over it. Click the yarn again to take it back.

All of that is checkboxes, labels and two animated custom properties — there is still no JavaScript on the page.

Running it

Open index.html. That's it — there's no build step needed to look at it.

npm install        # only needed for the tests
npm run build      # inlines the CSS into dist/
npm test           # builds, then runs the browser checks
npm run shots      # renders .shots/*.png for eyeballing changes
npm run deploy     # builds and deploys dist/ to Cloudflare Pages via Wrangler

npm run build writes:

  • dist/index.html — default root entry for static hosting (Cloudflare Pages, Vercel, Netlify)
  • dist/kitty-cafe.html — the whole thing as one self-contained page
  • dist/artifact.html — a body fragment for hosts that supply their own shell
  • dist/codepen.html and dist/codepen.css — the two CodePen panels

How it holds together

The scene is a container (container-type: inline-size) with a fixed 16:10 aspect ratio, and everything inside is measured in cqw or percentages. That means the picture scales as a single piece: it looks the same at 320px as it does at 1440px, and nothing needs a media query.

The scene also sizes itself to the window: because height follows width at a fixed 16:10, capping the width at (100dvh - 7rem) * 1.6 is the same as capping the height at the viewport, so the art fills a wide screen without ever running off the bottom of a short one.

Shared cat parts — ears, eyes, mouths, blush, whiskers — live in one place and get re-tuned per treat with custom properties:

.t-macaron {
  --ear-c: var(--pink);
  --ear-dip: 0.9cqw;   /* how far the ear tucks into a round head */
  --face-y: 36%;
  --eye-s: 0.88cqw;
}

Every colour comes from a token in css/tokens.css. Nothing downstream invents a value.

index.html          markup for the scene and the plain-text menu
css/tokens.css      colours, fonts, shared measurements
css/page.css        page shell, menu list, footer
css/room.css        wall, floor, sign, lamp, shelf, chalkboard, counter
css/case.css        display case, glass, shelf rows, price tags
css/parts.css       reusable ears, faces, blush, whiskers, berries
css/treats.css      the eight treats
css/critters.css    whole cake, shop cat, tip jar, mug
css/yarn.css        the ball of yarn, its states and the hearts
css/motion.css      idle animations and the reduced-motion opt-out

Accessibility

  • Each treat is a real button with an accessible name that includes its price.
  • Everything works with mouse, touch, and keyboard — tags show on hover and focus, so a tap or a Tab both work.
  • The art is small on a phone, so the full menu is repeated as plain text below the scene. That list is the accessible source of truth.
  • prefers-reduced-motion: reduce stops every animation and the hover lift. The price tags still fade in.

Eighteen browser tests cover all of the above, plus horizontal overflow from 320px to 1920px, treats staying inside the case at every width, the scene never outgrowing the window, and the page containing no <script> at all.

Licence

Apache 2.0 — see LICENSE.

Made with 💖 by Pink Pixel

About

No description, website, or topics provided.

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages