My pregnancyDue date: March 9
Baby is about 27 cm long
Next: second-trimester scan, Tue. 2:30 pm
A 180 px violet-to-pink shape whose eight corner radii keep changing over 8 s: the silhouette swells and hollows without ever leaving its square, with text at the center and a slight zoom on hover — pure CSS, zero JavaScript, a fixed silhouette when the user reduces motion.
Updated
This effect is free — the Liquid category contains 31 effects total, including 6 free. Effect.Labs has 840 vanilla effects. Explore the category →
My pregnancyDue date: March 9
Baby is about 27 cm long
Next: second-trimester scan, Tue. 2:30 pm
Applications until March 15 · open day Saturday, Feb 6
A single element, .blob-morph, 180 × 180 px, centered in the root .fx-0401-root (250 px tall, #1a1a24 background). It is painted with a 135° gradient from #a855f7 to #ec4899, wrapped in a double glow (box-shadow of 40 px violet at 40% and 80 px pink at 20%), and centers its text with flex: 1rem, weight 700, white, with a light drop shadow. The content is ordinary HTML: a word, a number, two lines.
The shape comes from border-radius written with all eight values: four horizontal radii, a slash, four vertical radii (60% 40% 30% 70% / 60% 30% 70% 40%). Each corner becomes an elliptical arc, and when neighboring values differ, the edge hollows on one side and bulges on the other. The blobMorph animation chains seven sets of radii, one about every 1.1 s, and returns to the first at 8 s with ease-in-out: the browser interpolates each radius, so the silhouette moves from one soft shape to the next without jerks. The 180 px square does not move: only the curves change, the shape breathes in place. On hover, transform: scale(1.08) enlarges it over 0.3 s.
The animated radius is not handed to the compositor: the shape and its glows are repainted every frame. Measured in Chromium 151 with software rendering (the slowest case): about 1.6 ms of rasterization per frame, a steady cost since the size never changes. Behavior is identical in Firefox 153 and WebKit 26 (2% of the frame's pixels change over 500 ms, ×1.08 zoom on hover in all three).
prefers-reduced-motion: reduce, a block scoped to .fx-0401-root removes the animation and fixes the loop's first silhouette (without it, the element would turn back into a square, since the rounding only exists in the keyframes); the hover zoom is removed too. Measured in all three engines: 0% of pixels change over 500 ms, and transform stays none on hover.#a855f7 and 3.53:1 on the pink #ec4899. That is enough for large text (at least 18.66 px bold, 3:1 threshold), not for the code's 16 px text (4.5:1 threshold). For a number or a word, set it at 24 px or more, as in the scenes above; for a sentence, darken the gradient.div, which does not receive focus; the zoom only exists on mouse hover. If it leads somewhere (a section, such as "Enrollment 2027"), make it an <a> link and give :focus-visible the same zoom.Pure CSS: animated eight-value border-radius, linear gradient, box-shadow, transform transition. Zero JavaScript, no dependencies. Measured in Chromium 151, Firefox 153 and WebKit 26: same silhouette at the same moment, same hover zoom, same stop under reduced motion.
Without CSS animations, the shape stays a 180 px square with sharp corners (the rounding is only declared in the keyframes); the text stays readable. Add border-radius: 50% to .blob-morph if you target such browsers.
Copy the three blocks into your page. No dependencies.
<div class="fx-0401-root">
<div class="blob-morph">BLOB</div>
</div>
.fx-0401-root,
.fx-0401-root *,
.fx-0401-root *::before,
.fx-0401-root *::after {
box-sizing: border-box
}
.fx-0401-root {
display: flex;
align-items: center;
justify-content: center;
width: 100%;
height: 250px;
overflow: hidden;
position: relative;
background: rgb(26, 26, 36);
color: rgb(255, 255, 255);
font-family: sans-serif;
}
.blob-morph {
width: 180px;
height: 180px;
background: linear-gradient(135deg, #a855f7, #ec4899);
animation: blobMorph 8s ease-in-out infinite;
display: flex;
align-items: center;
justify-content: center;
font-weight: 700;
font-size: 1rem;
color: white;
text-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
box-shadow:
0 0 40px rgba(168, 85, 247, 0.4),
0 0 80px rgba(236, 72, 153, 0.2);
transition: transform 0.3s ease;
}
.blob-morph:hover {
transform: scale(1.08);
}
@keyframes blobMorph {
0% {
border-radius: 60% 40% 30% 70% / 60% 30% 70% 40%;
}
14% {
border-radius: 40% 60% 70% 30% / 50% 60% 40% 50%;
}
28% {
border-radius: 70% 30% 50% 50% / 30% 50% 60% 70%;
}
42% {
border-radius: 30% 60% 70% 40% / 50% 30% 70% 60%;
}
56% {
border-radius: 50% 50% 30% 70% / 70% 40% 60% 30%;
}
70% {
border-radius: 40% 70% 60% 30% / 40% 60% 30% 70%;
}
84% {
border-radius: 70% 40% 40% 60% / 60% 50% 50% 40%;
}
100% {
border-radius: 60% 40% 30% 70% / 60% 30% 70% 40%;
}
}
/* Reduced motion: one fixed silhouette (the start of the loop), no zoom on hover. */
@media (prefers-reduced-motion: reduce) {
.fx-0401-root .blob-morph {
animation: none;
border-radius: 60% 40% 30% 70% / 60% 30% 70% 40%
}
.fx-0401-root .blob-morph:hover { transform: none }
}
Options passed to the API or data-* attributes:
| Option / property | Default | Effect |
|---|---|---|
Size (CSS — width and height of .blob-morph) |
180 × 180 px | The radii are percentages: the silhouette keeps its proportions at any size. Keep width and height equal; a rectangle gives a stretched shape that breathes less. |
Colors (CSS — linear-gradient(135deg, #a855f7, #ec4899) and box-shadow) |
violet → pink, violet 40% and pink 20% glows | Change the gradient and both glows together. On a light background, lower the glows' opacity (20% and 10%) to avoid a gray smudge. |
Speed (CSS — 8s in blobMorph) |
8 s for seven silhouettes | 12 to 16 s for a very calm background; 4 s gives a restless shape, best kept for an element without text. |
Silhouettes (CSS — eight values at each step of @keyframes blobMorph) |
seven sets of radii between 30 and 70% | Keep each pair of radii on the same side at about 100% in total (60% + 40%): beyond that, the browser scales all radii down and the shape turns almost round. Wider gaps (20% / 80%) hollow it more. |
Hover (CSS — scale(1.08) and transition: transform 0.3s) |
×1.08 over 0.3 s | Remove the :hover rule if the shape is not clickable: a zoom suggests a link. If it is, add :focus-visible to the same selector. |
Frame (CSS — .fx-0401-root) |
250 px tall, #1a1a24 background, overflow: hidden | The 80 px glow extends past the shape: in a frame shorter than 300 px, it is cut off sharply at the top and bottom. Remove overflow: hidden or enlarge the frame if the glow matters. |
Because the shape stays an HTML block: the text inside is real text, centered with flex, with no layer to stack and no coordinates to compute. The trade-off: border-radius only makes convex or nearly convex shapes, rounded at the four corners, never a star or a heart. To move from one figure to another, see SVG Path Morph (fx-0407), which animates the outline of a vector shape.
No, as long as it stays short. The 180 px square never changes, only the corners hollow out; the central area is always covered. Keep the text under 120 px wide and on two lines at most: beyond that, words touch the hollowed edges and seem to overflow.
A little more than a move: the animated radius forces the shape and its glows to be repainted every frame. Measured in Chromium with software rendering: about 1.6 ms per frame, steady. That is harmless for one or two shapes; for a grid of ten blobs, stagger their animation-delay rather than adding more, or shrink the glows, which are the most expensive part to paint.