UI Components Easy
Add to Cart Effect
Animated add-to-cart feedback with badge bump and flying item — satisfying shopping interaction.
Open in Lab
MCP
css vanilla-js
Targets: JS HTML
Code
* {
box-sizing: border-box;
}
body {
margin: 0;
min-height: 100vh;
background: #0f172a;
color: #e2e8f0;
font-family: system-ui, sans-serif;
display: flex;
align-items: center;
justify-content: center;
}
.demo {
display: flex;
flex-direction: column;
align-items: center;
gap: 2rem;
padding: 2rem;
}
/* Cart icon */
.cart {
position: relative;
color: #e2e8f0;
}
.cart-badge {
position: absolute;
top: -8px;
right: -10px;
min-width: 20px;
height: 20px;
padding: 0 6px;
background: #ef4444;
color: #fff;
font-size: 11px;
font-weight: 700;
border-radius: 10px;
display: flex;
align-items: center;
justify-content: center;
transition: transform 0.2s cubic-bezier(0.34, 1.56, 0.64, 1);
}
.cart-badge.bump {
transform: scale(1.4);
}
/* Products */
.products {
display: flex;
gap: 1rem;
flex-wrap: wrap;
justify-content: center;
}
.product-card {
width: 180px;
background: #1e293b;
border-radius: 14px;
overflow: hidden;
border: 1px solid rgba(255, 255, 255, 0.06);
}
.product-color {
height: 100px;
}
.product-info {
padding: 0.75rem 1rem 0.5rem;
display: flex;
flex-direction: column;
gap: 0.25rem;
}
.product-name {
font-size: 0.9rem;
font-weight: 600;
}
.product-price {
font-size: 0.8rem;
color: #94a3b8;
}
.add-btn {
display: block;
width: calc(100% - 1.5rem);
margin: 0.5rem auto 0.75rem;
padding: 0.5rem;
font-size: 0.8rem;
font-weight: 600;
color: #fff;
background: #3b82f6;
border: none;
border-radius: 8px;
cursor: pointer;
transition: background 0.15s, transform 0.12s;
}
.add-btn:active {
transform: scale(0.96);
}
.add-btn.added {
background: #22c55e;
pointer-events: none;
}
/* Flying dot */
.fly-dot {
position: fixed;
width: 12px;
height: 12px;
border-radius: 50%;
background: #3b82f6;
pointer-events: none;
z-index: 999;
transition: all 0.6s cubic-bezier(0.22, 1, 0.36, 1);
}const badge = document.getElementById("badge");
const cart = document.getElementById("cart");
let count = 0;
document.querySelectorAll(".add-btn").forEach((btn) => {
btn.addEventListener("click", function () {
const btnRect = this.getBoundingClientRect();
const cartRect = cart.getBoundingClientRect();
// Create flying dot
const dot = document.createElement("div");
dot.className = "fly-dot";
dot.style.left = btnRect.left + btnRect.width / 2 - 6 + "px";
dot.style.top = btnRect.top + btnRect.height / 2 - 6 + "px";
document.body.appendChild(dot);
// Button success state
const original = this.textContent;
this.textContent = "Added \u2713";
this.classList.add("added");
// Animate dot to cart
requestAnimationFrame(() => {
dot.style.left = cartRect.left + cartRect.width / 2 - 6 + "px";
dot.style.top = cartRect.top + cartRect.height / 2 - 6 + "px";
dot.style.opacity = "0";
dot.style.transform = "scale(0.3)";
});
// Update badge after dot arrives
setTimeout(() => {
dot.remove();
count++;
badge.textContent = count;
badge.classList.add("bump");
setTimeout(() => badge.classList.remove("bump"), 200);
}, 600);
// Reset button
const self = this;
setTimeout(() => {
self.textContent = original;
self.classList.remove("added");
}, 1500);
});
});<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Add to Cart Effect</title>
<link rel="stylesheet" href="style.css" />
</head>
<body>
<div class="demo">
<!-- Cart icon -->
<div class="cart" id="cart">
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="9" cy="21" r="1"/><circle cx="20" cy="21" r="1"/>
<path d="M1 1h4l2.68 13.39a2 2 0 0 0 2 1.61h9.72a2 2 0 0 0 2-1.61L23 6H6"/>
</svg>
<span class="cart-badge" id="badge">0</span>
</div>
<!-- Product cards -->
<div class="products">
<div class="product-card">
<div class="product-color" style="background: linear-gradient(135deg, #3b82f6, #8b5cf6);"></div>
<div class="product-info">
<span class="product-name">Pro Headphones</span>
<span class="product-price">$299</span>
</div>
<button type="button" class="add-btn" data-product="headphones">Add to Cart</button>
</div>
<div class="product-card">
<div class="product-color" style="background: linear-gradient(135deg, #f59e0b, #ef4444);"></div>
<div class="product-info">
<span class="product-name">Smart Watch</span>
<span class="product-price">$199</span>
</div>
<button type="button" class="add-btn" data-product="watch">Add to Cart</button>
</div>
<div class="product-card">
<div class="product-color" style="background: linear-gradient(135deg, #10b981, #06b6d4);"></div>
<div class="product-info">
<span class="product-name">Wireless Buds</span>
<span class="product-price">$149</span>
</div>
<button type="button" class="add-btn" data-product="buds">Add to Cart</button>
</div>
</div>
</div>
<script src="script.js"></script>
</body>
</html>Add to Cart Effect
Animated feedback when adding an item: flying dot to cart icon + badge count bump. Reference patterns from optimistic-ui and shopping-cart.
Features
- Flying dot animation from button to cart icon
- Badge count increment with scale bounce
- Checkmark success state on button
- No dependencies