CSS画像のプリロード


118

ボタンをクリックして展開される非表示の連絡フォームがあります。そのフィールドはCSS背景画像として設定され、トグルされたdivよりも常に少し遅れて表示されます。

<head>セクションでこのスニペットを使用していましたが、運が悪かった(キャッシュをクリアした後):

<script>
$(document).ready(function() {
        pic = new Image();
        pic2 = new Image();
        pic3 = new Image();
        pic.src="<?php bloginfo('template_directory'); ?>/images/inputs/input1.png";
        pic2.src="<?php bloginfo('template_directory'); ?>/images/inputs/input2.png";
        pic3.src="<?php bloginfo('template_directory'); ?>/images/inputs/input3.png";
});
</script>

私はライブラリとしてjQueryを使用していますが、この問題を整理するためにもそれを使用できればすばらしいでしょう。

ご清聴ありがとうございました。


コードを見せてください。このフォームをどのように切り替えますか?
n1313 2009

1
n1313、私は可能な限り最も簡単な方法を使用します:$( '#toggle')。click(function(){$( '#contact')。slideToggle();});
ピーナッツ

回答:


257

CSSのみを使用して画像をプリロードする

以下のコードでは、body要素がページに存在することが保証されている唯一の要素の1つであるため、ランダムに要素を選択しています。

「トリック」が機能するためには、複数の URLのロードcontentを快適に設定できるプロパティを使用する必要がありますが、図に示すように、疑似要素は非表示にれているため、画像はレンダリングされません。::after

body::after{
   position:absolute; width:0; height:0; overflow:hidden; z-index:-1; // hide images
   content:url(img1.png) url(img2.png) url(img3.gif) url(img4.jpg);   // load images
}

デモ


スプライト画像を使用してhttpリクエストを減らして(比較的サイズの小さい画像が多数ある場合)、HTTP2が使用されている場所で画像がホストされていることを確認することをお勧めします。


27
これはすごい!
Hengjie 2013

4
そのシンプルさと純粋なCSSアプローチのためのこれまでの最高のテクニック!唯一の欠点は、これらの画像がすぐに表示されるコンテンツと同時に読み込まれ、メインのコンテンツが読み込まれるまで遅延されないことです。これには、Javascriptが必要になります。しかし、何十もの画像をプリロードしているのでなければ、これは取引を妨げるものではありません。
ベンジャミン

2
これは、CSSボタンなどのホバーアセットをプリロードするのに最適です。これにより、アセットのロード中にボタンをオーバーしてもフリッカーが発生しません
Robert Petz

16
良い解決策。bodyただし、これらの画像はスタイルシートを参照するすべてのページに読み込まれるため、これをに適用しないことをお勧めします。代わりに、.contact_form:after {...}またはグローバルではない他のクラスを使用する必要があります。もちろん、お問い合わせフォームがすべてのページにある場合を
除き

3
@vsync、これは特にgifや小さな再利用可能なものには意味があります。私が最近遭遇した状況は、コンテンツが豊富なカルーセルの大きなbg画像であり、それらの大きなファイルをどこにもロードしたくありませんでした:)
CloudMagick

30

元のコードが機能しているように見えます。間違った経路の画像に何気なくこだわっていました。

ここにテストがあります:http : //paragraphe.org/slidetoggletest/test.html

<script>
    var pic = new Image();
    var pic2 = new Image();
    var pic3 = new Image();
    pic.src="images/inputs/input1.png";
    pic2.src="images/inputs/input2.png";
    pic3.src="images/inputs/input3.png";
</script>

CSS-ONLYとこのソリューションを使用したいくつかのテストの後、私の場合は特に、これが最良のソリューションです。
zequinha-bsb 2011年

その最も簡単なおかげで:)
BetaCoder

4
回答のURLは無効になりました。
Brandon Buck

こんにちは、私はそのURLのコンテンツ(段落e.org/slidetoggletest/test.html)を再アップロードしました。これを見逃して申し訳ありません。乾杯
ピーナッツ

25

HTML <link>タグを使用して画像をプリロードする

この質問のほとんどの訪問者は、「ページのレンダリングが始まる前に画像をプリロードするにはどうすればよいですか?」タグはページのそれ以上のレンダリングをブロックできる<link>ため、この問題の最善の解決策はタグを使用<link>することです。プリエンプティブを参照

