Recortar el centro de una imagen con CSS: object-fit y otra historia | Oloblogger Lo de recortar una imagen de forma genérica sin tener que usar JavaScript, siempre ha sido para mí u...

15 de abril de 2015

Recortar el centro de una imagen con CSS: object-fit y otra historia

Lo de recortar una imagen de forma genérica sin tener que usar JavaScript, siempre ha sido para mí un pequeño quebradero de cabeza.

En un principio podría ser tan fácil como definir una caja con un tamaño más pequeño que la imagen y añadirle un overflow:hidden para que lo que superara el tamaño de la caja no se viera. Pero obviando que a veces habrá imágenes más anchas que altas y otras al contrario, la primera traba la encontraremos en que si bien es fácil sacar esquinas con position, obtener justo el centro resulta complicado sin conocer a priori las medidas de la imagen.

Poner estas como fondo de la caja y luego usar background-position: 50% 50% empieza a resolver problemas, pero surgen otros nuevos por el hecho de tenerlas que incluir en el CSS en lugar del HTML... y esto último también pasa con el más moderno background-size que mejora en bastantes puntos al anterior.

Pero afortunadamente hay al menos un par de alternativas más sólo con CSS, que resultan bastante útiles. Vamos con ellas.

Recortes CSS

object-fit


El único inconveniente de esta propiedad es que actualmente es sólo una recomendación y su compatibilidad se limita a las versiones más modernas de los principales navegadores. Y tampoco de todos, salvo que IE no se considere un navegador, cosa que por otra parte algunos darán por hecho. Internet Explorer de momento no la soporta en ninguna de sus actualizaciones.

Básicamente lo que hace object-fit es adaptar el objeto (una imagen en este caso) al tamaño que determinemos. Lo hará siguiendo determinado patrón según los distintos valores que puede tomar: fill, none, contain, scale-down y cover.

No preguntéis mucho sobre esto porque sólo sé lo que se puede experimentar y ver a continuación y las explicaciones son una traducción libre de algunos documentos que leí en inglés. Para más info acudid a uno de los maestros del CSS.

Original (250x150px y 150x250px)





fill


img {width: 100px; height: 100px; object-fit: fill;}

Es el valor por defecto y ajustará la imagen a su contenedor rellenándolo totalmente y mostrando la imagen entera, por lo que la deformará si es necesario cambiando su proporción ancho/alto.



img {width: 280px; height: 280px; object-fit: fill;}



none


img {width: 100px; height: 100px; object-fit: none;}

La imagen ignorará la altura y ancho de su contenedor y conservará su tamaño original. Según el contenedor sea menor o mayor que la imagen, esto puede dar lugar a que la imagen parezca un recorte o en el segundo caso, que no lo rellene del todo en ninguna dimensión (nótese el fondo gris).



img {width: 280px; height: 280px; object-fit: none;}




contain


img {width: 100px; height: 100px; object-fit: contain;}

Se incrementa o disminuye el tamaño de la imagen sin cambiar sus proporciones, de manera que quepa completa en la caja por su dimensión mayor. Esto generará "huecos" en la dimensión más corta.



img {width: 280px; height: 280px; object-fit: contain;}




scale-down


img {width: 100px; height: 100px; object-fit: scale-down;}

Compara los diferentes resultados de usar none y contain para escoger de entre los dos aquel que tenga un menor tamaño, por lo que nunca saldrá una imagen de mayor tamaño que la original. En la práctica si el contenedor es menor que la imagen se producirá el mismo efecto que con contain y si el contenedor es mayor, entonces la salida será como la de none. Siempre respeta la proporción de la imagen original.



img {width: 280px; height: 280px; object-fit: scale-down;}



cover


img {width: 100px; height: 100px; object-fit: cover;}

La imagen rellenará tanto la altura como la anchura de su caja y al mismo tiempo mantiene sus proporciones, por lo que si el contenedor no tiene la misma proporción que el contenido, se producirá un recorte. La imagen se aumentará o disminuirá de tamaño según corresponda, por lo que con una imagen demasiado pequeña -como la del ejemplo- se generará un recorte con poca calidad (pixelado).



