MDN wants to learn about developers like you: https://qsurvey.mozilla.com/s3/MDN-Learn-Section-Survey

Esta traducción está incompleta. Por favor, ayuda a traducir este artículo del inglés.

En este artículo, aprenderemos sobre el concepto de las imágenes adaptables — imágenes que funcionan bien en dispositivos con una amplia diferencia de tamaño de pantallas, resoluciones y otras tantas características — y echar un vistazo  a las herramientas que HTML nos brinda para ayudar a implementarlas. Las imágenes adaptables son solo una parte de (y prepara el escenario para) diseño responsable web, un tema del que aprenderás mucho más en el futuro módulo de CSS topic.

Pre-requisitos: Deberías tener un conocimiento básico de HTML y cómo agregar imágenes estáticas a un sitio web.
 Objetivo:  Aprende a usar características como srcset y el elemento <picture> para implementar soluciones de imágenes adaptables a sitios web.

¿Por qué imágenes adaptables?

¿Qué problema estamos intentando solucionar con las imágenes adaptables? Vamos a examinar un escenario común. Una web normal, probablemente, tendrá una imagen de cabecera para hacerla más bonita a los visitantes. Además, seguramente, también tenga algunas imágenes como contenido debajo de la principal. Probablemente, querrás que la imagen de cabecera ocupe todo el ancho, y que las imágenes posteriores encajen perfectamente en las columnas. Echemos un vistazo a un ejemplo de lo que estamos hablando:

Our example site as viewed on a wide screen - here the first image works ok, as it is big enough to see the detail in the center.

Esto funciona bien en un dispositivo de pantalla ancha, tal como una computadora portatil o de escritorio (puedes  ver el ejemplo  y encontrar el  código fuente en Github.) No comentaremos mucho el CSS, excepto paralo siguiente:

  • El contenido del body se ha ajustado a un ancho máximo de 1200 píxeles - en viewports por encima de ese ancho, el cuerpo permanece a 1200px y se centra en el espacio disponible. En las viewports por debajo de ese ancho, el cuerpo permanecerá al 100% del ancho de la ventana.
  • La imagen de cabecera se ha configurado para que su centro siempre permanezca en el centro de la cabecera, no importa qué ancho sea el encabezado. Por lo tanto, si el sitio se visualiza en una pantalla más estrecha, aún se puede ver el detalle importante en el centro de la imagen (las personas) y el exceso se pierde en ambos lados. Tiene 200px de alto.
  • Las imágenes de contenido se han configurado de modo que si el cuerpo se vuelve más pequeño que la imagen, las imágenes comienzan a reducirse para que permanezcan siempre dentro del cuerpo, en lugar de desbordarlo.

Esto es correcto, pero el problema viene cuando empiezas a visitar la web en una pantalla más estrecha — la cabecera está bien, pero empieza a ocupar gran parte de la pantalla de un dispositivo móvil; la primera imagen de la parte del contenido, se ve fatal — ¡a ese tamaño apenas puedes ver a las personas que aparecen en la foto!

Our example site as viewed on a narrow screen; the first image has shrunk to the point where it is hard to make out the detail on it.

Sería mucho mejor mostrar una versión recortada de la imagen que contiene los detalles importantes del disparo cuando el sitio se visualiza en una pantalla estrecha, y tal vez algo entre los dos para un dispositivo de pantalla de ancho medio como una tableta: esto se conoce comúnmente como el problema de dirección de arte.

