This is a submission for Frontend Challenge - Comfort Food Edition, CSS Art.
Inspiration
I went out for ramen with friends yesterday, we went to one of those self-service spots where you got to pick different ramen options on the menu and build your own bowl from the topping bar. I picked mine, it looked really good, so I took a photo before I devoured it.
Then I saw this challenge this morning.
So I opened the photo again and thought:
What if I tried to rebuild this exact bowl using CSS?
That turned out to be considerably harder than eating it.
The goal was to capture the specific composition of the photograph: the shape of the bowl, the tangled noodles, the pieces of beef, the egg, bok choy, corn, spoon, shadows, highlights, and, of course, the steam.
So I treated the photograph almost like a reference sheet and broke the bowl down into individual visual layers.
Demo
The artwork itself uses no image assets. Everything in the illustration is constructed from HTML and CSS, with a small amount of vanilla JavaScript used for responsive scaling.
Journey
The first thing I learned was that a photograph makes complexity look deceptively simple.
Looking at the ramen, I initially saw a bowl of noodles, broth and toppings.
Trying to recreate it made me realize how many tiny visual relationships are hiding inside that one image: overlapping shapes, gradients, shadows, highlights, irregular edges, transparency and depth.
I started with the bowl and worked inward.
π₯£ Building the bowl
The bowl and broth use layered gradients to create the curved ceramic surface, dark broth and subtle highlights. I also added the small details around the rim to reproduce the character of the original bowl rather than making it look like a generic circle.
π The noodles
The noodles were probably the hardest part.
A few yellow squiggles looked nothing like the photograph, so I experimented with layered gradient patterns instead.
I ended up using multiple overlapping radial-gradient() layers with different rotations, offsets, colours and opacity. The layers overlap to create the tangled appearance of noodles while the darker edges help give the mass some depth.
This was one of those cases where a tiny change could completely alter the result.
Sometimes the difference between βnoodlesβ and βthat actually looks like noodlesβ was only a few pixels.
π₯© The toppings
The beef uses irregular clipped shapes rather than simple rectangles, with smaller details layered on top to suggest marbling and texture.
The egg uses a custom clipped silhouette, layered gradients for the yolk and subtle highlights.
The bok choy is assembled from overlapping clipped shapes for the leaves and stems, while the corn uses smaller rounded shapes and highlights scattered around the bowl.
The aim wasn't to make every ingredient perfectly geometric. The irregularities are what help the bowl feel like food rather than a collection of CSS shapes.
π₯ Getting the spoon right
The spoon was surprisingly annoying.
Its position, angle and depth relative to the bowl had to match the reference, so I had to repeatedly adjust its rotation, shadow and placement until it sat naturally behind the bowl.
It was one of the smallest elements in the composition, but getting it wrong made the entire scene feel wrong.
β¨οΈ Making the steam feel alive
The steam is made from four separate elements animated with CSS keyframes.
Each has a slightly different delay and movement so they don't rise in perfect synchronization. Opacity, scale and position change throughout the animation to make the steam feel softer and less mechanical.
I also added a prefers-reduced-motion fallback, so the animation can be disabled for users who prefer reduced motion.
What I'm particularly proud of
I'm probably most proud of the fact that the project started with a photograph from an actual meal and ended as something I could reconstruct entirely from code.
The reference gave me something very specific to aim for. Instead of asking βDoes this look like ramen?β, I kept asking:
βHow close can I get to the original?β
That made me pay much more attention to proportions, positioning, texture and the small details that I normally wouldn't notice.
It also made the project much more iterative than I expected. A topping might look right on its own but entirely wrong once it was placed beside the egg. A noodle layer could look good until another layer was added. Moving one element by a few pixels could change the balance of the whole bowl.
And eventually, it started to look like the photograph, at least I think it does....
Yesterday, this was just dinner with friends. Today, it's the same bowl of ramen, existing twice: once in the photo, and once in a pile of divs doing their best impression of food.
After staring at ramen for this many hours, I obviously started craving the real thing again. So I've already ordered the same bowl from the same place. It should be here in about 25 minutes, and I can't wait to have dinner. π

Top comments (2)
The recreation is impressively accurate! I really like the approach of layering multiple
radial-gradient()s to create the noodles and depth. Such a clever use of CSS. πΈI guess my dinner tonight is going to be shoyu ramen now π
Thank you! πΈ The noodles took years off my life but it was worth it. And now my ramen craving has officially spread to you, welcome to the club, dinner's on me (emotionally). π