img {width: 280px; height: 280px; object-fit: cover;}




Este sería un pequeño resumen de los efectos de cada uno de los valores anteriores aplicados a object-fit.

.fillnonecontainscale-downcover
Mantiene proporciónNoSiSiSiSi
Imagen mayor que originalSiNoSiNoSi
Imagen menor que originalSiNoSiSiSi
RecorteNoSiNoNoSi

Como habréis podido comprobar, la mejor opción para esto de recortar automáticamente el centro de una imagen desconociendo inicialmente sus medidas, sería object-fit: cover (siempre usando una imagen de mayor calidad que las que yo usé para los ejemplos).


La otra historia


La otra forma de recortar imágenes mientras que lo anterior no sea válido para todos los navegadores, sería este curioso efecto que se produce al usar un posicionamiento absoluto de la imagen con todos sus valores ajustados a -100%, dentro de una caja con dimensión limitada. No puedo acreditar de quién es el invento porque lo he visto por multitud de sitios, lo que por otra parte me indica que no es nada nuevo.

Concretamente consistiría en tener disponible en nuestro CSS este par de reglas y luego simplemente insertar cada imagen a recortar dentro de un div con clase crop

Recorte de 100x100px


.crop {
position: relative;
width: 100px;
height: 100px;
overflow: hidden;
}
.crop img {
position: absolute;
top: -100%;
bottom: -100%;
left: -100%;
right: -100%;
margin: auto;
height: auto;
width: auto;
}

(*) En algunas ocasiones puede funcionar mejor un width: 100%; en lugar del width: auto; (ver comentario de Jaume)

<div class="crop">
<img src="http://lorempixel.com/250/150/sports/5" />
</div>

<div class="crop">
<img src="http://lorempixel.com/150/250/sports/4" />
</div>


Recorte de 280x280px


