Saltar al contenido
imagenes-css.css · devschool

Imágenes en CSS

Lección 15 de 25 · 10 min de lectura · Actualizado el

En esta lección
  1. La base: imágenes que no se salen
  2. object-fit: encajar sin deformar
  3. aspect-ratio: la proporción de la caja
  4. Filtros: filter
  5. Mezclas y recortes
  6. Imagen de fondo o <img>: cuándo usar cada una
  7. Ejemplo completo: galería de miniaturas
  8. Errores frecuentes
  9. Resumen

Las imágenes suelen ser lo que más pesa y lo que más se “rompe” en una web: se salen de su caja, se deforman, dejan huecos raros. En esta lección aprenderás a hacer que se adapten al espacio disponible, a recortarlas sin deformarlas, a reservar su hueco con aspect-ratio y a aplicarles filtros y formas. Terminarás montando una galería de miniaturas.

Lo que toca al HTML (el atributo alt, srcset, <picture>, la carga diferida) está en las lecciones de imágenes e imágenes responsive del curso de HTML.

La base: imágenes que no se salen

Por defecto, una imagen se muestra a su tamaño real. Si mide 2000 px y el móvil 400 px, se sale de la pantalla y aparece scroll horizontal. La solución es esta regla, que casi todos los proyectos incluyen al principio:

img {
  max-width: 100%;   /* nunca más ancha que su contenedor */
  height: auto;      /* el alto se ajusta para no deformar */
  display: block;    /* quita el hueco de debajo */
}

Por qué max-width y no width

  • width: 100% estira la imagen hasta ocupar todo el ancho, aunque sea un icono de 32 px. Queda pixelada.
  • max-width: 100% solo la encoge si no cabe. Si es pequeña, se queda a su tamaño.

Por qué height: auto

Si en el HTML pusiste width="800" height="600" (y deberías, porque ayuda al navegador a reservar espacio), al encoger la imagen con CSS el alto seguiría siendo 600 px y la foto se aplastaría. height: auto recalcula el alto manteniendo la proporción.

Por qué display: block

<img> es un elemento en línea, como una letra. Se coloca sobre la línea base del texto y deja debajo un hueco de unos pocos píxeles reservado para las letras que bajan (como la “g” o la “p”). Ese hueco misterioso bajo las fotos desaparece al hacerla de bloque. Tienes más sobre esto en display.

object-fit: encajar sin deformar

Cuando fuerzas un ancho y un alto que no respetan la proporción original, la imagen se deforma:

.miniatura {
  width: 200px;
  height: 200px;   /* la foto era apaisada: ahora sale aplastada */
}

object-fit decide cómo se encaja la imagen dentro de esa caja, igual que background-size con los fondos:

.miniatura {
  width: 200px;
  height: 200px;
  object-fit: cover;
}
ValorQué hace
fillEstira la imagen hasta llenar la caja. Deforma (por defecto)
coverLlena la caja manteniendo la proporción. Recorta lo que sobra
containMuestra la imagen entera. Puede dejar bandas vacías
noneTamaño original, recortado por la caja
scale-downComo none o contain, el que dé la imagen más pequeña

cover es el que usarás el 90 % de las veces: avatares, tarjetas de producto, miniaturas. contain va mejor con logos, donde recortar sería un desastre.

object-position: qué parte se ve

Con cover se recorta algo. Por defecto, el centro. Si lo importante está arriba (una cara, por ejemplo), muévelo:

.avatar {
  width: 80px;
  height: 80px;
  border-radius: 50%;
  object-fit: cover;
  object-position: center top;   /* o 50% 20% */
}

Funciona igual que background-position: palabras (top, left…) o porcentajes.

aspect-ratio: la proporción de la caja

aspect-ratio fija la relación entre ancho y alto. Tú das el ancho y el navegador calcula el alto:

.video      { aspect-ratio: 16 / 9; width: 100%; }
.miniatura  { aspect-ratio: 1; }        /* cuadrada: equivale a 1 / 1 */
.retrato    { aspect-ratio: 3 / 4; }

Combinado con object-fit, es la forma moderna de conseguir imágenes todas iguales aunque las fotos originales tengan tamaños distintos:

