DEV Community

Ashitosh Lavhate
Ashitosh Lavhate

Posted on

थाळी — An Interactive Thali, Built Entirely in CSS

Frontend Challenge CSS Art Submission 🍲🥧

This is a submission for Frontend Challenge - Comfort Food Edition, CSS Art.

Inspiration

I'm Maharashtrian, and in our homes food never really arrives one dish at a time, it arrives as a थाळी. A steel plate, rice in the center, a ring of vaatis around it holding varan, bhaji, koshimbir, amti, a curl of lonche on the side, and always something to drink alongside — a glass of taak or lassi. That's what "comfort food" has always meant to me. Not one hero ingredient on a plate, but the whole spread landing in front of you at once, still steaming.

So when this challenge said "comfort food," I didn't want to draw one bowl of something. I wanted to draw the entire thali — the way it actually lands on the table at home — and build it purely out of CSS.

Demo

Hover over any dish for a quick description of what's in it, and try dragging one item onto another — they'll swap places on the plate.

Journey

Every piece of this — the brushed-gold steel plate, the katoris, the rice mound, the naan on its banana leaf, the lassi tumbler — is built from gradients, box-shadows, and clip-paths. No images anywhere. A few techniques I leaned on a lot:

  • Layered conic-gradient + radial-gradient for the brushed metal look of the plate and steel bowls
  • Stacked box-shadow values as a cheap way to scatter garnish — cilantro flecks, chili flakes, pistachio bits — without extra markup
  • clip-path for the tapered lassi tumbler and its ridged, fluted sides
  • Irregular border-radius values (different on every corner) so the rice mound and naan feel hand-shaped instead of like perfect circles

The one feature that pushed past "pure CSS" was letting people drag a dish and drop it on another to swap their places, with a smooth spring-like transition. The contest rules allow a light sprinkle of JS for CSS Art as long as the visuals stay CSS-driven, so I used Pointer Events just to track drag position and swap two items' coordinates — nothing about how the dishes actually look comes from JS.

The best bug of the whole build: after wiring up hover tooltips and drag, nothing responded — no hover cards, no dragging. Turned out a decorative etched-rim pattern on the plate, built as a ::after pseudo-element and masked down to a thin ring, was still sitting on top of everything in paint order. CSS mask makes pixels transparent, but it doesn't stop an element from intercepting clicks — so an "invisible" ring was quietly blocking every dish underneath it. One pointer-events: none later, everything came alive.

This one felt personal to build. Thanks for putting this challenge together! 🍛

Top comments (0)