Dar forma a las imágenes

Una imagen ocupa un rectángulo, y el texto que la rodea respeta ese rectángulo. Las propiedades de este documento sirven para dos cosas distintas: decidir qué parte de la foto se ve y decidir por dónde pasa el texto. No son lo mismo y conviene no confundirlas.

object-fit: qué parte de la foto se ve

Cuando a una imagen se le fija un ancho y un alto que no coinciden con su proporción, hay que decidir qué hacer con la diferencia. Eso es object-fit.

fill
El valor por defecto. La foto se estira hasta ocupar la caja entera, y se deforma. Casi nunca es lo que se quiere.
cover
La foto se amplía conservando su proporción hasta cubrir la caja, y lo que sobra se recorta. No se deforma; se pierde un trozo.
contain
La foto entra entera, conservando su proporción, y quedan franjas vacías a los lados o arriba y abajo.

la misma foto y la misma caja, con los tres valores

<div class="tira">
  <figure>
    <img class="rellenar" src="IMG/retrato-rizado.jpg" alt="Retrato">
    <figcaption>fill</figcaption>
  </figure>
  <figure>
    <img class="cubrir" src="IMG/retrato-rizado.jpg" alt="Retrato">
    <figcaption>cover</figcaption>
  </figure>
  <figure>
    <img class="contener" src="IMG/retrato-rizado.jpg" alt="Retrato">
    <figcaption>contain</figcaption>
  </figure>
</div>

Hay una propiedad hermana, object-position, que decide qué parte se conserva al recortar. Por defecto es el centro, y en un retrato eso puede cortar la cabeza: object-position: top lo arregla.

aspect-ratio: la forma de la caja

En lugar de dar un alto en píxeles, se le da a la caja una proporción y el alto sale del ancho. Así la caja sigue siendo fluida.

Se escribe con dos números separados por una barra: 1 / 1 es cuadrada, 16 / 9 apaisada, 3 / 4 vertical.

tres proporciones, todas con cover

<div class="tira">
  <figure>
    <img class="cuadrada" src="IMG/naturaleza-abetos.jpg" alt="Bosque">
    <figcaption>1 / 1</figcaption>
  </figure>
  <figure>
    <img class="apaisada" src="IMG/naturaleza-abetos.jpg" alt="Bosque">
    <figcaption>16 / 9</figcaption>
  </figure>
  <figure>
    <img class="vertical" src="IMG/naturaleza-abetos.jpg" alt="Bosque">
    <figcaption>3 / 4</figcaption>
  </figure>
</div>

Estrecha la ventana: las tres encogen y conservan su forma. Ese es el motivo de usar aspect-ratio en vez de una altura escrita.

border-radius: redondear

Redondea las esquinas. Admite una medida para las cuatro, o cuatro medidas, y con 50% convierte un cuadrado en círculo y un rectángulo en elipse.

cuatro formas con la misma propiedad

<div class="tira">
  <figure>
    <img class="r1" src="IMG/retrato-contraluz.jpg" alt="Retrato">
    <figcaption>12px</figcaption>
  </figure>
  <figure>
    <img class="r2" src="IMG/retrato-contraluz.jpg" alt="Retrato">
    <figcaption>50%</figcaption>
  </figure>
  <figure>
    <img class="r3" src="IMG/retrato-contraluz.jpg" alt="Retrato">
    <figcaption>una esquina</figcaption>
  </figure>
  <figure>
    <img class="r4" src="IMG/retrato-contraluz.jpg" alt="Retrato">
    <figcaption>hoja</figcaption>
  </figure>
</div>

clip-path: recortar con una forma

border-radius solo redondea. clip-path recorta con la forma que se quiera: un círculo, un polígono de los lados que haga falta, una elipse.

circle(50%)
Un círculo. El valor es el radio; se le puede dar centro con circle(50% at 30% 40%).
ellipse(40% 50%)
Una elipse, con su radio horizontal y su radio vertical.
polygon(...)
Una lista de vértices, cada uno con su par de coordenadas. 0% 0% es la esquina de arriba a la izquierda y 100% 100% la de abajo a la derecha. El último se une con el primero.
inset(10% round 1rem)
Un rectángulo metido hacia dentro, con esquinas redondeadas si se quiere.

Lo que queda fuera del recorte no se dibuja, pero la caja sigue ocupando el mismo sitio. Para el resto de la página, la imagen sigue siendo un rectángulo. De eso se encarga la propiedad siguiente.

círculo, triángulo, rombo y una forma libre

<div class="tira">
  <figure>
    <img class="c1" src="IMG/ciudad-amanecer.jpg" alt="Ciudad">
    <figcaption>circle</figcaption>
  </figure>
  <figure>
    <img class="c2" src="IMG/ciudad-amanecer.jpg" alt="Ciudad">
    <figcaption>triángulo</figcaption>
  </figure>
  <figure>
    <img class="c3" src="IMG/ciudad-amanecer.jpg" alt="Ciudad">
    <figcaption>rombo</figcaption>
  </figure>
  <figure>
    <img class="c4" src="IMG/ciudad-amanecer.jpg" alt="Ciudad">
    <figcaption>libre</figcaption>
  </figure>
