Precaricamento delle immagini CSS


118

Ho un modulo di contatto nascosto che viene distribuito facendo clic su un pulsante. I suoi campi sono impostati come immagini di sfondo CSS e appaiono sempre un po 'più tardi rispetto ai div che sono stati attivati.

Stavo usando questo frammento nella <head>sezione, ma senza fortuna (dopo aver svuotato la cache):

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

Sto usando jQuery come libreria e sarebbe bello se potessi usarlo anche per organizzare questo problema.

Grazie per i tuoi pensieri.


Per favore, mostra il tuo codice. Come si attiva questo modulo?
n1313

1
n1313, io uso il modo più semplice possibile: $ ('# toggle'). click (function () {$ ('# contact'). slideToggle ();});
Peanuts

Risposte:


257

Precaricamento delle immagini utilizzando solo CSS

Nel codice seguente sto scegliendo a caso l' bodyelemento, poiché è uno degli unici elementi garantiti per l'esistenza nella pagina.

Affinché il "trucco" funzioni, useremo la contentproprietà che consente comodamente di caricare più URL, ma come mostrato, lo ::afterpseudo elemento viene tenuto nascosto in modo che le immagini non vengano visualizzate:

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
}

dimostrazione


è meglio usare un'immagine sprite per ridurre le richieste http ... (se ci sono molte immagini di dimensioni relativamente piccole) e assicurarsi che le immagini siano ospitate dove viene utilizzato HTTP2 .


27
Questo e spettacolare!
Hengjie

4
La migliore tecnica finora per la sua semplicità e il puro approccio CSS! L'unico inconveniente è che queste immagini vengono caricate contemporaneamente al contenuto immediatamente visibile e non ritardate fino a dopo il caricamento del contenuto principale, il che richiederebbe Javascript. Ma a meno che tu non stia precaricando dozzine di immagini, questo non dovrebbe essere un rompicapo.
Benjamin

2
questo è fantastico per precaricare le risorse al passaggio del mouse per i pulsanti CSS e simili - in questo modo non si ottiene alcun tremolio quando si passa sopra il pulsante mentre le risorse vengono caricate
Robert Petz

16
Buona soluzione. Consiglierei di non applicarlo a body, tuttavia, poiché queste immagini verranno caricate su ogni pagina che fa riferimento al foglio di stile. Invece, dovresti usare .contact_form:after {...}o qualche altra classe meno globale. A meno che, ovviamente, il tuo modulo di contatto sia su ogni pagina;)
CloudMagick

3
@vsync, che ha senso, soprattutto per gif e piccoli riutilizzabili. La situazione in cui mi sono imbattuto di recente era per immagini bg di grandi dimensioni per un carosello ricco di contenuti, e di certo non volevo che quei file di grandi dimensioni
venissero

30

Posso confermare che il mio codice originale sembra funzionare. Mi sono attaccato casualmente a un'immagine con un percorso sbagliato.

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

Dopo alcuni test con CSS-ONLY e questa soluzione, nel mio caso in particolare, questa è la migliore.
zequinha-bsb

Grazie è il più semplice di tutti :)
BetaCoder

4
L'URL nella risposta non è più valido.
Brandon Buck

Salve, ho ricaricato i contenuti su quell'URL ( paragrafophe.org/slidetoggletest/test.html ), mi dispiace di essermi perso. Saluti,
Peanuts

25

Precaricamento delle immagini utilizzando il tag HTML <link>

Credo che la maggior parte dei visitatori di questa domanda stia cercando la risposta di "Come posso precaricare un'immagine prima che inizi il rendering della pagina?" e la migliore soluzione per questo problema è usare il <link>tag perché il <link>tag è in grado di bloccare l'ulteriore rendering della pagina. Vedi preventivo

Queste due opzioni di valore dell'attributo rel( relazione tra il documento corrente e il documento collegato ) sono le più rilevanti per il problema:

  • prefetch : carica la risorsa data durante il rendering della pagina
  • preload : carica la risorsa data prima che inizi il rendering della pagina

Quindi, se vuoi caricare una risorsa ( in questo caso è un'immagine ) prima che <body>inizi il processo di rendering del tag, usa:

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

e se desideri caricare una risorsa durante il <body>rendering ma prevedi di utilizzarla in un secondo momento in modo dinamico e non vuoi disturbare l'utente con il tempo di caricamento, usa:

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

Vale la pena notare che il motore del browser Mozilla verrà caricato solo prefetchquando il browser è inattivo, il che è determinato nsIWebProgressListenerdall'API. Vedi questo per maggiori informazioni.
Matthew Beckman

1
Non credo che questo blocchi effettivamente il rendering: w3c.github.io/preload "Ad esempio, l'applicazione può utilizzare la parola chiave preload per avviare il recupero anticipato, ad alta priorità e senza blocco del rendering di una risorsa CSS che può quindi essere applicato dall'applicazione al momento opportuno "
Michael Crenshaw

1
@MichaelCrenshaw è corretto, <link rel="preload">non senza bloccare il rendering, credo che l'autore frainteso la definizione. Da MDN Preloading content with rel = "preload" , "... che vuoi iniziare a caricare all'inizio del ciclo di vita della pagina, prima che si attivi il meccanismo di rendering principale dei browser." L'idea è che le risorse vengano recuperate il prima possibile, rendendo più probabile che la risorsa sia disponibile quando necessario, ad esempio durante il <img>rendering di un elemento.
MDMower

14

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

Tecnica n. 1

Carica l'immagine nello stato normale dell'elemento, spostala solo con la posizione dello sfondo. Quindi sposta la posizione dello sfondo per visualizzarlo al passaggio del mouse.

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

Tecnica n. 2

Se l'elemento in questione ha già un'immagine di sfondo applicata e devi cambiare quell'immagine, quanto sopra non funzionerà. In genere scegli uno sprite qui (un'immagine di sfondo combinata) e sposti semplicemente la posizione dello sfondo. Ma se non è possibile, prova questo. Applica l'immagine di sfondo a un altro elemento della pagina che è già in uso, ma non ha un'immagine di sfondo.

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

