web-dev-qa-db-ja.com

CSSイメージのプリロード

ボタンをクリックして展開される非表示の連絡先フォームがあります。そのフィールドは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を使用していますが、この問題を整理するためにもjQueryを使用できると便利です。

あなたの考えをありがとう。

103
Peanuts

元のコードが機能しているように見えることを確認できます。間違ったパスの画像に何気なくこだわりました。

テストは次のとおりです。 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>
26
Peanuts

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

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

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

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
}

デモ


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

229
vsync

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

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

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

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

この質問の訪問者のほとんどは、"ページのレンダリングが開始される前に画像をプリロードできますか?"の答えを探していると思います。 <link>タグはページのさらなるレンダリングをブロックできるため、<link>タグを使用しています。 preemptive を参照してください

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

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

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

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

また、<body>のレンダリング中にリソースをロードしたいが、後で動的に使用することを計画しており、ロード時間でユーザーを煩わせたくない場合は、次を使用します。

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

これで試してください:

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

このコードでは、背景画像をプリロードし、ロードされたときにフォームをレンダリングします

9
mck89

フォーム入力のためにこれらのbg画像をサイトの他の場所で再利用している場合は、おそらく画像Spriteを使用する必要があります。そうすれば、(pic1、pic2、pic3などを持たずに)画像を一元管理できます。

スプライトは、複数のファイルの代わりにサーバーから1つ(わずかに大きい)のファイルのみを要求しているため、一般にクライアントにとって高速です。その他の利点については、SOの記事を参照してください。

CSS画像スプライト

この場合も、これらを1つのフォームに使用しているだけで、ユーザーが連絡先フォームを要求した場合にのみロードしたい場合、これはまったく役に立ちません。

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

5
ajhit406

CSSを使用して背景画像セットをプリロードする場合、私が思いついた最も効率的な答えは、動作しないコードの修正バージョンです。

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

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

5
Deminetix

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

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

1
user1236048

その背景画像を非表示のどこかに読み込んでみてください。そうすれば、ページが開かれたときにロードされ、ajaxを使用してフォームが作成されると、時間はかかりません。

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

:beforeまたは:after疑似要素のCSSルールを使用してCSSコードを変更し、画像をプリロードする方法がない場合、読み込まれたスタイルシートのCSSルールをトラバースするJavaScriptコードを使用する別のアプローチを使用できます。動作させるために スクリプトはスタイルシートの後に含める必要があります 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
    });
});
1
Ezze

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

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

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

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

0
c_harm