【LazyLoad対策】遅延読み込みによるスクロール先の位置ずれを解決する方法

【LazyLoad対策】遅延読み込みによるスクロール先の位置ずれを解決する方法

LazyLoadで遅延読み込みをしていると、スムーススクロール先の位置がズレることなんてしばしばあります。

今回は、JavaScriptを使って簡単にできる対処法をいくつかご紹介します。

目次

LazyLoadは大きく分けて2種類ある

LazyLoadには大きく分けて、以下の2つがあります。

  1. JS不要のネイティブLazyLoad
  2. JavaScriptライブラリのLazyLoad

LazyLoadその①
JS不要のネイティブLazyLoad

こちらは、imgタグにloading="lazy"を加えるだけで、ブラウザによる遅延読み込みが実行されます。

<img src="画像のパス" alt="" loading="lazy">

loading属性の値は、3種類の指定可能です。

  • lazy(遅延読み込みする)
  • eager(すぐに読み込む)
  • auto(遅延読み込みをするかブラウザに委ねる)

こちらでは、widthとheight属性を実際の画像サイズに基づいて適切に指定しておくと、画像が表示される前にその領域が確保されるため、スムーススクロールによるレイアウトのズレが防げます。

<img src="画像のパス" alt="画像の説明" loading="lazy" width="600" height="400">

LazyLoadその②
JavaScriptライブラリのLazyLoad

JavaScriptライブラリによる遅延読み込みは少し工夫が必要です。

例えばよく使われる「lazysizes.js」では、以下のような形になっています。

<!-- 画像が読み込まれる前 -->
<img src="ダミー画像のパス" data-src="実際の画像パス" class="lazyload">

<!-- 読み込まれるタイミングでパスとクラスが変わる -->
<img src="実際の画像パス" data-src="実際の画像パス" class="lazyloaded">

画像が読み込まれる前には、「軽量なダミー画像」が表示されており、画像が表示される領域に入るとdata-src属性の値がsrc属性にコピーされ「実際の画像」に置き換わるという仕組みです。

ダミー画像は数ピクセルの非常に小さな画像なので、実際の画像に置き換わった際に高さが変わってしまい、スクロール前に計算された位置と異なってしまうというわけです。

このようにJavaScriptライブラリの場合、別途以下の処理が必要です。

LazyLoad対策

対策方法は、主に以下の2種類。

  1. 任意のタイミングで強制的に画像を読み込む
  2. 再スクロール処理

LazyLoad対策その①
任意のタイミングで強制的に画像を読み込む

今回は「lazysizes.js」に合わせてdeta-srcを指定していますが、使用するライブラリによっては属性名が異なるため、適切に変更してください。

// 画像の強制読み込み
function loadImages() {
  const targets = document.querySelectorAll("[data-src]");
  for (const target of targets) {
    const dataSrc = target.getAttribute("data-src");
    const currentSrc = target.getAttribute("src");

    // data-src と src が異なる場合のみコピーする
    if (dataSrc !== currentSrc) {
      target.setAttribute("src", dataSrc);
    }
  }
}

// 実行するタイミングで以下を記述
loadImages();

コードは単純で、data-src属性の値をsrc属性にコピーする処理を、読み込みたいタイミングで実行するだけです。

またdata-srcの値がsrcの値と異なる場合にのみ処理を行っているので、無駄な処理を防ぐことができます。

実行するタイミングは、

  1. アンカーリンクをクリック
  2. 画像を読み込む(ここで実行)
  3. 少し時間を空けてスクロール位置を取得
  4. スクロール実行

という順序で行えば、正しいスクロール位置を計算できます。

LazyLoad対策その②
再スクロール処理

こちらは、スクロールの最中に再度位置を取得して、新しい位置にスクロールし直すというものです。

// Lazy Load対策(再スクロール処理)
setTimeout(() => {
  // スクロール中に再度位置を取得
  const newPosition = target.getBoundingClientRect().top + window.scrollY - headerHeight;
  // 最初の位置と新しく取得した位置が異なる場合
  if (position !== newPosition) {
    // 新しく取得した位置へスクロール
    // ...newPosition

  }
}, 200); // 遅らせる時間(ミリ秒)

このコードは、1回目のスクロール実行処理の下に記述する必要があります。

jQuery('a[href^="#"]').click(function() {
  let header = jQuery("header").innerHeight();
  let speed = 300;
  let href = jQuery(this).attr("href");
  let target = jQuery(href == "#" || href == "" ? "html" : href);
  let position = jQuery(target).offset().top - header;
  // スクロール実行
  jQuery("html, body").animate({ scrollTop: position }, speed);

  // Lazy Load対策(再スクロール処理)
  setTimeout(() => {
    // スクロール中に再度位置を取得
    const newPosition = jQuery(target).offset().top - header;
    // 最初の位置と新しく取得した位置が異なる場合
    if (position !== newPosition) {
      // 新しく取得した位置へスクロール
      jQuery("html, body").animate({ scrollTop: newPosition }, speed);
    }
  }, 200); // 遅らせる時間(ミリ秒)

  return false;
});

仕組み

setTimeout()で、位置の再取得を数ミリ秒遅らせて処理しています。

位置の取得時間が遅すぎると、スクロールがシュイーン…シュイーンと2回行われ不自然な動きになり、早すぎると正しい位置がうまく読み取れず実行されません。

1度目と2度目のスクロールがシュイーーーンとうまく繋がるように、秒数を調整する必要があります。

HISA

イーズアウト系のイージングだと自然です

どれくらいずれているか確認する方法

const newPositionの下に、以下のconsole.logを追加することで、検証のコンソールから2つの位置を把握することができます。

// ...
const newPosition = target.getBoundingClientRect().top + window.scrollY - headerHeight;
// アンカー位置の確認
console.log('最初に取得した位置' +position);
console.log('新しく取得した位置' +newPosition);
// ...

この数値を見ながら遅らせる時間を調整すると、正確性が増します。

現在の位置は以下のコードで確認することができます。

// 現在のスクロール位置の確認
window.addEventListener("scroll", scroll);
function scroll(){
  scroll_position = window.scrollY;
  console.log( window.pageYOffset );
}

対策してもずれる場合の確認事項

  • アンカー要素にアニメーションをつけている
  • widthとheightを指定していない

これらが原因でずれる可能性があります。

アンカー要素にフェードインアップのようなアニメーションを行なっている場合は、要素が動いてしまうので当然スクロール位置もずれてしまいます。

親要素を作ってそこにアンカーをつけるなどの工夫をしましょう。

まとめ:自分に合ったLazyLoad対策を

今回はLazyLoadによるスクロールずれの対策を2つご紹介しました。

プラグインやライブラリによって当てはまらない場合があるので、検証しながら対策が必要です。

気になる箇所があればコメント頂ければ幸いです。

おすすめWEBスクール

WEB制作やWEBデザインを学びたいなら、SNSでも話題の「デイトラ」がおすすめ!
どのコースも10万円前後と業界最安値で、副業や転職に向けて十分なスキルを身につけることができます。

役に立ったら他の方にシェア

お気軽にコメントどうぞ

コメントする

目次