Además, no hay necesidad de incluir en la página imágenes de gran tamaño si será vista en la pequeña pantalla de un dispositivo móvil; esto es llamado el problema de cambio de resolución — una imagen de mapa de bits tiene un número definido de pixeles de ancho y un número definido de pixeles de alto; como vimos cuando tratamos gráficos vectoriales, una imagen de mapa de bits comienza a verse granulada y horrible si se muestra en un tamaño mayor al original (mientras que un gráfico vectorial no lo hace.) Y si es mostrada en un tamaño significantemente menor a su tamaño original, es un desperdicio de ancho de banda — especialmente los usuarios de dispositivos móviles no quieren gastar su ancho de banda descargando una imagen de gran tamaño que fue pensada para escritorio, cuando una imagen pequeña sería suficiente para su dispositivo. Una situación ideal sería tener múltiples resoluciones disponibles y servir tamaños apropiados dependiendo del dispositivo que está accediendo al sitio.

Para hacer las cosas más complicadas aún, algunos dispositivos tienen pantallas de alta resolución que necesitan imágenes más grandes de lo que imaginarías que necesitan, para que luzcan perfectas. Esto es, básicamente, el mismo problema, pero en un, levemente, diferente contexto.

Quizás pensarás que esto se soluciona usando imágenes vectorizadas, y hasta cierto punto es así — tienen un tamaño de archivo pequeño y buena escalabilidad, y deberías usarlas donde sea posible. De todas formas no son apropiadas para cualquier tipo de imagen — si bien son geniales para gráficas simples, patrones, elementos de interfaz, etc., se vuelve muy complicado crear una imagen basada en vectores con la cantidad de detalles que encontrarías, por ejemplo, en una foto. Formatos de imágenes de mapa de bits como JPEGs son más adecuados para el tipo de imágenes que vemos en el ejemplo superior.

Esta clase de problemas no existían al crearse la web al comienzo de los 90tas — en ese entonces el único dispositivo disponible para navegar eran los ordenadores de escritorio y laptops, por tanto los desarrolladores e ingenieros que programaban los navegadores ni siquiera pensaban en implementar estas soluciones. Las soluciones para imágenes Responsivas se implementaron recientemente para resolver los problemas descritos más arriba permitiéndote ofrecerle al navegador varias versiones de imágenes (en diferentes archivos), ya sea todas con el mismo contenido pero con distinto número de píxeles (resolución), o distintas imágenes apropiadas para distintas ubicaciones  en la página (dirección de arte).

Nota: Las nuevas características discutidas en este artículo — srcset/sizes/<picture> — son soportadas en las versiones disponibles de los navegadores modernos, tanto en móvil como en escritorio (incluyendo Edge de Microsoft, pero no Internet Explorer.) 

¿Cómo crear imágenes adaptables?

En esta sección, veremos los dos problemas mencionados anteriormente y pasaremos a mostrar como solucionarlos, usando las características de imágenes adaptables con HTML.  Es interesante destacar que nos centraremos en el HTML <img> para esta sección, tal como se muestra en el área de contenido del ejemplo que aparece arriba —  la imagen en la cabecera del sitio es solo de decoración, y por tanto se implementa usando imágenes de fondo con CSS. Se puede admitir que CSS posee mejores herramientas para realizar diseños adaptables que las que tiene HTML, y hablaremos sobre ellas en un futuro módulo de CSS.  

Cambio de resolución: Diferentes tamaños

Entonces, qué queremos solucionar con el cambio de resolución? Queremos mostrar la misma imágen, más grande o más pequeña dependiendo del dispositivo — Esta es la situación que mostramos en la segunda imágen de nuestro ejemplo. El elemento estandar <img> tradicionalmente solo admite apuntar a un archivo:

<img src="elva-fairy-800w.jpg" alt="Elva dressed as a fairy">

Sin embargo ahora podemos utilizar dos nuevos atributos — srcset y sizes — que proporciona rutas de imágenes adiccionales e indicaciones para mostrar al navegador cúal elegir. Puedes ver el ejemplo responsive.html en Github (revisa el código fuente):

<img srcset="elva-fairy-320w.jpg 320w,
             elva-fairy-480w.jpg 480w,
             elva-fairy-800w.jpg 800w"
     sizes="(max-width: 320px) 280px,
            (max-width: 480px) 440px,
            800px"
     src="elva-fairy-800w.jpg" alt="Elva dressed as a fairy">

