CSS Grid : l’outil parfait pour les galeries
CSS Grid permet de créer des galeries photo dynamiques et responsives en quelques lignes de code. Fini les calculs de largeur compliqués avec les float !
Galerie basique : grille uniforme
<div class="galerie">
<img src="photo1.jpg" alt="Description 1">
<img src="photo2.jpg" alt="Description 2">
<img src="photo3.jpg" alt="Description 3">
<img src="photo4.jpg" alt="Description 4">
<img src="photo5.jpg" alt="Description 5">
<img src="photo6.jpg" alt="Description 6">
</div>
<style>
.galerie {
display: grid;
grid-template-columns: repeat(3, 1fr); /* 3 colonnes égales */
gap: 15px;
padding: 20px;
}
.galerie img {
width: 100%;
height: 250px;
object-fit: cover; /* Recadre sans déformer */
border-radius: 8px;
transition: transform 0.3s;
}
.galerie img:hover {
transform: scale(1.05);
}
</style>
Galerie responsive avec auto-fill
La grille s’adapte automatiquement au nombre de colonnes selon la largeur :
.galerie-auto {
display: grid;
/* Colonnes de minimum 280px, maximum 1fr */
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
gap: 15px;
padding: 20px;
}
/* Plus besoin de media queries ! La grille s'adapte toute seule :
- Mobile : 1 colonne
- Tablette : 2 colonnes
- Desktop : 3-4 colonnes
*/
Galerie style Pinterest (Masonry)
<div class="galerie-pinterest">
<div class="item"><img src="tall.jpg" alt=""></div>
<div class="item wide"><img src="wide.jpg" alt=""></div>
<div class="item tall"><img src="portrait.jpg" alt=""></div>
<div class="item"><img src="square.jpg" alt=""></div>
<div class="item wide tall"><img src="large.jpg" alt=""></div>
<div class="item"><img src="normal.jpg" alt=""></div>
</div>
<style>
.galerie-pinterest {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
grid-auto-rows: 200px;
gap: 15px;
padding: 20px;
}
.galerie-pinterest .item {
border-radius: 12px;
overflow: hidden;
}
.galerie-pinterest img {
width: 100%;
height: 100%;
object-fit: cover;
}
/* Éléments qui prennent plus de place */
.item.wide { grid-column: span 2; }
.item.tall { grid-row: span 2; }
/* Responsive : pas de span sur mobile */
@media (max-width: 600px) {
.item.wide { grid-column: span 1; }
.item.tall { grid-row: span 1; }
}
</style>
Galerie avec overlay et légende
<div class="galerie-overlay">
<figure class="photo">
<img src="photo1.jpg" alt="Plage de Ngor">
<figcaption>
<h3>Plage de Ngor</h3>
<p>Dakar, Sénégal</p>
</figcaption>
</figure>
<!-- Répéter pour chaque photo -->
</div>
<style>
.galerie-overlay {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
gap: 20px;
padding: 20px;
}
.photo {
position: relative;
margin: 0;
overflow: hidden;
border-radius: 12px;
cursor: pointer;
}
.photo img {
width: 100%;
height: 300px;
object-fit: cover;
transition: transform 0.5s;
}
.photo:hover img { transform: scale(1.1); }
.photo figcaption {
position: absolute;
bottom: 0;
left: 0;
right: 0;
padding: 20px;
background: linear-gradient(transparent, rgba(0,0,0,0.8));
color: white;
transform: translateY(100%);
transition: transform 0.3s;
}
.photo:hover figcaption { transform: translateY(0); }
.photo figcaption h3 { margin: 0 0 5px; font-size: 18px; }
.photo figcaption p { margin: 0; opacity: 0.8; font-size: 14px; }
</style>
Filtres par catégorie (avec JavaScript)
<!-- Boutons de filtre -->
<div class="filtres">
<button class="active" data-filtre="all">Tout</button>
<button data-filtre="paysage">Paysages</button>
<button data-filtre="portrait">Portraits</button>
<button data-filtre="architecture">Architecture</button>
</div>
<div class="galerie-filtrable">
<div class="photo" data-categorie="paysage">...</div>
<div class="photo" data-categorie="portrait">...</div>
<div class="photo" data-categorie="architecture">...</div>
</div>
<script>
document.querySelectorAll('.filtres button').forEach(btn => {
btn.addEventListener('click', () => {
// Activer le bouton
document.querySelector('.filtres .active').classList.remove('active');
btn.classList.add('active');
const filtre = btn.dataset.filtre;
document.querySelectorAll('.galerie-filtrable .photo').forEach(photo => {
if (filtre === 'all' || photo.dataset.categorie === filtre) {
photo.style.display = '';
photo.style.animation = 'fadeIn 0.5s';
} else {
photo.style.display = 'none';
}
});
});
});
</script>
Lightbox simple en CSS et JS
<div id="lightbox">
<span class="close">×</span>
<img id="lightbox-img" src="" alt="">
</div>
<style>
#lightbox {
display: none;
position: fixed;
inset: 0;
background: rgba(0,0,0,0.9);
z-index: 9999;
align-items: center;
justify-content: center;
}
#lightbox.active { display: flex; }
#lightbox img { max-width: 90%; max-height: 90vh; border-radius: 8px; }
.close { position: absolute; top: 20px; right: 30px; color: white; font-size: 40px; cursor: pointer; }
</style>
<script>
const lightbox = document.getElementById('lightbox');
const lbImg = document.getElementById('lightbox-img');
document.querySelectorAll('.galerie img').forEach(img => {
img.addEventListener('click', () => {
lbImg.src = img.src;
lightbox.classList.add('active');
});
});
lightbox.addEventListener('click', () => lightbox.classList.remove('active'));
</script>
Exercice pratique
🎯 Défi : Galerie portfolio complète
- Créez une galerie avec 9 images en grille auto-fill responsive
- Ajoutez un overlay avec titre et description au survol
- Ajoutez 3 boutons de filtre par catégorie
- Implémentez une lightbox au clic
- Ajoutez
loading="lazy"sur toutes les images