Display card grid with hover preview images
by raviteja gunda
HTML
<div class="card-grid">
<div class="card">
<img src="https://images.unsplash.com/photo-1624555130581-1d9cca783bc0?q=80&w=3542&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D" data-full="full1.jpg" alt="Card 1" class="previewable-image" />
<h3>Card Title 1</h3>
<p>Short description goes here.</p>
</div>
<div class="card">
<img src="https://plus.unsplash.com/premium_photo-1683865776032-07bf70b0add1?q=80&w=3432&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D" data-full="full2.jpg" alt="Card 2" class="previewable-image" />
<h3>Card Title 2</h3>
<p>Another brief text.</p>
</div>
<div class="card">
<img src="https://images.pexels.com/photos/15752372/pexels-photo-15752372/free-photo-of-camera-menu-on-screen.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=2" data-full="full2.jpg" alt="Card 2" class="previewable-image" />
<h3>Card Title 2</h3>
<p>Another brief text.</p>
</div>
<!-- Add more cards as needed -->
</div>
CSS
/* Grid layout */
.card-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
gap: 16px;
padding: 20px;
}
/* Card styling */
.card {
background: #fff;
border: 1px solid #ddd;
border-radius: 8px;
overflow: hidden;
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.1);
transition: transform 0.2s;
}
.card:hover {
transform: translateY(-4px);
}
.card img {
width: 100%;
height: 160px;
object-fit: cover;
display: block;
}
.card h3 {
margin: 10px;
font-size: 1.1rem;
}
.card p {
margin: 0 10px 10px;
font-size: 0.95rem;
color: #555;
}
/* Hover preview container */
#hover-preview {
position: absolute;
display: none;
pointer-events: none;
border: 1px solid #ccc;
background: #fff;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
z-index: 1000;
max-width: 400px;
max-height: 400px;
overflow: hidden;
border-radius: 6px;
animation: fadeIn 0.2s ease-in-out;
}
#hover-preview img {
width: 100%;
height: auto;
display: block;
}
/* Optional fade-in animation */
@keyframes fadeIn {
from {
opacity: 0;
transform: scale(0.95);
}
to {
opacity: 1;
transform: scale(1);
}
}
JavaScript
// Create the floating preview container
const preview = document.createElement('div');
preview.id = 'hover-preview';
preview.innerHTML = '<img src="" alt="Full Preview">';
document.body.appendChild(preview);
const previewImg = preview.querySelector('img');
// Attach events to all previewable images
document.querySelectorAll('.previewable-image').forEach(img => {
img.addEventListener('mouseenter', () => {
const fullSrc = img.getAttribute('src') || img.src;
previewImg.src = fullSrc;
preview.style.display = 'block';
});
img.addEventListener('mousemove', (e) => {
preview.style.left = (e.pageX + 15) + 'px';
preview.style.top = (e.pageY + 15) + 'px';
});
img.addEventListener('mouseleave', () => {
preview.style.display = 'none';
});
});