Next patient: Mr B.
Room 2, end of the corridorWhile you wait: 5 minutes on the exercise bike, resistance 2, without forcing.
A still frosted panel inside a 340 × 230 px dark frame: the glass (backdrop-filter: blur(24px)) fills the frame 30 px from the edges while three gradient blobs drift and rotate behind it continuously, over 7, 8 and 10 s — the backdrop moves, never the text. Pure CSS.
Updated
Blobs move behind the frosted glass
This effect is free — the Glassmorphism category contains 47 effects total, including 6 free. Effect.Labs has 840 vanilla effects. Explore the category →
While you wait: 5 minutes on the exercise bike, resistance 2, without forcing.
with Josiane and Karim · 10 am – 11 am · gardening in the bocage
Level 27 · The Cliffs · 14 moves left
★★☆One frame, three blobs, one panel. The frame .frosted-panel-scene is 340 × 230 px, #080812 background, 16 px corners and overflow: hidden: it carries its own backdrop, the page around keeps its color, and blobs that overflow are cut cleanly at the edge. The three .frosted-blob blobs are 135° gradient circles blurred by filter: blur(30px): 160 px violet → indigo starting from the top-left corner (−30, −20 px), 140 px cyan → blue from the bottom-right corner, 100 px pink → raspberry placed in the middle (top: 50%; left: 60%). The panel .frosted-panel-element is position: absolute; inset: 30px — 280 × 170 px measured in the original frame —, 5% white, backdrop-filter: blur(24px) and -webkit-backdrop-filter, 10% white border, 12 px corners, content centered in a column (19.2 px bold title, 12 px text at 50% white, three 8 px dots in the blob colors).
All the motion is in the backdrop. blobDrift1 (8 s) walks the violet blob through four steps — (40, 20), (20, 60), (−10, 30) px — while turning it three quarters of a turn (0 → 270°), then back in the last quarter: since the blob is a gradient, its rotation turns the direction of the color under the glass. blobDrift2 (10 s) brings the cyan blob up to (−50, −40) px, rotating the other way; blobDrift3 (7 s) moves the pink blob by (−40, −30) px while growing it 30%. Three durations that do not divide one another (7, 8, 10 s): the pattern only repeats after 280 s, so the backdrop never seems to loop. Measured in Chromium and Firefox: three running animations, panel 30 px from each edge. No hover, no JavaScript, no site variable.
@media (prefers-reduced-motion: reduce) { .frosted-blob { animation: none } }: the panel keeps its colors, frozen.rgba(255,255,255,.85)), as in the three examples, so it holds wherever the blobs are.h3 title and a paragraph, read normally; blobs and dots are empty elements, ignored. The dots look like a page indicator but are wired to nothing: don't give them meaning ("3 messages") without saying it in text too, or hide them with aria-hidden="true".prefers-reduced-transparency. One rule is enough: @media (prefers-reduced-transparency: reduce) { .frosted-panel-element { background: rgba(20,20,40,.9); backdrop-filter: none } }.CSS only: backdrop-filter (with -webkit-backdrop-filter), filter: blur(), gradients, @keyframes on transform (translate, rotate, scale), inset. Zero JavaScript, zero dependency. Backdrop blur: Chrome 76+, Edge 79+, Firefox 103+, Safari 9+ prefixed (unprefixed since 18). Measured in Chromium 151: blur painted, three running animations. In Firefox 153 and WebKit 26.5 (Playwright), the computed value is blur(24px) and CSS.supports returns true, but their automated screenshots do not paint backdrop blur, even on a minimal test: the glass rendering was only seen in Chromium. Animations on transform run on the compositor: no layout recalculation.
Without backdrop-filter, the panel stays a 5% white veil over blobs that are already blurred (filter: blur(30px)): the moving color stays visible, only the frosting disappears, and the text still sits on the frame's dark backdrop. inset needs Chrome 87, Firefox 66 and Safari 14.1; before that, replace it with top/right/bottom/left: 30px.
Copy the three blocks into your page. No dependencies.
<div class="frosted-panel-scene">
<div class="frosted-blob frosted-blob--1"></div>
<div class="frosted-blob frosted-blob--2"></div>
<div class="frosted-blob frosted-blob--3"></div>
<div class="frosted-panel-element">
<h3>Frosted Panel</h3>
<p>Blobs move behind the frosted glass</p>
<div class="frosted-dots">
<span class="frosted-dot"></span>
<span class="frosted-dot"></span>
<span class="frosted-dot"></span>
</div>
</div>
</div>
.frosted-panel-scene {
width: 340px;
height: 230px;
position: relative;
overflow: hidden;
border-radius: 16px;
background: #080812;
}
.frosted-blob {
position: absolute;
border-radius: 50%;
filter: blur(30px);
}
.frosted-blob--1 {
width: 160px;
height: 160px;
background: linear-gradient(135deg, #a855f7, #6366f1);
top: -30px;
left: -20px;
animation: blobDrift1 8s ease-in-out infinite;
}
.frosted-blob--2 {
width: 140px;
height: 140px;
background: linear-gradient(135deg, #06b6d4, #3b82f6);
bottom: -40px;
right: -20px;
animation: blobDrift2 10s ease-in-out infinite;
}
.frosted-blob--3 {
width: 100px;
height: 100px;
background: linear-gradient(135deg, #ec4899, #f43f5e);
top: 50%;
left: 60%;
animation: blobDrift3 7s ease-in-out infinite;
}
.frosted-panel-element {
position: absolute;
inset: 30px;
background: rgba(255, 255, 255, 0.05);
backdrop-filter: blur(24px);
-webkit-backdrop-filter: blur(24px);
border-radius: 12px;
border: 1px solid rgba(255, 255, 255, 0.1);
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: 10px;
z-index: 1;
}
.frosted-panel-element h3 {
font-size: 1.2rem;
font-weight: 700;
color: #fff;
margin: 0;
}
.frosted-panel-element p {
font-size: 0.75rem;
color: rgba(255, 255, 255, 0.5);
margin: 0;
text-align: center;
padding: 0 20px;
}
.frosted-panel-element .frosted-dots {
display: flex;
gap: 6px;
margin-top: 4px;
}
.frosted-panel-element .frosted-dot {
width: 8px;
height: 8px;
border-radius: 50%;
background: rgba(255, 255, 255, 0.3);
}
.frosted-panel-element .frosted-dot:nth-child(1) {
background: #a855f7;
}
.frosted-panel-element .frosted-dot:nth-child(2) {
background: #06b6d4;
}
.frosted-panel-element .frosted-dot:nth-child(3) {
background: #ec4899;
}
@keyframes blobDrift1 {
0%,
100% {
transform: translate(0, 0) rotate(0deg);
}
25% {
transform: translate(40px, 20px) rotate(90deg);
}
50% {
transform: translate(20px, 60px) rotate(180deg);
}
75% {
transform: translate(-10px, 30px) rotate(270deg);
}
}
@keyframes blobDrift2 {
0%,
100% {
transform: translate(0, 0) rotate(0deg);
}
25% {
transform: translate(-30px, -20px) rotate(-90deg);
}
50% {
transform: translate(-50px, -40px) rotate(-180deg);
}
75% {
transform: translate(-20px, -10px) rotate(-270deg);
}
}
@keyframes blobDrift3 {
0%,
100% {
transform: translate(0, 0) scale(1);
}
50% {
transform: translate(-40px, -30px) scale(1.3);
}
}
Options passed to the API or data-* attributes:
| Option / property | Default | Effect |
|---|---|---|
Frame size (CSS — .frosted-panel-scene { width: 340px; height: 230px }) |
340 × 230 px, 16 px corners | The panel follows on its own thanks to inset: 30px. For a large screen, enlarge the blobs too (200–240 px): at their original size they only cover one corner of the glass. |
Panel inset (CSS — .frosted-panel-element { inset: 30px }) |
30 px on each side | The unblurred strip around the glass shows the blobs sharp and makes the frosting readable by contrast. inset: 30px 70px gives a narrower panel (game pause); inset: 0 removes the strip and the effect becomes a plain blurred backdrop. |
Glass blur (CSS — backdrop-filter: blur(24px) and -webkit-backdrop-filter) |
24 px | The blobs are already blurred at 30 px: below 12 px the glass no longer stands out from the strip around it. 24–32 px for even sheets of color under the text. |
Blob colors (CSS — .frosted-blob--1 to --3, linear-gradient(135deg, …)) |
violet → indigo, cyan → blue, pink → raspberry | Keep a two-tone gradient per blob: it is what makes the rotation visible. Match the dots (.frosted-dot:nth-child(n)) to the same colors. |
Drift speed (CSS — blobDrift1 8s, blobDrift2 10s, blobDrift3 7s) |
8, 10 and 7 s | Multiply all three by the same factor to slow down (×2: 16, 20, 14 s) while keeping durations that don't divide one another. Equal durations would make the blobs move as a block. |
Frame background (CSS — .frosted-panel-scene { background: #080812 }) |
#080812 | A color close to the blobs' dominant hue (#06141a for greens, #1a0f0a for oranges) gives a richer backdrop than black. An image works too: the blobs then pass over it. |
Glass Card is a card floating above its backdrop, with a drop shadow, a diagonal highlight and a 4 px lift on hover: you interact with it. Frosted Panel reacts to nothing: it fills its frame 30 px from the edges and the backdrop is what lives, three blobs drifting and rotating over 7, 8 and 10 s. Pick Frosted Panel when the screen is watched rather than touched (wall screen, live box, pause) and the motion must say "this is active" without moving the text.
Not much. The three animations only touch transform (translate, rotate, scale), which the browser hands to the compositor without recalculating layout. The real cost is the blur: the panel redoes its 24 px backdrop-filter every frame, over 280 × 170 px in the original frame. On a wall screen running all day, keep a reasonable frame size and add the prefers-reduced-motion rule; on a low-end TV, a 16 px blur lightens it further.
Yes: set the image as the frame's background (.frosted-panel-scene { background: url(...) center/cover }) and keep or remove the blobs. With the blobs, they pass over the image and tint the glass; without them, the panel becomes still on a still backdrop — then Glass Card (fx-0301), minus the hover, is what you need. The 30 px inset leaves the image sharp around the glass: that sharp/blurred contrast is what makes the frosting read.