¿Incrustar datos de imágenes de fondo en CSS como Base64 es una buena o mala práctica?


475

Estaba mirando la fuente de un script de usuario de greasemonkey y noté lo siguiente en su CSS:

.even { background: #fff url(data:image/gif;base64,R0lGODlhBgASALMAAOfn5+rq6uvr6+zs7O7u7vHx8fPz8/b29vj4+P39/f///wAAAAAAAAAAAAAAAAAAACwAAAAABgASAAAIMAAVCBxIsKDBgwgTDkzAsKGAhxARSJx4oKJFAxgzFtjIkYDHjwNCigxAsiSAkygDAgA7) repeat-x bottom}

Puedo apreciar que un script de greasemonkey querría agrupar todo lo que pueda dentro de la fuente en lugar de alojarlo en un servidor, eso es bastante obvio. Pero como no había visto esta técnica anteriormente, consideré su uso y parece atractivo por varias razones:

  1. Reducirá la cantidad de solicitudes HTTP en la carga de la página, mejorando así el rendimiento
  2. Si no hay CDN, reducirá la cantidad de tráfico generado a través de las cookies que se envían junto con las imágenes
  3. Los archivos CSS se pueden almacenar en caché
  4. Los archivos CSS pueden ser GZIPPED

Teniendo en cuenta que IE6 (por ejemplo) tiene problemas con el caché para imágenes de fondo, parece que no es la peor idea ...

Entonces, ¿es una buena o mala práctica, por qué NO la usarías y qué herramientas usarías para codificar las imágenes en base64?

actualización: resultados de las pruebas

Agradable, pero supongo que será un poco menos útil para imágenes más pequeñas.

ACTUALIZACIÓN: Bryan McQuade, un ingeniero de software de Google, que trabaja en PageSpeed, expresó en ChromeDevSummit 2013 que los datos: uris en CSS se considera un antipatrón de bloqueo de renderizado para entregar CSS crítico / mínimo durante su charla #perfmatters: Instant mobile web apps. Consulta http://developer.chrome.com/devsummit/sessions y tenlo en cuenta: diapositiva real


¿Hace algunas pruebas? Sería interesante cuánto puede compensar la compresión el hecho de que la codifique en base64.
Dykam

publicado los resultados de la prueba, también disponible en mi blog fragged.org/…
Dimitar Christoff

55
Buena pregunta. Solo quería agregar que no funciona para IE7 y versiones inferiores. Pero hay algunas soluciones alternativas. Aquí hay un buen artículo al respecto jonraasch.com/blog/css-data-uris-in-all-browsers
MartinF

2
Agregar más PRO:límites de caché en dispositivos celulares ... CON:algunas imágenes deben tratarse como contenido en lugar de una simple presentación y, por lo tanto, se ajustan mejor a las etiquetas HTML IMG que a las imágenes de fondo CSS.
one.beat.consumer

1
@DimitarChristoff: He sido fanático de incrustar pequeños iconos con base64 debido a su relativa facilidad (cuando se compara con la agitación agresiva) y estaba feliz de aceptar el tamaño de arriba. Gracias por señalar que no siempre es así (es decir, la incrustación de base64 comprimida también puede ser mejor en términos de tamaño de activo absoluto)
ov

Respuestas:


166

No es una buena idea cuando desea que sus imágenes e información de estilo se almacenen en caché por separado. Además, si codifica una imagen grande o una cantidad significativa de imágenes en su archivo CSS, el navegador tardará más en descargar el archivo que sale de su sitio sin ninguna información de estilo hasta que se complete la descarga. Para imágenes pequeñas que no tiene la intención de cambiar a menudo, si alguna vez es una buena solución.

en cuanto a generar la codificación base64:


less tenía una función uri de datos que alineará
Luke Page

es una buena idea si desea tener una protección mínima para esas imágenes para que no * se almacenen en caché o se puedan descargar haciendo clic derecho -> guardar
vsync

"No es una buena idea cuando desea que las imágenes y la información de estilo se almacenen en caché por separado": no hay nada que le impida tener todas las imágenes en un archivo .css separado.
magritte

Mi práctica y pruebas no confirman su declaración. Lo siento.
TomeeNS

55

Esta respuesta está desactualizada y no debe usarse.

1) La latencia promedio es mucho más rápida en dispositivos móviles en 2017. https://opensignal.com/reports/2016/02/usa/state-of-the-mobile-network

2) multiplexes HTTP2 https://http2.github.io/faq/#why-is-http2-multiplexed

