Carga previa de imágenes CSS

118

Tengo un formulario de contacto oculto que se despliega haciendo clic en un botón. Sus campos se establecen como imágenes de fondo CSS, y siempre aparecen un poco más tarde que el div que se ha cambiado.

Estaba usando este fragmento en la <head>sección, pero sin suerte (después de borrar el caché):

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

Estoy usando jQuery como mi biblioteca, y sería genial si pudiera usarlo también para arreglar este problema.

Gracias por tus pensamientos.

Miseria
fuente
Por favor, muestre su código. ¿Cómo se alterna este formulario?
n1313
1
n1313, utilizo la forma más sencilla posible: $ ('# toggle'). click (function () {$ ('# contact'). slideToggle ();});
Peanuts

Respuestas:

257

Precargar imágenes usando solo CSS

En el siguiente código, elijo el bodyelemento al azar , ya que es uno de los únicos elementos que se garantiza que existe en la página.

Para que el "truco" funcione, usaremos la contentpropiedad que permite cómodamente configurar múltiples URL para cargar, pero como se muestra, el ::afterpseudo elemento se mantiene oculto para que las imágenes no se rendericen:

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
}

Manifestación


es mejor usar una imagen de sprite para reducir las solicitudes http ... (si hay muchas imágenes de tamaño relativamente pequeño) y asegurarse de que las imágenes estén alojadas donde se usa HTTP2 .

vsync
fuente
27
¡Esto es asombroso!
Hengjie
4
¡La mejor técnica hasta ahora por su simplicidad y enfoque CSS puro! El único inconveniente es que estas imágenes se cargan al mismo tiempo que el contenido inmediatamente visible y no se demoran hasta que se carga el contenido principal, lo que requeriría Javascript. Pero a menos que esté precargando docenas de imágenes, esto no debería ser un factor decisivo.
Benjamín
2
esto es fantástico para precargar activos flotantes para botones CSS y tal, de esa manera no obtendrá ningún parpadeo cuando sobrepase el botón mientras se cargan los activos
Robert Petz
16
Buena solución. Sin embargo, recomendaría no aplicar esto body, ya que estas imágenes se cargarán en cada página que haga referencia a la hoja de estilo. En su lugar, debe usar .contact_form:after {...}o alguna otra clase que sea menos global. A menos, por supuesto, que su formulario de contacto esté en cada página;)
CloudMagick
3
@vsync, eso tiene sentido, especialmente para gifs y pequeños reutilizables. La situación con la que me encontré recientemente fue para imágenes grandes de bg para un carrusel rico en contenido, y ciertamente no quería que esos archivos grandes se cargaran en todas partes :)
CloudMagick
30

Puedo confirmar que mi código original parece funcionar. Me estaba apegando casualmente a una imagen con un camino equivocado.

Aquí hay una prueba: 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>
Miseria
fuente
Después de algunas pruebas con CSS-ONLY y esta solución, en mi caso específicamente, esta es la mejor.
zequinha-bsb
Gracias, es el más fácil de todos :)
BetaCoder
4
La URL de la respuesta ya no es válida.
Brandon Buck
Hola, volví a subir el contenido en esa URL ( paragraphe.org/slidetoggletest/test.html ), lo siento por haberme perdido esto. Saludos,
Peanuts
25

Carga previa de imágenes con etiqueta HTML <link>

Creo que la mayoría de los visitantes de esta pregunta buscan la respuesta de "¿Cómo puedo precargar una imagen antes de que comience el procesamiento de la página?" y la mejor solución para este problema es usar la <link>etiqueta porque la <link>etiqueta es capaz de bloquear el procesamiento posterior de la página. Ver preventivo

Estas dos opciones de valor del atributo rel( relación entre el documento actual y el documento vinculado ) son las más relevantes con el problema:

  • prefetch : carga el recurso dado mientras se renderiza la página
  • precarga : carga el recurso dado antes de que comience la representación de la página

Entonces, si desea cargar un recurso ( en este caso es una imagen ) antes de que comience el proceso de representación de la <body>etiqueta, use:

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

y si desea cargar un recurso mientras se <body>está procesando, pero planea usarlo más adelante de forma dinámica y no quiere molestar al usuario con el tiempo de carga, use:

<link rel="prefetch" href="RESOURCE_URL">
mertyildiran
fuente
Vale la pena señalar que el motor del navegador de Mozilla solo se cargará prefetchcuando el navegador esté inactivo, lo cual está determinado por la nsIWebProgressListenerAPI. Vea esto para más información.
Matthew Beckman
1
No creo que esto realmente bloquee la representación: w3c.github.io/preload "Por ejemplo, la aplicación puede usar la palabra clave de precarga para iniciar la obtención temprana, de alta prioridad y sin bloqueo de representación de un recurso CSS que luego puede ser aplicado por la aplicación en el momento apropiado "
Michael Crenshaw
1
@MichaelCrenshaw es correcta, <link rel="preload">no no bloquear la representación, creo que el autor entiende mal la definición. Desde MDN Preloading content with rel = "preload" , "... que desea comenzar a cargar temprano en el ciclo de vida de la página, antes de que la maquinaria de renderización principal de los navegadores entre en funcionamiento". La idea es que los recursos se recuperen lo antes posible, por lo que es más probable que el recurso esté disponible cuando se necesite, por ejemplo, cuando se <img>está renderizando un elemento.
MDMower
14

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