rel現在のドキュメントとリンクされたドキュメント間の関係)属性のこれらの2つの値オプションは、問題に最も関連しています。

  • prefetch:ページのレンダリング中に指定されたリソースをロードします
  • preload:ページのレンダリングが開始する前に、指定されたリソースをロードします

したがって、タグのレンダリングプロセスが開始する前にリソース(この場合は画像)をロードする場合<body>は、次を使用します。

<link rel="preload" as="image" href="IMAGE_URL">

<body>レンダリング中にリソースをロードしたいが、後で動的に使用する予定であり、ロード時間でユーザーを煩わせたくない場合は、以下を使用します。

<link rel="prefetch" href="RESOURCE_URL">

Mozillaブラウザーエンジンはprefetch、ブラウザーがアイドル状態のときにのみ読み込まれることに注意してくださいnsIWebProgressListener。これは、API によって決定されます。詳しくはこちらをご覧ください。
Matthew Beckman

1
これは実際にレンダリングをブロックするとは思いません:w3c.github.io/preload "たとえば、アプリケーションはpreloadキーワードを使用して、CSSリソースの早期、高優先度、非レンダリングブロックフェッチを開始できます。アプリケーションによって適切なタイミングで適用される」
Michael Crenshaw

1
@MichaelCrenshawは正しいですが、レンダリングをブロック<link rel="preload">しませ。著者が定義を誤解していると思います。MDN Preloading content with rel = "preload"、 "...これは、ブラウザのメインレンダリング機構が起動する前に、ページライフサイクルの早い段階でロードを開始する必要があります。" アイデアは、リソースはできるだけ早くフェッチされ、<img>要素がレンダリングされているときなど、必要なときにリソースが利用可能になる可能性を高めることです。
MDMower

14

http://css-tricks.com/snippets/css/css-only-image-preloading/

テクニック#1

要素の通常の状態で画像をロードし、背景の位置でのみそれをシフトします。次に、背景の位置を移動して、ホバーに表示します。

#grass { background: url(images/grass.png) no-repeat -9999px -9999px; }
#grass:hover { background-position: bottom left; }

テクニック#2

問題の要素に既に背景画像が適用されていて、その画像を変更する必要がある場合、上記は機能しません。通常は、ここでスプライト(結合された背景画像)を使用して、背景の位置をシフトします。しかし、それが不可能な場合は、これを試してください。既に使用されているが背景画像がない別のページ要素に背景画像を適用します。

#random-unsuspecting-element { background: url(images/grass.png) no-repeat -9999px -9999px; }
#grass:hover { background: url(images/grass.png) no-repeat; }

4
常に外部リンクのコンテンツを提供します。それ以外の場合、リンクが壊れた場合の答えは役に立ちません!
sra、

@Fatih +1は非常に優れたリンクです。3つの異なる方法でリンクされた記事の最新バージョンは、こちらからperishablepress.com/3-ways-preload-images-css-javascript-ajax
xmojmr

@xmojmrリンクにCSSのみのソリューションはありません。
最大

10

これで試してください:

var c=new Image("Path to the background image");
c.onload=function(){
   //render the form
}

このコードを使用して、背景画像をプリロードし、ロード時にフォームをレンダリングします


mck89、ありがとうございます。しかし、このコードを「ヘッド」またはインライン内で使用する必要がありますか?つまり、htmlで埋めなければなりませんか?
ピーナッツ

頭の中で使用する必要があります。私はあなたが$(ドキュメント).ready内で使用できると思います
mck89

6

CSSで設定された背景画像をプリロードする場合、私が思いついた最も効率的な答えは、動作しないことがわかったコードの修正バージョンでした:

$(':hidden').each(function() {
  var backgroundImage = $(this).css("background-image");
  if (backgroundImage != 'none') {
    tempImage = new Image();
    tempImage.src = backgroundImage;
  }
});

これの大きな利点は、将来新しい背景画像を取り込むときに更新する必要がないことです。新しい背景画像を見つけてプリロードします!


各画像に非表示要素を追加することは正しく理解できますか?それはあなたのCSSファイルをスキャンして画像を見つけることができるということではありませんか?:)
bvdb

