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" 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://images.unsplash.com/photo-1626808642875-0aa545482dfb" 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" 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

.card-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
    gap: 16px;
    padding: 20px;
  }

  .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, .card p {
    margin: 10px;
  }

  /* Fixed-position hover preview */
  #hover-preview {
    position: fixed;
    bottom: 20px;
    right: 20px;
    width: 300px;
    height: 300px;
    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;
    border-radius: 8px;
    overflow: hidden;
    padding: 4px;
  }

  #hover-preview img {
    width: 100%;
    height: 100%;
    object-fit: contain; /* Maintain aspect ratio without cropping */
  }

JavaScript

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');

  document.querySelectorAll('.previewable-image').forEach(img => {
    img.addEventListener('mouseenter', () => {
      const fullSrc = img.src;
      previewImg.src = fullSrc;
      preview.style.display = 'block';
    });

    img.addEventListener('mouseleave', () => {
      preview.style.display = 'none';
      previewImg.src = '';
    });
  });