Néstor Domínguez

Ajustar imagen al tamaño del contenedor con object-fit

Cortando y centrando una imagen en CSS con object-fit

Publicado el

Desde la aparición de la propiedad background-size: cover en los navegadores de vanguardia en 2010, hemos estado aguardando una solución semejante para tratar las imágenes contenidas en etiquetas img. Hasta hace bien poco, todas las posibles soluciones presentaban algún problema: o bien requerían de JavaScript (lo que suponía introducir cierta parafernalia externa ajena a la hoja de estilos) o bien limitarse a funcionar bien en determinadas situaciones (por ejemplo, cuando las medidas del padre eran fijas). A día de hoy, sin embargo, gozamos de una herramienta potente que ronda por los navegadores desde hace unos años: las propiedades object-fit y object-position.

¿Cómo ajustar una imagen a su contenedor sólo con CSS?

Estas dos reglas de CSS existen en Chrome desde el año 2013 y desde entonces los demás navegadores lo han ido incorporando poco a poco: Opera y Safari en 2014 y Firefox en 2015. Faltaba Edge por introducirlo y finalmente la versión 16 soporta (limitado a imágenes pero no a vídeo) object-fit y object-position. Esto son muy buenas noticias pues nos asegura que esta función tan útil empieza a ser un sustituto a considerar para centrar imágenes en nuestros proyectos, dejando de lado aproximaciones más antiguas con considerables inconvenientes.

Entonces, ¿cómo se pueden utilizar a día de hoy estas reglas con seguridad? Dado que el soporte global supera ya el 90% y que en breve los usuarios de Edge adquirirán soporte para estas reglas, la clave está en utilizarlas sin miedo, pero acompañadas de un fallback que no reste utilidad al usuario. Para ello estamos casi forzados a utilizar la regla de CSS @supports, pues para que object-fit funcione, necesita que la imagen a escalar posea medidas fijas, aunque sean dadas en porcentaje. Esto significa que no podemos utilizar la propiedad height: auto; para ajustar la altura manteniendo la proporción. De este modo, si utilizásemos width: 100% height: 100%; y el navegador usado no soportase la regla object-fit, el resultado sería una imagen horrorosamente estirada a las proporciones del contenedor. Por esta razón, en el snippet que he desarrollado abajo, mantengo la imagen ajustada al ancho con la altura automática de manera genérica y tan sólo le doy altura 100% en el caso de que sepa con seguridad que la propiedad object-fit funciona en el actual navegador:

.box img{
  width: 100%;
  height: auto;
}
@supports(object-fit: cover){
    .box img{
      height: 100%;
      object-fit: cover;
      object-position: center center;
    }
}

Pros y contras en relación a los métodos anteriores

Empecemos por las ventajas más evidentes. Antes de existir esta regla, si no se quería utilizar JavaScript, había dos opciones: o bien cargar la imagen como imagen de fondo, o bien dar medidas fijas al padre. El primer caso no es muy recomendable si se desea que la imagen forme parte del contenido de la página web. La segunda, por su lado, tiene una limitación obvia: sólo funciona cuando el contenedor tiene una medida fija. Para evitar estas dos restricciones se suele utilizar JavaScript para reajustar con márgenes negativos o posicionamiento absoluto o relativo la imagen respecto a su padre, sin embargo este proceso es mucho más farragoso que la utilización de object-fit en una sencilla condición CSS. Además la solución para JS debe estar observando de manera continuada si el padre cambia de tamaño por alguna razón, para reajustar de nuevo el posicionamiento a la nueva medida del contenedor.

Pero evidentemente no todo en esta nueva solución es positivo. Hay un aspecto en el que método de JavaScript para ajustar la imagen es mejor: el soporte de los navegadores. Casi cualquier usuario, use el navegador que use, verá el ajuste con la solución que utiliza JS. En cambio, con la aproximación de object-fit, algunos usuarios con navegadores anticuados, verán simplemente la imagen ajustada a lo ancho, con un espacio restante por la parte inferior. Si para vuestro proyecto esto es algo tan insoportable, debéis optar por la solución de JavaScript, de lo contrario, mi recomendación es utilizar object-fit y object-position, ¡yo ya lo estoy usando en las imágenes de esta misma web, echad un vistazo a la home!