This is a submission for Frontend Challenge - Comfort Food Edition, CSS Art.
Inspiration
Okroshka is the soup you eat when it's too hot to eat soup — a cold kvass (or
kefir) base over a confetti of diced cucumber, radish, potato and egg, buried
under more fresh dill than seems reasonable, with one proud dollop of smetana
in the middle.
Mine comes with a memory. When I was six, my parents took me haymaking in
the water meadows. At noon we would hide in the dense shade of a fresh
haystack, and my father would pull a jar wrapped in a thick towel out of a
canvas bag: ice-cold okroshka my mother had made back at dawn. The cucumbers
crunched, the sharp homemade kvass stung the tongue, and every sip drove the
exhaustion away. (The full memory lives in my sister entry, linked below.)
The scene I painted is the okroshka of my imagination's summer table:
a Khokhloma bowl — that black-lacquered Russian wooden ware painted with
gold leaves and red berries — on a red lacquer saucer, over a green gingham
tablecloth, with rye bread, a painted wooden spoon, and a little bowl of
smetana standing by.
Demo
Click (or Tab + Space) the bowl to stir the smetana into the soup. The
cream sweeps a full turn and a half through the dill, the herb blanket gets
dragged along with it, and it all settles back slowly when you let go.
There is no JavaScript anywhere on this page — not for the art, and not
for the interaction. The stir is a visually-hidden (but fully keyboard-real)
checkbox, a :has() selector, and one registered @property transition.
Journey
Some of the tricks I'm proudest of, in the order they saved me:
The curved rim bands ("ellipse shingles"). A Khokhloma bowl has a red lip
and a gold band that curve with the rim. Horizontal gradient stripes can't
bend — so each band is the same ellipse as the bowl opening, dropped a couple
of cqi lower. Only its curved front crescent peeks out from behind the
ellipse above it. Three stacked ellipses, a perfectly curved rim.
The dill blanket. The photo-real signature of okroshka is a surface
buried in chopped dill. Mine is five overlapping speckle patterns with
deliberately co-prime-ish background-size tiles (2.3×1.7, 1.7×1.3,
2.9×2.1…) so the grids never visually align, a tiny blur() to melt them
into herb texture, and a radial ring mask that opens the center for the
smetana dollop.
Stirring a flat ellipse. Rotating the dill layer in screen space swings
it out of the soup plane like a slab (I know because I shipped it for five
minutes). The fix is the old animator's trick — squash → rotate → unsquash:
transform: scaleY(0.25) rotate(38deg) scaleY(4) stretches the ellipse into
a circle, rotates it in that space, and squashes it back. The silhouette
never moves; the texture swirls in the plane of the soup.
The smetana swirl. A conic-gradient comma masked into a ring, whose start
angle is a registered custom property:
@property --swirl { syntax: '<angle>'; inherits: true; initial-value: 0deg; }
.stage:has(.stir:checked) .soup { --swirl: 540deg; }
.soup { transition: --swirl 1.6s cubic-bezier(0.3, 0.7, 0.2, 1); }
Registration is the whole trick — an unregistered custom property would snap
instead of sweeping. Unchecking transitions back over 2.4s, because cream
settles slower than it stirs.
Dill fronds with mask-composite. A frond is a repeating-conic fan of
needle rays intersected with a 96° wedge — without the wedge the fan is a
360° starburst (also shipped that for five minutes).
Accessibility, because art is still a page. The scene is one
role="img" figure with alt text written like a photo caption. The checkbox
and its label live outside the figure (role="img" flattens its subtree
for assistive tech), the label announces "Stir the sour cream into the soup",
and focus draws a gold ring around the bowl's lip. Every animation and
transition lives inside @media (prefers-reduced-motion: no-preference) —
reduced-motion visitors get a finished still life, and the stir still works
as an instant state change.
Everything is sized in cqi container units, so the same fragment drops
into any page at any width — which is exactly what my sister entry does:
Dear Okroshka — a love letter to a cold soup, a full landing page for the same dish.
Code is MIT-licensed.


Top comments (0)