Los atributos srcsetsizes parecen complicados, pero resultan más sencillos si los formateas como el ejemplo anterior, con un valor en cada linea. Cada valor contiene una lista separada por coma, y cada parte de la lista está compuesta por tres sub-partes. Repasemos ahora los contenidos de cada una:

srcset define un conjunto de imágenes entre las que le permitiremos al navegador elegir, y de que medida es cada una. Antes de cada coma, escribimos:

  1. El nombre de archivo de una imagen (elva-fairy-480w.jpg.)
  2. Un espacio.
  3. El ancho inherente de la imagen en pixeles (480w) — note que se usa la unidad w, no px como podría esperar. Esta es la medida real de la imagen, que puede ser hallada al inspeccionar el archivo de imagen en su computadora (por ejemplo en una Mac puede seleccionar la imagen en Finder y presionar Cmd + I para ver la pantalla de información.)

sizes define un conjunto de condiciones de medios (ej: anchos de pantalla) e indica que tamaño de imagen sería mejor elegir cuando se cumplen ciertas condiciones de medios  — estos son los indicios de los que hablabamos antes. En este caso, antes de cada coma escribimos

  1. una condición de medios  ((max-width:480px)) — aprenderá más sobre esto en el tópico CSS, pero por ahora basta decir que una condición de medios describe un posible estado en el que la pantalla puede encontrarse. En este caso, decimos "cuando el ancho del viewport es de 480 pixeles o menos".
  2. Un espacio.
  3. El ancho de la ranura que la imagen llenará cuando la condición de medios sea verdadera (440px.)

Note: Para el ancho de la ranura, debe indicar una longitud absoluta (px, em) o relativa (como un porcentaje.) Usted debe haber advertido que el ancho de la última ranura no tiene condición de medios — esta es la opción por defecto que se elige cuando ninguna de las condiciones de medios se cumplen.) El navegador ignora todo lo posterior a la primera condición coincidente, por eso sea cuidadoso con el orden de las condiciones de medios.

Entonces, con estos atributos establecidos, el navegador:

  1. Verificará el ancho del dispositivo.
  2. Resolverá qué condición de medios en la lista sizes es la primera que se cumple.
  3. Verificará la medida de la ranura dada a esa consulta de medios.
  4. Cargará la imagen referenciada en la lista srcset que más cercanamente coincida con la medida de la ranura.

¡Y eso es todo! Hasta este punto, si un navegador soportado con un ancho de viewport de 480px carga la página, la condición de medios (max-width: 480px) se cumplirá, por lo tanto la ranura de 440px será elegida y se cargará el archivo de imagen elva-fairy-480w.jpg, ya que el ancho inherente (480w) es el más cercano a 440px. La imagen de 800px tiene 128KB en disco mientras que la versión de 480px tiene solo 63KB — un ahorro de 65KB. Ahora imagine si esta fuera una página que tuviera muchas fotos. Usar esta técnica puede ahorrarle a los usuarios de dispositivos móviles mucho ancho de banda.

Navegadores más antiguos que no soportan estas características solo las ignorarán, y continuarán con la carga de la imagen referenciada en el atributo src como lo hacen habitualmente.

Note: En el <head> del documento usted hallará la línea <meta name="viewport" content="width=device-width">: esto fuerza a los dispositivos móviles a adoptar su ancho real de viewport para cargar las páginas web (algunos navegadores móviles enmascaran su ancho de viewport, y en su lugar cargan las páginas en un ancho de viewport mayor y luego las encogen, lo cual no es de mucha ayuda para las imágenes o el diseño adaptables. Le enseñaremos más sobre esto en un futuro módulo.)

Useful developer tools

