placeholderUse Medium-Zoom in Hexo Blog

Use Medium-Zoom in Hexo Blog

Integrate medium-zoom into a Hexo blog to replace image-link jumps with an in-page zoom interaction, including Icarus and PJAX notes.

Intro

When the Icarus theme processes images, it uses a wrap method to wrap images in an <a> tag and sets the href (hypertext reference) to the image’s src. Clicking an image then jumps to the original image URL.

// File: main.js(function($, moment, ClipboardJS, config) {    $('.article img:not(".not-gallery-item")').each(function() {        // wrap images with link and add caption if possible        if ($(this).parent('a').length === 0) {            $(this).wrap('<a class="gallery-item" href="' + $(this).attr('src') + '"></a>');            if (this.alt) {                $(this).after('<p class="has-text-centered is-size-6 caption">' + this.alt + '</p>');            }        }    });    ......}(jQuery, window.moment, window.ClipboardJS, window.IcarusThemeSettings));

Using an href link causes a page navigation. The mobile experience is poor, and the desktop experience is only passable. Someone raised this issue in an Icarus GitHub issue. To improve the interaction after a reader clicks an image, we can use the lightweight medium-zoom library. It creates a smooth zoom effect within the current page when an image is clicked, which provides a better visual experience and makes viewing images more direct and immersive.

Steps

  • Import medium-zoom. Taking Icarus as an example, add the following code to layout.jsx:
    <script src="https://cdn.jsdelivr.net/npm/medium-zoom@latest/dist/medium-zoom.min.js"></script>

  • Initialize it in main.js.

    main.js
    (function($, moment, ClipboardJS, config) {   $('.article img:not(".not-gallery-item")').each(function() {       // wrap images with link and add caption if possible // [!code --]       if ($(this).parent('a').length === 0) {           $(this).wrap('<a class="gallery-item" href="' + $(this).attr('src') + '"> </a>');           if (this.alt) {               $(this).after('<p class="has-text-centered is-size-6 caption">' + this.alt  + '</p>');           }       }   });    ......    document.addEventListener("DOMContentLoaded", function () {        mediumZoom('.content img', {            background: 'rgba(30, 30, 46, 0.5)',        });    });}(jQuery, window.moment, window.ClipboardJS, window.IcarusThemeSettings));
  • Add styles according to personal preference. I recommend adjusting z-index to make sure the zoomed image appears above everything else. You can also use backdrop-filter to create a blur effect.

    .medium-zoom-overlay {  backdrop-filter: blur(8px);  -webkit-backdrop-filter: blur(8px);  z-index: 150 !important;}.medium-zoom-image--opened {  z-index: 151;  position: fixed;}

Q&A

The Zoomed Image Is Outside the Visible Viewport

The images where I encountered this problem all used style="zoom: 30%"[1] to control scaling. This is incompatible with medium-zoom, causing the zoomed image to shift away from the center. The fix is to replace the zoom property with width: 30%, or use transform: scale(0.3) for scaling.

PJAX Issue

Some Hexo themes, such as Icarus, use PJAX or partial refreshes to load pages. For blog pages loaded through PJAX or asynchronously, medium-zoom needs to be reinitialized after the content updates. Assuming PJAX is used, call mediumZoom again in the PJAX completion event:

document.addEventListener("pjax:complete", () => {  mediumZoom(".content img", {    background: "rgba(30, 30, 46, 0.5)",  });  // TODO pace stop loading animation});

  1. zoom | CSS-Tricks ↩︎