Los "URI de datos" definitivamente deberían considerarse para los sitios móviles. El acceso HTTP a través de redes celulares viene con una mayor latencia por solicitud / respuesta. Por lo tanto, hay algunos casos de uso en los que bloquear sus imágenes como datos en plantillas CSS o HTML podría ser beneficioso para las aplicaciones web móviles. Debería medir el uso caso por caso: no estoy abogando por que los URI de datos se usen en todas partes en una aplicación web móvil.

Tenga en cuenta que los navegadores móviles tienen limitaciones en el tamaño total de los archivos que se pueden almacenar en caché. Los límites para iOS 3.2 eran bastante bajos (25K por archivo), pero se están volviendo más grandes (100K) para las versiones más nuevas de Mobile Safari. Por lo tanto, asegúrese de controlar el tamaño total de su archivo al incluir los URI de datos.

http://www.yuiblog.com/blog/2010/06/28/mobile-browser-cache-limits/


23

Si hace referencia a esa imagen solo una vez, no veo ningún problema para incrustarla en su archivo CSS. Pero una vez que use más de una imagen o necesite hacer referencia a ella varias veces en su CSS, puede considerar usar un solo mapa de imagen en su lugar y luego puede recortar sus imágenes individuales (consulte CSS Sprites ).


16
Simplemente significa que debe tener una clase css en un elemento para hacer referencia a la imagen de fondo, y otra clase css para hacer referencia a los desplazamientos en esa imagen para usar para ese elemento.
Duncan Beevers

44
no debe tener clases sobre los elementos que describen cómo se presenta el material; esas clases deben estar bien nombradas y semánticas (esto no siempre es posible, pero es bueno tomar fotos) Si varios elementos usan la misma imagen, y le gustaría codifique esa imagen en el CSS, simplemente deje la imagen fuera de las declaraciones y use una regla css posterior para declarar e incrustar la imagen para múltiples selectores / clases.
Adam Tolley

1
Si está fotografiando para clases semánticas y también quiere los datos de la imagen solo una vez, puede tener un estilo separado que enumere todos los selectores relevantes y luego los desplazamientos definidos en estilos por selector. Por supuesto, para una imagen muy pequeña en muchos lugares, la lista de selección podría ser más grande que los datos ...
Leo

Para evitar varias clases y solo especificar una hoja de sprites una vez, puede usar un selector de atributos:[emoji] {background-image: url(data:image/png;base64,qwedfcsfrtgyu/=);} [emoji=happy] {background-position: -20px 0px;}
Chinoto Vokro

21

Una de las cosas que sugeriría es tener dos hojas de estilo separadas: una con sus definiciones de estilo regulares y otra que contenga sus imágenes en codificación base64.

Debe incluir la hoja de estilo base antes de la hoja de estilo de imagen, por supuesto.

De esta forma, se asegurará de que su hoja de estilo regular se descargue y aplique lo antes posible al documento, pero al mismo tiempo se beneficiará de la reducción de las solicitudes http y otros beneficios que le brindan los datos uris.


1
Me gusta esto en teoría. ¿Alguien puede pensar en algún argumento en contra?
Rob

Estaba buscando esto en Google para averiguar si es una buena idea y vine aquí. En mi caso, las imágenes son solo cosas de la interfaz de usuario y estaba pensando que sería una buena idea. No estoy seguro de si es mejor que usar sprites css, pero creo que es más fácil de administrar si realiza cambios en el futuro. Me encantaría saber si alguien tiene algo en contra de esto?
Craig

20

Base64 agrega aproximadamente un 10% al tamaño de la imagen después de GZipped, pero eso supera los beneficios cuando se trata de dispositivos móviles. Dado que existe una tendencia general con un diseño web receptivo, es muy recomendable.

W3C también recomienda este enfoque para dispositivos móviles y, si utiliza la canalización de activos en rieles, esta es una característica predeterminada al comprimir su CSS

http://www.w3.org/TR/mwabp/#bp-conserve-css-images


buen punto es móvil / receptivo, aunque no estoy seguro del 10%, ¿de dónde obtiene esos datos?
Dimitar Christoff

3
Esto es correcto. Lo más lento en cualquier dispositivo móvil es abrir / cerrar las conexiones http. Se recomienda minimizarlos.
Rafael Sanches