</div>

Escribir un polígono a mano resulta laborioso. Existen editores visuales que generan la declaración arrastrando los vértices; se localizan buscando «clip-path maker».

shape-outside: por dónde pasa el texto

Esta es la que de verdad cambia la maqueta. clip-path recorta lo que se ve; shape-outside dice por dónde tiene que pasar el texto de al lado.

Tiene dos condiciones, y las dos son obligatorias:

  1. El elemento tiene que llevar float: left o float: right. Sin float no hace absolutamente nada.
  2. El elemento tiene que tener un ancho y un alto declarados.

el texto rodea el círculo

<img class="redonda" src="IMG/bn-caballo.jpg" alt="Caballo">

<p>Una fotografía ocupa un rectángulo. Casi siempre eso basta, pero hay composiciones en las que el rectángulo estorba: un retrato en un listado de personas, una pieza que tiene que encajar con otras, un texto que debería acompañar a la imagen en vez de quedarse a su lado. CSS permite recortar la caja y, además, decirle al texto por dónde tiene que pasar.</p>

<p>El recorte no cambia el archivo ni el tamaño que ocupa la imagen en la página: solo decide qué parte de ella se dibuja. Lo que queda fuera sigue ahí, invisible, igual que el trozo de foto que se sale de un marco.</p>

Las dos propiedades llevan el mismo valor, y esa es la forma normal de usarlas: una recorta la imagen y la otra hace que el texto siga ese mismo contorno. Si solo se pone clip-path, la foto se ve redonda pero el texto sigue trazando un cuadrado alrededor.

Hay un ajuste útil, shape-margin, que separa el texto del contorno. El margin normal solo separa del rectángulo.

un polígono, con el texto siguiendo la diagonal

<img class="cuna" src="IMG/naturaleza-valle.jpg" alt="Valle">

<p>Una fotografía ocupa un rectángulo. Casi siempre eso basta, pero hay composiciones en las que el rectángulo estorba: un retrato en un listado de personas, una pieza que tiene que encajar con otras, un texto que debería acompañar a la imagen en vez de quedarse a su lado. CSS permite recortar la caja y, además, decirle al texto por dónde tiene que pasar.</p>

<p>El recorte no cambia el archivo ni el tamaño que ocupa la imagen en la página: solo decide qué parte de ella se dibuja. Lo que queda fuera sigue ahí, invisible, igual que el trozo de foto que se sale de un marco.</p>

mask-image: desvanecer

Las anteriores cortan en seco: un píxel se ve o no se ve. mask-image permite que la imagen se vaya desvaneciendo, porque usa una segunda imagen como plantilla de opacidad: donde la plantilla es opaca, la foto se ve; donde es transparente, desaparece; y donde hay medio tono, se ve a medias.

Lo habitual es usar un degradado como plantilla, que no es un archivo sino algo que CSS sabe dibujar.

desvanecido por abajo y en círculo

<div class="tira">
  <figure>
    <img class="m1" src="IMG/naturaleza-arroyo.jpg" alt="Arroyo">
    <figcaption>hacia abajo</figcaption>
  </figure>
  <figure>
    <img class="m2" src="IMG/naturaleza-arroyo.jpg" alt="Arroyo">
    <figcaption>en círculo</figcaption>
  </figure>
  <figure>
    <img class="m3" src="IMG/naturaleza-arroyo.jpg" alt="Arroyo">
    <figcaption>por los dos lados</figcaption>
  </figure>
</div>

El color del degradado es indiferente: solo cuenta su opacidad. Se declara black por convención.

En navegadores antiguos puede hacer falta repetir la declaración con el prefijo -webkit-mask-image.

Cuál usar

Lo que quieroLa propiedad
Que la foto llene una caja sin deformarse object-fit: cover
Que la caja tenga una forma fija y se adapte al ancho aspect-ratio
Esquinas redondeadas o un círculo border-radius
Cualquier otra forma clip-path
Que el texto rodee esa forma shape-outside con float
Que el borde se desvanezca en vez de cortarse mask-image

Resumen

  1. clip-path cambia lo que se ve; shape-outside cambia por dónde pasa el texto. Para que las dos cosas coincidan hay que escribirlas las dos, con el mismo valor.
  2. shape-outside sin float no hace nada.
  3. Recortar no cambia el sitio que ocupa la caja.
  4. Una foto recortada sigue teniendo su alt: la forma es decoración, el contenido es la foto.

Reconocimientos

Las fotos son de Pexels, con licencia libre: se pueden usar y modificar sin pagar y sin citar la fuente. Citarla no es obligatorio, pero es lo correcto, y aquí sirve además de ejemplo de cómo se hace.