.producto img {
  width: 100%;
  aspect-ratio: 4 / 3;
  object-fit: cover;
}

Cada tarjeta de la tienda tendrá una foto de 4:3, venga como venga el archivo.

aspect-ratio sirve para cualquier caja, no solo imágenes: un <iframe> de YouTube, un mapa, un <div> con fondo. Antes se usaba un truco con padding-top: 56.25%; ya no hace falta.

Consejo: poner width y height en la etiqueta <img> hace que el navegador calcule solo el aspect-ratio y reserve el hueco antes de que llegue la imagen. Así el texto no “salta” al cargar la página.

Filtros: filter

filter aplica efectos de edición de fotos directamente desde CSS. La imagen original no cambia; el navegador la retoca al pintarla.

.gris        { filter: grayscale(1); }         /* blanco y negro: 0 a 1 */
.borrosa     { filter: blur(4px); }            /* desenfoque */
.clara       { filter: brightness(1.2); }      /* 1 = normal, más = más brillo */
.contraste   { filter: contrast(1.3); }
.sepia       { filter: sepia(0.8); }
.saturada    { filter: saturate(1.5); }
.negativo    { filter: invert(1); }
.tono        { filter: hue-rotate(90deg); }    /* gira los colores */

Puedes encadenar varios, separados por espacios:

.antigua { filter: sepia(0.6) contrast(1.1) brightness(0.95); }

Efecto al pasar el ratón

Un uso clásico: fotos del equipo en gris que recuperan el color al pasar por encima.

.equipo img {
  filter: grayscale(1);
  transition: filter 0.3s;
}
.equipo img:hover {
  filter: grayscale(0);
}

La transición se explica en transiciones y animaciones.

drop-shadow: sombra con la forma real

box-shadow siempre dibuja una sombra rectangular (o con la forma del border-radius). Si tienes un PNG o un SVG con transparencia, como un logo, drop-shadow sigue el contorno real del dibujo:

.logo {
  filter: drop-shadow(0 4px 6px rgb(0 0 0 / 0.3));
}

Sus valores son los de box-shadow, pero sin expansión ni inset.

Cuidado: blur() y drop-shadow() sobre imágenes grandes o muchos elementos cuestan rendimiento, sobre todo si se animan. Úsalos con mesura.

Mezclas y recortes

mix-blend-mode en pocas palabras

Decide cómo se mezclan los colores de un elemento con lo que tiene detrás, como los modos de capa de un programa de edición:

.titulo-sobre-foto {
  color: white;
  mix-blend-mode: difference;   /* invierte según el fondo */
}
.logo-con-fondo-blanco {
  mix-blend-mode: multiply;     /* el blanco desaparece sobre fondos claros */
}

multiply es el más práctico: hace que el fondo blanco de un logo en JPG se “funda” con un fondo de color claro. Para fondos múltiples existe también background-blend-mode.

clip-path: recortar con formas

clip-path recorta el elemento con una forma. Lo que queda fuera no se ve (ni recibe clics):

.circulo  { clip-path: circle(50%); }
.elipse   { clip-path: ellipse(50% 35%); }
.rombo    { clip-path: polygon(50% 0, 100% 50%, 50% 100%, 0 50%); }
.diagonal { clip-path: polygon(0 0, 100% 0, 100% 85%, 0 100%); } /* cabecera con corte inclinado */

En polygon() das los puntos de la forma como pares x y, en porcentajes del elemento, empezando arriba a la izquierda. Para formas sencillas como un círculo es más fácil border-radius: 50%; clip-path brilla con polígonos y cortes diagonales.

Imagen de fondo o <img>: cuándo usar cada una

Ya viste las imágenes de fondo en fondos, bordes y sombras. La pregunta clave es: ¿la imagen es contenido o decoración?

<img> en el HTMLbackground-image en el CSS
Qué esContenido: aporta informaciónDecoración
Texto alternativoSí, con altNo: los lectores de pantalla la ignoran
La indexa Google ImágenesSíNormalmente no
Carga diferidaloading="lazy"No de forma nativa
Imágenes según pantallasrcset y <picture>Media queries o image-set()
Recorteobject-fitbackground-size
EjemplosFoto de un producto, gráfico, foto de una noticiaTextura, portada decorativa detrás de un titular