There are some useful developer tools in browsers to help with working out the necessary slot widths, etc, that you need to use. When I was working them out, I first loaded up the non-responsive version of my example (not-responsive.html), then went into Responsive Design View (Tools > Web Developer > Responsive Design View), which allows you to look at your web page layouts as if they were being viewed through a variety of different device screen sizes.

I set the viewport width to 320px then 480px; for each one I went into the DOM Inspector, clicked on the <img> element we are interested in, then looked at its size in the Box Model view tab on the right hand side of the display. This should give you the inherent image widths you need.

A screenshot of the firefox devtools with an image element highlighted in the dom, showing its dimensions as 440 by 293 pixels.

Next, you can check whether the srcset is working by setting the viewport width to what you want (set it to a narrow width, for example), opening the Network Inspector (Tools > Web Developer > Network), then reloading the page. This should give you a list of the assets that were downloaded to make up the webpage, and here you can check which image file was chosen for download.

a screenshot of the network inspector in firefox devtools, showing that the HTML for the page has been downloaded, along with three images, which include the two 800 wide versions of the responsive images

Resolution switching: Same size, different resolutions

If you're supporting multiple display resolutions, but everyone sees your image at the same real-world size on the screen, you can allow the browser to choose an appropriate resolution image by using srcset with x-descriptors and without sizes — a somewhat easier syntax! You can find an example of what this looks like in srcset-resolutions.html (see also the source code):

<img srcset="elva-fairy-320w.jpg,
             elva-fairy-480w.jpg 1.5x,
             elva-fairy-640w.jpg 2x"
     src="elva-fairy-640w.jpg" alt="Elva dressed as a fairy">

A picture of a little girl dressed up as a fairy, with an old camera film effect applied to the imageIn this example, the following CSS is applied to the image so that it will have a width of 320 pixels on the screen (also called CSS pixels):

img {
  width: 320px;
}

