<!DOCTYPE html>
Steam & Soul — A Bowl Written in CSS
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
:root {
--wood1: #3b1710;
--wood2: #71351f;
--wood3: #a9572d;
--red1: #43050c;
--red2: #86101a;
--red3: #d72b28;
--broth1: #721006;
--broth2: #c9330d;
--broth3: #ff9228;
--noodle1: #fff2ad;
--noodle2: #ffd35c;
--noodle3: #a95e1d;
--gold: #ffbe42;
}
body {
min-height: 100vh;
overflow: hidden;
display: grid;
place-items: center;
background:
radial-gradient(
circle at 50% 32%,
#fffdf4 0%,
#ffe9c7 28%,
#e9a269 65%,
#864029 100%
);
font-family:
Inter,
Arial,
sans-serif;
}
/* =====================================================
SCENE
===================================================== */
.scene {
position: relative;
width: 800px;
height: 800px;
perspective: 1100px;
cursor: pointer;
animation: floatingScene 7s ease-in-out infinite;
}
@keyframes floatingScene {
0%,100% {
transform: translateY(0);
}
50% {
transform: translateY(-5px);
}
}
/* =====================================================
TITLE
===================================================== */
.title {
position: absolute;
top: 30px;
left: 0;
width: 100%;
text-align: center;
color: #641f12;
font-size: 36px;
font-weight: 950;
letter-spacing: 10px;
text-shadow:
2px 2px 0 #ffd99e,
0 8px 20px rgba(70,20,0,.15);
z-index: 200;
}
.subtitle {
position: absolute;
top: 82px;
width: 100%;
text-align: center;
color: #8b4a2d;
font-size: 11px;
font-weight: 700;
letter-spacing: 5px;
z-index: 200;
}
/* =====================================================
LIGHT
===================================================== */
.light {
position: absolute;
left: 50%;
top: 170px;
width: 550px;
height: 420px;
transform: translateX(-50%);
background:
radial-gradient(
ellipse,
rgba(255,220,150,.4),
transparent 68%
);
filter: blur(20px);
animation: lightPulse 5s ease-in-out infinite;
z-index: 0;
}
@keyframes lightPulse {
0%,100% { opacity: .55; }
50% { opacity: .9; }
}
/* =====================================================
TABLE
===================================================== */
.table {
position: absolute;
left: -100px;
right: -100px;
bottom: -40px;
height: 280px;
background:
repeating-linear-gradient(
92deg,
#572819 0 30px,
#74351e 31px 60px,
#4a2117 61px 92px,
#8a4224 93px 120px
);
border-top: 13px solid #37150e;
box-shadow:
inset 0 15px 30px rgba(255,180,100,.12),
0 -15px 35px rgba(40,5,0,.25);
transform:
perspective(800px)
rotateX(9deg);
z-index: 1;
}
.table::after {
content: "";
position: absolute;
inset: 25px;
background:
repeating-linear-gradient(
8deg,
transparent 0 23px,
rgba(30,8,2,.15) 24px 27px,
transparent 28px 50px
);
opacity: .7;
}
/* =====================================================
PLATE
===================================================== */
.plate-shadow {
position: absolute;
width: 610px;
height: 110px;
left: 50%;
bottom: 145px;
transform: translateX(-50%);
border-radius: 50%;
background:
radial-gradient(
ellipse,
rgba(30,5,0,.48),
rgba(30,5,0,.18) 45%,
transparent 73%
);
filter: blur(10px);
z-index: 2;
}
.plate {
position: absolute;
width: 600px;
height: 175px;
left: 50%;
bottom: 140px;
transform: translateX(-50%);
border-radius: 50%;
background:
radial-gradient(
ellipse,
#fffdf0 0%,
#ead8b5 60%,
#b28d69 100%
);
box-shadow:
0 20px 25px rgba(50,10,0,.28),
inset 0 -10px 16px rgba(80,35,10,.18);
z-index: 3;
}
.plate::after {
content: "";
position: absolute;
inset: 22px 35px;
border-radius: 50%;
border:
3px solid rgba(130,65,25,.18);
}
/* =====================================================
BOWL
===================================================== */
.bowl {
position: absolute;
left: 50%;
bottom: 180px;
width: 525px;
height: 345px;
transform:
translateX(-50%)
rotateX(6deg);
border-radius:
30px
30px
48%
48%;
background:
linear-gradient(
90deg,
#40040b 0%,
#700913 10%,
#b81720 25%,
#e03b2d 47%,
#c01b22 67%,
#710913 88%,
#3b0409 100%
);
box-shadow:
inset 0 -40px 45px rgba(30,0,0,.55),
inset 18px 0 28px rgba(255,100,70,.16),
inset -22px 0 30px rgba(30,0,0,.35),
0 30px 30px rgba(40,7,0,.38);
overflow: hidden;
z-index: 10;
}
.bowl::before {
content: "";
position: absolute;
top: 25px;
left: 50px;
width: 90px;
height: 245px;
border-radius: 50%;
background:
linear-gradient(
90deg,
transparent,
rgba(255,200,160,.2),
transparent
);
transform: rotate(8deg);
filter: blur(2px);
}
.bowl::after {
content: "";
position: absolute;
left: 45px;
right: 45px;
bottom: 55px;
height: 7px;
border-radius: 50%;
background: var(--gold);
box-shadow:
0 23px 0 rgba(255,190,66,.9),
0 46px 0 rgba(255,190,66,.3);
z-index: 60;
}
/* =====================================================
SOUP
===================================================== */
.soup {
position: absolute;
left: 50%;
top: -10px;
width: 470px;
height: 165px;
transform: translateX(-50%);
border-radius: 50%;
background:
radial-gradient(
ellipse at 45% 38%,
#ffad3c 0%,
#f06b1d 27%,
#bd3110 57%,
#6d0e08 100%
);
border: 12px solid #f3a82e;
box-shadow:
inset 0 12px 20px rgba(255,220,100,.3),
inset 0 -15px 25px rgba(70,0,0,.35),
0 5px 10px rgba(40,5,0,.4);
z-index: 20;
}
/* =====================================================
BROTH SHIMMER
===================================================== */
.shimmer {
position: absolute;
width: 170px;
height: 35px;
border-radius: 50%;
background:
linear-gradient(
100deg,
transparent,
rgba(255,240,170,.45),
transparent
);
filter: blur(3px);
animation: shimmer 4s ease-in-out infinite;
z-index: 70;
}
.shimmer1 {
left: 80px;
top: 45px;
}
.shimmer2 {
left: 245px;
top: 82px;
animation-delay: 1.7s;
}
@keyframes shimmer {
0%,100% {
transform: translateX(-25px);
opacity: .25;
}
50% {
transform: translateX(35px);
opacity: .8;
}
}
/* =====================================================
NOODLES
===================================================== */
.noodle {
position: absolute;
height: 9px;
border-radius: 50%;
background:
linear-gradient(
180deg,
var(--noodle1),
var(--noodle2) 55%,
var(--noodle3)
);
box-shadow:
0 2px 3px rgba(75,20,0,.5);
z-index: 40;
}
.n1 {
width: 285px;
left: 40px;
top: 54px;
transform: rotate(4deg);
}
.n2 {
width: 310px;
left: 65px;
top: 72px;
transform: rotate(-7deg);
}
.n3 {
width: 245px;
left: 80px;
top: 91px;
transform: rotate(13deg);
}
.n4 {
width: 230px;
left: 145px;
top: 42px;
transform: rotate(-16deg);
}
.n5 {
width: 270px;
left: 125px;
top: 80px;
transform: rotate(19deg);
}
.n6 {
width: 200px;
left: 115px;
top: 108px;
transform: rotate(-6deg);
}
/* Curved noodles */
.curve {
position: absolute;
width: 105px;
height: 32px;
border:
8px solid var(--noodle2);
border-left-color: transparent;
border-radius: 50%;
z-index: 42;
}
.curve1 {
left: 50px;
top: 45px;
transform: rotate(-18deg);
}
.curve2 {
right: 45px;
top: 75px;
transform: rotate(20deg);
}
.curve3 {
left: 170px;
top: 102px;
transform: rotate(8deg);
}
/* =====================================================
EGG
===================================================== */
.egg {
position: absolute;
width: 110px;
height: 125px;
left: 65px;
top: 4px;
border-radius:
54% 46%
48% 52%;
background:
radial-gradient(
ellipse at 38% 30%,
#ffffff,
#fff4d0 63%,
#d9bc82
);
transform: rotate(-17deg);
box-shadow:
0 5px 8px rgba(60,15,0,.4);
z-index: 50;
}
.yolk {
position: absolute;
width: 55px;
height: 55px;
left: 28px;
top: 35px;
border-radius: 50%;
background:
radial-gradient(
circle at 32% 27%,
#ffe35c,
#ff9d0a 55%,
#cf5700
);
box-shadow:
inset -7px -8px 10px rgba(150,50,0,.25),
0 3px 5px rgba(80,20,0,.35);
}
/* =====================================================
SEAWEED
===================================================== */
.seaweed {
position: absolute;
width: 40px;
height: 92px;
right: 145px;
top: 25px;
border-radius: 6px;
background:
repeating-linear-gradient(
90deg,
#041c14 0 5px,
#145436 6px 10px
);
transform: rotate(12deg);
box-shadow:
3px 4px 6px rgba(0,0,0,.4);
z-index: 47;
}
/* =====================================================
NARUTO
===================================================== */
.naruto {
position: absolute;
width: 76px;
height: 76px;
right: 75px;
top: 20px;
border-radius: 50%;
background:
radial-gradient(
circle,
#fff8d8 0 57%,
#df4930 58% 65%,
#fff8d8 66%
);
border: 5px solid #e55535;
box-shadow:
0 4px 7px rgba(60,15,0,.35);
z-index: 52;
}
.naruto::before {
content: "";
position: absolute;
left: 15px;
top: 14px;
width: 36px;
height: 36px;
border:
5px solid #d7442f;
border-left-color: transparent;
border-radius: 50%;
transform: rotate(45deg);
}
/* =====================================================
MUSHROOM
===================================================== */
.mushroom {
position: absolute;
right: 115px;
bottom: 8px;
width: 82px;
height: 60px;
z-index: 50;
}
.mushroom-cap {
position: absolute;
width: 82px;
height: 46px;
border-radius:
50%
50%
35%
35%;
background:
radial-gradient(
circle at 40% 25%,
#f09a5d,
#a94024
);
box-shadow:
0 4px 5px rgba(60,15,0,.3);
}
.mushroom-stem {
position: absolute;
width: 30px;
height: 38px;
left: 26px;
top: 25px;
border-radius:
20%
20%
40%
40%;
background:
linear-gradient(
90deg,
#c48c5c,
#fff0c9,
#c18a59
);
}
/* =====================================================
CORN
===================================================== */
.corn {
position: absolute;
width: 14px;
height: 14px;
border-radius: 50%;
background:
radial-gradient(
circle at 35% 30%,
#fff68c,
#ffd23c 60%,
#d88800
);
box-shadow:
1px 2px 3px rgba(80,30,0,.3);
z-index: 55;
}
.c1 { left: 238px; top: 52px; }
.c2 { left: 264px; top: 66px; }
.c3 { left: 291px; top: 52px; }
.c4 { left: 315px; top: 75px; }
.c5 { left: 278px; top: 95px; }
.c6 { left: 245px; top: 99px; }
/* =====================================================
GREEN ONION
===================================================== */
.onion {
position: absolute;
width: 7px;
height: 67px;
border-radius: 10px;
background:
linear-gradient(
90deg,
#236c32,
#76d05b,
#236c32
);
transform-origin: bottom;
z-index: 57;
}
.o1 {
left: 190px;
top: 25px;
transform: rotate(-30deg);
}
.o2 {
left: 215px;
top: 20px;
transform: rotate(14deg);
}
.o3 {
left: 235px;
top: 29px;
transform: rotate(36deg);
}
.o4 {
left: 257px;
top: 20px;
transform: rotate(-10deg);
}
/* =====================================================
SESAME
===================================================== */
.sesame {
position: absolute;
width: 8px;
height: 3px;
border-radius: 50%;
background: #fff3bd;
transform: rotate(35deg);
z-index: 60;
}
.s1 { left: 130px; top: 72px; }
.s2 { left: 168px; top: 96px; }
.s3 { left: 205px; top: 67px; }
.s4 { left: 335px; top: 61px; }
.s5 { left: 355px; top: 89px; }
.s6 { left: 305px; top: 105px; }
/* =====================================================
CHILI OIL
===================================================== */
.oil {
position: absolute;
width: 18px;
height: 8px;
border-radius: 50%;
background:
radial-gradient(
circle,
#ffbd35,
#e43a0c
);
box-shadow:
0 0 8px rgba(255,80,0,.45);
animation:
oilPulse 3.5s ease-in-out infinite;
z-index: 65;
}
.oil1 {
left: 95px;
top: 108px;
}
.oil2 {
left: 310px;
top: 96px;
animation-delay: 1s;
}
.oil3 {
left: 220px;
top: 43px;
animation-delay: 2s;
}
@keyframes oilPulse {
0%,100% {
transform: scale(1);
}
50% {
transform: scale(1.35);
}
}
/* =====================================================
BOWL RIM
===================================================== */
.rim {
position: absolute;
left: 50%;
top: -8px;
width: 505px;
height: 120px;
transform: translateX(-50%);
border:
10px solid #ffb537;
border-radius: 50%;
box-shadow:
0 3px 5px rgba(60,10,0,.35);
z-index: 100;
pointer-events: none;
}
/* =====================================================
BOWL PATTERN
===================================================== */
.pattern {
position: absolute;
left: 50%;
bottom: 82px;
width: 310px;
transform: translateX(-50%);
display: flex;
justify-content: space-between;
z-index: 90;
opacity: .7;
}
.pattern span {
width: 18px;
height: 18px;
border:
3px solid #ffc148;
transform: rotate(45deg);
}
/* =====================================================
CHOPSTICKS
===================================================== */
.chopsticks {
position: absolute;
right: 105px;
top: 115px;
width: 250px;
height: 470px;
z-index: 150;
transform: rotate(5deg);
}
.chopstick {
position: absolute;
width: 15px;
height: 470px;
border-radius: 10px;
background:
linear-gradient(
90deg,
#461a10,
#d08443 45%,
#642719
);
box-shadow:
4px 6px 10px rgba(30,5,0,.4);
transform-origin: bottom;
}
.cs1 {
right: 75px;
transform: rotate(29deg);
}
.cs2 {
right: 117px;
transform: rotate(37deg);
}
/* =====================================================
NOODLE FROM CHOPSTICKS
===================================================== */
.lifted {
position: absolute;
right: 195px;
top: 275px;
width: 240px;
height: 260px;
z-index: 145;
transform: rotate(-8deg);
}
/* Multiple curved strands */
.lifted span {
position: absolute;
width: 210px;
height: 150px;
border-left:
9px solid var(--noodle2);
border-bottom:
9px solid var(--noodle1);
border-radius:
0 0 0 80%;
filter:
drop-shadow(0 3px 2px rgba(70,20,0,.45));
transform-origin: top left;
}
.lifted span:nth-child(1) {
left: 0;
top: 0;
transform:
rotate(8deg)
skewY(-8deg);
}
.lifted span:nth-child(2) {
left: 25px;
top: 5px;
transform:
rotate(12deg)
skewY(-10deg);
}
.lifted span:nth-child(3) {
left: 50px;
top: 12px;
transform:
rotate(16deg)
skewY(-12deg);
}
/* Noodle ends */
.lifted span::after {
content: "";
position: absolute;
right: -8px;
bottom: -8px;
width: 15px;
height: 15px;
border-radius: 50%;
background: #ffd66b;
}
/* =====================================================
STEAM
===================================================== */
.steam-glow {
position: absolute;
left: 50%;
top: 145px;
width: 470px;
height: 280px;
transform: translateX(-50%);
background:
radial-gradient(
ellipse,
rgba(255,255,255,.25),
transparent 70%
);
filter: blur(20px);
z-index: 110;
}
.steam-container {
position: absolute;
left: 50%;
top: 125px;
width: 450px;
height: 330px;
transform: translateX(-50%);
z-index: 120;
pointer-events: none;
}
.steam {
position: absolute;
bottom: 0;
width: 25px;
height: 210px;
border-left:
9px solid rgba(255,255,255,.6);
border-radius: 50%;
filter: blur(2px);
opacity: 0;
animation:
steamRise 4.5s ease-in-out infinite;
}
.steam:nth-child(1) {
left: 55px;
}
.steam:nth-child(2) {
left: 145px;
height: 250px;
animation-delay: 1.1s;
}
.steam:nth-child(3) {
left: 245px;
height: 195px;
animation-delay: 2s;
}
.steam:nth-child(4) {
left: 330px;
height: 235px;
animation-delay: 2.8s;
}
@keyframes steamRise {
0% {
opacity: 0;
transform:
translateY(30px)
rotate(5deg)
scale(.7);
}
20% {
opacity: .65;
}
50% {
opacity: .35;
transform:
translateY(-65px)
rotate(-12deg)
scale(1);
}
80% {
opacity: .18;
}
100% {
opacity: 0;
transform:
translateY(-190px)
rotate(17deg)
scale(1.3);
}
}
/* =====================================================
INTERACTION
===================================================== */
.scene.active .steam {
animation-duration: 2.1s;
}
.scene.active .lifted {
animation:
noodleLift 1.5s ease-in-out;
}
.scene.active .chopsticks {
animation:
chopMove 1.5s ease-in-out;
}
@keyframes noodleLift {
0%,100% {
transform:
rotate(-8deg)
translateY(0);
}
50% {
transform:
rotate(-3deg)
translateY(-40px);
}
}
@keyframes chopMove {
0%,100% {
transform: rotate(5deg);
}
50% {
transform:
rotate(1deg)
translateY(-12px);
}
}
/* =====================================================
BADGE
===================================================== */
.badge {
position: absolute;
left: 50%;
bottom: 35px;
transform: translateX(-50%);
padding:
9px 20px;
border-radius: 30px;
background:
rgba(255,244,216,.72);
border:
1px solid rgba(100,40,15,.2);
backdrop-filter: blur(8px);
color: #71351f;
font-size: 10px;
font-weight: 800;
letter-spacing: 3px;
z-index: 200;
}
/* =====================================================
RESPONSIVE
===================================================== */
@media(max-width:850px) {
.scene {
transform: scale(.8);
}
}
@media(max-width:650px) {
.scene {
transform: scale(.6);
}
}
@media(max-height:720px) {
.scene {
transform: scale(.65);
}
}
STEAM & SOUL
A BOWL WRITTEN IN CSS
CSS ART • MINIMAL JS • 100% HAND CODED
const scene = document.getElementById("ramen");
scene.addEventListener("click", () => {
scene.classList.remove("active");
// Restart CSS animation
void scene.offsetWidth;
scene.classList.add("active");
});
Top comments (0)