🖨️

遅延読み込み(Lazy Loading)設定画像が印刷プレビューに表示されない問題について

に公開

問題

html
<button type="button" onclick="window.print()">印刷ボタン</button>

上記のように window.print() メソッドのみで印刷ボタンを実装し、印刷を実行すると、loading="lazy"属性が設定された遅延読み込み画像が印刷プレビューに表示されない問題がある。この現象はChromeやEdge、Safariなどで確認できるが、Firefoxでは問題なく表示される(Windows11で確認)。

ただし、Ctrl + P(印刷のWindowsショートカット)で印刷プレビューを確認すると、問題なく遅延読み込み画像が表示される。
この挙動は下記のGithub Issuesでも報告されている。
https://github.com/whatwg/html/issues/6581

解決方法(コード例)

印刷ボタン押下した際に、ページ内に存在する全ての画像を読み込むことで解決できる。

html
<button type="button" class="js-print">印刷ボタン</button>
js
/**
 * 印刷ボタンがクリックされたときの処理
 */
const btn = document.querySelector(".js-print");

if (btn) {
  btn.addEventListener("click", function () {
    const images = document.querySelectorAll("img");
    let imagesLoaded = 0;
    const totalImages = images.length;

    // ページに画像がない場合は、すぐに印刷を実行
    if (totalImages === 0) {
      window.print();
      return;
    }

    /**
     * 遅延読み込み画像の強制読み込み
     */
    images.forEach((img) => {
      // 遅延読み込み属性を削除して強制読み込み
      if (img.loading === "lazy") {
        img.loading = "eager";
      }

      // data-src属性が遅延読み込みに使用されている場合、srcに移動
      if (img.dataset.src && !img.src) {
        img.src = img.dataset.src;
      }
    });

    /**
     * 全ての画像の読み込み状態を確認し、全て読み込まれたら印刷を実行
     */
    const handleImageProcessed = () => {
      imagesLoaded++;
      if (imagesLoaded === totalImages) {
        window.print();
      }
    };

    images.forEach((img) => {
      if (img.complete) {
        // 画像がすでに読み込まれている場合
        handleImageProcessed();
      } else {
        // 画像が読み込まれていない場合、loadイベントを登録
        img.addEventListener("load", handleImageProcessed);

        // エラーが発生した場合のイベントを登録
        img.addEventListener("error", handleImageProcessed);
      }
    });
  });
}

Discussion