Técnica # 1

Cargue la imagen en el estado regular del elemento, solo cámbiela con la posición de fondo. Luego, mueva la posición de fondo para mostrarlo al pasar el mouse.

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

Técnica # 2

Si el elemento en cuestión ya tiene una imagen de fondo aplicada y necesita cambiar esa imagen, lo anterior no funcionará. Por lo general, elegiría un objeto aquí (una imagen de fondo combinada) y simplemente cambiaría la posición del fondo. Pero si eso no es posible, intente esto. Aplique la imagen de fondo a otro elemento de la página que ya esté en uso, pero que no tenga una imagen de fondo.

#random-unsuspecting-element { background: url(images/grass.png) no-repeat -9999px -9999px; }
#grass:hover { background: url(images/grass.png) no-repeat; }
Fatih Hayrioğlu
fuente
4
Siempre proporcione contenido de enlaces externos. De lo contrario, su respuesta no tendrá ningún valor si se rompe el enlace.
sra
@Fatih +1 por muy buen enlace. La versión más actual del artículo vinculado con 3 formas diferentes está aquí perishablepress.com/3-ways-preload-images-css-javascript-ajax
xmojmr
@xmojmr No hay soluciones solo CSS en su enlace.
Max
10

prueba con esto:

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

Con este código, precargas la imagen de fondo y renderizas el formulario cuando está cargado

mck89
fuente
mck89, gracias, esto se ve bastante bien. Pero, ¿debería usar este código dentro del 'encabezado' o en línea? Quiero decir, ¿debo llenarlo con html?
Peanuts
Debes usarlo en la cabeza. Creo que puede usarlo dentro de $ (document) .ready
mck89
6

Para precargar imágenes de fondo configuradas con CSS, la respuesta más eficiente que se me ocurrió fue una versión modificada de un código que encontré que no funcionaba:

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

El gran beneficio de esto es que no necesita actualizarlo cuando traiga nuevas imágenes de fondo en el futuro, ¡encontrará las nuevas y las precargará!

Deminetix
fuente
¿Entiendo correctamente que agrega un elemento oculto para cada imagen? No es que pueda escanear su archivo CSS en busca de imágenes, ¿verdad? :)
bvdb
5

Si está reutilizando estas imágenes bg en cualquier otro lugar de su sitio para entradas de formulario, probablemente desee utilizar un objeto de imagen. De esa manera, puede administrar sus imágenes de forma centralizada (en lugar de tener pic1, pic2, pic3, etc ...).

Los sprites son generalmente más rápidos para el cliente, ya que solo solicitan un archivo (aunque un poco más grande) del servidor en lugar de varios archivos. Consulte el artículo SO para obtener más beneficios:

Sprites de imagen CSS

Por otra parte, esto podría no ser útil en absoluto si solo los está usando para un formulario y realmente solo desea cargarlos si el usuario solicita el formulario de contacto ... sin embargo, podría tener sentido.

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

ajhit406
fuente
Sí, CSS Sprites es el camino a seguir. Solo asegúrate de que una de las imágenes de ese objeto aparezca antes de que se inicie el formulario oculto (como al cargar la página).
Steve
1

¿Qué tal cargar esa imagen de fondo en algún lugar oculto? De esa manera, se cargará cuando se abra la página y no tomará ningún tiempo una vez que se cree el formulario usando ajax:

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

Puede usar este complemento de jQuery waitForImage o puede poner sus imágenes en un div oculto o (ancho: 0 y alto: 0) y usar el evento onload en las imágenes.

Si solo tiene como 2-3 imágenes, puede vincular eventos y activarlos en una cadena para que después de cada imagen pueda hacer algo de código.

user1236048
fuente
1

La única forma es codificar la imagen en Base64 y colocarla dentro del código HTML para que no necesite ponerse en contacto con el servidor para descargar la imagen.

Esto codificará una imagen de la URL para que pueda copiar el código del archivo de imagen e insertarlo en su página así ...

body {
  background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIA...);
}
mheager
fuente
2
si desea usar la misma imagen nuevamente en su CSS ... no se almacenará en caché y tendrá que cargarla nuevamente.
vsync
1

Cuando no hay forma de modificar el código CSS y precargar imágenes con reglas CSS :beforeo :afterpseudo elementos, se puede usar otro enfoque con código JavaScript que atraviesa las reglas CSS de las hojas de estilo cargadas. Para que funcione, los scripts deben incluirse después de las hojas de estilo en HTML, por ejemplo, antes de cerrar la bodyetiqueta o justo después de las hojas de estilo.

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

Si los elementos de la página y sus imágenes de fondo ya están en el DOM (es decir, no los está creando / cambiando dinámicamente), entonces sus imágenes de fondo ya estarán cargadas. En ese punto, es posible que desee ver los métodos de compresión :)


fuente
mmmm ... buen punto cpharmston, y esto explica por qué el problema persiste incluso con las imágenes almacenadas en caché. Entonces, ¿eso significa que no hay solución?
Peanuts
¡Crea imágenes más pequeñas! Los archivos JPEG se comprimen fácilmente, existen herramientas de línea de comandos para reducir el tamaño de los archivos PNG ( pmt.sourceforge.net/pngcrush ) y puede reducir el número de colores de la imagen para reducir el tamaño de los GIF. Por supuesto, también puede buscar un servicio de Internet más rápido;)