Vorladen von CSS-Bildern

118

Ich habe ein verstecktes Kontaktformular, das durch Klicken auf eine Schaltfläche bereitgestellt wird. Die Felder werden als CSS-Hintergrundbilder festgelegt und erscheinen immer etwas später als das umgeschaltete div.

Ich habe dieses Snippet in der <head>Sektion verwendet, aber ohne Glück (nachdem ich den Cache geleert habe):

<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>

Ich verwende jQuery als meine Bibliothek, und es wäre cool, wenn ich es auch zum Arrangieren dieses Problems verwenden könnte.

Vielen Dank für Ihre Gedanken.

Erdnüsse
quelle
Bitte zeigen Sie Ihren Code. Wie schaltet man dieses Formular um?
n1313
1
n1313 verwende ich den einfachsten Weg: $ ('# toggle'). click (function () {$ ('# contact'). slideToggle ();});
Erdnüsse

Antworten:

256

Vorladen von Bildern nur mit CSS

Im folgenden Code wähle ich das bodyElement zufällig aus , da es eines der wenigen Elemente ist, die garantiert auf der Seite vorhanden sind.

Damit der "Trick" funktioniert, verwenden wir die contentEigenschaft, mit der bequem mehrere URLs geladen werden können. Wie gezeigt, ::afterbleibt das Pseudoelement jedoch verborgen, damit die Bilder nicht gerendert werden:

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
}

Demo


Es ist besser, ein Sprite-Image zu verwenden, um http-Anforderungen zu reduzieren ... (wenn es viele relativ kleine Images gibt) und sicherzustellen, dass die Images dort gehostet werden, wo HTTP2 verwendet wird.

vsync
quelle
26
Das ist fantastisch!
Hengjie
4
Die bisher beste Technik für ihre Einfachheit und den reinen CSS-Ansatz! Der einzige Nachteil ist, dass diese Bilder gleichzeitig mit dem sofort sichtbaren Inhalt geladen werden und erst verzögert werden, nachdem der Hauptinhalt geladen wurde, was Javascript erfordern würde. Aber wenn Sie nicht Dutzende von Bildern vorladen, sollte dies kein Deal-Breaker sein.
Benjamin
2
Dies ist fantastisch, um Hover-Assets für CSS-Schaltflächen und dergleichen vorzuladen. Auf diese Weise erhalten Sie kein Flimmern, wenn Sie beim Laden der Assets über Ihre Schaltfläche fahren
Robert Petz
16
Gute Lösung. Ich würde jedoch empfehlen, dies nicht anzuwenden body, da diese Bilder auf jede Seite geladen werden, die auf das Stylesheet verweist. Verwenden Sie stattdessen .contact_form:after {...}eine andere Klasse, die weniger global ist. Es sei denn natürlich, Ihr Kontaktformular befindet sich auf jeder Seite;)
CloudMagick
3
@vsync, das macht Sinn, besonders für Gifs und kleine wiederverwendbare. Die Situation, auf die ich kürzlich
gestoßen
30

Ich kann bestätigen, dass mein ursprünglicher Code zu funktionieren scheint. Ich hielt mich beiläufig an ein Bild mit einem falschen Weg.

Hier ist ein Test: 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>
Erdnüsse
quelle
Nach einigen Tests mit CSS-ONLY und dieser Lösung, in meinem Fall speziell, ist dies die beste.
Zequinha-bsb
Vielen Dank, es ist das einfachste von allen :)
BetaCoder
4
Die URL in der Antwort ist nicht mehr gültig.
Brandon Buck
Hallo, ich habe den Inhalt dieser URL ( paragraphe.org/slidetoggletest/test.html ) erneut hochgeladen. Es tut mir leid, dass ich dies verpasst habe. Prost,
Erdnüsse
25

Vorladen von Bildern mit dem HTML <link> -Tag

Ich glaube, die meisten Besucher dieser Frage suchen nach der Antwort "Wie kann ich ein Bild vorab laden, bevor das Rendern der Seite beginnt?" Die beste Lösung für dieses Problem ist die Verwendung von <link>Tags, da <link>Tag das weitere Rendern der Seite blockieren kann. Siehe präventiv