In this case, sizes is not needed — the browser simply works out what resolution the display is that it is being shown on, and serves the most appropriate image referenced in the srcset. So if the device accessing the page has a standard/low resolution display, with one device pixel representing each CSS pixel, the elva-fairy-320w.jpg image will be loaded (the 1x is implied, so you don't need to include it.) If the device has a high resolution of two device pixels per CSS pixel or more, the elva-fairy-640w.jpg image will be loaded. The 640px image is 93KB, whereas the 320px image is only 39KB.

Art direction

To recap, the art direction problem involves wanting to change the image displayed to suit different image display sizes. For example, if a large landscape shot with a person in the middle is shown on a website when viewed on a desktop browser, then shrunk down when the website is viewed on a mobile browser, it will look bad as the person will be really tiny and hard to see. It would probably be better to show a smaller, portrait image on mobile, which shows the person zoomed in. The <picture> element allows us to implement just this kind of solution.

Returning to our original not-responsive.html example, we have an image that badly needs art direction:

<img src="elva-800w.jpg" alt="Chris standing up holding his daughter Elva">

Let's fix this, with <picture>! Like <video> and <audio>, The <picture> element is a wrapper containing several <source> elements that provide several different sources for the browser to choose between, followed by the all-important <img> element. The code in responsive.html looks like so:

<picture>
  <source media="(max-width: 799px)" srcset="elva-480w-close-portrait.jpg">
  <source media="(min-width: 800px)" srcset="elva-800w.jpg">
  <img src="elva-800w.jpg" alt="Chris standing up holding his daughter Elva">
</picture>
  • The <source> elements include a media attribute that contains a media condition — as with the first srcset example, these conditions are tests that decide which image is shown — the first one that returns true will be displayed. In this case, If the viewport width is 799px wide or less, the first <source> element's image will be displayed. If the viewport width is 800px or more, it'll be the second one.
  • The srcset attributes contain the path to the image to display. Note that just as we saw with <img> above, <source> can take a srcset attribute with multiple images referenced, and a sizes attribute too. So you could offer multiple images via a <picture> element, but then also offer multiple resolutions of each one too. Realistically, you probably won't want to do this kind of thing very often.
  • In all cases, you must provide an <img> element, with src and alt, right before </picture>, otherwise no images will appear. This provides a default case that will apply when none of the media conditions return true (you could actually remove the second <source> element in this example), and a fallback for browsers that don't support the <picture> element.

This code allows us to display a suitable image on both wide screen and narrow screen displays, as shown below:

Our example site as viewed on a wide screen - here the first image works ok, as it is big enough to see the detail in the center.Our example site as viewed on a narrow screen with the picture element used to switch the first image to a portrait close up of the detail, making it a lot more useful on a narrow screen

Note: You should use the media attribute only in art direction scenarios; when you do use media, don't also offer media conditions within the sizes attribute.

¿Por qué no podemos usar, simplemente, CSS o Javascript?

Cuando el navegador comienza a cargar una página, empieza a descargar (precargar) cualquier imagen before the main parser has started to load and interpret the page's CSS and JavaScript. This is a useful technique, which on average has shaved 20% off page load times. However, it is not helpful for responsive images, hence the need to implement solutions like srcset. You couldn't for example load the <img> element, then detect the viewport width with JavaScript and dynamically change the source image to a smaller one if desired. By then, the original image would already have been loaded, and you would load the small image as well, which is even worse in responsive image terms.

Use modern image formats boldly

There are several exciting new image formats (such as WebP and JPEG-2000) that can maintain a low file size and high quality at the same time. However, browser support is spotty.

<picture> lets us continue catering to older browsers. You can supply MIME types inside type attributes so the browser can immediately reject unsupported file types:

<picture>
  <source type="image/svg+xml" srcset="pyramid.svg">
  <source type="image/webp" srcset="pyramid.webp"> 
  <img src="pyramid.png" alt="regular pyramid built from four equilateral triangles">
</picture>
  • No uses el atributo media, unless you also need art direction.
  • En un elemento <source> , solo puedes enlazar a imágenes del tipo que has declarado en type.
  • Al igual que antes, puedes usar sin ningún problema listas separadas con comas tanto en srcset , como en sizes, así como lo necesites.

Aprendizaje activo: Implementando sus propias imágenes adaptables

For this active learning, we're expecting you to be brave and go it alone ... mostly. We want you to implement your own suitable art directed narrow screen/wide screen shot using <picture>, and a resolution switching example that uses srcset.

  1. Write some simple HTML to contain your code (use not-responsive.html as a starting point, if you like)
  2. Find a nice wide screen landscape image with some kind of detail contained in it somewhere. Create a web-sized version of it using a graphics editor, then crop it to show a smaller part that zooms in on the detail, and create a second image (about 480px wide is good for this.)
  3. Use the <picture> element to implement an art direction picture switcher!
  4. Create multiple image files of different sizes, each showing the same picture.
  5. Use srcset/size to create a resolution switcher example, either to serve the same size image at different resolutions, or different image sizes at different viewport widths.

Note: Use the browser devtools to help work out what sizes you need, as mentioned above.

Resúmen

That's a wrap for responsive images — we hope you enjoyed playing with these new techniques. As a recap, there are two distinct problems we've been discussing here:

  • Art direction: The problem whereby you want to serve cropped images for different layouts — for example a landscape image showing a full scene for a desktop layout, and a portrait image showing the main subject zoomed in close for a mobile layout. This can be solved using the <picture> element.
  • Resolution switching: The problem whereby you want to serve smaller image files to narrow screen devices, as they don't need huge images like desktop displays do — and also optionally that you want to serve different resolution images to high density/low density screens. This can be solved using vector graphics (SVG images), and the srcset and sizes attributes.

This also draws to a close the entire Multimedia and embedding module! The only thing to do now before moving on is to try our multimedia assessment, and see how you get on. Have fun.

Vea también

Etiquetas y colaboradores del documento

Última actualización por: kuntur-studio,