Phone mockup
Pure CSSA phone with real thickness: screen, back, four thin walls and a stack of rounded slabs that fills the corners. It turns to show both sides.
A faceted glass bottle you can see into: an octagonal prism of glass around a smaller prism of liquid, a fluted gold cap and a label. A glint sweeps across each time it faces you.
Your edited version
rotateY(n × 45deg) and pushed out to their distance from the axis.(w − d) / 2 / √2, alternately left and right.--w --d --c --h), so the liquid is simply the same prism again, a glass thickness smaller, standing on the thick glass bottom.clip-path.overflow: hidden), moved with translateX while the bottle passes the front.--u, tied to the canvas, so the bottle is the same share of a gallery card, the editor and a recording canvas.octagonal prism: 8 faces at 45° stepssee-through faces drawn from both sidesa prism inside a prism for the liquidglint = translated gradient in a clipped face<div class="scene">
<div class="bottle">
<i class="shadow"></i>
<div class="prism liquid">
<i style="--n:0"></i>
<i style="--n:1"></i>
<i style="--n:2"></i>
<i style="--n:3"></i>
<i style="--n:4"></i>
<i style="--n:5"></i>
<i style="--n:6"></i>
<i style="--n:7"></i>
<b class="octagon surface"></b>
</div>
<b class="octagon floor"></b>
<div class="prism glass">
<i style="--n:0"><em class="glint"></em></i>
<i style="--n:1"></i>
<i style="--n:2"></i>
<i style="--n:3"></i>
<i style="--n:4"></i>
<i style="--n:5"></i>
<i style="--n:6"></i>
<i style="--n:7"></i>
</div>
<b class="octagon top"></b>
<span class="label"><b>LUMEN</b><small>EAU DE PARFUM</small></span>
<div class="box neck"><i></i><i></i><i></i><i></i></div>
<div class="box cap"><i><em class="glint"></em></i><i></i><i></i><i></i><i></i></div>
</div>
</div>
.scene {
/* one base unit: every length below is a multiple of it, so the bottle is the same share of a
card, the editor, a full screen and a recording canvas */
--u: 0.4vmin;
perspective: calc(800 * var(--u));
}
.bottle {
--gold: #ffcf87;
--gold-deep: #aa6c16;
position: relative;
width: calc(84 * var(--u));
height: calc(96 * var(--u));
transform-style: preserve-3d;
/* the neck and the cap stand on top of this box, so the drawing's middle is above the box's:
move the box down by that much, and the whole bottle is centred */
translate: 0 calc(17 * var(--u));
animation: sway 8s ease-in-out infinite alternate;
}
.shadow {
position: absolute;
left: calc(-18 * var(--u));
top: calc(56 * var(--u));
width: calc(120 * var(--u));
height: calc(80 * var(--u));
border-radius: 50%;
background: radial-gradient(closest-side, rgb(80 20 50 / 0.55), transparent);
transform: rotateX(90deg);
}
/* --- the octagonal prism: width, depth, corner cut, height --- */
.prism {
position: absolute;
left: calc((84 * var(--u) - var(--w)) / 2);
width: var(--w);
height: var(--h);
transform-style: preserve-3d;
}
.glass { --w: calc(84 * var(--u)); --d: calc(44 * var(--u)); --c: calc(9 * var(--u)); --h: calc(96 * var(--u)); top: 0; }
.liquid { --w: calc(74 * var(--u)); --d: calc(34 * var(--u)); --c: calc(6.93 * var(--u)); --h: calc(50 * var(--u)); top: calc(33 * var(--u)); } /* 5 units glass walls, 13 units glass floor */
.prism > i {
position: absolute;
top: 0;
box-sizing: border-box;
left: calc((var(--w) - var(--fw)) / 2);
width: var(--fw);
height: var(--h);
transform: rotateY(calc(var(--n) * 45deg)) translateX(var(--fx, 0)) translateZ(var(--fz));
}
/* front and back */
.prism > i:nth-child(4n + 1) { --fw: calc(var(--w) - 2 * var(--c)); --fz: calc(var(--d) / 2); }
/* the two sides */
.prism > i:nth-child(4n + 3) { --fw: calc(var(--d) - 2 * var(--c)); --fz: calc(var(--w) / 2); }
/* the four corner cuts: 45deg, but also slid sideways when w != d */
.prism > i:nth-child(even) {
--fw: calc(var(--c) * 1.4142);
--fz: calc((var(--w) / 2 + var(--d) / 2 - var(--c)) / 1.4142);
}
.prism > i:nth-child(4n + 2) { --fx: calc((var(--w) - var(--d)) / 2 / 1.4142); }
.prism > i:nth-child(4n) { --fx: calc((var(--d) - var(--w)) / 2 / 1.4142); }
/* an octagon of the prism's footprint, laid flat */
.octagon {
position: absolute;
left: 0;
width: var(--w, calc(84 * var(--u)));
height: var(--d, calc(44 * var(--u)));
--c: calc(9 * var(--u));
clip-path: polygon(var(--c) 0, calc(100% - var(--c)) 0, 100% var(--c), 100% calc(100% - var(--c)),
calc(100% - var(--c)) 100%, var(--c) 100%, 0 calc(100% - var(--c)), 0 var(--c));
}
.top {
top: calc(-22 * var(--u));
background: radial-gradient(ellipse calc(16 * var(--u)) calc(11 * var(--u)), rgb(255 255 255 / 0.3), transparent), rgb(200 190 255 / 0.18);
transform: rotateX(90deg);
}
.floor {
top: calc(74 * var(--u));
background: rgb(190 175 255 / 0.2);
transform: rotateX(-90deg);
}
/* glass: tinted, light edges, drawn from both sides; the lower 13 units is the thick bottom */
.glass > i {
--lit: 0.1;
/* an inner line plus a soft shade instead of a hard border: swaying, the corner cuts turn
nearly side-on, where a 1 units line breaks up; the shade survives */
box-shadow: inset 0 0 0 calc(1 * var(--u)) rgb(236 238 251 / 0.38), inset 0 0 calc(6 * var(--u)) rgb(236 238 251 / 0.15);
border-radius: calc(2 * var(--u));
background:
linear-gradient(transparent calc(100% - 15 * var(--u)), rgb(255 255 255 / 0.35) calc(100% - 14 * var(--u)), rgb(255 255 255 / 0.12) calc(100% - 11 * var(--u)), rgb(255 255 255 / 0.2)),
linear-gradient(90deg, rgb(255 255 255 / calc(var(--lit) * 1.8)), rgb(255 255 255 / var(--lit)) 30%, rgb(255 255 255 / calc(var(--lit) * 0.5)) 70%, rgb(255 255 255 / var(--lit))),
rgb(139 108 255 / 0.08);
}
.glass > i:nth-child(even) { --lit: 0.24; } /* the corner cuts catch the light */
.glass > i:nth-child(3),
.glass > i:nth-child(7) { --lit: 0.05; }
.glass > i:first-child { overflow: hidden; } /* flat face: clipping is safe */
.liquid > i {
background:
linear-gradient(90deg, rgb(255 255 255 / 0.18), transparent 35% 70%, rgb(0 0 0 / 0.18)),
linear-gradient(#ff7a78, #f0569f);
opacity: 0.82;
}
.surface {
--w: calc(74 * var(--u));
--d: calc(34 * var(--u));
--c: calc(6.93 * var(--u));
top: calc(-17 * var(--u));
background: radial-gradient(ellipse 60% 70% at 40% 40%, rgb(255 255 255 / 0.45), transparent), #ff8a70;
opacity: 0.9;
transform: rotateX(90deg);
}
.glint {
position: absolute;
top: -20%;
left: 0;
width: calc(22 * var(--u));
height: 140%;
background: linear-gradient(90deg, transparent, rgb(255 255 255 / 0.7) 45% 55%, transparent);
transform: translateX(calc(-40 * var(--u))) rotate(18deg);
animation: glint 8s linear infinite;
}
.label {
position: absolute;
left: calc(13 * var(--u));
top: calc(26 * var(--u));
display: grid;
place-items: center;
align-content: center;
gap: calc(3 * var(--u));
box-sizing: border-box;
width: calc(58 * var(--u));
height: calc(36 * var(--u));
border: calc(1 * var(--u)) solid var(--gold);
background: #0d0e17;
box-shadow: inset 0 0 0 calc(2 * var(--u)) #0d0e17, inset 0 0 0 calc(2.6 * var(--u)) var(--gold-deep);
color: var(--gold);
font-family: Georgia, 'Times New Roman', serif;
line-height: 1;
backface-visibility: hidden;
transform: translateZ(calc(22.6 * var(--u))); /* just in front of the glass */
}
.label b { font-size: calc(11 * var(--u)); font-weight: 400; letter-spacing: calc(2.5 * var(--u)); text-indent: calc(2.5 * var(--u)); }
.label small { font: calc(4.5 * var(--u)) Inter, system-ui, sans-serif; letter-spacing: calc(0.8 * var(--u)); white-space: nowrap; opacity: 0.85; }
/* --- neck and cap: four walls and a lid --- */
.box {
position: absolute;
transform-style: preserve-3d;
}
.box > * { position: absolute; top: 0; left: 0; width: 100%; height: 100%; }
.box > :nth-child(1) { transform: translateZ(calc(var(--bd) / 2)); }
.box > :nth-child(2) { transform: rotateY(180deg) translateZ(calc(var(--bd) / 2)); }
.box > :nth-child(3),
.box > :nth-child(4) { left: calc(50% - var(--bd) / 2); width: var(--bd); }
.box > :nth-child(3) { transform: rotateY(90deg) translateZ(calc(var(--bw) / 2)); }
.box > :nth-child(4) { transform: rotateY(-90deg) translateZ(calc(var(--bw) / 2)); }
.box > :nth-child(5) { top: calc(var(--bd) / -2); height: var(--bd); transform: rotateX(90deg); }
.neck {
--bw: calc(24 * var(--u));
--bd: calc(18 * var(--u));
left: calc(30 * var(--u));
top: calc(-7 * var(--u));
width: calc(24 * var(--u));
height: calc(7 * var(--u));
}
.neck > * { background: linear-gradient(var(--gold-deep), var(--gold) 50%, var(--gold-deep)); }
.cap {
--bw: calc(42 * var(--u));
--bd: calc(30 * var(--u));
left: calc(21 * var(--u));
top: calc(-39 * var(--u));
width: calc(42 * var(--u));
height: calc(32 * var(--u));
}
/* vertical fluting over polished gold */
.cap > * {
background:
repeating-linear-gradient(90deg, rgb(255 255 255 / 0.22) 0 calc(1.5 * var(--u)), transparent calc(1.5 * var(--u)) calc(3 * var(--u)), rgb(0 0 0 / 0.12) calc(3 * var(--u)) calc(4.5 * var(--u)), transparent calc(4.5 * var(--u)) calc(6 * var(--u))),
linear-gradient(90deg, var(--gold-deep), var(--gold) 40%, #fff6dc 50%, var(--gold) 60%, var(--gold-deep));
}
.cap > :nth-child(1) { overflow: hidden; }
.cap > :nth-child(3),
.cap > :nth-child(4) {
background:
repeating-linear-gradient(90deg, rgb(255 255 255 / 0.18) 0 calc(1.5 * var(--u)), transparent calc(1.5 * var(--u)) calc(3 * var(--u)), rgb(0 0 0 / 0.14) calc(3 * var(--u)) calc(4.5 * var(--u)), transparent calc(4.5 * var(--u)) calc(6 * var(--u))),
linear-gradient(90deg, var(--gold-deep), #e2a54f);
}
.cap > :nth-child(5) {
background:
radial-gradient(circle, transparent 0 calc(7 * var(--u)), var(--gold-deep) calc(7.5 * var(--u)) calc(8.5 * var(--u)), transparent calc(9 * var(--u))),
linear-gradient(135deg, #fff6dc, var(--gold) 45%, var(--gold-deep));
}
.cap .glint { animation-delay: -0.5s; }
@keyframes sway {
from { transform: rotateX(-12deg) rotateY(-38deg); }
to { transform: rotateX(-12deg) rotateY(38deg); }
}
/* one sweep per half swing, while the bottle passes the front */
@keyframes glint {
0%, 36% { transform: translateX(calc(-40 * var(--u))) rotate(18deg); }
64%, 100% { transform: translateX(calc(90 * var(--u))) rotate(18deg); }
}