Imágenes en diseño responsive: El problema de max-width

En principio este venía a ser un artículo para solucionar el aparente problema con max-width cuando tratamos con imágenes en Firefox. Tras leer un montonazo de artículos y posts la conclusión es que no existe tal problema, al menos no al 100%. Suele funcionar bien, salvo cuanto tratamos con una tabla o definimos un div con display:table, este es el problema real, sin embargo hay montones de artículos pululando por la red que aseguran que max-width no funciona correctamente en Firefox. No es cierto, salvo al menos en los dos casos anteriores.

Así que como uno no es manco, voy a retomar el artículo desde otro punto. Vamos a ver como dar fluidez a las imágenes para un diseño responsive, y además abordaré el tema de max-width y sus problemas en Firefox dando una solución, que al menos a mi me funciona.

Lo primero de todo es tener claro que es un diseño responsive, que no es ni más ni menos que una evolución lógica del diseño líquido que se usaba hace algunos años, aunque mejorado con la incorporación de las media queries. En el diseño responsive trabajamos con medidas relativas, nada de medidas absolutas, y es ahí donde viene el problema con las imágenes, porque al fin y al cabo una imagen tiene unas medidas concretas.

La primera aproximación a una imagen fluida sería la siguiente:


img {
    width:100%;
}

Con esto conseguimos una imagen que se adapta al contenedor en el que se encuentra. Funciona muy bien si el contenedor es de igual o menor tamaño que la imagen, sin embargo cuando este es más grande la imagen se adapta a él y salvo que esta se un archivo SVG (gráficos vectoriales) se rompe, un efecto evidentemente nada deseable.

Por eso una de las reglas básicas para trabajar con imágenes en diseño responsive es usar la propiedad max-width, ya que nos fija el ancho máximo que tendrá el elemento sobre el que se aplique. Si por ejemplo tenemos una imagen de 400x250px, y aplicamos esta propiedad al 100%, como máximo la imagen tendrá el 100% de su ancho, osea 400px, con lo cual evitaremos que se rompa. Por contra si su contenedor es más pequeño, la imagen se adaptará a él y su ancho será el del propio contenedor. Para esta regla es aconsejable asignar el valor auto al alto de la imagen:


img {
   max-width:100%;
   height: auto;
}

Todo sería muy sencillo sino fuese por los bugs de algunos navegadores, en este caso no es IE como cabría esperar, sino Firefox, y es que el equipo de Mozilla lleva nada menos que desde el 2004 peleándose con la propiedad max-width, se han arreglado muchas cosas, pero su funcionamiento cuando tratamos con imágenes en tablas o con display:table no es el esperado.

La solución ha este problema, que puede no ser la más correcta, se me apareció, como suele ser habitual, de la forma más inesperada (podría haber sido una fórmula para acertar la primitiva, ¡pero no!). Los problemas con las imágenes comenzaron a producirse en este blog con la implantación del nuevo menú off-canvas, ya que para que el menú se adapte en alto al contenido usé la técnica para igualar columnas basada en diplay:table y display:table-cell, y ahí comenzaron las idas y venidas con Firefox.

Lo curioso es que la solución al problema sea usar las misma propiedad que lo causa para arreglarlo, sí has acertado display:table. De forma general las imágenes se suelen colocar desperdigadas por un post de una manera más o menos ordenada, en mi caso la cosa fue, por suerte, diferente. Para dar autoría a la foto uso un elemento figure, y dentro de él la imagen y un figcaption, de esta forma semánticamente la imagen y el elemento figcaption quedan directamente relacionados. El hecho de estar la imagen dentro de un contenedor padre de forma directa fue lo que me dio la idea al pensar en como funcionan las tablas, y por tanto los elementos con display:table.

Una tabla o un elemento definido con display:table, siempre que no se la asignen valores a width y height, se adapta a su contenido, ya que por defecto estos valores son auto. Eso sí, siempre y cuando le sea posible, ya que si su contenedor tiene un tamaño menor, entonces de adaptará a éste y no a su contenido. Con esta peculiar forma de comportamiento, conseguimos imitar el funcionamiento de max-width. Vemos un ejemplo y luego te explico:


<figure>
    <img src="#" alt="">
    <figcaption>texto asociado a la imagen</figcaption>
</figure>

figure {
    display:table;
}

img {
    width:100%;
    height:auto;
}

La imitación al comportamiento de max-width se consigue a causa de la imposibilidad de determinar el valor del tamaño de la imagen con un width del 100%, ya que el elemento figure toma su valor a partir del tamaño de la propia imagen, y la imagen a partir del tamaño de su contenedor y claro (la pescadilla que se muerde la cola) ¿cuál es el 100% de un valor indeterminado?. La cosa es, por contra, bien sencilla: figure toma el valor de su ancho en función al ancho de su contenido, como la imagen en este primer paso no tiene un valor aún definido, toma como valor su tamaño original, según el ejemplo que estamos usando 400x250px, así que el elemento figure tomará como ancho el valor de 400px. En el siguiente paso la imagen tomará el valor 100% de su contenedor, en este caso 400px, con lo que independientemente de donde esté contenido el elemento figure nunca sobrepasará el valor original de la imagen, evitando que esta se rompa.

Si el contenedor del elemento figure es menor que el tamaño original de la imagen, no hay problema, recuerda como funciona un elemento al que se le aplica la propiedad display:table. En este caso figure tomará el valor de su contenedor padre, y por tanto la imagen hará lo mismo, una perfecta imitación de la propiedad max-width.

Es una solución como otra cualquiera a un viejo problema, y no, no creo haber inventado la rueda (no tengo tanto ego), aunque por otra parte, nunca he visto esta forma de imitar la propiedad max-width y de paso solucionar el problemilla de Firefox con las imágenes en diseño responsive. Eso sí, nadie me puede quitar el cosquilleo que se siente al solucionar un problema sin mirar el examen del compañero de al lado :-).