30 CSS Keyframe Animations 05 / 30
CSS Morphing Blob Animation
Six organic morphing blob animations — duo-colour, gradient shift, blend cluster, breathing ring and labelled blob — using staggered border-radius keyframes.
This is a full-page demo — interact inside the frame above, or open it in the playground for the full-screen experience.
The code
<div class="kf-05">
<div class="kf-05__row">
<div class="kf-05__cell">
<div class="kf-05__blob--1"></div>
<span class="kf-05__label">Classic Blob</span>
</div>
<div class="kf-05__cell">
<div class="kf-05__blob--2"></div>
<span class="kf-05__label">Duo-Color</span>
</div>
<div class="kf-05__cell">
<div class="kf-05__blob--3"></div>
<span class="kf-05__label">Gradient Shift</span>
</div>
</div>
<div class="kf-05__row">
<div class="kf-05__cell">
<div class="kf-05__cluster"><div class="kf-05__cluster-b"></div><div class="kf-05__cluster-b"></div><div class="kf-05__cluster-b"></div></div>
<span class="kf-05__label">Blend Cluster</span>
</div>
<div class="kf-05__cell">
<div class="kf-05__blob--5"></div>
<span class="kf-05__label">Breathing Ring</span>
</div>
<div class="kf-05__cell">
<div class="kf-05__blob--6">FLUID<br>DESIGN</div>
<span class="kf-05__label">Label Blob</span>
</div>
</div>
</div> <div class="kf-05">
<div class="kf-05__row">
<div class="kf-05__cell">
<div class="kf-05__blob--1"></div>
<span class="kf-05__label">Classic Blob</span>
</div>
<div class="kf-05__cell">
<div class="kf-05__blob--2"></div>
<span class="kf-05__label">Duo-Color</span>
</div>
<div class="kf-05__cell">
<div class="kf-05__blob--3"></div>
<span class="kf-05__label">Gradient Shift</span>
</div>
</div>
<div class="kf-05__row">
<div class="kf-05__cell">
<div class="kf-05__cluster"><div class="kf-05__cluster-b"></div><div class="kf-05__cluster-b"></div><div class="kf-05__cluster-b"></div></div>
<span class="kf-05__label">Blend Cluster</span>
</div>
<div class="kf-05__cell">
<div class="kf-05__blob--5"></div>
<span class="kf-05__label">Breathing Ring</span>
</div>
<div class="kf-05__cell">
<div class="kf-05__blob--6">FLUID<br>DESIGN</div>
<span class="kf-05__label">Label Blob</span>
</div>
</div>
</div>@import url('https://fonts.googleapis.com/css2?family=Syne:wght@400;700;800&display=swap');
.kf-05,.kf-05 *,.kf-05 *::before,.kf-05 *::after{box-sizing:border-box;margin:0;padding:0}
.kf-05 ::selection{background:#ff6bd6;color:#fff}
.kf-05{
--bg:#fff8f5;
--coral:#ff6b6b;
--teal:#06d6a0;
--indigo:#3d5af1;
--pink:#ff6bd6;
--yellow:#ffe45e;
--dark:#1a1a2e;
font-family:'Syne',sans-serif;
background:var(--bg);
min-height:100vh;
display:flex;flex-direction:column;align-items:center;justify-content:center;
padding:60px 24px;
gap:64px;
overflow:hidden;
position:relative;
}
/* Soft BG blobs */
.kf-05::before{content:'';position:absolute;top:-10%;right:-5%;width:500px;height:500px;border-radius:63% 37% 54% 46%/55% 48% 52% 45%;
background:rgba(255,107,214,.08);animation:kf-05-bg 12s ease-in-out infinite;z-index:0}
.kf-05::after{content:'';position:absolute;bottom:-10%;left:-5%;width:400px;height:400px;border-radius:42% 58% 37% 63%/55% 38% 62% 45%;
background:rgba(6,214,160,.07);animation:kf-05-bg 10s ease-in-out infinite reverse;z-index:0}
@keyframes kf-05-bg{
0%,100%{border-radius:63% 37% 54% 46%/55% 48% 52% 45%}
50%{border-radius:37% 63% 46% 54%/45% 55% 48% 52%;transform:scale(1.08)}
}
.kf-05__row{display:flex;gap:48px;flex-wrap:wrap;justify-content:center;position:relative;z-index:1}
.kf-05__cell{display:flex;flex-direction:column;align-items:center;gap:20px}
.kf-05__label{font-size:11px;letter-spacing:.2em;text-transform:uppercase;color:#aaa}
/* 1 — Classic blob */
.kf-05__blob--1{
width:140px;height:140px;
background:linear-gradient(135deg,var(--coral),var(--pink));
animation:kf-05-blob1 6s ease-in-out infinite;
}
@keyframes kf-05-blob1{
0%,100%{border-radius:63% 37% 54% 46%/55% 48% 52% 45%}
25%{border-radius:40% 60% 35% 65%/60% 30% 70% 40%}
50%{border-radius:55% 45% 65% 35%/35% 65% 45% 55%}
75%{border-radius:30% 70% 50% 50%/40% 60% 70% 30%}
}
/* 2 — Duo-color blob */
.kf-05__blob--2{
width:140px;height:140px;
position:relative;
animation:kf-05-blob2 7s ease-in-out infinite;
}
.kf-05__blob--2::before{
content:'';position:absolute;inset:0;
background:linear-gradient(135deg,var(--indigo),var(--teal));
animation:kf-05-blob1 7s ease-in-out infinite;
border-radius:63% 37% 54% 46%/55% 48% 52% 45%;
}
.kf-05__blob--2::after{
content:'';position:absolute;inset:20px;
background:rgba(255,248,245,.6);
animation:kf-05-blob1 5s ease-in-out infinite reverse;
border-radius:50%;
}
/* 3 — Gradient shift blob */
.kf-05__blob--3{
width:140px;height:140px;
animation:kf-05-blob3 8s ease-in-out infinite;
background:linear-gradient(0deg,var(--yellow),var(--coral));
background-size:100% 200%;
}
@keyframes kf-05-blob3{
0%,100%{border-radius:60% 40% 55% 45%/50% 55% 45% 50%;background-position:0% 0%}
33%{border-radius:40% 60% 30% 70%/60% 40% 60% 40%;background-position:0% 50%}
66%{border-radius:55% 45% 68% 32%/38% 68% 32% 62%;background-position:0% 100%}
}
/* 4 — Multi-blob cluster */
.kf-05__cluster{width:180px;height:180px;position:relative}
.kf-05__cluster-b{position:absolute;border-radius:63% 37% 54% 46%/55% 48% 52% 45%;mix-blend-mode:multiply}
.kf-05__cluster-b:nth-child(1){width:100px;height:100px;background:rgba(255,107,107,.7);top:0;left:0;animation:kf-05-blob1 5s ease-in-out infinite}
.kf-05__cluster-b:nth-child(2){width:100px;height:100px;background:rgba(61,90,241,.7);top:30px;left:50px;animation:kf-05-blob1 6s ease-in-out infinite .5s}
.kf-05__cluster-b:nth-child(3){width:100px;height:100px;background:rgba(255,228,94,.7);top:60px;left:20px;animation:kf-05-blob1 7s ease-in-out infinite 1s}
/* 5 — Breathing ring blob */
.kf-05__blob--5{
width:140px;height:140px;
border:12px solid var(--pink);
background:transparent;
animation:kf-05-blob1 6s ease-in-out infinite 0.5s,kf-05-ring 3s ease-in-out infinite;
}
@keyframes kf-05-ring{
0%,100%{border-width:12px;box-shadow:0 0 0 0 rgba(255,107,214,.3)}
50%{border-width:4px;box-shadow:0 0 0 20px rgba(255,107,214,0)}
}
/* 6 — Text inside blob */
.kf-05__blob--6{
width:160px;height:160px;
background:linear-gradient(135deg,var(--indigo),#7c3aed);
display:grid;place-items:center;
color:#fff;
font-weight:800;font-size:1.2rem;text-align:center;line-height:1.2;
animation:kf-05-blob1 7s ease-in-out infinite;
box-shadow:0 20px 60px rgba(61,90,241,.35);
}
@media(max-width:600px){.kf-05__row{gap:24px}.kf-05__blob--1,.kf-05__blob--2,.kf-05__blob--3,.kf-05__blob--5,.kf-05__blob--6{width:110px;height:110px}}
@media(prefers-reduced-motion:reduce){.kf-05 *{animation:none!important;border-radius:50%!important}} @import url('https://fonts.googleapis.com/css2?family=Syne:wght@400;700;800&display=swap');
.kf-05,.kf-05 *,.kf-05 *::before,.kf-05 *::after{box-sizing:border-box;margin:0;padding:0}
.kf-05 ::selection{background:#ff6bd6;color:#fff}
.kf-05{
--bg:#fff8f5;
--coral:#ff6b6b;
--teal:#06d6a0;
--indigo:#3d5af1;
--pink:#ff6bd6;
--yellow:#ffe45e;
--dark:#1a1a2e;
font-family:'Syne',sans-serif;
background:var(--bg);
min-height:100vh;
display:flex;flex-direction:column;align-items:center;justify-content:center;
padding:60px 24px;
gap:64px;
overflow:hidden;
position:relative;
}
/* Soft BG blobs */
.kf-05::before{content:'';position:absolute;top:-10%;right:-5%;width:500px;height:500px;border-radius:63% 37% 54% 46%/55% 48% 52% 45%;
background:rgba(255,107,214,.08);animation:kf-05-bg 12s ease-in-out infinite;z-index:0}
.kf-05::after{content:'';position:absolute;bottom:-10%;left:-5%;width:400px;height:400px;border-radius:42% 58% 37% 63%/55% 38% 62% 45%;
background:rgba(6,214,160,.07);animation:kf-05-bg 10s ease-in-out infinite reverse;z-index:0}
@keyframes kf-05-bg{
0%,100%{border-radius:63% 37% 54% 46%/55% 48% 52% 45%}
50%{border-radius:37% 63% 46% 54%/45% 55% 48% 52%;transform:scale(1.08)}
}
.kf-05__row{display:flex;gap:48px;flex-wrap:wrap;justify-content:center;position:relative;z-index:1}
.kf-05__cell{display:flex;flex-direction:column;align-items:center;gap:20px}
.kf-05__label{font-size:11px;letter-spacing:.2em;text-transform:uppercase;color:#aaa}
/* 1 — Classic blob */
.kf-05__blob--1{
width:140px;height:140px;
background:linear-gradient(135deg,var(--coral),var(--pink));
animation:kf-05-blob1 6s ease-in-out infinite;
}
@keyframes kf-05-blob1{
0%,100%{border-radius:63% 37% 54% 46%/55% 48% 52% 45%}
25%{border-radius:40% 60% 35% 65%/60% 30% 70% 40%}
50%{border-radius:55% 45% 65% 35%/35% 65% 45% 55%}
75%{border-radius:30% 70% 50% 50%/40% 60% 70% 30%}
}
/* 2 — Duo-color blob */
.kf-05__blob--2{
width:140px;height:140px;
position:relative;
animation:kf-05-blob2 7s ease-in-out infinite;
}
.kf-05__blob--2::before{
content:'';position:absolute;inset:0;
background:linear-gradient(135deg,var(--indigo),var(--teal));
animation:kf-05-blob1 7s ease-in-out infinite;
border-radius:63% 37% 54% 46%/55% 48% 52% 45%;
}
.kf-05__blob--2::after{
content:'';position:absolute;inset:20px;
background:rgba(255,248,245,.6);
animation:kf-05-blob1 5s ease-in-out infinite reverse;
border-radius:50%;
}
/* 3 — Gradient shift blob */
.kf-05__blob--3{
width:140px;height:140px;
animation:kf-05-blob3 8s ease-in-out infinite;
background:linear-gradient(0deg,var(--yellow),var(--coral));
background-size:100% 200%;
}
@keyframes kf-05-blob3{
0%,100%{border-radius:60% 40% 55% 45%/50% 55% 45% 50%;background-position:0% 0%}
33%{border-radius:40% 60% 30% 70%/60% 40% 60% 40%;background-position:0% 50%}
66%{border-radius:55% 45% 68% 32%/38% 68% 32% 62%;background-position:0% 100%}
}
/* 4 — Multi-blob cluster */
.kf-05__cluster{width:180px;height:180px;position:relative}
.kf-05__cluster-b{position:absolute;border-radius:63% 37% 54% 46%/55% 48% 52% 45%;mix-blend-mode:multiply}
.kf-05__cluster-b:nth-child(1){width:100px;height:100px;background:rgba(255,107,107,.7);top:0;left:0;animation:kf-05-blob1 5s ease-in-out infinite}
.kf-05__cluster-b:nth-child(2){width:100px;height:100px;background:rgba(61,90,241,.7);top:30px;left:50px;animation:kf-05-blob1 6s ease-in-out infinite .5s}
.kf-05__cluster-b:nth-child(3){width:100px;height:100px;background:rgba(255,228,94,.7);top:60px;left:20px;animation:kf-05-blob1 7s ease-in-out infinite 1s}
/* 5 — Breathing ring blob */
.kf-05__blob--5{
width:140px;height:140px;
border:12px solid var(--pink);
background:transparent;
animation:kf-05-blob1 6s ease-in-out infinite 0.5s,kf-05-ring 3s ease-in-out infinite;
}
@keyframes kf-05-ring{
0%,100%{border-width:12px;box-shadow:0 0 0 0 rgba(255,107,214,.3)}
50%{border-width:4px;box-shadow:0 0 0 20px rgba(255,107,214,0)}
}
/* 6 — Text inside blob */
.kf-05__blob--6{
width:160px;height:160px;
background:linear-gradient(135deg,var(--indigo),#7c3aed);
display:grid;place-items:center;
color:#fff;
font-weight:800;font-size:1.2rem;text-align:center;line-height:1.2;
animation:kf-05-blob1 7s ease-in-out infinite;
box-shadow:0 20px 60px rgba(61,90,241,.35);
}
@media(max-width:600px){.kf-05__row{gap:24px}.kf-05__blob--1,.kf-05__blob--2,.kf-05__blob--3,.kf-05__blob--5,.kf-05__blob--6{width:110px;height:110px}}
@media(prefers-reduced-motion:reduce){.kf-05 *{animation:none!important;border-radius:50%!important}}How this works
Each blob uses asymmetric border-radius values like 63% 37% 54% 46% / 55% 48% 52% 45% — the slash separates horizontal and vertical radii, producing organic, non-elliptical curves. The keyframe walks through four different radius profiles at 0/25/50/75/100% with ease-in-out timing, so the silhouette appears to morph fluidly rather than stretch.
The duo-color variant stacks two ::before/::after blobs at different inset levels, each running the same keyframe but at 5s vs 7s reverse so they constantly desync. The blend cluster relies on mix-blend-mode: multiply across three semi-transparent overlapping blobs — the colour mix shifts as each runs at a different duration. The breathing ring layers two animations: the morph plus a border-width: 12px → 4px with expanding box-shadow.
Customize
- Generate fresh blob profiles by adjusting the four radius percentages — keep all four 25-75% for natural shapes.
- Recolour via the
--coral,--pink,--indigo,--tealcustom properties on the.kf-05root. - Slow the morph by changing
6son.kf-05__blob--1to10sfor a more meditative pace. - Change the blend-cluster mix by switching
mix-blend-mode: multiplytoscreenfor lighter overlap colours.
Watch out for
mix-blend-modeforces the element into its own stacking context — childz-indexvalues inside the cluster stop working as expected.- Animating
border-radiusevery frame is cheap, but combining it with a largefilter: blur()tanks performance on integrated GPUs. - The background blobs use
overflow: hiddenon the parent — removing that lets the soft shadow extend visibly past the section edge.
Browser support
| Chrome | Safari | Firefox | Edge |
|---|---|---|---|
| 55+ | 10.1+ | 52+ | 55+ |
mix-blend-mode on the cluster needs Safari 10.1+; older versions render solid overlaps.