Diese beiden Wertoptionen des Attributs rel( Beziehung zwischen dem aktuellen Dokument und dem verknüpften Dokument ) sind für das Problem am relevantesten:

  • Prefetch : Laden Sie die angegebene Ressource beim Rendern der Seite
  • Preload : Laden Sie die angegebene Ressource, bevor das Rendern der Seite beginnt

Wenn Sie also eine Ressource laden möchten ( in diesem Fall ein Bild ), bevor der Rendervorgang des <body>Tags beginnt, verwenden Sie:

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

Wenn Sie eine Ressource während des <body>Renderns laden möchten, diese aber später dynamisch verwenden möchten und den Benutzer nicht mit der Ladezeit belästigen möchten , verwenden Sie:

<link rel="prefetch" href="RESOURCE_URL">
Mertyildiran
quelle
Es ist erwähnenswert, dass die Mozilla-Browser-Engine nur geladen wird, prefetchwenn der Browser inaktiv ist, was von der nsIWebProgressListenerAPI festgelegt wird. Sehen Sie diese für weitere Informationen.
Matthew Beckman
1
Ich glaube nicht, dass dies das Rendern tatsächlich blockiert: w3c.github.io/preload "Zum Beispiel kann die Anwendung das Preload-Schlüsselwort verwenden, um einen frühen Abruf einer CSS-Ressource mit hoher Priorität und ohne Renderblockierung zu initiieren, der dies dann kann von der Bewerbung zu gegebener Zeit beantragt werden "
Michael Crenshaw
1
@MichaelCrenshaw korrekt ist, <link rel="preload">ist nicht Rendering - Block, glaube ich , der Autor die Definition falsch verstanden. Aus MDN Vorladen von Inhalten mit rel = "Preload" , "... die Sie früh im Seitenlebenszyklus laden möchten, bevor die Haupt-Rendering-Maschinerie des Browsers aktiviert wird ." Die Idee ist, dass Ressourcen so schnell wie möglich abgerufen werden, wodurch es wahrscheinlicher wird, dass die Ressource bei Bedarf verfügbar ist, beispielsweise wenn ein <img>Element gerendert wird.
MDMower
14

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

Technik # 1

Laden Sie das Bild in den regulären Zustand des Elements und verschieben Sie es nur mit der Hintergrundposition. Verschieben Sie dann die Hintergrundposition, um sie beim Hover anzuzeigen.

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

Technik Nr. 2

Wenn auf das betreffende Element bereits ein Hintergrundbild angewendet wurde und Sie dieses Bild ändern müssen, funktioniert das oben Gesagte nicht. Normalerweise wählen Sie hier ein Sprite (ein kombiniertes Hintergrundbild) und verschieben einfach die Hintergrundposition. Aber wenn das nicht möglich ist, versuchen Sie es. Wenden Sie das Hintergrundbild auf ein anderes Seitenelement an, das bereits verwendet wird, aber kein Hintergrundbild hat.

#random-unsuspecting-element { background: url(images/grass.png) no-repeat -9999px -9999px; }
#grass:hover { background: url(images/grass.png) no-repeat; }
Fatih Hayrioğlu
quelle
4
Stellen Sie immer Inhalte externer Links bereit. Andernfalls ist Ihre Antwort wertlos, wenn der Link unterbrochen wird!
sra
@ Fatih +1 für sehr guten Link. Weitere aktuelle Version des verlinkten Artikel mit 3 verschiedene Möglichkeiten ist hier perishablepress.com/3-ways-preload-images-css-javascript-ajax
xmojmr
@xmojmr Ihr Link enthält keine Nur-CSS-Lösungen.
Max
10

versuche es damit:

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

Mit diesem Code laden Sie das Hintergrundbild vor und rendern das Formular beim Laden

mck89
quelle
mck89, danke das sieht ziemlich gut aus. Aber sollte ich diesen Code im 'Kopf' oder inline verwenden? Ich meine, muss ich es mit HTML füllen?
Erdnüsse
Sie müssen es im Kopf verwenden. Ich denke, dass Sie es in der $ (Dokument) .ready
mck89
6

Zum Vorladen von mit CSS festgelegten Hintergrundbildern war die effizienteste Antwort eine modifizierte Version eines Codes, den ich gefunden habe und der nicht funktionierte:

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

