Add to cart animation

Flying Product to Cart Animation

May 25, 2025
81 views
CSS GSAP HTML JavaScript


Flying Product to Cart Animation


This project creates an elegant e-commerce interface featuring a visually appealing animation when products are added to the shopping cart. The product image smoothly flies from its original position to the cart icon, providing users with satisfying visual feedback. The cart panel slides in from the right side when clicked, displaying all added items with quantity controls and a checkout button.

Elegant Shop - Flying Cart Animation

The application showcases a responsive product grid with modern card designs. Each product card contains an image, title, description, price, and an "Add to Cart" button. When users click this button, the product image animates and flies to the cart icon in the header, creating a delightful user experience.

The sliding cart panel provides a comprehensive overview of all selected items, allowing users to increase or decrease quantities or remove items entirely. The total amount updates in real-time as users modify their cart contents.

The design emphasizes clean aesthetics with rounded corners, subtle shadows, and a pleasing color palette. The interface is fully responsive, adapting seamlessly to different screen sizes while maintaining functionality and visual appeal.
HTML (html)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Elegant Shop - Flying Cart Animation</title> <!-- Font Awesome for icons --> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css" /> <!-- Google Fonts --> <link rel="preconnect" href="https://fonts.googleapis.com" /> <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin /> <link href="https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;500;600;700&display=swap" rel="stylesheet" /> <!-- GSAP for animations --> <script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.2/gsap.min.js"></script> <link rel="stylesheet" href="./style.css" /> </head> <body> <!-- Header with Navigation --> <header> <div class="container"> <nav> <div class="logo"> <i class="fas fa-shopping-bag"></i> <span>Elegant Shop</span> </div> <div class="cart-icon" id="cartIcon"> <i class="fas fa-shopping-cart"></i> <span class="cart-count" id="cartCount">0</span> </div> </nav> </div> </header> <!-- Main Content --> <main class="container"> <div class="products" id="products"> <!-- Products will be added dynamically --> </div> </main> <!-- Cart Panel --> <div class="cart-overlay" id="cartOverlay"></div> <div class="cart-panel" id="cartPanel"> <div class="cart-header"> <div class="cart-title"> <i class="fas fa-shopping-cart"></i> <span>Your Cart</span> </div> <button class="close-cart" id="closeCart"> <i class="fas fa-times"></i> </button> </div> <div class="cart-items" id="cartItems"> <div class="empty-cart" id="emptyCart"> <i class="fas fa-shopping-basket"></i> <p>Your cart is empty</p> <p>Add some products to see them here!</p> </div> <!-- Cart items will be added dynamically --> </div> <div class="cart-footer"> <div class="cart-total"> <span>Total:</span> <span class="total-amount" id="totalAmount">$0.00</span> </div> <button class="checkout-btn" id="checkoutBtn"> <i class="fas fa-credit-card"></i> <span>Proceed to Pay</span> </button> </div> </div> <script src="./script.js"></script> </body> </html>
CSS (css)
:root { --primary: #6366f1; --primary-light: #818cf8; --primary-dark: #4f46e5; --secondary: #f97316; --text-dark: #1f2937; --text-light: #6b7280; --bg-light: #f9fafb; --bg-dark: #111827; --white: #ffffff; --shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06); --shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05); --radius: 0.5rem; } * { margin: 0; padding: 0; box-sizing: border-box; } body { font-family: "Poppins", sans-serif; background-color: var(--bg-light); color: var(--text-dark); min-height: 100vh; overflow-x: hidden; } .container { max-width: 1200px; margin: 0 auto; padding: 0 1rem; } /* Header Styles */ header { background-color: var(--white); box-shadow: var(--shadow); position: sticky; top: 0; z-index: 100; } nav { display: flex; justify-content: space-between; align-items: center; padding: 1rem 0; } .logo { font-size: 1.5rem; font-weight: 700; color: var(--primary); display: flex; align-items: center; gap: 0.5rem; } .logo i { color: var(--secondary); } .cart-icon { position: relative; cursor: pointer; font-size: 1.5rem; color: var(--primary); transition: transform 0.3s ease; } .cart-icon:hover { transform: scale(1.1); } .cart-count { position: absolute; top: -8px; right: -8px; background-color: var(--secondary); color: var(--white); font-size: 0.7rem; font-weight: 600; width: 20px; height: 20px; border-radius: 50%; display: flex; justify-content: center; align-items: center; } /* Product Grid */ .products { display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: 2rem; padding: 2rem 0; } .product { background-color: var(--white); border-radius: var(--radius); overflow: hidden; box-shadow: var(--shadow); transition: transform 0.3s ease, box-shadow 0.3s ease; } .product:hover { transform: translateY(-5px); box-shadow: var(--shadow-lg); } .product-img { position: relative; height: 200px; overflow: hidden; background-color: #f3f4f6; } .product-img img { width: 100%; height: 100%; object-fit: cover; transition: transform 0.5s ease; } .product:hover .product-img img { transform: scale(1.05); } .product-info { padding: 1.5rem; } .product-title { font-size: 1.1rem; font-weight: 600; margin-bottom: 0.5rem; } .product-price { display: flex; justify-content: space-between; align-items: center; margin-top: 1rem; } .price { font-size: 1.2rem; font-weight: 700; color: var(--primary); } .add-to-cart { background: linear-gradient(135deg, var(--primary), var(--primary-dark)); color: var(--white); border: none; padding: 0.5rem 1rem; border-radius: var(--radius); font-weight: 500; cursor: pointer; transition: transform 0.3s ease, box-shadow 0.3s ease; display: flex; align-items: center; gap: 0.5rem; } .add-to-cart:hover { transform: translateY(-2px); box-shadow: 0 4px 12px rgba(79, 70, 229, 0.3); } .product-description { color: var(--text-light); font-size: 0.9rem; margin-bottom: 1rem; line-height: 1.5; } /* Cart Panel */ .cart-overlay { position: fixed; top: 0; left: 0; width: 100%; height: 100%; background-color: rgba(0, 0, 0, 0.5); z-index: 200; opacity: 0; visibility: hidden; transition: opacity 0.3s ease; } .cart-panel { position: fixed; top: 0; right: -100%; width: 100%; max-width: 400px; height: 100%; background-color: var(--white); z-index: 300; box-shadow: -5px 0 15px rgba(0, 0, 0, 0.1); transition: right 0.5s cubic-bezier(0.68, -0.55, 0.27, 1.55); display: flex; flex-direction: column; } .cart-header { display: flex; justify-content: space-between; align-items: center; padding: 1.5rem; border-bottom: 1px solid #e5e7eb; } .cart-title { font-size: 1.2rem; font-weight: 600; display: flex; align-items: center; gap: 0.5rem; } .close-cart { background: none; border: none; font-size: 1.5rem; cursor: pointer; color: var(--text-dark); transition: transform 0.3s ease; } .close-cart:hover { transform: rotate(90deg); } .cart-items { flex: 1; overflow-y: auto; padding: 1rem; } .empty-cart { display: flex; flex-direction: column; align-items: center; justify-content: center; height: 100%; color: var(--text-light); text-align: center; padding: 2rem; } .empty-cart i { font-size: 4rem; margin-bottom: 1rem; color: #e5e7eb; } .cart-item { display: flex; align-items: center; gap: 1rem; padding: 1rem; border-radius: var(--radius); background-color: #f9fafb; margin-bottom: 1rem; transition: transform 0.3s ease; } .cart-item:hover { transform: translateX(-5px); } .cart-item-img { width: 80px; height: 80px; border-radius: var(--radius); overflow: hidden; flex-shrink: 0; } .cart-item-img img { width: 100%; height: 100%; object-fit: cover; } .cart-item-info { flex: 1; } .cart-item-title { font-weight: 500; margin-bottom: 0.25rem; } .cart-item-price { color: var(--primary); font-weight: 600; margin-bottom: 0.5rem; } .cart-item-quantity { display: flex; align-items: center; gap: 0.5rem; } .quantity-btn { width: 28px; height: 28px; border-radius: 50%; border: 1px solid #e5e7eb; background-color: var(--white); display: flex; justify-content: center; align-items: center; cursor: pointer; transition: background-color 0.3s ease; } .quantity-btn:hover { background-color: var(--primary); color: var(--white); } .quantity { font-weight: 500; } .remove-item { color: #ef4444; background: none; border: none; cursor: pointer; font-size: 1.2rem; transition: transform 0.3s ease; } .remove-item:hover { transform: scale(1.1); } .cart-footer { padding: 1.5rem; border-top: 1px solid #e5e7eb; background-color: #f9fafb; } .cart-total { display: flex; justify-content: space-between; align-items: center; margin-bottom: 1rem; font-weight: 600; } .total-amount { font-size: 1.2rem; color: var(--primary); } .checkout-btn { width: 100%; padding: 1rem; border-radius: var(--radius); background: linear-gradient(135deg, var(--primary), var(--primary-dark)); color: var(--white); border: none; font-weight: 600; cursor: pointer; transition: transform 0.3s ease, box-shadow 0.3s ease; display: flex; justify-content: center; align-items: center; gap: 0.5rem; } .checkout-btn:hover { transform: translateY(-2px); box-shadow: 0 4px 12px rgba(79, 70, 229, 0.3); } /* Flying Image Animation */ .flying-item { position: fixed; z-index: 1000; pointer-events: none; border-radius: var(--radius); box-shadow: var(--shadow); } /* Responsive Styles */ @media (max-width: 768px) { .products { grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: 1.5rem; } .cart-panel { max-width: 100%; } .product-title { font-size: 1rem; } .product-description { font-size: 0.8rem; } .price { font-size: 1rem; } .add-to-cart { padding: 0.4rem 0.8rem; font-size: 0.9rem; } } @media (max-width: 480px) { .products { grid-template-columns: repeat(auto-fill, minmax(160px, 1fr)); gap: 1rem; } .product-img { height: 150px; } .product-info { padding: 1rem; } .cart-item { flex-direction: column; align-items: flex-start; } .cart-item-img { width: 100%; height: 120px; } .remove-item { position: absolute; top: 1rem; right: 1rem; background-color: rgba(255, 255, 255, 0.8); border-radius: 50%; width: 30px; height: 30px; display: flex; justify-content: center; align-items: center; } .cart-item { position: relative; } } /* Animation Classes */ .fade-in { animation: fadeIn 0.5s ease forwards; } @keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } } /* Badge for new products */ .badge { position: absolute; top: 10px; left: 10px; background: var(--secondary); color: white; padding: 0.25rem 0.5rem; border-radius: 20px; font-size: 0.7rem; font-weight: 600; z-index: 10; }
JAVASCRIPT (javascript)
// Product Data const products = [ { id: 1, name: "Premium Wireless Headphones", price: 129.99, image: "https://images.unsplash.com/photo-1505740420928-5e560c06d30e?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=1000&q=80", description: "Immersive sound quality with noise cancellation technology.", isNew: true, }, { id: 2, name: "Smart Fitness Watch", price: 89.99, image: "https://images.unsplash.com/photo-1523275335684-37898b6baf30?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=1000&q=80", description: "Track your fitness goals with advanced health monitoring.", isNew: false, }, { id: 3, name: "Ultra HD Camera", price: 349.99, image: "https://images.unsplash.com/photo-1526170375885-4d8ecf77b99f?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=1000&q=80", description: "Capture stunning photos and videos with this professional camera.", isNew: true, }, { id: 4, name: "Designer Sunglasses", price: 79.99, image: "https://images.unsplash.com/photo-1572635196237-14b3f281503f?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=1000&q=80", description: "Stylish protection with 100% UV filtering technology.", isNew: false, }, { id: 5, name: "Portable Bluetooth Speaker", price: 59.99, image: "https://images.unsplash.com/photo-1608043152269-423dbba4e7e1?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=1000&q=80", description: "Powerful sound in a compact, waterproof design.", isNew: true, }, { id: 6, name: "Leather Wallet", price: 49.99, image: "https://images.unsplash.com/photo-1627123424574-724758594e93?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=1000&q=80", description: "Handcrafted genuine leather with RFID protection.", isNew: false, }, ]; // Cart State let cart = []; let isCartOpen = false; // DOM Elements const productsContainer = document.getElementById("products"); const cartIcon = document.getElementById("cartIcon"); const cartCount = document.getElementById("cartCount"); const cartPanel = document.getElementById("cartPanel"); const cartOverlay = document.getElementById("cartOverlay"); const closeCart = document.getElementById("closeCart"); const cartItems = document.getElementById("cartItems"); const emptyCart = document.getElementById("emptyCart"); const totalAmount = document.getElementById("totalAmount"); const checkoutBtn = document.getElementById("checkoutBtn"); // Initialize Products function initProducts() { productsContainer.innerHTML = ""; products.forEach((product) => { const productElement = document.createElement("div"); productElement.classList.add("product"); productElement.innerHTML = ` <div class="product-img"> ${product.isNew ? '<span class="badge">New</span>' : ""} <img src="${product.image}" alt="${ product.name }" id="product-img-${product.id}"> </div> <div class="product-info"> <h3 class="product-title">${product.name}</h3> <p class="product-description">${product.description}</p> <div class="product-price"> <span class="price">$${product.price.toFixed(2)}</span> <button class="add-to-cart" data-id="${product.id}"> <i class="fas fa-cart-plus"></i> <span>Add to Cart</span> </button> </div> </div> `; productsContainer.appendChild(productElement); }); // Add Event Listeners to Add to Cart Buttons document.querySelectorAll(".add-to-cart").forEach((button) => { button.addEventListener("click", handleAddToCart); }); } // Handle Add to Cart function handleAddToCart(e) { const button = e.currentTarget; const productId = parseInt(button.getAttribute("data-id")); const product = products.find((p) => p.id === productId); // Create flying image createFlyingImage(productId, button); // Add to cart addToCart(product); } // Create Flying Image Animation function createFlyingImage(productId, button) { // Get positions const productImg = document.getElementById(`product-img-${productId}`); const cartIconRect = cartIcon.getBoundingClientRect(); const productImgRect = productImg.getBoundingClientRect(); // Create flying image element const flyingImg = document.createElement("img"); flyingImg.classList.add("flying-item"); flyingImg.src = productImg.src; flyingImg.style.width = "80px"; flyingImg.style.height = "80px"; flyingImg.style.objectFit = "cover"; flyingImg.style.position = "fixed"; flyingImg.style.left = `${productImgRect.left}px`; flyingImg.style.top = `${productImgRect.top}px`; document.body.appendChild(flyingImg); // Animate with GSAP gsap.to(flyingImg, { duration: 0.8, x: cartIconRect.left - productImgRect.left + cartIconRect.width / 2 - 40, y: cartIconRect.top - productImgRect.top + cartIconRect.height / 2 - 40, scale: 0.3, ease: "power2.out", onComplete: () => { // Remove flying image document.body.removeChild(flyingImg); // Animate cart icon gsap.to(cartIcon, { scale: 1.3, duration: 0.2, onComplete: () => { gsap.to(cartIcon, { scale: 1, duration: 0.2, }); }, }); }, }); } // Add to Cart Function function addToCart(product) { const existingItem = cart.find((item) => item.id === product.id); if (existingItem) { existingItem.quantity += 1; } else { cart.push({ ...product, quantity: 1, }); } updateCartUI(); } // Update Cart UI function updateCartUI() { // Update cart count const totalItems = cart.reduce((total, item) => total + item.quantity, 0); cartCount.textContent = totalItems; // Update cart items if (cart.length === 0) { emptyCart.style.display = "flex"; } else { emptyCart.style.display = "none"; // Clear current items cartItems.innerHTML = ""; // Add cart items cart.forEach((item) => { const cartItem = document.createElement("div"); cartItem.classList.add("cart-item"); cartItem.innerHTML = ` <div class="cart-item-img"> <img src="${item.image}" alt="${item.name}"> </div> <div class="cart-item-info"> <h4 class="cart-item-title">${item.name}</h4> <div class="cart-item-price">$${( item.price * item.quantity ).toFixed(2)}</div> <div class="cart-item-quantity"> <button class="quantity-btn decrease" data-id="${ item.id }">-</button> <span class="quantity">${item.quantity}</span> <button class="quantity-btn increase" data-id="${ item.id }">+</button> </div> </div> <button class="remove-item" data-id="${item.id}"> <i class="fas fa-trash"></i> </button> `; cartItems.appendChild(cartItem); }); // Add event listeners to cart item buttons document.querySelectorAll(".quantity-btn.decrease").forEach((button) => { button.addEventListener("click", decreaseQuantity); }); document.querySelectorAll(".quantity-btn.increase").forEach((button) => { button.addEventListener("click", increaseQuantity); }); document.querySelectorAll(".remove-item").forEach((button) => { button.addEventListener("click", removeItem); }); } // Update total amount const total = cart.reduce( (total, item) => total + item.price * item.quantity, 0 ); totalAmount.textContent = `$${total.toFixed(2)}`; } // Decrease Quantity function decreaseQuantity(e) { const productId = parseInt(e.currentTarget.getAttribute("data-id")); const item = cart.find((item) => item.id === productId); if (item.quantity > 1) { item.quantity -= 1; } else { cart = cart.filter((item) => item.id !== productId); } updateCartUI(); } // Increase Quantity function increaseQuantity(e) { const productId = parseInt(e.currentTarget.getAttribute("data-id")); const item = cart.find((item) => item.id === productId); item.quantity += 1; updateCartUI(); } // Remove Item function removeItem(e) { const productId = parseInt(e.currentTarget.getAttribute("data-id")); cart = cart.filter((item) => item.id !== productId); updateCartUI(); } // Toggle Cart Panel function toggleCart() { if (isCartOpen) { closeCartPanel(); } else { openCartPanel(); } } // Open Cart Panel function openCartPanel() { cartPanel.style.right = "0"; cartOverlay.style.opacity = "1"; cartOverlay.style.visibility = "visible"; isCartOpen = true; } // Close Cart Panel function closeCartPanel() { cartPanel.style.right = "-100%"; cartOverlay.style.opacity = "0"; // Wait for the opacity transition to complete before hiding setTimeout(() => { if (!isCartOpen) { cartOverlay.style.visibility = "hidden"; } }, 300); isCartOpen = false; } // Event Listeners cartIcon.addEventListener("click", toggleCart); closeCart.addEventListener("click", closeCartPanel); cartOverlay.addEventListener("click", closeCartPanel); checkoutBtn.addEventListener("click", () => { if (cart.length > 0) { alert("Thank you for your purchase! Your order has been placed."); cart = []; updateCartUI(); closeCartPanel(); } }); // Initialize document.addEventListener("DOMContentLoaded", () => { initProducts(); updateCartUI(); });

Download Source Code

Get the complete source code for this tutorial to use in your projects.

Comments (0)

No comments yet. Be the first to comment!