Animated Card Components
A collection of modern animated card components with hover effects, transitions, and interactive features for web applications
Responsive Design
Yes
Dark Mode Support
No
lines
98
Browser Compatibility
No
Live Preview
Interact with the component without leaving the page.
Animated Card Components
A comprehensive collection of modern animated card components featuring smooth hover effects, elegant transitions, and interactive elements perfect for showcasing content, products, or services.
Features
- Multiple Card Styles: Product cards, profile cards, blog cards, and feature cards
- Smooth Animations: CSS-powered transitions and hover effects
- Interactive Elements: Buttons, badges, and clickable areas
- Responsive Design: Adapts to all screen sizes
- Customizable: Easy to modify colors, sizes, and animations
- Accessibility: Keyboard navigation and screen reader support
- Performance Optimized: Hardware-accelerated animations
- Modern Design: Clean, contemporary aesthetics
Demo
<div class="cards-container">
<div class="card product-card">
<div class="card-image">
<img src="https://images.unsplash.com/photo-1542291026-7eec264c27ff?w=400" alt="Product">
<div class="card-badge">New</div>
<div class="card-overlay">
<button class="quick-view-btn">Quick View</button>
</div>
</div>
<div class="card-content">
<div class="card-category">Sneakers</div>
<h3 class="card-title">Nike Air Max 270</h3>
<p class="card-description">Comfortable and stylish sneakers perfect for everyday wear.</p>
<div class="card-price">
<span class="current-price">$129.99</span>
<span class="original-price">$159.99</span>
</div>
<div class="card-actions">
<button class="btn-primary">Add to Cart</button>
<button class="btn-secondary" aria-label="Add to wishlist">
<svg viewBox="0 0 24 24" fill="currentColor">
<path d="M12 21.35l-1.45-1.32C5.4 15.36 2 12.28 2 8.5 2 5.42 4.42 3 7.5 3c1.74 0 3.41.81 4.5 2.09C13.09 3.81 14.76 3 16.5 3 19.58 3 22 5.42 22 8.5c0 3.78-3.4 6.86-8.55 11.54L12 21.35z"/>
</svg>
</button>
</div>
</div>
</div>
<div class="card profile-card">
<div class="card-header">
<div class="profile-image">
<img src="https://images.unsplash.com/photo-1494790108755-2616b612b786?w=150" alt="Profile">
<div class="status-indicator online"></div>
</div>
<div class="profile-info">
<h3 class="profile-name">Sarah Johnson</h3>
<p class="profile-role">UI/UX Designer</p>
<div class="profile-stats">
<div class="stat">
<span class="stat-number">127</span>
<span class="stat-label">Projects</span>
</div>
<div class="stat">
<span class="stat-number">2.4k</span>
<span class="stat-label">Followers</span>
</div>
</div>
</div>
</div>
<div class="card-content">
<p class="profile-bio">Passionate designer creating beautiful and functional user experiences. Love working with modern technologies.</p>
<div class="skills">
<span class="skill-tag">Figma</span>
<span class="skill-tag">Sketch</span>
<span class="skill-tag">Prototyping</span>
</div>
</div>
<div class="card-actions">
<button class="btn-primary">Follow</button>
<button class="btn-secondary">Message</button>
</div>
</div>
<div class="card blog-card">
<div class="card-image">
<img src="https://images.unsplash.com/photo-1486312338219-ce68d2c6f44d?w=400" alt="Blog post">
<div class="read-time">5 min read</div>
</div>
<div class="card-content">
<div class="card-meta">
<span class="category">Technology</span>
<span class="date">Jan 15, 2024</span>
</div>
<h3 class="card-title">The Future of Web Development</h3>
<p class="card-excerpt">Exploring the latest trends and technologies that are shaping the future of web development...</p>
<div class="author">
<img src="https://images.unsplash.com/photo-1472099645785-5658abf4ff4e?w=40" alt="Author" class="author-avatar">
<div class="author-info">
<span class="author-name">John Doe</span>
<span class="author-title">Senior Developer</span>
</div>
</div>
</div>
<div class="card-footer">
<div class="engagement">
<button class="engagement-btn">
<svg viewBox="0 0 24 24" fill="currentColor">
<path d="M12 21.35l-1.45-1.32C5.4 15.36 2 12.28 2 8.5 2 5.42 4.42 3 7.5 3c1.74 0 3.41.81 4.5 2.09C13.09 3.81 14.76 3 16.5 3 19.58 3 22 5.42 22 8.5c0 3.78-3.4 6.86-8.55 11.54L12 21.35z"/>
</svg>
<span>24</span>
</button>
<button class="engagement-btn">
<svg viewBox="0 0 24 24" fill="currentColor">
<path d="M21 6h-2l-1-2H6L5 6H3c-.55 0-1 .45-1 1s.45 1 1 1h1l1.5 9c.08.46.46.8.93.8h9.14c.47 0 .85-.34.93-.8L17 8h1c.55 0 1-.45 1-1s-.45-1-1-1z"/>
</svg>
<span>8</span>
</button>
</div>
<button class="read-more-btn">Read More</button>
</div>
</div>
<div class="card feature-card">
<div class="feature-icon">
<svg viewBox="0 0 24 24" fill="currentColor">
<path d="M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z"/>
</svg>
</div>
<div class="card-content">
<h3 class="card-title">Premium Features</h3>
<p class="card-description">Unlock advanced functionality with our premium plan including priority support and exclusive features.</p>
<ul class="feature-list">
<li>Advanced Analytics</li>
<li>Priority Support</li>
<li>Custom Integrations</li>
<li>Team Collaboration</li>
</ul>
</div>
<div class="card-actions">
<button class="btn-primary">Upgrade Now</button>
<a href="#" class="learn-more">Learn More</a>
</div>
</div>
</div>
.cards-container {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
gap: 2rem;
padding: 2rem;
max-width: 1400px;
margin: 0 auto;
}.card {
background: white;
border-radius: 16px;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.05);
overflow: hidden;
transition: all 0.3s ease;
position: relative;
cursor: pointer;
}
.card:hover {
transform: translateY(-8px);
box-shadow: 0 20px 40px rgba(0, 0, 0, 0.1);
}
.card-content {
padding: 1.5rem;
}
.card-title {
font-size: 1.25rem;
font-weight: 600;
color: #1a1a1a;
margin: 0 0 0.5rem 0;
line-height: 1.3;
}
.card-description,
.card-excerpt {
color: #6b7280;
line-height: 1.6;
margin: 0 0 1rem 0;
}.product-card {
max-width: 350px;
}
.product-card .card-image {
position: relative;
overflow: hidden;
height: 250px;
}
.product-card .card-image img {
width: 100%;
height: 100%;
object-fit: cover;
transition: transform 0.3s ease;
}
.product-card:hover .card-image img {
transform: scale(1.1);
}
.card-badge {
position: absolute;
top: 1rem;
left: 1rem;
background: #ef4444;
color: white;
padding: 0.25rem 0.75rem;
border-radius: 20px;
font-size: 0.75rem;
font-weight: 600;
text-transform: uppercase;
letter-spacing: 0.5px;
}
.card-overlay {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.7);
display: flex;
align-items: center;
justify-content: center;
opacity: 0;
transition: opacity 0.3s ease;
}
.product-card:hover .card-overlay {
opacity: 1;
}
.quick-view-btn {
background: white;
color: #1a1a1a;
border: none;
padding: 0.75rem 1.5rem;
border-radius: 25px;
font-weight: 600;
cursor: pointer;
transform: translateY(20px);
transition: all 0.3s ease;
}
.product-card:hover .quick-view-btn {
transform: translateY(0);
}
.card-category {
color: #3b82f6;
font-size: 0.875rem;
font-weight: 500;
text-transform: uppercase;
letter-spacing: 0.5px;
margin-bottom: 0.5rem;
}
.card-price {
display: flex;
align-items: center;
gap: 0.5rem;
margin: 1rem 0;
}
.current-price {
font-size: 1.5rem;
font-weight: 700;
color: #1a1a1a;
}
.original-price {
font-size: 1rem;
color: #9ca3af;
text-decoration: line-through;
}
.card-actions {
display: flex;
gap: 0.75rem;
align-items: center;
}
.btn-primary {
flex: 1;
background: linear-gradient(135deg, #3b82f6, #1d4ed8);
color: white;
border: none;
padding: 0.75rem 1rem;
border-radius: 8px;
font-weight: 600;
cursor: pointer;
transition: all 0.3s ease;
}
.btn-primary:hover {
transform: translateY(-2px);
box-shadow: 0 8px 20px rgba(59, 130, 246, 0.3);
}
.btn-secondary {
width: 44px;
height: 44px;
background: #f3f4f6;
border: none;
border-radius: 8px;
color: #6b7280;
cursor: pointer;
transition: all 0.3s ease;
display: flex;
align-items: center;
justify-content: center;
}
.btn-secondary:hover {
background: #e5e7eb;
color: #ef4444;
}
.btn-secondary svg {
width: 20px;
height: 20px;
}.profile-card {
max-width: 350px;
text-align: center;
}
.card-header {
padding: 2rem 1.5rem 1rem;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
position: relative;
}
.profile-image {
position: relative;
display: inline-block;
margin-bottom: 1rem;
}
.profile-image img {
width: 80px;
height: 80px;
border-radius: 50%;
border: 4px solid white;
object-fit: cover;
}
.status-indicator {
position: absolute;
bottom: 5px;
right: 5px;
width: 16px;
height: 16px;
border-radius: 50%;
border: 2px solid white;
}
.status-indicator.online {
background: #10b981;
}
.profile-name {
font-size: 1.5rem;
font-weight: 700;
margin: 0 0 0.25rem 0;
color: white;
}
.profile-role {
color: rgba(255, 255, 255, 0.8);
margin: 0 0 1rem 0;
}
.profile-stats {
display: flex;
justify-content: center;
gap: 2rem;
}
.stat {
text-align: center;
}
.stat-number {
display: block;
font-size: 1.25rem;
font-weight: 700;
color: white;
}
.stat-label {
font-size: 0.875rem;
color: rgba(255, 255, 255, 0.7);
}
.profile-bio {
text-align: left;
margin-bottom: 1rem;
}
.skills {
display: flex;
flex-wrap: wrap;
gap: 0.5rem;
margin-bottom: 1rem;
}
.skill-tag {
background: #f3f4f6;
color: #4b5563;
padding: 0.25rem 0.75rem;
border-radius: 20px;
font-size: 0.75rem;
font-weight: 500;
}.blog-card {
max-width: 400px;
}
.blog-card .card-image {
position: relative;
height: 200px;
overflow: hidden;
}
.blog-card .card-image img {
width: 100%;
height: 100%;
object-fit: cover;
transition: transform 0.3s ease;
}
.blog-card:hover .card-image img {
transform: scale(1.05);
}
.read-time {
position: absolute;
top: 1rem;
right: 1rem;
background: rgba(0, 0, 0, 0.7);
color: white;
padding: 0.25rem 0.75rem;
border-radius: 20px;
font-size: 0.75rem;
font-weight: 500;
}
.card-meta {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 0.75rem;
font-size: 0.875rem;
}
.category {
color: #3b82f6;
font-weight: 500;
}
.date {
color: #9ca3af;
}
.author {
display: flex;
align-items: center;
gap: 0.75rem;
margin-top: 1rem;
}
.author-avatar {
width: 40px;
height: 40px;
border-radius: 50%;
object-fit: cover;
}
.author-info {
display: flex;
flex-direction: column;
}
.author-name {
font-weight: 600;
color: #1a1a1a;
font-size: 0.875rem;
}
.author-title {
color: #6b7280;
font-size: 0.75rem;
}
.card-footer {
padding: 1rem 1.5rem;
border-top: 1px solid #f3f4f6;
display: flex;
justify-content: space-between;
align-items: center;
}
.engagement {
display: flex;
gap: 1rem;
}
.engagement-btn {
display: flex;
align-items: center;
gap: 0.25rem;
background: none;
border: none;
color: #6b7280;
cursor: pointer;
transition: color 0.3s ease;
font-size: 0.875rem;
}
.engagement-btn:hover {
color: #3b82f6;
}
.engagement-btn svg {
width: 16px;
height: 16px;
}
.read-more-btn {
background: none;
border: none;
color: #3b82f6;
font-weight: 600;
cursor: pointer;
transition: color 0.3s ease;
}
.read-more-btn:hover {
color: #1d4ed8;
}.feature-card {
max-width: 350px;
text-align: center;
border: 2px solid #f3f4f6;
transition: all 0.3s ease;
}
.feature-card:hover {
border-color: #3b82f6;
transform: translateY(-8px);
}
.feature-icon {
width: 80px;
height: 80px;
background: linear-gradient(135deg, #3b82f6, #1d4ed8);
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
margin: 2rem auto 1.5rem;
transition: transform 0.3s ease;
}
.feature-card:hover .feature-icon {
transform: scale(1.1);
}
.feature-icon svg {
width: 40px;
height: 40px;
color: white;
}
.feature-list {
list-style: none;
padding: 0;
margin: 1.5rem 0;
text-align: left;
}
.feature-list li {
padding: 0.5rem 0;
color: #4b5563;
position: relative;
padding-left: 1.5rem;
}
.feature-list li::before {
content: '✓';
position: absolute;
left: 0;
color: #10b981;
font-weight: bold;
}
.learn-more {
color: #6b7280;
text-decoration: none;
font-weight: 500;
transition: color 0.3s ease;
}
.learn-more:hover {
color: #3b82f6;
}.dark .card {
background: #1f2937;
border: 1px solid #374151;
}
.dark .card-title {
color: white;
}
.dark .card-description,
.dark .card-excerpt {
color: #d1d5db;
}
.dark .btn-secondary {
background: #374151;
color: #d1d5db;
}
.dark .btn-secondary:hover {
background: #4b5563;
}
.dark .skill-tag {
background: #374151;
color: #d1d5db;
}
.dark .card-footer {
border-top-color: #374151;
}
.dark .feature-card {
border-color: #374151;
}
.dark .feature-card:hover {
border-color: #3b82f6;
}@media (max-width: 768px) {
.cards-container {
grid-template-columns: 1fr;
padding: 1rem;
gap: 1.5rem;
}
.card {
max-width: none;
}
.profile-stats {
gap: 1rem;
}
.card-actions {
flex-direction: column;
}
.btn-secondary {
width: 100%;
height: 44px;
}
}
@media (max-width: 480px) {
.card-content {
padding: 1rem;
}
.card-header {
padding: 1.5rem 1rem 1rem;
}
.card-title {
font-size: 1.125rem;
}
}@keyframes fadeInUp {
from {
opacity: 0;
transform: translateY(30px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
@keyframes pulse {
0%, 100% {
transform: scale(1);
}
50% {
transform: scale(1.05);
}
}
.card {
animation: fadeInUp 0.6s ease;
}
.feature-icon:hover {
animation: pulse 1s infinite;
}
class AnimatedCards {
constructor(selector) {
this.container = document.querySelector(selector);
this.cards = this.container.querySelectorAll('.card');
this.observerOptions = {
threshold: 0.1,
rootMargin: '0px 0px -50px 0px'
};
this.init();
}
init() {
this.setupIntersectionObserver();
this.setupEventListeners();
this.setupLazyLoading();
this.setupAccessibility();
}
setupIntersectionObserver() {
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
entry.target.classList.add('animate-in');
observer.unobserve(entry.target);
}
});
}, this.observerOptions);
this.cards.forEach(card => {
observer.observe(card);
});
}
setupEventListeners() {
this.cards.forEach(card => {
const addToCartBtn = card.querySelector('.btn-primary');
if (addToCartBtn && card.classList.contains('product-card')) {
addToCartBtn.addEventListener('click', (e) => {
e.stopPropagation();
this.handleAddToCart(card);
});
}
const wishlistBtn = card.querySelector('.btn-secondary');
if (wishlistBtn && card.classList.contains('product-card')) {
wishlistBtn.addEventListener('click', (e) => {
e.stopPropagation();
this.handleWishlist(card, wishlistBtn);
});
}
const followBtn = card.querySelector('.btn-primary');
if (followBtn && card.classList.contains('profile-card')) {
followBtn.addEventListener('click', (e) => {
e.stopPropagation();
this.handleFollow(card, followBtn);
});
}
const readMoreBtn = card.querySelector('.read-more-btn');
if (readMoreBtn) {
readMoreBtn.addEventListener('click', (e) => {
e.stopPropagation();
this.handleReadMore(card);
});
}
const engagementBtns = card.querySelectorAll('.engagement-btn');
engagementBtns.forEach(btn => {
btn.addEventListener('click', (e) => {
e.stopPropagation();
this.handleEngagement(btn);
});
});
card.addEventListener('click', () => {
this.handleCardClick(card);
});
card.addEventListener('keydown', (e) => {
if (e.key === 'Enter' || e.key === ' ') {
e.preventDefault();
this.handleCardClick(card);
}
});
});
}
setupLazyLoading() {
const images = this.container.querySelectorAll('img[data-src]');
const imageObserver = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const img = entry.target;
img.src = img.dataset.src;
img.classList.remove('lazy');
imageObserver.unobserve(img);
}
});
});
images.forEach(img => {
imageObserver.observe(img);
});
}
setupAccessibility() {
this.cards.forEach((card, index) => {
card.setAttribute('tabindex', '0');
card.setAttribute('role', 'article');
const title = card.querySelector('.card-title')?.textContent;
if (title) {
card.setAttribute('aria-label', `Card: ${title}`);
}
});
}
handleAddToCart(card) {
const btn = card.querySelector('.btn-primary');
const originalText = btn.textContent;
btn.textContent = 'Added!';
btn.style.background = '#10b981';
const productTitle = card.querySelector('.card-title').textContent;
window.dispatchEvent(new CustomEvent('addToCart', {
detail: { product: productTitle, card }
}));
setTimeout(() => {
btn.textContent = originalText;
btn.style.background = '';
}, 2000);
}
handleWishlist(card, btn) {
const isActive = btn.classList.contains('active');
if (isActive) {
btn.classList.remove('active');
btn.style.color = '';
} else {
btn.classList.add('active');
btn.style.color = '#ef4444';
}
const productTitle = card.querySelector('.card-title').textContent;
window.dispatchEvent(new CustomEvent('toggleWishlist', {
detail: { product: productTitle, added: !isActive }
}));
}
handleFollow(card, btn) {
const isFollowing = btn.classList.contains('following');
if (isFollowing) {
btn.textContent = 'Follow';
btn.classList.remove('following');
} else {
btn.textContent = 'Following';
btn.classList.add('following');
}
const profileName = card.querySelector('.profile-name').textContent;
window.dispatchEvent(new CustomEvent('toggleFollow', {
detail: { profile: profileName, following: !isFollowing }
}));
}
handleReadMore(card) {
const title = card.querySelector('.card-title').textContent;
window.dispatchEvent(new CustomEvent('readMore', {
detail: { title, card }
}));
}
handleEngagement(btn) {
const countSpan = btn.querySelector('span');
if (countSpan) {
const currentCount = parseInt(countSpan.textContent);
const isActive = btn.classList.contains('active');
if (isActive) {
countSpan.textContent = currentCount - 1;
btn.classList.remove('active');
} else {
countSpan.textContent = currentCount + 1;
btn.classList.add('active');
btn.style.transform = 'scale(1.2)';
setTimeout(() => {
btn.style.transform = '';
}, 200);
}
}
}
handleCardClick(card) {
card.style.transform = 'scale(0.98)';
setTimeout(() => {
card.style.transform = '';
}, 150);
const title = card.querySelector('.card-title')?.textContent;
window.dispatchEvent(new CustomEvent('cardClick', {
detail: { title, card }
}));
}
addCard(cardHTML, position = 'end') {
const tempDiv = document.createElement('div');
tempDiv.innerHTML = cardHTML;
const newCard = tempDiv.firstElementChild;
if (position === 'start') {
this.container.insertBefore(newCard, this.container.firstChild);
} else {
this.container.appendChild(newCard);
}
this.setupEventListeners();
newCard.style.opacity = '0';
newCard.style.transform = 'translateY(30px)';
setTimeout(() => {
newCard.style.transition = 'all 0.3s ease';
newCard.style.opacity = '1';
newCard.style.transform = 'translateY(0)';
}, 100);
}
removeCard(cardElement) {
cardElement.style.transition = 'all 0.3s ease';
cardElement.style.opacity = '0';
cardElement.style.transform = 'translateY(-30px)';
setTimeout(() => {
cardElement.remove();
}, 300);
}
filterCards(filterFn) {
this.cards.forEach(card => {
const shouldShow = filterFn(card);
card.style.display = shouldShow ? 'block' : 'none';
});
}
sortCards(sortFn) {
const cardsArray = Array.from(this.cards);
cardsArray.sort(sortFn);
cardsArray.forEach(card => {
this.container.appendChild(card);
});
}
destroy() {
this.cards.forEach(card => {
card.removeEventListener('click', this.handleCardClick);
card.removeEventListener('keydown', this.handleKeydown);
});
}
}
document.addEventListener('DOMContentLoaded', () => {
const cardsContainer = document.querySelector('.cards-container');
if (cardsContainer) {
const animatedCards = new AnimatedCards('.cards-container');
window.animatedCards = animatedCards;
window.addEventListener('addToCart', (e) => {
console.log('Product added to cart:', e.detail.product);
});
window.addEventListener('toggleWishlist', (e) => {
console.log('Wishlist toggled:', e.detail);
});
window.addEventListener('toggleFollow', (e) => {
console.log('Follow toggled:', e.detail);
});
window.addEventListener('cardClick', (e) => {
console.log('Card clicked:', e.detail.title);
});
}
});
Usage Examples
Basic Implementation
const cards = new AnimatedCards('.cards-container');
window.addEventListener('addToCart', (e) => {
console.log('Added to cart:', e.detail.product);
});
Dynamic Card Management
const newCardHTML = `
<div class="card product-card">
</div>
`;
cards.addCard(newCardHTML);
cards.filterCards(card => {
return card.classList.contains('product-card');
});
cards.sortCards((a, b) => {
const priceA = parseFloat(a.querySelector('.current-price').textContent.replace('$', ''));
const priceB = parseFloat(b.querySelector('.current-price').textContent.replace('$', ''));
return priceA - priceB;
});
Custom Styling
.card.custom-theme {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
}
.card.custom-theme .card-title {
color: white;
}
.card.custom-theme .card-description {
color: rgba(255, 255, 255, 0.8);
}
API Methods
| Method | Description | Parameters |
|---|---|---|
addCard(html, position) | Add new card to container | html: Card HTML, position: ‘start’ or ‘end’ |
removeCard(element) | Remove card with animation | element: Card DOM element |
filterCards(filterFn) | Filter visible cards | filterFn: Function returning boolean |
sortCards(sortFn) | Sort cards in container | sortFn: Comparison function |
destroy() | Clean up event listeners | - |
Customization Options
CSS Variables
:root {
--card-bg: white;
--card-shadow: 0 4px 6px rgba(0, 0, 0, 0.05);
--card-hover-shadow: 0 20px 40px rgba(0, 0, 0, 0.1);
--card-border-radius: 16px;
--card-padding: 1.5rem;
--primary-color: #3b82f6;
--text-color: #1a1a1a;
--text-secondary: #6b7280;
}
Animation Settings
.card {
--hover-transform: translateY(-8px);
--hover-duration: 0.3s;
--hover-easing: ease;
}
Accessibility Features
- Keyboard Navigation: Full keyboard support with Tab and Enter
- Screen Reader Support: Proper ARIA labels and roles
- Focus Management: Clear focus indicators
- Color Contrast: WCAG 2.1 AA compliant
- Semantic HTML: Proper heading hierarchy and structure
Browser Support
- Chrome 60+
- Firefox 55+
- Safari 12+
- Edge 79+
- iOS Safari 12+
- Android Chrome 60+
Performance Considerations
- Hardware Acceleration: CSS transforms for smooth animations
- Intersection Observer: Efficient scroll-based animations
- Lazy Loading: Images loaded only when needed
- Event Delegation: Optimized event handling
- Minimal Reflows: CSS-only animations where possible
Integration Example
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Animated Cards Demo</title>
<link rel="stylesheet" href="cards.css">
</head>
<body>
<div class="cards-container">
</div>
<script src="cards.js"></script>
<script>
document.addEventListener('DOMContentLoaded', () => {
const cards = new AnimatedCards('.cards-container');
window.addEventListener('addToCart', (e) => {
showNotification(`${e.detail.product} added to cart!`);
});
});
</script>
</body>
</html> HTML
23
lines
CSS
75
lines
<div class="card-container">
<div class="card card-hover">
<div class="card-image">
<img src="https://via.placeholder.com/300x200" alt="Card Image">
</div>
<div class="card-content">
<h3 class="card-title">Product Card</h3>
<p class="card-description">Modern animated card with hover effects and smooth transitions.</p>
<button class="card-button">Learn More</button>
</div>
</div>
<div class="card card-scale">
<div class="card-image">
<img src="https://via.placeholder.com/300x200" alt="Card Image">
</div>
<div class="card-content">
<h3 class="card-title">Scale Card</h3>
<p class="card-description">Card with scale animation on hover for enhanced interaction.</p>
<button class="card-button">View Details</button>
</div>
</div>
</div>