Preview
Our Gallery
Browse through our collection of beautiful images
Export
HTML
<section class="gallery-section">
<div class="gallery-container">
<div class="gallery-header" style="text-align: center;">
<h2 class="gallery-title">Our Gallery</h2>
<p class="gallery-subtitle">Browse through our collection of beautiful images</p>
</div>
<div class="gallery-grid">
<div class="gallery-item" onclick="openLightbox(0)">
<img src="https://picsum.photos/800/600?random=1" alt="Gallery image 1" class="gallery-image" loading="lazy">
<div class="gallery-overlay">
<span class="gallery-image-title">Landscape View</span>
</div>
</div>
<div class="gallery-item" onclick="openLightbox(1)">
<img src="https://picsum.photos/600/800?random=2" alt="Gallery image 2" class="gallery-image" loading="lazy">
<div class="gallery-overlay">
<span class="gallery-image-title">Portrait Shot</span>
</div>
</div>
<div class="gallery-item" onclick="openLightbox(2)">
<img src="https://picsum.photos/700/700?random=3" alt="Gallery image 3" class="gallery-image" loading="lazy">
<div class="gallery-overlay">
<span class="gallery-image-title">Square Format</span>
</div>
</div>
<div class="gallery-item" onclick="openLightbox(3)">
<img src="https://picsum.photos/1000/500?random=4" alt="Gallery image 4" class="gallery-image" loading="lazy">
<div class="gallery-overlay">
<span class="gallery-image-title">Wide Panorama</span>
</div>
</div>
<div class="gallery-item" onclick="openLightbox(4)">
<img src="https://picsum.photos/750/750?random=5" alt="Gallery image 5" class="gallery-image" loading="lazy">
<div class="gallery-overlay">
<span class="gallery-image-title">Nature Scene</span>
</div>
</div>
<div class="gallery-item" onclick="openLightbox(5)">
<img src="https://picsum.photos/900/600?random=6" alt="Gallery image 6" class="gallery-image" loading="lazy">
<div class="gallery-overlay">
<span class="gallery-image-title">Urban Photography</span>
</div>
</div>
</div>
</div>
<!-- Lightbox -->
<div class="lightbox" id="lightbox" onclick="closeLightbox()">
<button class="lightbox-close" onclick="closeLightbox()">×</button>
<button class="lightbox-prev" onclick="event.stopPropagation(); prevImage()">‹</button>
<img src="" alt="" class="lightbox-image" id="lightbox-image" onclick="event.stopPropagation()">
<button class="lightbox-next" onclick="event.stopPropagation(); nextImage()">›</button>
</div>
</section>CSS
.gallery-section {
background: #ffffff;
padding: 64px 48px;
}
.gallery-container {
max-width: 1200px;
margin: 0 auto;
}
.gallery-header {
margin-bottom: 48px;
}
.gallery-title {
font-size: 32px;
font-weight: 700;
color: #111827;
margin: 0 0 12px 0;
}
.gallery-subtitle {
font-size: 18px;
color: #6b7280;
margin: 0;
}
.gallery-grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 16px;
}
.gallery-grid.masonry {
grid-auto-rows: 200px;
}
.gallery-item {
position: relative;
overflow: hidden;
border-radius: 8px;
aspect-ratio: 1/1;
cursor: pointer;
}
.gallery-grid.masonry .gallery-item.tall {
grid-row: span 2;
}
.gallery-grid.masonry .gallery-item.wide {
grid-column: span 2;
}
.gallery-image {
width: 100%;
height: 100%;
object-fit: cover;
transition: transform 0.4s ease;
}
.gallery-placeholder {
width: 100%;
height: 100%;
min-height: 200px;
background: #e5e7eb;
display: flex;
align-items: center;
justify-content: center;
color: #9ca3af;
}
.gallery-item:hover .gallery-image {
transform: scale(1.1);
}
.gallery-overlay {
position: absolute;
inset: 0;
background: linear-gradient(to top, rgba(0,0,0,0.5), transparent 50%);
display: flex;
align-items: flex-end;
padding: 20px;
opacity: 1;
transition: opacity 0.3s ease;
}
.gallery-image-title {
color: #ffffff;
font-size: 16px;
font-weight: 500;
}
/* Lightbox */
.lightbox {
display: none;
position: fixed;
inset: 0;
background: rgba(0,0,0,0.95);
z-index: 1000;
align-items: center;
justify-content: center;
}
.lightbox.active {
display: flex;
}
.lightbox-image {
max-width: 90vw;
max-height: 90vh;
object-fit: contain;
}
.lightbox-close {
position: absolute;
top: 20px;
right: 20px;
background: none;
border: none;
color: white;
font-size: 40px;
cursor: pointer;
padding: 10px;
}
.lightbox-prev,
.lightbox-next {
position: absolute;
top: 50%;
transform: translateY(-50%);
background: rgba(255,255,255,0.1);
border: none;
color: white;
font-size: 48px;
padding: 20px;
cursor: pointer;
transition: background 0.3s ease;
}
.lightbox-prev:hover,
.lightbox-next:hover {
background: rgba(255,255,255,0.2);
}
.lightbox-prev {
left: 20px;
}
.lightbox-next {
right: 20px;
}
@media (max-width: 768px) {
.gallery-grid {
grid-template-columns: repeat(2, 1fr);
}
.gallery-grid.masonry .gallery-item.wide {
grid-column: span 1;
}
}
@media (max-width: 480px) {
.gallery-grid {
grid-template-columns: 1fr;
}
}JavaScript
// Lightbox functionality
const images = ["https://picsum.photos/800/600?random=1","https://picsum.photos/600/800?random=2","https://picsum.photos/700/700?random=3","https://picsum.photos/1000/500?random=4","https://picsum.photos/750/750?random=5","https://picsum.photos/900/600?random=6"];
let currentIndex = 0;
function openLightbox(index) {
currentIndex = index;
const lightbox = document.getElementById('lightbox');
const lightboxImage = document.getElementById('lightbox-image');
lightboxImage.src = images[index] || '';
lightbox.classList.add('active');
document.body.style.overflow = 'hidden';
}
function closeLightbox() {
document.getElementById('lightbox').classList.remove('active');
document.body.style.overflow = '';
}
function nextImage() {
currentIndex = (currentIndex + 1) % images.length;
document.getElementById('lightbox-image').src = images[currentIndex] || '';
}
function prevImage() {
currentIndex = (currentIndex - 1 + images.length) % images.length;
document.getElementById('lightbox-image').src = images[currentIndex] || '';
}
// Keyboard navigation
document.addEventListener('keydown', (e) => {
const lightbox = document.getElementById('lightbox');
if (!lightbox.classList.contains('active')) return;
if (e.key === 'Escape') closeLightbox();
if (e.key === 'ArrowRight') nextImage();
if (e.key === 'ArrowLeft') prevImage();
});React Component
import React, { useState } from 'react';
const ImageGallery = () => {
const [lightboxOpen, setLightboxOpen] = useState(false);
const [currentIndex, setCurrentIndex] = useState(0);
const images = [
{
"title": "Landscape View",
"url": "https://picsum.photos/800/600?random=1",
"alt": "Gallery image 1"
},
{
"title": "Portrait Shot",
"url": "https://picsum.photos/600/800?random=2",
"alt": "Gallery image 2"
},
{
"title": "Square Format",
"url": "https://picsum.photos/700/700?random=3",
"alt": "Gallery image 3"
},
{
"title": "Wide Panorama",
"url": "https://picsum.photos/1000/500?random=4",
"alt": "Gallery image 4"
},
{
"title": "Nature Scene",
"url": "https://picsum.photos/750/750?random=5",
"alt": "Gallery image 5"
},
{
"title": "Urban Photography",
"url": "https://picsum.photos/900/600?random=6",
"alt": "Gallery image 6"
}
];
const openLightbox = (index) => {
setCurrentIndex(index);
setLightboxOpen(true);
};
const closeLightbox = () => setLightboxOpen(false);
const nextImage = () => setCurrentIndex((prev) => (prev + 1) % images.length);
const prevImage = () => setCurrentIndex((prev) => (prev - 1 + images.length) % images.length);
return (
<section style={{
background: '#ffffff',
padding: '64px 48px'
}}>
<div style={{ maxWidth: '1200px', margin: '0 auto' }}>
<div style={{ textAlign: 'center', marginBottom: '48px' }}>
<h2 style={{ fontSize: '32px', fontWeight: 700, color: '#111827', margin: '0 0 12px' }}>
Our Gallery
</h2>
<p style={{ fontSize: '18px', color: '#6b7280', margin: 0 }}>
Browse through our collection of beautiful images
</p>
</div>
<div style={{
display: 'grid',
gridTemplateColumns: 'repeat(3, 1fr)',
gap: '16px'
}}>
{images.map((img, idx) => (
<div
key={idx}
onClick={() => openLightbox(idx)}
style={{
position: 'relative',
overflow: 'hidden',
borderRadius: '8px',
aspectRatio: '1/1',
cursor: 'pointer'
}}
>
<img
src={img.url}
alt={img.alt}
style={{
width: '100%',
height: '100%',
objectFit: 'cover',
transition: 'transform 0.4s ease'
}}
/>
<div style={{
position: 'absolute',
inset: 0,
background: 'linear-gradient(to top, rgba(0,0,0,0.5), transparent 50%)',
display: 'flex',
alignItems: 'flex-end',
padding: '20px'
}}>
<span style={{ color: '#ffffff', fontSize: '16px', fontWeight: 500 }}>
{img.title}
</span>
</div>
</div>
))}
</div>
</div>
{lightboxOpen && (
<div
onClick={closeLightbox}
style={{
position: 'fixed',
inset: 0,
background: 'rgba(0,0,0,0.95)',
zIndex: 1000,
display: 'flex',
alignItems: 'center',
justifyContent: 'center'
}}
>
<button
onClick={closeLightbox}
style={{
position: 'absolute',
top: '20px',
right: '20px',
background: 'none',
border: 'none',
color: 'white',
fontSize: '40px',
cursor: 'pointer'
}}
>
×
</button>
<button
onClick={(e) => { e.stopPropagation(); prevImage(); }}
style={{
position: 'absolute',
left: '20px',
background: 'rgba(255,255,255,0.1)',
border: 'none',
color: 'white',
fontSize: '48px',
padding: '20px',
cursor: 'pointer'
}}
>
‹
</button>
<img
src={images[currentIndex].url}
alt={images[currentIndex].alt}
onClick={(e) => e.stopPropagation()}
style={{
maxWidth: '90vw',
maxHeight: '90vh',
objectFit: 'contain'
}}
/>
<button
onClick={(e) => { e.stopPropagation(); nextImage(); }}
style={{
position: 'absolute',
right: '20px',
background: 'rgba(255,255,255,0.1)',
border: 'none',
color: 'white',
fontSize: '48px',
padding: '20px',
cursor: 'pointer'
}}
>
›
</button>
</div>
)}
</section>
);
};
export default ImageGallery;