Der enorme Vorteil davon ist, dass Sie es nicht aktualisieren müssen, wenn Sie in Zukunft neue Hintergrundbilder einfügen. Es wird die neuen finden und sie vorladen!

Deminetix
quelle
Verstehe ich es richtig, dass Sie für jedes Bild ein verstecktes Element hinzufügen? Es ist nicht so, dass es Ihre CSS-Datei nach Bildern durchsuchen kann, oder? :)
bvdb
5

Wenn Sie diese Hintergrundbilder an einer anderen Stelle auf Ihrer Site für Formulareingaben wiederverwenden, möchten Sie wahrscheinlich ein Bildsprite verwenden. Auf diese Weise können Sie Ihre Bilder zentral verwalten (anstatt Bild1, Bild2, Bild3 usw. zu haben).

Sprites sind für den Client im Allgemeinen schneller, da sie nur eine (wenn auch etwas größere) Datei vom Server anfordern, anstatt mehrere Dateien. Weitere Vorteile finden Sie im SO-Artikel:

CSS-Bild-Sprites

Andererseits ist dies möglicherweise überhaupt nicht hilfreich, wenn Sie diese nur für ein Formular verwenden und sie wirklich nur laden möchten, wenn der Benutzer das Kontaktformular anfordert. Dies ist jedoch möglicherweise sinnvoll.

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

ajhit406
quelle
Ja, CSS Sprites sind der richtige Weg. Stellen Sie einfach sicher, dass eines der Bilder in diesem Sprite angezeigt wird, bevor das ausgeblendete Formular gestartet wird (wie beim Laden der Seite).
Steve
1

Wie wäre es, wenn Sie das Hintergrundbild an einem versteckten Ort laden? Auf diese Weise wird es beim Öffnen der Seite geladen und benötigt keine Zeit, sobald das Formular mit Ajax erstellt wurde:

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

Sie können dieses jQuery-Plugin waitForImage verwenden oder Ihre Bilder in ein verstecktes div oder (Breite: 0 und Höhe: 0) einfügen und das Onload-Ereignis für Bilder verwenden.

Wenn Sie nur 2-3 Bilder haben, können Sie Ereignisse binden und in einer Kette auslösen, sodass Sie nach jedem Bild Code ausführen können.

user1236048
quelle
1

Die einzige Möglichkeit besteht darin, das Image in Base64 zu codieren und im HTML-Code zu platzieren, sodass es nicht den Server kontaktieren muss, um das Image herunterzuladen.

Dadurch wird ein Bild aus der URL codiert, sodass Sie den Code der Bilddatei kopieren und wie folgt in Ihre Seite einfügen können ...

body {
  background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIA...);
}
mheager
quelle
2
Wenn Sie dasselbe Bild erneut in Ihrem CSS verwenden möchten, wird es nicht zwischengespeichert und muss erneut geladen werden.
vsync
1

Wenn es keine Möglichkeit gibt, CSS-Code zu ändern und Bilder mit CSS-Regeln für :beforeoder :afterPseudoelementen vorzuladen, kann ein anderer Ansatz mit JavaScript-Code verwendet werden, der CSS-Regeln geladener Stylesheets durchläuft. Damit es funktioniert, sollten Skripte nach Stylesheets in HTML eingefügt werden, z. B. vor dem Schließen von bodyTags oder direkt nach Stylesheets.

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
    });
});
ezze
quelle
0

Befinden sich die Seitenelemente und ihre Hintergrundbilder bereits im DOM (dh Sie erstellen / ändern sie nicht dynamisch), werden ihre Hintergrundbilder bereits geladen. An diesem Punkt möchten Sie vielleicht die Komprimierungsmethoden betrachten :)


quelle
mmmm ... guter Punkt cpharmston, und dies erklärt, warum das Problem auch bei zwischengespeicherten Bildern weiterhin besteht. Das heißt also, dass es keine Problemumgehung gibt?
Erdnüsse
Erstellen Sie kleinere Bilder! JPEGs lassen sich leicht komprimieren, es gibt Befehlszeilen-Tools zum Reduzieren der Größe von PNGs ( pmt.sourceforge.net/pngcrush ) und Sie können die Anzahl der Farben im Bild reduzieren, um die Größe von GIFs zu reduzieren. Natürlich können Sie auch für einen schnelleren Internet-Service