4
Fornisci sempre contenuti di link esterni. Altrimenti la tua risposta è inutile se il collegamento si interrompe!
sra

@ Fatih +1 per un ottimo collegamento. La versione più recente dell'articolo collegato con 3 modi diversi è qui perishablepress.com/3-ways-preload-images-css-javascript-ajax
xmojmr

@xmojmr Non ci sono soluzioni solo CSS nel tuo link.
Max

10

prova con questo:

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

Con questo codice precarichi l'immagine di sfondo ed esegui il rendering del modulo quando viene caricato


mck89, grazie sembra abbastanza buono. Ma dovrei usare questo codice all'interno di "head" o inline? Voglio dire, devo riempirlo con html?
Peanuts

Devi usarlo nella testa. Penso che tu possa usarlo all'interno di $ (document) .ready
mck89

6

Per il precaricamento delle immagini di sfondo impostate con CSS, la risposta più efficiente che ho trovato è stata una versione modificata di un codice che ho scoperto che non funzionava:

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

Il grande vantaggio di questo è che non è necessario aggiornarlo quando si introducono nuove immagini di sfondo in futuro, troverà quelle nuove e le precaricherà!


Ho capito bene che aggiungi un elemento nascosto per ogni immagine? Non è che è in grado di scansionare il tuo file CSS per le immagini, giusto? :)
bvdb

5

Se stai riutilizzando queste immagini bg in qualsiasi altra parte del tuo sito per gli input del modulo, probabilmente vorrai usare un'immagine sprite. In questo modo puoi gestire centralmente le tue immagini (invece di avere pic1, pic2, pic3, ecc ...).

Gli sprite sono generalmente più veloci per il client, poiché richiedono solo un file (anche se leggermente più grande) dal server anziché più file. Vedere l'articolo SO per ulteriori vantaggi:

Sprite di immagini CSS

Inoltre, questo potrebbe non essere affatto utile se li stai usando solo per un modulo e vuoi davvero caricarli solo se l'utente richiede il modulo di contatto ... potrebbe avere senso però.

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


Sì, i CSS Sprites sono la strada da percorrere. Assicurati solo che una delle immagini in quello sprite appaia prima che il modulo nascosto venga lanciato (come al caricamento della pagina).
Steve

1

che ne dici di caricare quell'immagine di sfondo da qualche parte nascosta. In questo modo verrà caricato all'apertura della pagina e non impiegherà tempo una volta creato il modulo utilizzando ajax:

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

1

Potresti usare questo plugin jQuery waitForImage o potresti mettere le tue immagini in un div nascosto o (larghezza: 0 e altezza: 0) e usare l'evento onload sulle immagini.

Se hai solo 2-3 immagini puoi associare eventi e attivarli in una catena, quindi dopo ogni immagine puoi fare del codice.


1

L'unico modo è codificare in Base64 l'immagine e inserirla nel codice HTML in modo che non sia necessario contattare il server per scaricare l'immagine.

Questo codificherà un'immagine dall'URL in modo da poter copiare il codice del file immagine e inserirlo nella tua pagina in questo modo ...

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

2
se desideri utilizzare di nuovo la stessa immagine nel tuo CSS ... non verrà memorizzata nella cache e dovrai caricarla di nuovo.
vsync

1

Quando non è possibile modificare il codice CSS e precaricare le immagini con regole CSS :beforeo :afterpseudo elementi, è possibile utilizzare un altro approccio con codice JavaScript che attraversa le regole CSS dei fogli di stile caricati. Per farlo funzionare gli script dovrebbero essere inclusi dopo i fogli di stile in HTML, ad esempio, prima di chiudere il bodytag o subito dopo i fogli di stile.

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

Se gli elementi della pagina e le loro immagini di sfondo sono già nel DOM (cioè non li stai creando / modificando dinamicamente), le loro immagini di sfondo saranno già caricate. A quel punto, potresti voler esaminare i metodi di compressione :)


mmmm ... buon punto cpharmston, e questo spiega perché il problema persiste anche con le immagini memorizzate nella cache. Quindi, questo significa che non ci sono suoni di lavoro?
Peanuts

Crea immagini più piccole! I JPEG sono facilmente compressi, ci sono strumenti a riga di comando per ridurre le dimensioni dei PNG ( pmt.sourceforge.net/pngcrush ) e puoi ridurre il numero di colori nell'immagine per ridurre la dimensione delle GIF. Ovviamente, puoi anche
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.