Regla práctica: si al quitar la imagen se pierde información, va en <img>. Si solo se pierde “ambiente”, puede ir de fondo.

Ejemplo completo: galería de miniaturas

Juntamos todo: una rejilla que se adapta al ancho, miniaturas cuadradas sin deformar y un efecto al pasar el ratón.

<ul class="galeria">
  <li><a href="img/sala-1.jpg"><img src="img/sala-1-mini.jpg" alt="Sala de musculación" width="400" height="300"></a></li>
  <li><a href="img/sala-2.jpg"><img src="img/sala-2-mini.jpg" alt="Sala de spinning" width="400" height="300"></a></li>
  <li><a href="img/piscina.jpg"><img src="img/piscina-mini.jpg" alt="Piscina climatizada" width="400" height="600"></a></li>
</ul>
.galeria {
  list-style: none;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
  gap: 12px;
}

.galeria img {
  display: block;
  width: 100%;
  aspect-ratio: 1;
  object-fit: cover;
  border-radius: 8px;
  transition: transform 0.3s, filter 0.3s;
}

.galeria a:hover img,
.galeria a:focus-visible img {
  transform: scale(1.03);
  filter: brightness(1.1);
}

Fíjate en tres detalles:

  1. La foto de la piscina es vertical (400 x 600), pero aspect-ratio: 1 y object-fit: cover la dejan cuadrada como las demás.
  2. repeat(auto-fill, minmax(150px, 1fr)) crea tantas columnas como quepan, sin media queries. Lo tienes explicado en Grid.
  3. El efecto también se activa con :focus-visible, para quien navega con el teclado.

Errores frecuentes

  • Poner width y height fijos sin object-fit. La imagen se deforma. Añade object-fit: cover.
  • Usar width: 100% en todas las imágenes. Los iconos pequeños se estiran y pixelan. Usa max-width: 100%.
  • Olvidar height: auto cuando el HTML tiene height. La foto se aplasta al encogerse.
  • El hueco de unos píxeles bajo la imagen. Es por ser en línea: display: block lo elimina.
  • Poner fotos importantes como fondo. Se pierde el alt y la accesibilidad.
  • Confundir object-fit con background-size. El primero es para <img> y <video>; el segundo, para fondos.
  • Recortar con object-fit: cover y cortar la parte importante. Ajusta object-position.
  • Animar blur() en muchas imágenes. Va lento en móviles modestos.

Resumen

PropiedadPara qué sirveEjemplo
max-width: 100%Que la imagen no se salgaEn la regla base de img
height: autoMantener la proporciónJunto a max-width
display: blockQuitar el hueco inferiorEn la regla base de img
object-fitEncajar sin deformarcover, contain
object-positionQué parte se ve al recortarcenter top
aspect-ratioProporción de la caja16 / 9, 1
filterEfectos de color y desenfoquegrayscale(1) blur(2px)
drop-shadow()Sombra con la forma realLogos PNG o SVG
mix-blend-modeMezclar con lo de detrásmultiply
clip-pathRecortar con una formapolygon(...), circle(50%)

Con las imágenes bajo control, el siguiente paso es dar estilo a otros elementos muy comunes: listas y tablas.

Pruébalo tú

Cambia el código y pulsa Ejecutar (o Ctrl + Enter).

imagenes-css.html
Resultado

Pon a prueba lo que has aprendido

[CSS] Una foto apaisada se ve aplastada en una miniatura cuadrada. ¿Qué la arregla sin deformarla?
.miniatura {
  width: 200px;
  height: 200px;
}

[CSS] ¿Por qué se prefiere img { max-width: 100%; } en lugar de img { width: 100%; }?

[CSS] Tienes un logo PNG con fondo transparente y quieres una sombra que siga su silueta. ¿Qué usas?

[CSS] ¿Qué imagen de una tienda online debería ir en un <img> y no como background-image?

¿Te ha quedado claro? Márcala y verás tu progreso en el explorador.