.crop {
position: relative;
width: 280px;
height: 280px;

overflow: hidden;
}
.crop img {
position: absolute;
...

Con este sistema, evidentemente, si usamos una imagen más pequeña (250x150 y 150x250) que el tamaño del recorte(280x280), al no producirse redimensionado esta se verá completa, de manera análoga a cuando antes usamos object-fit: none.


Pero si usamos otra lo suficientemente grande (500x300 y 300x500), sin problemas.



Y para practicar...

¿Vemos otro post al azar por si le encuentras utilidad o quizás prefieres ser más metódico y suscribirte a nuestras entradas por correo? También puedes imprimir este artículo y por supuesto compartirlo en redes sociales si fue de tu agrado.

Compartir
Copy URL

Y muchos más artículos interesantes si nos sigues en...

follow us in feedly

16 comentarios :

  1. Muy útil tu artículo. Este se va a los marcadores de cabeza :)
    Gracias!

    ResponderEliminar
  2. Como siempre buenos datos, un saludo

    ResponderEliminar
  3. Un quebradero de cabeza...sí que lo es. Yo he probado un montón de formas desde el navegador y me quedo con background-size:cover ...y aseguras soporte desde IE9.

    Saludos Oloman!

    ResponderEliminar
    Respuestas
    1. Te recomiendo que pruebes el truco del final, pues así te evitarás tener que meter las imágenes como fondo y las podrás usar con normalidad, dentro de la etiqueta IMG ;)

      Eliminar
  4. Hola Oloman,

    En la portada del blog http://panama2015.celadel.org, las fotos aparecen deformadas. ¿Cómo puedo solucionar el problema?. gracias

    ResponderEliminar
    Respuestas
    1. Simplemente usando imágenes algo más grandes en las entradas, pues de ahí se toman para la portada. Que sean de al menos 210x210px

      Eliminar
  5. disculpa que ponga esto en este tema, tal vez me puedas ayudar, quiero poner un indice o lista con imágenes de las entradas publicadas en mi blog te explico, ( en una pagina de mi blog poner el indice pero en ves de poner el nombre de la entrada o publicacion poner una imagen y al darle clic a la imagen te envie a la publicacion y asi seguir poniendo una imagen para cada publicacion ) aqui te dejo el link de un blog para que me entiendas mejor:
    dsants-subs.net

    ResponderEliminar
    Respuestas
    1. No sé exactamente qué quieres hacer Adriana, porque el enlace que me pusiste lo que hace es despistarme más. ¿Eso sería para la página de portada a modo de sumarios sólo con imágenes o realmente quieres un índice par una página estática pero en lugar de con los títulos de las entradas con una imagen?

      Eliminar
  6. Fíjate que tienes un error en el código del post:

    .crop {
    ...
    width: 280px;< height: 280px;
    ...


    ;)

    ResponderEliminar
  7. Hola de nuevo Oloman.
    Llevo un buen rato pegandome con este código y al fin lo he podido hacer funcionar. Lo comento por si a alguien mas le pasa.
    Estoy diseñando un blog para ina página que tengo hecha y en el listado de artículos muestro una introducción al artículo y una imágen que la ajustaba con el "object-fit: cover;" y quedaba genial porque fuera cual fuera el tamaño de la imagen se ajustaba sobrepasando los límites del contenedor y al entrar a leer la notícia la muestro ya con su tamaño... Quedaba genial con Chrome y Firefox claro porque al empezar a probar con Explorer las imagenes en la introducción pues se veían con el aspect ratio mal.
    Entonces me he puesto a aplicar la segunda solución que das. La de aplicar la clase ".crop" pero tal y como la has puesto no he conseguido que funcionara.
    He tenido que modificar el width así:

    .crop img {
    position: absolute;
    top: -100%;
    bottom: -100%;
    left: -100%;
    right: -100%;
    margin: auto;
    height: auto;
    width: auto;
    }


    .crop img {
    position: absolute;
    top: -100%;
    bottom: -100%;
    left: -100%;
    right: -100%;
    margin: auto;
    height: auto;
    width: 100%;
    }


    Con esto ya me ha funcionado muy bien.

    Tengo que decir que no uso blogger sino que lo estoy aplicando a un diseño mio. No se si tendrá algo que ver pero ahí dejo el dato.

    Gracias por el código tan útil :)

    Os dejo el enlace por si queréis ver el resultado: http://angloiberianlanguages.com/blog.php
    Si os da por mirar el código la clase ".crop" lo he pasado por a través de la id "#title-image".

    ResponderEliminar
    Respuestas
    1. No tiene nada que ver con Blogger. Las propiedades de CSS son válidas para cualquier plataforma.

      Lo que si puede ser es que por la estructura de tu página, falte o sobre por ejemplo algún POSITION o que algún ancho de caja no esté definido en el mismo sitio que en mi demo.

      He visto que en tu página, con width:auto; sí que se produce el recorte correctamente, pero sobre una imagen más grande de lo que lo haría con el 100%.

      Intuyo (no lo he comprobado) que también podría ser por la proporción de las imágenes que usas, que son cuadradas o casi más altas que anchas, mientras que tu recorte es claramente rectangular apaisado. Puede que en ese caso convenga lo que dices. Bueno, que convenga no, que es LO CORRECTO para el fin que persigues.

      Gracias de nuevo a tí por los apuntes Jaume.

      Eliminar
  8. Muchas gracias, excelente aporte

    ResponderEliminar
  9. No pude crear esa especie de cuadrícula/galería con imágenes en miniatura, ¿alguien puede ayudarme?

    ResponderEliminar
  10. Necesito algo como esto https://2.bp.blogspot.com/-dlFCDPzp06k/V3Bbrha6LzI/AAAAAAABXgE/ezioSvkHVVIRMhVraY6M9GOeuBUUmOltgCLcB/s1600/1.png Ayudaaa

    ResponderEliminar
    Respuestas
    1. Planet, eso que viste es la manera de crear un recorte en imágenes. Sólo tendrías que subirlas a una entrada y aplicar este código.

      Si quieres otra cosa más sencilla, prueba con esto.

      Eliminar