Bootstrap 5
Product Card
E Commerce
Ui Design
Responsive
Carte produit minimaliste avec image, prix, notation étoiles et bouton d'achat. Animation hover fluide et responsive.
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8" />
<meta name="copyright" content="MEZGANI Said" />
<meta name="author" content="AngularForAll" />
<meta name="robots" content="noindex, nofollow" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Snippet Product Bootstrap 5 2026 042122 | AngularForAll</title>
<!-- Bootstrap 5 CSS -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
<!-- Bootstrap Icons -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.0/font/bootstrap-icons.css">
<style>
.product-viewer {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
border-radius: 20px;
padding: 20px;
cursor: grab;
transition: transform 0.3s ease;
min-height: 500px;
display: flex;
align-items: center;
justify-content: center;
}
.product-viewer:active {
cursor: grabbing;
}
.feature-card {
transition: all 0.3s ease;
border: none;
box-shadow: 0 5px 15px rgba(0,0,0,0.1);
}
.feature-card:hover {
transform: translateY(-5px);
box-shadow: 0 10px 25px rgba(0,0,0,0.15);
}
.badge-offer {
background: linear-gradient(135deg, #ff6b6b, #ee5a24);
position: absolute;
top: 20px;
right: 20px;
z-index: 10;
}
.price {
font-size: 2rem;
font-weight: bold;
color: #2c3e8f;
}
.old-price {
text-decoration: line-through;
color: #999;
font-size: 1.2rem;
}
.btn-buy {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
border: none;
padding: 12px 30px;
font-weight: bold;
transition: all 0.3s ease;
}
.btn-buy:hover {
transform: scale(1.05);
box-shadow: 0 10px 20px rgba(102, 126, 234, 0.4);
}
.angle-indicator {
background: rgba(0,0,0,0.7);
border-radius: 20px;
padding: 5px 15px;
display: inline-block;
}
@keyframes pulse {
0%, 100% { opacity: 1; }
50% { opacity: 0.5; }
}
.loading {
animation: pulse 1s infinite;
}
</style>
</head>
<body class="bg-light">
<div class="container py-5">
<div class="row g-4">
<!-- Colonne gauche - Visualisation produit -->
<div class="col-lg-6">
<div class="card border-0 shadow-lg overflow-hidden">
<div class="badge-offer">
<span class="badge bg-danger fs-6 m-2"><i class="bi bi-lightning-charge"></i> -10% OFF</span>
</div>
<div class="product-viewer" id="viewer3D">
<canvas id="phoneCanvas" style="width:100%; height:auto; max-width:500px;"></canvas>
</div>
<div class="p-4 bg-white">
<div class="d-flex justify-content-between align-items-center mb-3">
<div class="angle-indicator bg-dark text-white">
<i class="bi bi-arrow-repeat"></i> Angle: <span id="angleValue">0</span>° / 360°
</div>
<div class="btn-group" role="group">
<button class="btn btn-outline-primary" id="prevBtn" aria-label="Angle précédent">
<i class="bi bi-chevron-left"></i>
</button>
<button class="btn btn-outline-primary" id="autoRotateBtn" aria-label="Rotation automatique">
<i class="bi bi-play-fill"></i>
</button>
<button class="btn btn-outline-primary" id="nextBtn" aria-label="Angle suivant">
<i class="bi bi-chevron-right"></i>
</button>
</div>
</div>
<input type="range" id="angleSlider" class="form-range" min="0" max="360" step="1" value="0">
<div class="alert alert-info mt-3 mb-0">
<i class="bi bi-info-circle"></i>
<small>Cliquez et glissez sur le téléphone pour le faire pivoter à 360°</small>
</div>
</div>
</div>
</div>
<!-- Colonne droite - Informations produit -->
<div class="col-lg-6">
<div class="card border-0 shadow-lg">
<div class="card-body p-4">
<h1 class="h2 mb-2">Samsung Galaxy A26 5G</h1>
<div class="mb-3">
<i class="bi bi-star-fill text-warning"></i>
<i class="bi bi-star-fill text-warning"></i>
<i class="bi bi-star-fill text-warning"></i>
<i class="bi bi-star-fill text-warning"></i>
<i class="bi bi-star-half text-warning"></i>
<span class="text-muted ms-2">(234 avis)</span>
</div>
<div class="mb-4">
<span class="price">349€</span>
<span class="old-price ms-2">399€</span>
<span class="badge bg-success ms-2">Économisez 50€</span>
</div>
<div class="mb-4">
<h6 class="fw-bold">Couleurs disponibles :</h6>
<div class="d-flex gap-2 mt-2">
<button aria-label="Bleu" class="btn btn-sm rounded-circle" style="width:40px;height:40px;background:#2c3e8f;" onclick="changeColor('blue')"></button>
<button aria-label="Noir" class="btn btn-sm rounded-circle" style="width:40px;height:40px;background:#000;" onclick="changeColor('black')"></button>
<button aria-label="Blanc" class="btn btn-sm rounded-circle" style="width:40px;height:40px;background:#fff;border:1px solid #ddd;" onclick="changeColor('white')"></button>
</div>
</div>
<div class="mb-4">
<h6 class="fw-bold">Capacité :</h6>
<div class="btn-group w-100" role="group">
<input type="radio" class="btn-check" name="storage" id="storage128" autocomplete="off" checked>
<label class="btn btn-outline-primary" for="storage128">128 Go</label>
<input type="radio" class="btn-check" name="storage" id="storage256" autocomplete="off">
<label class="btn btn-outline-primary" for="storage256">256 Go</label>
</div>
</div>
<button class="btn btn-buy btn-primary w-100 mb-3">
<i class="bi bi-cart-plus"></i> Ajouter au panier
</button>
<div class="row g-2 text-center">
<div class="col-4">
<div class="feature-card card p-2">
<i class="bi bi-truck fs-2 text-primary"></i>
<small>Livraison offerte</small>
</div>
</div>
<div class="col-4">
<div class="feature-card card p-2">
<i class="bi bi-arrow-repeat fs-2 text-primary"></i>
<small>14 jours retour</small>
</div>
</div>
<div class="col-4">
<div class="feature-card card p-2">
<i class="bi bi-shield-check fs-2 text-primary"></i>
<small>Garantie 2 ans</small>
</div>
</div>
</div>
</div>
</div>
<!-- Caractéristiques techniques -->
<div class="card border-0 shadow-lg mt-4">
<div class="card-body">
<h5 class="fw-bold mb-3"><i class="bi bi-gear"></i> Caractéristiques</h5>
<div class="row">
<div class="col-6 mb-2">
<small class="text-muted">Écran</small>
<div class="fw-bold">6.7" Super AMOLED</div>
</div>
<div class="col-6 mb-2">
<small class="text-muted">Processeur</small>
<div class="fw-bold">Exynos 1380</div>
</div>
<div class="col-6 mb-2">
<small class="text-muted">Appareil photo</small>
<div class="fw-bold">50 MP + OIS</div>
</div>
<div class="col-6 mb-2">
<small class="text-muted">Batterie</small>
<div class="fw-bold">5000 mAh</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<script>
// Configuration du canvas 3D
const canvas = document.getElementById('phoneCanvas');
const ctx = canvas.getContext('2d');
let currentAngle = 0;
let autoRotateInterval = null;
let isDragging = false;
let dragStartX = 0;
let dragStartAngle = 0;
function resizeCanvas() {
const container = canvas.parentElement;
const size = Math.min(container.clientWidth, 500);
canvas.width = size;
canvas.height = size * 0.8;
canvas.style.width = '100%';
canvas.style.height = 'auto';
drawPhone();
}
function drawPhone() {
if (!ctx) return;
const w = canvas.width;
const h = canvas.height;
ctx.clearRect(0, 0, w, h);
const angleRad = (currentAngle * Math.PI) / 180;
ctx.save();
const centerX = w / 2;
const centerY = h / 2;
const phoneWidth = Math.min(w * 0.5, 250);
const phoneHeight = phoneWidth * 2.1;
const perspective = Math.cos(angleRad) * 0.3 + 0.7;
const currentWidth = phoneWidth * perspective;
const currentHeight = phoneHeight;
const x = centerX - currentWidth / 2;
const y = centerY - currentHeight / 2;
// Corps du téléphone
ctx.save();
ctx.shadowColor = 'rgba(0,0,0,0.3)';
ctx.shadowBlur = 15;
const gradient = ctx.createLinearGradient(x, y, x + currentWidth, y + currentHeight);
if (currentAngle < 90 || currentAngle > 270) {
gradient.addColorStop(0, '#2c3e8f');
gradient.addColorStop(0.5, '#3498db');
gradient.addColorStop(1, '#2980b9');
} else {
gradient.addColorStop(0, '#1a252f');
gradient.addColorStop(0.5, '#2c3e50');
gradient.addColorStop(1, '#1a252f');
}
ctx.fillStyle = gradient;
ctx.fillRect(x, y, currentWidth, currentHeight);
ctx.restore();
// Écran
if (currentAngle > 270 || currentAngle < 90) {
ctx.save();
const screenMargin = currentWidth * 0.08;
const screenWidth = currentWidth - (screenMargin * 2);
const screenHeight = currentHeight - (screenMargin * 2.5);
const screenX = x + screenMargin;
const screenY = y + screenMargin;
ctx.fillStyle = '#0a0e27';
ctx.fillRect(screenX, screenY, screenWidth, screenHeight);
ctx.fillStyle = '#00ff88';
ctx.font = `bold ${Math.max(12, screenWidth * 0.08)}px Arial`;
ctx.textAlign = 'center';
ctx.fillText('SAMSUNG', screenX + screenWidth/2, screenY + screenHeight/3);
ctx.fillStyle = '#ffffff';
ctx.font = `${Math.max(10, screenWidth * 0.05)}px Arial`;
ctx.fillText('Galaxy A26', screenX + screenWidth/2, screenY + screenHeight/2);
ctx.restore();
}
drawPhone();
}
function updateAngle(angle) {
currentAngle = angle;
document.getElementById('angleValue').textContent = currentAngle;
document.getElementById('angleSlider').value = currentAngle;
drawPhone();
}
function nextAngle() {
let newAngle = currentAngle + 10;
if (newAngle >= 360) newAngle = 0;
updateAngle(newAngle);
}
function prevAngle() {
let newAngle = currentAngle - 10;
if (newAngle < 0) newAngle = 350;
updateAngle(newAngle);
}
function toggleAutoRotate() {
if (autoRotateInterval) {
clearInterval(autoRotateInterval);
autoRotateInterval = null;
document.getElementById('autoRotateBtn').innerHTML = '<i class="bi bi-play-fill"></i>';
} else {
autoRotateInterval = setInterval(nextAngle, 100);
document.getElementById('autoRotateBtn').innerHTML = '<i class="bi bi-pause-fill"></i>';
}
}
function changeColor(color) {
console.log('Couleur changée:', color);
// Ici vous pouvez changer la couleur du téléphone
}
// Événements
function handleMouseDown(e) {
isDragging = true;
dragStartX = e.clientX;
dragStartAngle = currentAngle;
canvas.style.cursor = 'grabbing';
if (autoRotateInterval) toggleAutoRotate();
}
function handleMouseMove(e) {
if (!isDragging) return;
const deltaX = e.clientX - dragStartX;
const angleChange = (deltaX / canvas.width) * 180;
let newAngle = dragStartAngle + angleChange;
newAngle = ((newAngle % 360) + 360) % 360;
updateAngle(Math.round(newAngle));
}
function handleMouseUp() {
isDragging = false;
canvas.style.cursor = 'grab';
}
// Initialisation
window.addEventListener('resize', resizeCanvas);
canvas.addEventListener('mousedown', handleMouseDown);
window.addEventListener('mousemove', handleMouseMove);
window.addEventListener('mouseup', handleMouseUp);
canvas.style.cursor = 'grab';
document.getElementById('prevBtn').addEventListener('click', () => {
if (autoRotateInterval) toggleAutoRotate();
prevAngle();
});
document.getElementById('nextBtn').addEventListener('click', () => {
if (autoRotateInterval) toggleAutoRotate();
nextAngle();
});
document.getElementById('autoRotateBtn').addEventListener('click', toggleAutoRotate);
document.getElementById('angleSlider').addEventListener('input', (e) => {
if (autoRotateInterval) toggleAutoRotate();
updateAngle(parseInt(e.target.value));
});
resizeCanvas();
updateAngle(0);
// Ajout du changement de couleur
window.changeColor = changeColor;
</script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>
Ouvrir cet aperçu dans un nouvel onglet du navigateur
🔗 Ouvrir dans le navigateur