﻿---
title: Use Medium-Zoom in Hexo Blog
date: 2025-02-23
excerpt: Integrate medium-zoom into a Hexo blog to replace image-link jumps with an in-page zoom interaction, including Icarus and PJAX notes.
tags: [Hexo, Icarus, Web, Blog, Pjax]
cover: https://assets.vluv.space/cover/FrontEnd/medium-zoom.webp
updated: 2026-07-08 07:59:08
lang: en
i18n:
  cn: /medium-zoom
  translation: 2
---

## 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.

```js
// 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](<(https://github.com/ppoffice/hexo-theme-icarus/issues/868)>). To improve the interaction after a reader clicks an image, we can use the lightweight [medium-zoom](https://github.com/francoischalifour/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.

<div style="display: flex; justify-content: space-between; align-items: flex-start; gap: .5rem;">
  <div style="flex: 1;">
   <video autoplay loop muted playsinline><source src="https://assets.vluv.space/medium_zoom1.mp4" type="video/mp4"></video>
  </div>
  <div style="flex: 1;">
    <video autoplay loop muted playsinline><source src="https://assets.vluv.space/medium-zoom.mp4" type="video/mp4"></video>
  </div>
</div>

## Steps

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

  ```js main.js
  (function($, moment, ClipboardJS, config) {
     $('.article img:not(".not-gallery-item")').each(function() { // [!code --]
         // wrap images with link and add caption if possible // [!code --]
         if ($(this).parent('a').length === 0) { // [!code --]
             $(this).wrap('<a class="gallery-item" href="' + $(this).attr('src') + '"> </a>'); // [!code --]
             if (this.alt) { // [!code --]
                 $(this).after('<p class="has-text-centered is-size-6 caption">' + this.alt  + '</p>'); // [!code --]
             } // [!code --]
         } // [!code --]
     }); // [!code --]
      ......
      document.addEventListener("DOMContentLoaded", function () { // [!code ++]
          mediumZoom('.content img', { // [!code ++]
              background: 'rgba(30, 30, 46, 0.5)', // [!code ++]
          }); // [!code ++]
      }); // [!code ++]
  }(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.

  ```css
  .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:

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

[^1]: [zoom | CSS-Tricks](https://css-tricks.com/almanac/properties/z/zoom/)