a pesar de los resultados de w3, en algunas pruebas hice que el tamaño de las imágenes aumentara en ~ 25% :(
Fabrizio Calderan

2
Supongo que puede aumentar hasta un 33% si es imposible comprimirlo.
Léon Pelletier

1
en el móvil 10% no es nada en comparación con la creación de conexiones http
Rafael Sanches

4

No estoy de acuerdo con la recomendación de crear archivos CSS separados para imágenes no editoriales.

Suponiendo que las imágenes son para fines de interfaz de usuario, es el estilo de la capa de presentación, y como se mencionó anteriormente, si está haciendo una interfaz de usuario móvil, definitivamente es una buena idea mantener todo el estilo en un solo archivo para que se pueda almacenar en caché una vez.


3

En mi caso, me permite aplicar una hoja de estilo CSS sin preocuparme por copiar imágenes asociadas, ya que ya están incrustadas en su interior.


3

Traté de crear un concepto en línea de la herramienta de análisis CSS / HTML:

http://www.motobit.com/util/base64/css-images-to-base64.asp

Puede:

  • Descargue y analice archivos HTML / CSS, extraiga elementos href / src / url
  • Detectar compresión (gzip) y datos de tamaño en la URL
  • Compare el tamaño de datos original, el tamaño de datos base64 y el tamaño de datos base64 comprimido.
  • Convierta la URL (imagen, fuente, css, ...) en un esquema de URI de datos base64.
  • Cuente el número de solicitudes que pueden ser ahorradas por los URI de datos

Comentarios / sugerencias son bienvenidos.

Antonin


3

Puedes codificarlo en PHP :)

<img src="data:image/gif;base64,<?php echo base64_encode(file_get_contents("feed-icon.gif")); ?>">

Or display in our dynamic CSS.php file:

background: url("data:image/gif;base64,<?php echo base64_encode(file_get_contents("feed-icon.gif")); ?>");

1 That’s sort of a “quick-n-dirty” technique but it works. Here is another encoding method using fopen() instead of file_get_contents():

<?php // convert image to dataURL
$img_source = "feed-icon.gif"; // image path/name
$img_binary = fread(fopen($img_source, "r"), filesize($img_source));
$img_string = base64_encode($img_binary);
?>

Fuente



0

Gracias por la información aquí. Considero que esta incrustación es útil y particularmente para dispositivos móviles, especialmente con el archivo css de las imágenes incrustadas en caché.

Para ayudar a hacer la vida más fácil, ya que mi (s) editor (es) de archivos no manejan esto de manera nativa, hice un par de scripts simples para el trabajo de edición de computadora portátil / escritorio, compartir aquí en caso de que sean de utilidad para alguien más. Me he quedado con php ya que está manejando estas cosas directamente y muy bien.

En Windows 8.1 diga ---

C:\Users\`your user name`\AppData\Roaming\Microsoft\Windows\SendTo

... allí, como administrador, puede establecer un acceso directo a un archivo por lotes en su ruta. Ese archivo por lotes llamará a un script php (cli).

Luego puede hacer clic con el botón derecho en una imagen en el explorador de archivos y Enviar al archivo por lotes.

Acepte la solicitud del Admiinstartor y espere a que se cierren las ventanas negras del shell de comandos.

Luego, simplemente pegue el resultado del portapapeles en su editor de texto ...

<img src="|">

o

 `background-image : url("|")` 

Los siguientes deben ser adaptables para otros sistemas operativos.

Archivo por lotes...

rem @echo 0ff
rem Puts 64 encoded version of a file on clipboard
php c:\utils\php\make64Encode.php %1

Y con php.exe en su camino, eso llama un script php (cli) ...

<?php 

function putClipboard($text){
 // Windows 8.1 workaround ...

  file_put_contents("output.txt", $text);

  exec("  clip < output.txt");

}


// somewhat based on http://perishablepress.com/php-encode-decode-data-urls/
// convert image to dataURL

$img_source = $argv[1]; // image path/name
$img_binary = fread(fopen($img_source, "r"), filesize($img_source));
$img_string = base64_encode($img_binary);

$finfo = finfo_open(FILEINFO_MIME_TYPE); 
$dataType = finfo_file($finfo, $img_source); 


$build = "data:" . $dataType . ";base64," . $img_string; 

putClipboard(trim($build));

?>

0

Por lo que he investigado,

Uso: 1. Cuando usa un sprite svg. 2. Cuando sus imágenes son de menor tamaño (máximo 200mb).

No utilice: 1. Cuando son imágenes más grandes. 2. Iconos como svg's. Como ya están bien y gzip después de la compresión.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.