web-dev-qa-db-ja.com

「レスポンシブ」画像(高さが不明)による遅延読み込み

パーセンテージに基づくCSSグリッドシステムを使用しています。グリッドが4列あり、各ページの合計幅の25%です。次のように、各「25%セル」内にイメージタグを出力します。

<img src="foo.jpg" style="max-width:100%" />

ブラウザのサイズが変更されると、画像もサイズ変更され、各25%セルの100%が埋められます。ブラウザは、「height:auto」(省略された場合は暗黙的)を置いたかのように、高さを選択します。

これに遅延読み込み機能を追加したいと思います。問題は、画像が読み込まれる前は、ページ上の画像の高さが不明であることです。ブラウザは画像をダウンロードしてアスペクト比を観察し、その高さを計算する必要があります。これより前は、すべての画像の高さが1ピクセルです。すべての画像の高さは1pxであるため、すべて「ビューポート内」と見なされ、すぐに読み込まれます。

現在、私はimgタグを出力する前に、サーバーで画像のアスペクト比を計算し、データ属性で出力するという概念実証を行っています。

<img src="foo.jpg" style="max-width:100%" data-aspect="1.7742" />

次に、「ドキュメントの準備ができました」というイベントが発生すると、すべての画像をループして、遅延読み込みの前にピクセル単位で固定の「高さ」値を設定します。

$('img').each(function() {
        var img = $(this);
        var width = img.width();
        var ratio = img.data('aspectratio');
        var height = width / ratio;
        $(this).css('height', height+'px');
    });

これは、すべての画像を同時にロードするのではなく、スクロールするときにのみ画像をロードするという意味で、機能しているようです。

ただし、ユーザーがブラウザのサイズを変更すると画像が引き伸ばされるなど、新しい問題が発生する可能性があります。遅延読み込みが完了したためにコールバックが発生した場合、「高さ」を「自動」に戻す必要があります。これにより、ユーザーに表示される画像が処理されます。ただし、スクロールせずに見える画像は、ブラウザーのサイズが変更されても、不適切な「高さ」の値を保持します。ブラウザーのサイズが変更されるたびに、以前はスクロールせずにいたすべての画像を繰り返し処理し、更新された幅を測定し、アスペクト比を読み取り、新しい高さを更新してから、遅延ロードを再トリガーして、折る。これを行わないと、画像の高さの値が正しくないために、読み込みが早すぎたり遅すぎたりする可能性があります。

私の質問は、ここで説明した正確な方法以外に、高さが不明な画像を遅延読み込みする他の方法はありますか?これにはどのような影響がありますか?プログラムするのが面倒なこと以外に、私の方法には欠点がありますか?

15
Josh Ribakoff

最近同様の問題が発生し、レスポンシブレイアウトで IsotopeLazy Load を組み合わせました。 Isotopeは、ページが読み込まれたときの画像の幅と高さに基づいてレイアウトを決定します。したがって、Isotopeが正しいサイズを計算していなかったため、最初はアイテムがすべて重なり合っていました。

プレースホルダーアイテムがスペースを節約していることを確認するために、私はあなたが言及したパディングボトムトリックを使用しました: http://thisisthat.co.uk/notebook/2013-10-07-lazy-loading-responsive-images (正確な投稿ではなかったかもしれませんが。)これが私のマークアップです。

    <article class="portfolio-item">
        <a class="portfolio-link" href="img/gallery/thumb90.jpg" style="padding-bottom: 66.2%">
            <div class="portfolio-image-wrapper">
                <img class="portfolio-image" data-original="img/gallery/thumb90.jpg" width="1000" height="662">
            </div>
            <div class="portfolio-text">
                <h1 class="portfolio-item-name">
                    <span href="#" class="icon" data-icon="e"></span>
                    <span class="portfolio-item-tags">Bridals</span>
                </h1>
            </div>
        </a>
    </article>

これはおそらく必要以上に複雑になります(.portfolio-text div全体がオーバーレイであり、かなりのスタイル設定が行われているため)。実際のキーは、画像の幅と高さに基づいて下のパディングを計算し(PHPを使用したテンプレートでこれを行いました)、スペースを節約したい項目のパディングの下として設定することでした。

5
jpsingleton

さらにクリーナー:

  1. 画像の高さと幅を任意の大きな数値に設定します(2000px x 1000pxなど)
  2. (おそらく共有クラスを介して)必要な各画像に次のCSSを適用します。
    max-width: 100%およびheight: auto
  3. スマイルワイド:)

このGithubの問題 で示されているように、このアプローチの功績は、上記のGithubユーザーdryabに提供されます。

4
Isaac Gregson

コメントから、これはよりエレガントなソリューションです。アスペクト比のサーバー側を記述する必要がありますが、ラッパーdivを使用します。

<div class="lazy"><img src="foo.jpg" style="max-width:100%" data-aspect="0.75" /></div>

次に、JSでラッパーにdiv a padding-bottom

$('div.lazy').livequery(function() {
    var c = $(this);
    var r = c.data('ar');
    c.css('padding-bottom', r * 100 + '%');
});

これにより、divimgが最終的に消費する正確な寸法が得られます。次に、次のLESSを使用して、paddingが消費する領域内に画像を読み込みます。

div.lazy {
  max-width:100%;
  position:relative;
  img {
    position:absolute;
    width:100%;
    height:100%;
  }
}
2
Josh Ribakoff

heightおよびwidth props(WordPressのデフォルト)をロードした1x1px gif in src-デフォルトでは一部のプラグイン(あなたを見ている-wp-smush)次に、この小さな獣をスクリプトのdocreadyイベントに接続するだけで、遅延読み込み時に画像の厄介な垂直ジャンプが自動修正されます。これは古い投稿であることはわかっていますが、これは最新のjs解決:

$('.lazyload').each(function(i,j){
    var h = $(j).attr( 'height' );
    var w = $(j).attr( 'width' );
    var at = `data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 ${w} ${h}'%3E%3C/svg%3E`;
    $(j).attr('src', at);
});
0
Kresimir Pendic