FreeNewBlockMedia

Image Zoom

Hover-to-zoom image grid for editorial PDPs and detail shots.

#image#zoom#pdp#detail#lookbook#custom-liquid

Live preview

See it in action.

Fully interactive, drag, click, scroll inside the frame, toggle to mobile.

About this block

Magnify any image under the cursor on hover (or tap on touch devices). Transform-origin tracks the pointer so the zoom area follows you. No zoom library, no third-party SDK, just pure CSS transform plus a few lines of JS for pointer tracking.

Install in 90 seconds

  1. 01

    Open your Shopify admin and go to Online Store → Themes → Customize.

  2. 02

    On any template, click "Add section" where you want the block to appear.

  3. 03

    Choose "Custom Liquid" from the section list.

  4. 04

    Paste the code from this page into the Custom Liquid setting and click Save.

  5. 05

    Edit text and colors directly in the code (look for the comments marking edit points).

The code

Paste the snippet below into the Custom Liquid setting on a Custom Liquid section in your Theme Editor. Edit text, colors, and links directly in the code, every editable spot is marked with an EDIT comment.

modblo-image-zoom.liquid
{%- comment -%}
  modblo. Image Zoom Block
  Paste into a Shopify "Custom Liquid" section via Theme Editor.
  Hover (or tap) any image in the block to magnify it under the cursor.
  Pure CSS transform + a few lines of JS to track pointer position.
{%- endcomment -%}

<style>
  .modblo-iz { background:#fff; padding:clamp(40px,6vw,72px) 0; }                 /* EDIT colors */
  .modblo-iz__inner { max-width:1100px; margin:0 auto; padding:0 24px; }
  .modblo-iz__h { font-size:clamp(22px,2.5vw,30px); letter-spacing:-.02em; margin:0 0 24px; text-align:center; color:#0b0b0c; }

  .modblo-iz__grid { display:grid; gap:18px; grid-template-columns:repeat(auto-fit,minmax(260px,1fr)); }
  .modblo-iz__frame {
    position:relative; aspect-ratio:1; overflow:hidden;
    border-radius:16px; cursor:zoom-in;
    background:#fafafa;
    border:1px solid rgba(11,11,12,.06);
  }
  .modblo-iz__img {
    width:100%; height:100%; object-fit:cover; display:block;
    transition:transform .25s ease;
    transform-origin:center center;
  }
  .modblo-iz__frame.is-zoomed .modblo-iz__img {
    transform:scale(2.4);                                                     /* EDIT zoom strength */
    transition:none;
  }
  .modblo-iz__frame.is-zoomed { cursor:zoom-out; }

  .modblo-iz__hint {
    position:absolute; bottom:10px; left:10px;
    background:rgba(0,0,0,.6); color:#fff;
    padding:4px 8px; border-radius:6px;
    font-size:10px; font-weight:600;
    text-transform:uppercase; letter-spacing:.08em;
    opacity:0; transition:opacity .2s;
    pointer-events:none;
  }
  .modblo-iz__frame:hover .modblo-iz__hint { opacity:1; }
  .modblo-iz__frame.is-zoomed .modblo-iz__hint { opacity:0; }

  .modblo-iz__cap { font-size:13px; opacity:.65; margin:10px 0 0; text-align:center; color:#0b0b0c; }
</style>

<section class="modblo-iz">
  <div class="modblo-iz__inner">
    <h2 class="modblo-iz__h">Detail close-ups</h2>                                {%- comment -%} EDIT heading or remove {%- endcomment -%}

    <div class="modblo-iz__grid">
      {%- comment -%} EDIT each image: replace src with your asset URL {%- endcomment -%}
      <figure>
        <div class="modblo-iz__frame" data-modblo-iz>
          <img class="modblo-iz__img" src="https://images.unsplash.com/photo-1512436991641-6745cdb1723f?w=800" alt="" width="800" height="800" loading="lazy">
          <span class="modblo-iz__hint">Hover to zoom</span>
        </div>
        <figcaption class="modblo-iz__cap">Heritage knit detail</figcaption>
      </figure>

      <figure>
        <div class="modblo-iz__frame" data-modblo-iz>
          <img class="modblo-iz__img" src="https://images.unsplash.com/photo-1542838132-92c53300491e?w=800" alt="" width="800" height="800" loading="lazy">
          <span class="modblo-iz__hint">Hover to zoom</span>
        </div>
        <figcaption class="modblo-iz__cap">Stitch close-up</figcaption>
      </figure>

      <figure>
        <div class="modblo-iz__frame" data-modblo-iz>
          <img class="modblo-iz__img" src="https://images.unsplash.com/photo-1556905055-8f358a7a47b2?w=800" alt="" width="800" height="800" loading="lazy">
          <span class="modblo-iz__hint">Hover to zoom</span>
        </div>
        <figcaption class="modblo-iz__cap">Color detail</figcaption>
      </figure>
    </div>
  </div>
</section>

<script>
  (function () {
    document.querySelectorAll('[data-modblo-iz]').forEach(function (frame) {
      var img = frame.querySelector('.modblo-iz__img');
      if (!img) return;
      var supportsHover = window.matchMedia('(hover: hover)').matches;

      function setOriginFromEvent(e) {
        var rect = frame.getBoundingClientRect();
        var x = ((e.clientX - rect.left) / rect.width) * 100;
        var y = ((e.clientY - rect.top) / rect.height) * 100;
        img.style.transformOrigin = x + '% ' + y + '%';
      }

      if (supportsHover) {
        frame.addEventListener('mouseenter', function () {
          frame.classList.add('is-zoomed');
        });
        frame.addEventListener('mousemove', setOriginFromEvent);
        frame.addEventListener('mouseleave', function () {
          frame.classList.remove('is-zoomed');
          img.style.transformOrigin = 'center center';
        });
      } else {
        // Touch: tap toggles zoom, second tap or tap-elsewhere unzooms
        frame.addEventListener('click', function (e) {
          if (frame.classList.contains('is-zoomed')) {
            frame.classList.remove('is-zoomed');
            img.style.transformOrigin = 'center center';
          } else {
            setOriginFromEvent({ clientX: e.clientX, clientY: e.clientY });
            frame.classList.add('is-zoomed');
          }
        });
      }
    });
  })();
</script>

What you can customize

Custom Liquid sections don't expose theme-editor settings, so customization happens in the code. Here's what to edit:

WhatHow to edit
HeadingFind the value in the code and change it directly.
Each figureReplace each <img src=...> with your asset URL. Edit the figcaption text.
Zoom strengthLook for transform:scale(2.4). Higher numbers zoom more.

SEO & accessibility notes

  • Real <img> with loading="lazy" and alt attributes, fully crawlable for image SEO.
  • Native <figure>/<figcaption> markup, semantic and screen-reader friendly.
  • Falls back to tap-to-zoom on touch devices via matchMedia '(hover: hover)' detection.
  • Uses transform-origin (CSS) plus pointer events, no JS animation library.