Html5
Css3
Javascript
E Commerce
Template
Panier Dynamique
Filtres
Responsive
Vanilla Js
Boutique
Template e-commerce interactif en HTML5, CSS3 et JavaScript vanilla avec panier dynamique, filtres produits en temps réel et animations.
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8" />
<meta name="copyright" content="AngularForAll" />
<meta name="author" content="AngularForAll" />
<meta name="robots" content="noindex, nofollow" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="Cache-Control" content="public, max-age=604800" />
<title>Template E Commerce HTML CSS JS 2026 04291651 | AngularForAll</title>
<style>
/* Reset & Variables */
:root {
--primary: #2563eb;
--primary-dark: #1d4ed8;
--secondary: #10b981;
--dark: #1e293b;
--light: #f8fafc;
--gray: #64748b;
--gray-light: #e2e8f0;
--white: #ffffff;
--shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
--shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.1);
--radius: 12px;
--transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
background: var(--light);
color: var(--dark);
line-height: 1.6;
}
/* Header & Navigation */
.header {
background: var(--white);
box-shadow: var(--shadow);
position: sticky;
top: 0;
z-index: 1000;
backdrop-filter: blur(10px);
}
.nav {
max-width: 1400px;
margin: 0 auto;
padding: 1rem 2rem;
display: flex;
justify-content: space-between;
align-items: center;
}
.logo {
font-size: 1.8rem;
font-weight: 800;
color: var(--primary);
text-decoration: none;
display: flex;
align-items: center;
gap: 0.5rem;
}
.logo span {
background: var(--primary);
color: white;
padding: 0.3rem 0.8rem;
border-radius: 8px;
font-size: 1rem;
}
.nav-links {
display: flex;
list-style: none;
gap: 2rem;
align-items: center;
}
.nav-links a {
text-decoration: none;
color: var(--dark);
font-weight: 500;
transition: var(--transition);
position: relative;
}
.nav-links a::after {
content: '';
position: absolute;
bottom: -5px;
left: 0;
width: 0;
height: 2px;
background: var(--primary);
transition: var(--transition);
}
.nav-links a:hover::after {
width: 100%;
}
.cart-icon {
background: var(--primary);
color: white;
padding: 0.5rem 1rem;
border-radius: 50px;
cursor: pointer;
position: relative;
border: none;
font-size: 1rem;
transition: var(--transition);
}
.cart-icon:hover {
background: var(--primary-dark);
transform: translateY(-2px);
}
.cart-count {
background: var(--secondary);
color: white;
border-radius: 50%;
padding: 0.2rem 0.5rem;
font-size: 0.8rem;
margin-left: 0.5rem;
}
.menu-toggle {
display: none;
background: none;
border: none;
font-size: 1.5rem;
cursor: pointer;
color: var(--dark);
}
/* Hero Section */
.hero {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
padding: 4rem 2rem;
text-align: center;
margin-bottom: 2rem;
}
.hero h1 {
font-size: 3rem;
margin-bottom: 1rem;
animation: fadeInUp 0.8s ease;
}
.hero p {
font-size: 1.2rem;
opacity: 0.9;
margin-bottom: 2rem;
}
.hero-btn {
background: white;
color: var(--primary);
padding: 1rem 2rem;
border: none;
border-radius: 50px;
font-size: 1.1rem;
font-weight: 600;
cursor: pointer;
transition: var(--transition);
text-decoration: none;
display: inline-block;
}
.hero-btn:hover {
transform: translateY(-3px);
box-shadow: var(--shadow-lg);
}
/* Main Content */
.container {
max-width: 1400px;
margin: 0 auto;
padding: 0 2rem;
}
.filters {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 2rem;
flex-wrap: wrap;
gap: 1rem;
}
.search-bar {
display: flex;
gap: 1rem;
flex: 1;
max-width: 500px;
}
.search-bar input {
flex: 1;
padding: 0.8rem 1.2rem;
border: 2px solid var(--gray-light);
border-radius: 50px;
font-size: 1rem;
transition: var(--transition);
background: var(--white);
}
.search-bar input:focus {
outline: none;
border-color: var(--primary);
box-shadow: 0 0 0 3px rgba(37, 99, 235, 0.1);
}
.category-filters {
display: flex;
gap: 1rem;
flex-wrap: wrap;
}
.filter-btn {
padding: 0.6rem 1.5rem;
border: 2px solid var(--gray-light);
border-radius: 50px;
background: var(--white);
cursor: pointer;
transition: var(--transition);
font-weight: 500;
color: var(--dark);
}
.filter-btn.active {
background: var(--primary);
color: white;
border-color: var(--primary);
}
.filter-btn:hover {
border-color: var(--primary);
color: var(--primary);
}
/* Products Grid */
.products-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
gap: 2rem;
margin-bottom: 3rem;
}
.product-card {
background: var(--white);
border-radius: var(--radius);
overflow: hidden;
box-shadow: var(--shadow);
transition: var(--transition);
display: flex;
flex-direction: column;
}
.product-card:hover {
transform: translateY(-5px);
box-shadow: var(--shadow-lg);
}
.product-image {
position: relative;
overflow: hidden;
height: 250px;
background: linear-gradient(45deg, #f3f4f6, #e5e7eb);
}
.product-image img {
width: 100%;
height: 100%;
object-fit: cover;
transition: var(--transition);
}
.product-card:hover .product-image img {
transform: scale(1.1);
}
.badge {
position: absolute;
top: 1rem;
right: 1rem;
background: var(--secondary);
color: white;
padding: 0.3rem 0.8rem;
border-radius: 50px;
font-size: 0.9rem;
font-weight: 600;
}
.product-info {
padding: 1.5rem;
flex: 1;
display: flex;
flex-direction: column;
}
.product-category {
color: var(--gray);
font-size: 0.9rem;
margin-bottom: 0.5rem;
}
.product-name {
font-size: 1.2rem;
font-weight: 600;
margin-bottom: 0.5rem;
}
.product-description {
color: var(--gray);
font-size: 0.9rem;
margin-bottom: 1rem;
}
.product-rating {
color: #f59e0b;
margin-bottom: 0.5rem;
}
.product-price {
font-size: 1.5rem;
font-weight: 700;
color: var(--primary);
margin-bottom: 1rem;
}
.add-to-cart {
background: var(--primary);
color: white;
border: none;
padding: 0.8rem;
border-radius: 8px;
cursor: pointer;
transition: var(--transition);
font-weight: 600;
font-size: 1rem;
margin-top: auto;
}
.add-to-cart:hover {
background: var(--primary-dark);
transform: translateY(-2px);
}
/* Modal */
.modal {
display: none;
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.5);
z-index: 2000;
align-items: center;
justify-content: center;
backdrop-filter: blur(5px);
}
.modal.active {
display: flex;
}
.modal-content {
background: var(--white);
padding: 2rem;
border-radius: var(--radius);
max-width: 500px;
width: 90%;
animation: slideUp 0.3s ease;
max-height: 80vh;
overflow-y: auto;
}
.modal-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 1.5rem;
}
.close-modal {
background: none;
border: none;
font-size: 1.5rem;
cursor: pointer;
color: var(--gray);
}
.cart-item {
display: flex;
justify-content: space-between;
align-items: center;
padding: 1rem 0;
border-bottom: 1px solid var(--gray-light);
}
.cart-total {
font-size: 1.3rem;
font-weight: 700;
text-align: right;
margin: 1.5rem 0;
}
.checkout-btn {
width: 100%;
background: var(--secondary);
color: white;
border: none;
padding: 1rem;
border-radius: 8px;
font-size: 1.1rem;
font-weight: 600;
cursor: pointer;
transition: var(--transition);
}
.checkout-btn:hover {
background: #059669;
}
.remove-item {
background: #ef4444;
color: white;
border: none;
padding: 0.4rem 0.8rem;
border-radius: 6px;
cursor: pointer;
font-size: 0.9rem;
}
/* Toast Notification */
.toast {
position: fixed;
top: 20px;
right: 20px;
background: var(--secondary);
color: white;
padding: 1rem 2rem;
border-radius: 8px;
box-shadow: var(--shadow-lg);
transform: translateX(400px);
transition: var(--transition);
z-index: 3000;
}
.toast.show {
transform: translateX(0);
}
/* Animations */
@keyframes fadeInUp {
from {
opacity: 0;
transform: translateY(30px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
@keyframes slideUp {
from {
transform: translateY(50px);
opacity: 0;
}
to {
transform: translateY(0);
opacity: 1;
}
}
.hidden {
display: none;
}
/* Responsive Design */
@media (max-width: 768px) {
.nav {
flex-wrap: wrap;
padding: 1rem;
}
.menu-toggle {
display: block;
order: 3;
}
.nav-links {
display: none;
width: 100%;
flex-direction: column;
padding: 1rem 0;
gap: 1rem;
}
.nav-links.active {
display: flex;
}
.hero h1 {
font-size: 2rem;
}
.hero p {
font-size: 1rem;
}
.products-grid {
grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
gap: 1rem;
}
.filters {
flex-direction: column;
align-items: stretch;
}
.search-bar {
max-width: 100%;
}
.category-filters {
overflow-x: auto;
flex-wrap: nowrap;
padding-bottom: 0.5rem;
}
.filter-btn {
white-space: nowrap;
flex-shrink: 0;
}
}
@media (max-width: 480px) {
.products-grid {
grid-template-columns: 1fr;
}
.hero {
padding: 2rem 1rem;
}
.container {
padding: 0 1rem;
}
}
</style>
</head>
<body>
<!-- Header -->
<header class="header">
<nav class="nav">
<a href="#" class="logo">
Shop<span>Moderne</span>
</a>
<button class="menu-toggle" aria-label="Menu">
☰
</button>
<ul class="nav-links">
<li><a href="#">Accueil</a></li>
<li><a href="#">Produits</a></li>
<li><a href="#">À propos</a></li>
<li><a href="#">Contact</a></li>
<li>
<button class="cart-icon" aria-label="Panier">
🛒 Panier <span class="cart-count" id="cartCount">0</span>
</button>
</li>
</ul>
</nav>
</header>
<!-- Hero Section -->
<section class="hero">
<h1>Collection Moderne</h1>
<p>Découvrez notre sélection de produits tendance à prix imbattables</p>
<a href="#products" class="hero-btn">Voir les produits</a>
</section>
<!-- Main Content -->
<main class="container" id="products">
<!-- Filters -->
<div class="filters">
<div class="search-bar">
<input type="text" id="searchInput" placeholder="Rechercher un produit...">
</div>
<div class="category-filters">
<button class="filter-btn active" data-category="all">Tout</button>
<button class="filter-btn" data-category="electronique">Électronique</button>
<button class="filter-btn" data-category="mode">Mode</button>
<button class="filter-btn" data-category="maison">Maison</button>
</div>
</div>
<!-- Products Grid -->
<div class="products-grid" id="productsGrid">
<!-- Produits générés par JavaScript -->
</div>
</main>
<!-- Cart Modal -->
<div class="modal" id="cartModal">
<div class="modal-content">
<div class="modal-header">
<h2>🛒 Votre Panier</h2>
<button class="close-modal" aria-label="Fermer">×</button>
</div>
<div id="cartItems">
<p style="text-align: center; color: var(--gray);">Votre panier est vide</p>
</div>
<div class="cart-total" id="cartTotal">Total: 0€</div>
<button class="checkout-btn" onclick="checkout()">Passer la commande</button>
</div>
</div>
<!-- Toast Notification -->
<div class="toast" id="toast"></div>
<script>
// Données des produits
const products = [
{
id: 1,
name: "Smartphone Pro X",
category: "electronique",
price: 799.99,
rating: 4.5,
description: "Dernier cri de la technologie avec appareil photo 108MP",
image: "public/phoneL.webp",
badge: "Nouveau"
},
{
id: 2,
name: "Écouteurs Sans Fil",
category: "electronique",
price: 149.99,
rating: 4.8,
description: "Son haute fidélité avec réduction de bruit active",
image: "public/baff.webp",
badge: "Best Seller"
},
{
id: 3,
name: "Montre Connectée",
category: "electronique",
price: 299.99,
rating: 4.3,
description: "Suivi santé, notifications et design élégant",
image: "public/smartwash.webp"
},
{
id: 4,
name: "Sac à Main Élégant",
category: "mode",
price: 89.99,
rating: 4.6,
description: "Cuir véritable, design intemporel",
image: "public/baff.webp",
badge: "Promo"
},
{
id: 5,
name: "Baskets Tendance",
category: "mode",
price: 129.99,
rating: 4.7,
description: "Confort et style pour tous les jours",
image: "public/ordinateur-portable-laptop.webp"
},
{
id: 6,
name: "Lampe Design",
category: "maison",
price: 59.99,
rating: 4.4,
description: "Éclairage LED intelligent pour votre intérieur",
image: "public/mobile2.png"
},
{
id: 7,
name: "Tablette Tactile",
category: "electronique",
price: 449.99,
rating: 4.2,
description: "Parfaite pour le travail et les loisirs",
image: "public/phoneL.webp",
badge: "Populaire"
},
{
id: 8,
name: "Plaid Confort",
category: "maison",
price: 39.99,
rating: 4.9,
description: "Doux et chaud, idéal pour les soirées cocooning",
image: "public/mobile4.png"
}
];
// État de l'application
let cart = [];
let currentFilter = 'all';
// Initialisation
function init() {
displayProducts(products);
setupEventListeners();
}
// Affichage des produits
function displayProducts(productsToShow) {
const grid = document.getElementById('productsGrid');
if (productsToShow.length === 0) {
grid.innerHTML = '<p style="text-align: center; grid-column: 1/-1; color: var(--gray); font-size: 1.2rem;">Aucun produit trouvé</p>';
return;
}
grid.innerHTML = productsToShow.map(product => `
<article class="product-card" data-category="${product.category}">
<div class="product-image">
<img src="${product.image}" alt="${product.name}" loading="lazy">
${product.badge ? `<span class="badge">${product.badge}</span>` : ''}
</div>
<div class="product-info">
<span class="product-category">${product.category}</span>
<h3 class="product-name">${product.name}</h3>
<p class="product-description">${product.description}</p>
<div class="product-rating">
${generateStars(product.rating)}
<span style="color: var(--gray); margin-left: 0.5rem;">${product.rating}</span>
</div>
<div class="product-price">${product.price.toFixed(2)}€</div>
<button class="add-to-cart" onclick="addToCart(${product.id})">
Ajouter au panier
</button>
</div>
</article>
`).join('');
}
// Génération des étoiles
function generateStars(rating) {
const fullStars = Math.floor(rating);
const halfStar = rating % 1 >= 0.5;
const emptyStars = 5 - fullStars - (halfStar ? 1 : 0);
return '★'.repeat(fullStars) + (halfStar ? '½' : '') + '☆'.repeat(emptyStars);
}
// Ajout au panier
function addToCart(productId) {
const product = products.find(p => p.id === productId);
const existingItem = cart.find(item => item.id === productId);
if (existingItem) {
existingItem.quantity++;
} else {
cart.push({
...product,
quantity: 1
});
}
updateCartCount();
showToast(`${product.name} ajouté au panier !`);
// Animation du bouton
const buttons = document.querySelectorAll('.add-to-cart');
buttons.forEach(btn => {
btn.style.transform = 'scale(0.95)';
setTimeout(() => {
btn.style.transform = 'scale(1)';
}, 100);
});
}
// Mise à jour du compteur du panier
function updateCartCount() {
const totalItems = cart.reduce((sum, item) => sum + item.quantity, 0);
document.getElementById('cartCount').textContent = totalItems;
}
// Affichage du panier
function displayCart() {
const cartItems = document.getElementById('cartItems');
const cartTotal = document.getElementById('cartTotal');
if (cart.length === 0) {
cartItems.innerHTML = '<p style="text-align: center; color: var(--gray);">Votre panier est vide</p>';
cartTotal.textContent = 'Total: 0€';
return;
}
cartItems.innerHTML = cart.map(item => `
<div class="cart-item">
<div>
<strong>${item.name}</strong>
<br>
<small>Quantité: ${item.quantity} × ${item.price.toFixed(2)}€</small>
</div>
<div>
<span style="font-weight: 600;">${(item.price * item.quantity).toFixed(2)}€</span>
<button class="remove-item" onclick="removeFromCart(${item.id})">Supprimer</button>
</div>
</div>
`).join('');
const total = cart.reduce((sum, item) => sum + (item.price * item.quantity), 0);
cartTotal.textContent = `Total: ${total.toFixed(2)}€`;
}
// Suppression du panier
function removeFromCart(productId) {
cart = cart.filter(item => item.id !== productId);
updateCartCount();
displayCart();
showToast('Produit retiré du panier');
}
// Toast notification
function showToast(message) {
const toast = document.getElementById('toast');
toast.textContent = message;
toast.classList.add('show');
setTimeout(() => {
toast.classList.remove('show');
}, 3000);
}
// Filtrage des produits
function filterProducts(category) {
currentFilter = category;
// Mise à jour des boutons actifs
document.querySelectorAll('.filter-btn').forEach(btn => {
btn.classList.remove('active');
if (btn.dataset.category === category) {
btn.classList.add('active');
}
});
// Filtrer et afficher
const searchTerm = document.getElementById('searchInput').value.toLowerCase();
let filtered = category === 'all' ? [...products] : products.filter(p => p.category === category);
if (searchTerm) {
filtered = filtered.filter(p =>
p.name.toLowerCase().includes(searchTerm) ||
p.description.toLowerCase().includes(searchTerm) ||
p.category.toLowerCase().includes(searchTerm)
);
}
// Animation de transition
const grid = document.getElementById('productsGrid');
grid.style.opacity = '0';
grid.style.transform = 'translateY(20px)';
grid.style.transition = 'all 0.3s ease';
setTimeout(() => {
displayProducts(filtered);
grid.style.opacity = '1';
grid.style.transform = 'translateY(0)';
}, 300);
}
// Recherche
function searchProducts() {
filterProducts(currentFilter);
}
// Checkout
function checkout() {
if (cart.length === 0) {
showToast('Votre panier est vide !');
return;
}
showToast('Commande validée avec succès ! Merci de votre achat.');
cart = [];
updateCartCount();
displayCart();
document.getElementById('cartModal').classList.remove('active');
}
// Configuration des événements
function setupEventListeners() {
// Menu mobile
const menuToggle = document.querySelector('.menu-toggle');
const navLinks = document.querySelector('.nav-links');
menuToggle.addEventListener('click', () => {
navLinks.classList.toggle('active');
});
// Fermer le menu mobile en cliquant sur un lien
navLinks.querySelectorAll('a').forEach(link => {
link.addEventListener('click', () => {
navLinks.classList.remove('active');
});
});
// Modal du panier
const cartIcon = document.querySelector('.cart-icon');
const cartModal = document.getElementById('cartModal');
const closeModal = document.querySelector('.close-modal');
cartIcon.addEventListener('click', () => {
displayCart();
cartModal.classList.add('active');
});
closeModal.addEventListener('click', () => {
cartModal.classList.remove('active');
});
cartModal.addEventListener('click', (e) => {
if (e.target === cartModal) {
cartModal.classList.remove('active');
}
});
// Filtres de catégorie
document.querySelectorAll('.filter-btn').forEach(btn => {
btn.addEventListener('click', () => {
filterProducts(btn.dataset.category);
});
});
// Recherche avec debounce
let searchTimeout;
document.getElementById('searchInput').addEventListener('input', () => {
clearTimeout(searchTimeout);
searchTimeout = setTimeout(searchProducts, 300);
});
// Fermer le menu mobile en cliquant en dehors
document.addEventListener('click', (e) => {
if (!e.target.closest('.nav') && navLinks.classList.contains('active')) {
navLinks.classList.remove('active');
}
});
}
// Démarrage de l'application
document.addEventListener('DOMContentLoaded', init);
</script>
</body>
</html>
Télécharger le fichier source