5

これらのbg画像をサイトの他の場所でフォーム入力に再利用している場合は、画像スプライトを使用することをお勧めします。そうすることで、(pic1、pic2、pic3などの代わりに)画像を集中管理できます。

スプライトは、複数のファイルではなく、サーバーから1つの(わずかに大きい)ファイルを要求するだけなので、クライアントにとっては一般的に高速です。その他のメリットについては、SOの記事をご覧ください。

CSS画像スプライト

繰り返しになりますが、これらを1つのフォームで使用しているだけで、ユーザーが連絡先フォームをリクエストした場合にのみロードしたい場合は、まったく役に立たない可能性があります。

http://www.alistapart.com/articles/sprites


はい、CSSスプライトを使用する方法です。非表示のフォームが起動する前に(ページの読み込み時など)、そのスプライト内の画像の1つが表示されることを確認してください。
Steve

1

背景画像をどこかに隠して読み込んでみてはいかがでしょうか。これにより、ページが開かれたときに読み込まれ、ajaxを使用してフォームが作成されると時間がかかりません。

body {
background: #ffffff url('img_tree.png') no-repeat -100px -100px;
}

1

このjQueryプラグインのwaitForImageを使用するか、非表示のdivまたは(width:0およびheight:0)に画像を配置して、画像に対してonloadイベントを使用できます。

2〜3個の画像しかない場合は、イベントをバインドしてチェーンでトリガーできるため、すべての画像の後にコードを実行できます。


1

唯一の方法は、画像をBase64エンコードしてHTMLコード内に配置することです。これにより、サーバーに接続して画像をダウンロードする必要がなくなります。

これはurlから画像をエンコードするので、画像ファイルのコードをコピーしてページに挿入できます...

body {
  background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIA...);
}

2
CSSで同じ画像をもう一度使用したい場合...キャッシュされないため、再度ロードする必要があります。
vsync 2013年

1

CSSコードを変更して、CSSルール:beforeまたは:after疑似要素で画像をプリロードする方法がない場合、JavaScriptコードがロードされたスタイルシートのCSSルールをトラバースする別のアプローチを使用できます。これを行うには、HTMLのスタイルシートの後に、たとえばbodyタグを閉じる前、またはスタイルシートの直後に、スクリプトを含める必要があります。

getUrls() {
    const urlRegExp = /url\(('|")?([^'"()]+)('|")\)?/;

    let urls = [];
    for (let i = 0; i < document.styleSheets.length; i++) {
        let cssRules = document.styleSheets[i].cssRules;
        for (let j = 0; j < cssRules.length; j++) {
            let cssRule = cssRules[j];
            if (!cssRule.selectorText) {
                continue;
            }

            for (let k = 0; k < cssRule.style.length; k++) {
                let property = cssRule.style[k],
                    urlMatch = cssRule.style[property].match(urlRegExp);
                if (urlMatch !== null) {
                    urls.push(urlMatch[2]);
                }
            }
        }
    }
    return urls;
}

preloadImages() {
    return new Promise(resolve => {
        let urls = getUrls(),
            loadedCount = 0;

        const onImageLoad = () => {
            loadedCount++;
            if (urls.length === loadedCount) {
                resolve();
            }
        };

        for (var i = 0; i < urls.length; i++) {
            let image = new Image();
            image.src = urls[i];
            image.onload = onImageLoad;
        }
    });
}

document.addEventListener('DOMContentLoaded', () => {
    preloadImages().then(() => {
        // CSS images are loaded here
    });
});

0

ページ要素とその背景画像が既にDOMにある場合(つまり、動的に作成/変更していない場合)、それらの背景画像は既に読み込まれています。その時点で、圧縮方法を確認したいと思うかもしれません:)


mmmm ...良い点cpharmston、そしてこれは、画像がキャッシュされても問題が解決しない理由を説明しています。だから、それはworkaraoundがないことを意味しますか?
ピーナッツ

小さい画像を作成してください!JPEGは簡単に圧縮され、PNGのサイズを縮小するコマンドラインツール(pmt.sourceforge.net/pngcrush)があり、画像の色数を減らしてGIFのサイズを縮小できます。もちろん、より高速なインターネットサービスを利用することもできます;)
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.