Módulo 03: Imágenes y multimedia

Objetivos del módulo

  • Insertar imágenes con img y todos sus atributos importantes (src, alt, width, height, loading, decoding)
  • Escribir textos alternativos útiles y saber cuándo dejarlos vacíos
  • Elegir el formato de imagen adecuado: JPEG, PNG, WebP, AVIF, SVG o GIF
  • Servir imágenes adaptadas a cada pantalla con srcset y sizes
  • Usar picture y source para dirección de arte y formatos modernos con alternativa
  • Asociar pies de foto con figure y figcaption
  • Incrustar audio y vídeo nativos, con varias fuentes, póster y subtítulos
  • Incrustar contenido externo (YouTube, mapas) con iframe de forma segura
  • Dibujar gráficos sencillos con SVG en línea
  • Aplicar buenas prácticas de rendimiento y accesibilidad multimedia

1. Imágenes: el elemento img

📘 Concepto: El elemento <img> inserta una imagen en el documento. Es un elemento vacío (no tiene etiqueta de cierre) y en línea por defecto. La imagen no forma parte del HTML: es un fichero aparte que el navegador descarga con una petición HTTP independiente.

<img src="img/playa-de-las-catedrales.jpg" alt="Arcos de roca de la Playa de las Catedrales con la marea baja">

Atributos fundamentales

Atributo Obligatorio Para qué sirve
src Sí Ruta (relativa o absoluta) del fichero de imagen
alt Sí Texto alternativo: describe la imagen para quien no puede verla
width / height Muy recomendable Dimensiones intrínsecas en píxeles (sin unidad)
loading Opcional lazy para cargar la imagen solo cuando se acerque a la zona visible
decoding Opcional async para que la decodificación no bloquee el resto de la página
fetchpriority Opcional high para priorizar la imagen principal; low para restarle prioridad
srcset / sizes Opcional Versiones de distintos tamaños (sección 4)
title Opcional Tooltip; no sustituye a alt

El atributo alt: el más importante

El texto alternativo se usa cuando:

  • Una persona ciega navega con un lector de pantalla, que lee el alt en voz alta.
  • La imagen no carga (conexión lenta, ruta incorrecta): se muestra el texto en su lugar.
  • Los buscadores indexan la imagen: el alt les dice qué contiene.

📘 Concepto: Un buen alt responde a la pregunta: “si tuviera que describir esta imagen por teléfono a alguien, ¿qué información necesitaría para entender la página igual que yo?”. Depende del contexto, no solo de la imagen.

Tipo de imagen Qué poner en alt Ejemplo
Informativa (aporta contenido) Descripción breve y precisa de lo relevante alt="Gráfico: las ventas crecieron un 25 % en 2026"
Funcional (dentro de un enlace o botón) La acción o el destino, no el dibujo alt="Ir a la página de inicio" en el logo enlazado
Decorativa (solo adorno) Vacío: alt="" Una floritura, un fondo, un icono junto a un texto que ya lo dice
Con texto El texto que aparece en la imagen alt="Rebajas: 50 % en toda la tienda"
Compleja (gráficos, mapas, infografías) Resumen breve en alt y descripción completa en el texto de la página alt="Mapa de la red de metro" + explicación aparte
<!-- Informativa -->
<img src="img/equipo.jpg" alt="Las cinco personas del equipo posando frente a la oficina de Bilbao">

<!-- Funcional: el logo lleva a la portada -->
<a href="index.html">
  <img src="img/logo.svg" alt="Cafetería La Taza: ir a la página de inicio">
</a>

<!-- Decorativa: alt vacío, el lector de pantalla la ignora -->
<img src="img/separador-floral.svg" alt="">

⚠️ Importante: Nunca omitas el atributo alt. Si falta, muchos lectores de pantalla leen el nombre del fichero (“IMG guion bajo cuatro mil trescientos veintiuno punto jota pe ge”). Si la imagen es decorativa, escribe alt="" (vacío): así se ignora de forma intencionada.

Mal alt Por qué Mejor
alt="imagen" / alt="foto" No aporta nada Describe el contenido
alt="Imagen de un perro" “Imagen de” sobra: el lector ya anuncia que es una imagen alt="Perro labrador tumbado en la hierba"
alt="IMG_4321.jpg" Nombre de fichero Descripción real
alt="perro, mascota, labrador, comprar perro" Relleno de palabras clave para SEO Una frase natural
Un párrafo de 300 palabras Demasiado largo Resumen en alt; detalle en el texto

width y height: evita los saltos de contenido

<img src="img/portada.jpg" alt="Vista del puerto de Cádiz al atardecer" width="1200" height="800">

📘 Concepto: Si no indicas width y height, el navegador no sabe cuánto espacio reservar hasta que descarga la imagen. Mientras tanto coloca el texto, y cuando la imagen llega todo salta hacia abajo. Este efecto, muy molesto, se mide con la métrica CLS (Cumulative Layout Shift) y penaliza en Lighthouse y en el posicionamiento de Google.

Con width y height, el navegador calcula la proporción (aquí 3:2) y reserva el hueco antes de descargar la imagen. Aunque luego con CSS hagas la imagen flexible, la proporción se mantiene:

/* Adelanto de CSS: imágenes que nunca se salen de su contenedor */
img {
  max-width: 100%; /* Como mucho, el ancho del contenedor */
  height: auto;    /* La altura se ajusta para mantener la proporción */
}

💡 Consejo: Pon en width y height las dimensiones reales del fichero (o cualquier pareja con la misma proporción). El tamaño visual lo controlarás con CSS.

loading="lazy": carga diferida

<!-- Esta imagen está muy abajo en la página: que no se cargue hasta que haga falta -->
<img src="img/galeria-07.jpg" alt="Interior de la catedral de León" width="800" height="600" loading="lazy">
Valor Comportamiento
eager Carga inmediata (valor por defecto)
lazy Carga cuando la imagen se acerca a la zona visible de la pantalla

⚠️ Importante: No uses loading="lazy" en las imágenes visibles al cargar (la cabecera, el logo, la foto principal). Retrasarías justamente lo que el usuario necesita ver primero. Para la imagen principal, haz lo contrario: fetchpriority="high".

decoding="async" y fetchpriority

<!-- Imagen principal (hero): máxima prioridad -->
<img src="img/hero.webp" alt="Ciclistas recorriendo la Vía Verde del Aceite"
     width="1600" height="900" fetchpriority="high">

<!-- Imágenes secundarias: carga diferida y decodificación asíncrona -->
<img src="img/detalle.webp" alt="Detalle del cambio de marchas"
     width="800" height="600" loading="lazy" decoding="async">

decoding="async" indica al navegador que puede decodificar la imagen (convertir el fichero comprimido en píxeles) sin retrasar el pintado del resto del contenido.


2. Formatos de imagen

Elegir bien el formato puede reducir el peso de una imagen a la mitad o menos sin pérdida visible de calidad.

📘 Concepto: Los formatos se dividen en mapas de bits (raster: la imagen es una cuadrícula de píxeles; al ampliarla se pixela) y vectoriales (la imagen se describe con formas geométricas; se puede ampliar infinitamente sin perder calidad). Dentro de los mapas de bits, la compresión puede ser con pérdida (descarta información que el ojo apenas percibe) o sin pérdida (conserva todos los píxeles exactos).

Formato Tipo Compresión Transparencia Animación Uso ideal
JPEG (.jpg) Mapa de bits Con pérdida No No Fotografías (formato universal)
PNG (.png) Mapa de bits Sin pérdida Sí No* Capturas de pantalla, gráficos con texto, imágenes con transparencia
GIF (.gif) Mapa de bits Sin pérdida, solo 256 colores Sí (binaria) Sí Pequeñas animaciones antiguas (mejor sustituir por vídeo)
WebP (.webp) Mapa de bits Con o sin pérdida Sí Sí Sustituto general de JPEG y PNG, en torno a un 25-35 % más ligero
AVIF (.avif) Mapa de bits Con o sin pérdida Sí Sí La mejor compresión actual para fotografías
SVG (.svg) Vectorial (Es texto XML) Sí Sí (CSS/SMIL) Logotipos, iconos, ilustraciones planas, gráficos

* Existe la variante APNG (PNG animado), poco utilizada.

¿Qué formato elijo?

flowchart TD
    A{¿Logotipo, icono o<br/>ilustración plana?} -->|Sí| B[SVG]
    A -->|No| C{¿Es una fotografía?}
    C -->|Sí| D["AVIF o WebP<br/>(con JPEG de respaldo si lo necesitas)"]
    C -->|No| E{¿Necesita transparencia<br/>o es una captura?}
    E -->|Sí| F["WebP o PNG"]
    E -->|No| G{¿Es una animación?}
    G -->|Sí| H["Vídeo MP4/WebM<br/>mejor que GIF"]
    G -->|No| D

💡 Consejo: Un GIF animado de 5 MB suele ocupar menos de 500 KB convertido a vídeo MP4 o WebM. Usa <video autoplay muted loop playsinline> (lo verás en la sección 7) en lugar de GIF para animaciones.

Compatibilidad

WebP y AVIF funcionan en todos los navegadores modernos (Chrome, Edge, Firefox y Safari en sus versiones actuales). Si necesitas dar soporte a navegadores muy antiguos, usa <picture> con un JPEG de respaldo (sección 5).

Optimizar el peso

Herramienta Tipo Para qué
Squoosh (squoosh.app) Web, gratuita Comparar formatos y calidades lado a lado y convertir a WebP/AVIF
SVGOMG Web, gratuita Limpiar y reducir ficheros SVG
TinyPNG Web Comprimir PNG y JPEG
ImageMagick, Sharp Línea de comandos Convertir y redimensionar en lote

⚠️ Importante: No subas una foto de 6000 × 4000 píxeles (8 MB) directamente de la cámara para mostrarla a 600 píxeles de ancho. Redimensiona primero a un tamaño razonable (por ejemplo, el doble del tamaño de visualización para pantallas de alta densidad) y comprime. Una foto web rara vez necesita más de 200-300 KB.


3. Rutas de imágenes y errores típicos

<!-- Relativa: carpeta img junto al HTML -->
<img src="img/logo.svg" alt="Logo de la empresa">

<!-- Relativa: subiendo un nivel -->
<img src="../img/logo.svg" alt="Logo de la empresa">

<!-- Absoluta: imagen de otro servidor -->
<img src="https://upload.wikimedia.org/wikipedia/commons/6/61/HTML5_logo_and_wordmark.svg"
     alt="Logotipo de HTML5" width="200" height="200">
Síntoma Causa Solución
Icono de imagen rota y se ve el texto del alt Ruta o nombre incorrecto Revisa la pestaña Network: verás un 404 con la ruta exacta
Funciona en tu PC, no en el servidor Mayúsculas: Foto.JPG frente a foto.jpg Nombres siempre en minúsculas
La imagen se ve deformada width y height con proporción distinta a la real Usa las dimensiones reales; ajusta el tamaño con CSS
La página tarda mucho en cargar Imágenes enormes sin optimizar Redimensiona, comprime y usa formatos modernos

⚠️ Importante: Enlazar imágenes de otros sitios web (hotlinking) consume el ancho de banda ajeno, puede vulnerar derechos de autor y la imagen puede desaparecer en cualquier momento. Descarga las imágenes con licencia adecuada (Unsplash, Pexels, Wikimedia Commons…) y sírvelas desde tu propio servidor.


4. Imágenes adaptativas: srcset y sizes

Un móvil con una pantalla de 400 píxeles no necesita descargar la misma imagen de 2000 píxeles que un monitor grande. Con srcset y sizes ofreces varias versiones y el navegador elige la más adecuada.

📘 Concepto: Con srcset tú das el menú (las versiones disponibles y su tamaño) y con sizes das una pista del tamaño al que se mostrará. El navegador, que conoce la pantalla, la densidad de píxeles e incluso la conexión, elige el plato. Tú no decides cuál se descarga: lo decide el navegador.

Descriptor x: imágenes de tamaño fijo en pantallas de alta densidad

Para imágenes que se muestran siempre al mismo tamaño (un logo, un avatar), indica versiones para cada densidad de píxeles:

<img src="img/avatar-100.jpg"
     srcset="img/avatar-100.jpg 1x,
             img/avatar-200.jpg 2x,
             img/avatar-300.jpg 3x"
     alt="Foto de perfil de Lucía Martín" width="100" height="100">

Una pantalla normal descarga la versión 1x; un móvil con pantalla de alta densidad (Retina), la 2x o la 3x.

Descriptor w + sizes: imágenes de tamaño variable

Para imágenes que cambian de tamaño según la pantalla (lo habitual en webs responsive):

<img src="img/paisaje-800.jpg"
     srcset="img/paisaje-400.jpg 400w,
             img/paisaje-800.jpg 800w,
             img/paisaje-1200.jpg 1200w,
             img/paisaje-1600.jpg 1600w"
     sizes="(max-width: 600px) 100vw,
            (max-width: 1200px) 50vw,
            800px"
     alt="Campos de lavanda en flor en Brihuega"
     width="1600" height="1067">
Parte Significado
paisaje-400.jpg 400w Este fichero mide 400 píxeles de ancho real
sizes Lista de condiciones y el ancho al que se mostrará la imagen
(max-width: 600px) 100vw En pantallas de hasta 600 px, la imagen ocupa el 100 % del ancho de la ventana
(max-width: 1200px) 50vw Hasta 1200 px, ocupa la mitad
800px En cualquier otro caso, se muestra a 800 px
src Imagen de respaldo para navegadores sin soporte de srcset

Cómo decide el navegador: en un móvil de 400 px de ancho con densidad 2x, la imagen se mostrará a 100vw = 400 px, que con densidad 2 son 800 píxeles reales, así que descargará paisaje-800.jpg.

💡 Consejo: Si no pones sizes, el navegador asume 100vw (todo el ancho de la ventana) y puede descargar imágenes más grandes de lo necesario. Con sizes="auto" y loading="lazy", los navegadores que lo soportan calculan el tamaño automáticamente, pero no todos lo admiten todavía: indica sizes de forma explícita.

⚠️ Importante: Las versiones de srcset deben ser la misma imagen a distintas resoluciones. Si quieres mostrar imágenes diferentes (por ejemplo, un recorte distinto en móvil), necesitas <picture>.


5. El elemento picture

<picture> envuelve un <img> y uno o varios <source>. El navegador recorre los source en orden y usa el primero que cumpla sus condiciones; si ninguno encaja, usa el img.

⚠️ Importante: Dentro de <picture>, el <img> es obligatorio y debe ir al final. Es el que realmente se muestra (los source solo le cambian el fichero), así que es el que lleva alt, width, height y loading.

Caso 1: formatos modernos con respaldo

<picture>
  <!-- 1.º Si el navegador entiende AVIF, usa este -->
  <source srcset="img/torre-hercules.avif" type="image/avif">
  <!-- 2.º Si no, pero entiende WebP, usa este -->
  <source srcset="img/torre-hercules.webp" type="image/webp">
  <!-- 3.º En otro caso, JPEG -->
  <img src="img/torre-hercules.jpg" alt="Torre de Hércules en A Coruña bajo un cielo nublado"
       width="1200" height="800" loading="lazy">
</picture>

Caso 2: dirección de arte (art direction)

Mostrar recortes diferentes según el tamaño de la pantalla: en móvil, un primer plano vertical; en escritorio, una panorámica.

<picture>
  <!-- Pantallas anchas: foto panorámica -->
  <source media="(min-width: 1000px)" srcset="img/concierto-panoramica.webp" width="1600" height="600">
  <!-- Tabletas: foto en formato 4:3 -->
  <source media="(min-width: 600px)" srcset="img/concierto-4x3.webp" width="1000" height="750">
  <!-- Móviles: primer plano vertical -->
  <img src="img/concierto-vertical.webp" alt="Cantante sobre el escenario frente al público"
       width="600" height="900">
</picture>

Fíjate en que los source también pueden llevar width y height para que el navegador reserve el espacio correcto en cada caso.

Comparativa

Necesidad Solución
La misma imagen a distintas resoluciones img con srcset (y sizes)
Formatos modernos con respaldo picture + source con type
Imágenes distintas según la pantalla picture + source con media
Ambas cosas picture + source con media, type y srcset con descriptores w

6. Pies de foto: figure y figcaption

📘 Concepto: <figure> representa un contenido autónomo (una imagen, un diagrama, un fragmento de código, una cita) que se referencia desde el texto principal pero que podría moverse a otro lugar (un anexo, un lateral) sin romper el discurso. <figcaption> es su leyenda o pie.

<p>
  Como muestra la figura 1, la temperatura media ha subido de forma
  sostenida desde 1980.
</p>

<figure>
  <img src="img/grafico-temperaturas.svg"
       alt="Gráfico de líneas: la temperatura media en España pasa de 14,2 °C en 1980 a 15,9 °C en 2025"
       width="800" height="450">
  <figcaption>Figura 1. Evolución de la temperatura media anual en España (1980-2025). Datos de ejemplo.</figcaption>
</figure>
  • figcaption puede ir al principio o al final del figure, pero solo puede haber uno.
  • Un figure puede contener varias imágenes con una única leyenda.
  • No es solo para imágenes: también para código, citas, tablas o vídeos.
<!-- figure con código -->
<figure>
  <figcaption>Listado 1. Hola mundo en JavaScript</figcaption>
  <pre><code>console.log("Hola, mundo");</code></pre>
</figure>

<!-- figure con varias imágenes -->
<figure>
  <img src="img/antes.webp" alt="Salón antes de la reforma, con paredes oscuras" width="600" height="400">
  <img src="img/despues.webp" alt="Salón después de la reforma, luminoso y con suelo de madera" width="600" height="400">
  <figcaption>Reforma integral del salón: antes y después.</figcaption>
</figure>

💡 Consejo: figcaption y alt no son lo mismo. El alt sustituye a la imagen para quien no la ve; el figcaption complementa a la imagen para todos. No repitas el mismo texto en ambos.


7. Audio

<audio controls>
  <source src="audio/podcast-episodio-12.mp3" type="audio/mpeg">
  <source src="audio/podcast-episodio-12.ogg" type="audio/ogg">
  <p>
    Tu navegador no puede reproducir audio.
    <a href="audio/podcast-episodio-12.mp3">Descarga el episodio en MP3</a>.
  </p>
</audio>

Resultado esperado: un reproductor con botón de reproducir/pausa, barra de progreso, tiempo y control de volumen. Su aspecto varía según el navegador.

Atributos de audio (y de video)

Atributo Efecto
controls Muestra los controles del navegador. Sin él, no se ve nada
autoplay Intenta reproducir automáticamente (los navegadores lo bloquean si hay sonido)
muted Empieza silenciado
loop Repite al terminar
preload none (no descarga nada), metadata (solo duración y datos), auto (puede descargar todo)
src Fichero único (alternativa a usar varios source)

Formatos de audio

Formato Tipo MIME Notas
MP3 audio/mpeg Universal
AAC / M4A audio/mp4 Muy compatible, buena calidad
Ogg Vorbis / Opus audio/ogg Libre, excelente compresión
WAV audio/wav Sin compresión: ficheros enormes, no recomendable para web

⚠️ Importante: Los navegadores bloquean la reproducción automática con sonido hasta que el usuario interactúa con la página. Y aunque no la bloquearan, que una web empiece a sonar sola es una de las peores experiencias posibles (y un problema de accesibilidad para usuarios de lectores de pantalla). No uses autoplay en audio.

💡 Consejo: Para podcasts y entrevistas, ofrece también una transcripción en texto. Es imprescindible para personas sordas, útil para quien no puede poner sonido y excelente para el SEO.

<figure>
  <figcaption>Episodio 12: Accesibilidad web para principiantes (28 min)</figcaption>
  <audio controls preload="metadata" src="audio/episodio-12.mp3"></audio>
  <p><a href="transcripciones/episodio-12.html">Leer la transcripción completa</a></p>
</figure>

8. Vídeo

<video controls width="1280" height="720" poster="img/video-portada.jpg" preload="metadata">
  <source src="video/presentacion.webm" type="video/webm">
  <source src="video/presentacion.mp4" type="video/mp4">
  <track src="subtitulos/presentacion-es.vtt" kind="subtitles" srclang="es" label="Español" default>
  <track src="subtitulos/presentacion-en.vtt" kind="subtitles" srclang="en" label="English">
  <p>
    Tu navegador no admite vídeo HTML5.
    <a href="video/presentacion.mp4">Descarga el vídeo (MP4, 18 MB)</a>.
  </p>
</video>

Atributos específicos de video

Además de los que comparte con audio (controls, autoplay, muted, loop, preload):

Atributo Efecto
poster Imagen que se muestra antes de reproducir (portada)
width / height Dimensiones; como en img, evitan saltos de contenido
playsinline En iPhone, reproduce dentro de la página en lugar de a pantalla completa

Formatos de vídeo

Contenedor Códec habitual Tipo MIME Notas
MP4 H.264 + AAC video/mp4 Compatible con todo; úsalo siempre como respaldo
WebM VP9 o AV1 + Opus video/webm Libre y más ligero
MP4 AV1 video/mp4 Excelente compresión en navegadores modernos

💡 Consejo: Para convertir vídeos puedes usar herramientas gratuitas como HandBrake (interfaz gráfica) o FFmpeg (línea de comandos). Por ejemplo:

# Convierte a MP4 (H.264) optimizado para web
ffmpeg -i original.mov -c:v libx264 -crf 23 -preset slow -c:a aac -b:a 128k -movflags +faststart presentacion.mp4

# Convierte a WebM (VP9)
ffmpeg -i original.mov -c:v libvpx-vp9 -crf 32 -b:v 0 -c:a libopus presentacion.webm

Vídeo como fondo o como sustituto de un GIF

<!-- Se reproduce solo, sin sonido, en bucle y dentro de la página -->
<video autoplay muted loop playsinline width="800" height="450" poster="img/animacion-poster.jpg">
  <source src="video/animacion.webm" type="video/webm">
  <source src="video/animacion.mp4" type="video/mp4">
</video>

⚠️ Importante: Para que autoplay funcione, el vídeo debe ir silenciado (muted). Y por accesibilidad, cualquier contenido que se mueva solo durante más de 5 segundos debe poder pausarse (criterio 2.2.2 de las pautas WCAG): añade controls o un botón de pausa, y respeta la preferencia de movimiento reducido (lo verás en el módulo 13).

Subtítulos con track y WebVTT

📘 Concepto: El elemento <track> asocia al vídeo un fichero de texto sincronizado en formato WebVTT (.vtt). El navegador lo muestra sobre el vídeo y añade un menú para elegir idioma.

Valor de kind Uso
subtitles Traducción de los diálogos para quien no entiende el idioma (valor por defecto)
captions Transcripción de diálogos y sonidos relevantes ([suena el teléfono]) para personas sordas
descriptions Descripción textual de lo que ocurre en imagen, para personas ciegas
chapters Títulos de capítulos para navegar por el vídeo
Atributo de track Significado
src Ruta del fichero .vtt
kind Tipo de pista (tabla anterior)
srclang Idioma de la pista (es, en…); obligatorio si kind="subtitles"
label Nombre que aparece en el menú del reproductor
default Pista activada por defecto

Un fichero WebVTT (subtitulos/presentacion-es.vtt) es texto plano:

WEBVTT

00:00:00.500 --> 00:00:03.000
Hola, bienvenidos al curso de HTML y CSS.

00:00:03.500 --> 00:00:07.000
En este vídeo aprenderás a insertar
contenido multimedia en tus páginas.

00:00:07.500 --> 00:00:09.000
[Música de fondo]

⚠️ Importante: Los subtítulos no funcionan si abres el HTML con doble clic (file://): el navegador bloquea la carga del .vtt por seguridad. Usa Live Server. Además, el fichero .vtt debe estar en tu mismo dominio (o el otro servidor debe permitirlo mediante CORS).


9. Contenido incrustado: iframe

📘 Concepto: Un <iframe> (inline frame) inserta otra página web completa dentro de la tuya, como una ventana dentro de la ventana. Se usa para vídeos de YouTube o Vimeo, mapas, reproductores de música, formularios externos, etc.

Vídeo de YouTube

En YouTube, debajo del vídeo: Compartir → Insertar. Obtendrás un código que, limpiado y mejorado, queda así:

<iframe
  width="560" height="315"
  src="https://www.youtube-nocookie.com/embed/ID_DEL_VIDEO"
  title="Tutorial: cómo usar las DevTools de Chrome"
  allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
  referrerpolicy="strict-origin-when-cross-origin"
  allowfullscreen
  loading="lazy">
</iframe>
Atributo Para qué
src URL de la página incrustada. El dominio youtube-nocookie.com (modo de privacidad mejorada) evita cookies de seguimiento hasta que el usuario reproduce el vídeo
title Obligatorio por accesibilidad: el lector de pantalla anuncia qué contiene el marco
width / height Dimensiones
allow Permisos que concedes al contenido incrustado (pantalla completa, reproducción automática, etc.)
allowfullscreen Permite el botón de pantalla completa
referrerpolicy Qué información de procedencia se envía al servidor incrustado
loading="lazy" No carga el iframe hasta que se acerca a la zona visible (muy recomendable: un vídeo de YouTube incrustado descarga cientos de KB)

💡 Consejo: El código de YouTube incluye frameborder="0", un atributo obsoleto en HTML5. Elimínalo y quita el borde con CSS: iframe { border: 0; }.

Para que el vídeo sea flexible y mantenga la proporción 16:9:

/* Adelanto de CSS */
iframe {
  width: 100%;
  height: auto;
  aspect-ratio: 16 / 9;
  border: 0;
}

Mapas

Google Maps: busca el lugar → Compartir → Insertar un mapa → Copiar HTML. Obtendrás un iframe con una URL del tipo https://www.google.com/maps/embed?pb=.... Revisa el código, elimina style y atributos obsoletos y añade un title descriptivo.

OpenStreetMap (alternativa libre): en openstreetmap.org, Compartir → HTML:

<iframe
  width="600" height="400"
  src="https://www.openstreetmap.org/export/embed.html?bbox=-3.7100,40.4130,-3.6980,40.4200&layer=mapnik&marker=40.4168,-3.7038"
  title="Mapa de la Puerta del Sol, Madrid"
  loading="lazy">
</iframe>
<p>
  <a href="https://www.openstreetmap.org/?mlat=40.4168&mlon=-3.7038#map=17/40.4168/-3.7038">
    Ver el mapa a pantalla completa
  </a>
</p>

💡 Consejo: Incluye siempre la dirección en texto junto al mapa. Un mapa incrustado no es accesible para todos, y la dirección en texto es útil para copiarla, para los buscadores y para los lectores de pantalla.

Seguridad: sandbox y allow

Un iframe ejecuta código de otra web dentro de la tuya. Si no confías plenamente en ese contenido, restríngelo con sandbox:

<!-- Sandbox total: sin scripts, sin formularios, sin ventanas emergentes -->
<iframe src="https://ejemplo.com/widget" title="Widget de ejemplo" sandbox></iframe>

<!-- Sandbox con excepciones: permite scripts y formularios, nada más -->
<iframe src="https://ejemplo.com/encuesta" title="Encuesta de satisfacción"
        sandbox="allow-scripts allow-forms"></iframe>
Valor de sandbox Permite
(vacío) Nada: máxima restricción
allow-scripts Ejecutar JavaScript
allow-forms Enviar formularios
allow-same-origin Tratar el contenido como de su origen real (acceso a sus cookies y almacenamiento)
allow-popups Abrir ventanas nuevas
allow-modals Mostrar alert(), confirm()…
allow-downloads Iniciar descargas

⚠️ Importante: No combines allow-scripts y allow-same-origin para contenido de tu propio dominio: el contenido podría eliminar el propio sandbox y la protección desaparecería. Concede solo los permisos imprescindibles (principio de mínimo privilegio).

El atributo allow (la Permissions Policy) controla funciones del dispositivo: allow="camera; microphone", allow="geolocation", allow="fullscreen". Por defecto, un iframe de otro dominio no puede usarlas.

📘 Concepto: No todas las webs se pueden incrustar. Muchos sitios (bancos, redes sociales, Google.com) prohíben que se les meta en un iframe mediante cabeceras HTTP (X-Frame-Options o Content-Security-Policy: frame-ancestors), para evitar ataques de clickjacking. Si tu iframe aparece en blanco o con un error, probablemente sea por eso.


10. SVG en línea

Además de usarse como fichero en un <img src="logo.svg">, el SVG se puede escribir directamente dentro del HTML. Así puedes cambiar sus colores con CSS y animarlo.

📘 Concepto: SVG (Scalable Vector Graphics) es un formato de imagen vectorial basado en XML: la imagen se describe con formas (círculos, rectángulos, trazados) y coordenadas. Se ve perfecta a cualquier tamaño y suele pesar muy poco.

Formas básicas

<svg width="300" height="200" viewBox="0 0 300 200" role="img" aria-labelledby="titulo-svg">
  <title id="titulo-svg">Un sol sobre una colina verde</title>

  <!-- Cielo: rectángulo que ocupa todo -->
  <rect x="0" y="0" width="300" height="200" fill="#bfdbfe" />

  <!-- Sol: círculo con centro (240, 50) y radio 30 -->
  <circle cx="240" cy="50" r="30" fill="#facc15" />

  <!-- Colina: elipse -->
  <ellipse cx="120" cy="210" rx="200" ry="80" fill="#22c55e" />

  <!-- Línea del horizonte -->
  <line x1="0" y1="160" x2="300" y2="160" stroke="#15803d" stroke-width="2" />

  <!-- Texto -->
  <text x="20" y="40" font-family="sans-serif" font-size="20" fill="#1e3a8a">Buenos días</text>
</svg>
Elemento Atributos principales Dibuja
rect x, y, width, height, rx (esquinas) Rectángulo
circle cx, cy (centro), r (radio) Círculo
ellipse cx, cy, rx, ry Elipse
line x1, y1, x2, y2 Línea
polyline / polygon points="x,y x,y ..." Línea quebrada / polígono cerrado
path d (comandos de trazado) Cualquier forma
text x, y Texto
Atributo de estilo Efecto
fill Color de relleno (none para vacío)
stroke Color del borde
stroke-width Grosor del borde

El viewBox

📘 Concepto: viewBox="0 0 300 200" define el sistema de coordenadas interno del dibujo: un lienzo de 300 × 200 unidades, empezando en (0, 0) en la esquina superior izquierda. width y height definen el tamaño en pantalla. Si cambias width a 600, el dibujo se escala al doble sin perder calidad.

Iconos SVG que heredan el color del texto

<a href="carrito.html" class="enlace-carrito">
  <svg width="24" height="24" viewBox="0 0 24 24" aria-hidden="true" focusable="false">
    <path fill="currentColor"
          d="M7 18a2 2 0 1 0 0 4 2 2 0 0 0 0-4zm10 0a2 2 0 1 0 0 4 2 2 0 0 0 0-4zM5.2 4l.9 2H20l-3.6 7.3a2 2 0 0 1-1.8 1.1H8.1l-1 1.6H19v2H7a2 2 0 0 1-1.7-3l1.4-2.4L3 4H1V2h3.3z"/>
  </svg>
  Ver carrito
</a>
  • fill="currentColor" hace que el icono tome el color del texto del elemento padre: si cambias el color del enlace con CSS, el icono cambia también.
  • aria-hidden="true" oculta el icono a los lectores de pantalla porque es decorativo: el texto “Ver carrito” ya dice lo que hace.

Accesibilidad del SVG

Caso Qué hacer
SVG decorativo aria-hidden="true" en el <svg>
SVG informativo en línea role="img" + <title> (y aria-labelledby apuntando al id del título)
SVG como fichero en img Como cualquier imagen: alt descriptivo o alt=""
Icono solo (sin texto) dentro de un botón o enlace aria-hidden="true" en el SVG y texto accesible en el botón (aria-label="Cerrar")

💡 Consejo: No hace falta dibujar los iconos a mano. Bibliotecas como Bootstrap Icons (la usarás en el módulo 17), Heroicons o Lucide ofrecen miles de iconos SVG gratuitos listos para copiar.

img con SVG o SVG en línea

Aspecto <img src="icono.svg"> <svg> en línea
Caché del navegador Sí: se descarga una vez No: va dentro de cada página
Cambiar colores con CSS de la página No Sí
Animar partes con CSS No Sí
HTML limpio Sí El HTML crece
Ideal para Logos, ilustraciones grandes Iconos que deben adaptarse al color del texto

11. Ejemplo completo: página de un destino turístico

💻 Ejemplo: destino.html reúne imágenes responsive, figuras, vídeo y mapa:

<!DOCTYPE html>
<html lang="es">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Albarracín: qué ver y cómo llegar | Rutas por Aragón</title>
  <style>
    /* Adelanto de CSS: imágenes, vídeos e iframes flexibles */
    body { max-width: 900px; margin: 0 auto; padding: 0 16px; font-family: system-ui, sans-serif; }
    img, video { max-width: 100%; height: auto; }
    iframe { width: 100%; height: auto; aspect-ratio: 16 / 9; border: 0; }
  </style>
</head>
<body>
  <h1>Albarracín</h1>

  <!-- Imagen principal: formatos modernos, prioridad alta, sin lazy -->
  <picture>
    <source type="image/avif"
            srcset="img/albarracin-800.avif 800w, img/albarracin-1600.avif 1600w"
            sizes="(max-width: 900px) 100vw, 900px">
    <source type="image/webp"
            srcset="img/albarracin-800.webp 800w, img/albarracin-1600.webp 1600w"
            sizes="(max-width: 900px) 100vw, 900px">
    <img src="img/albarracin-1600.jpg"
         alt="Casas colgadas de color rojizo sobre el río Guadalaviar en Albarracín"
         width="1600" height="900" fetchpriority="high">
  </picture>

  <p>
    Albarracín es uno de los pueblos más bonitos de España, con su
    caserío medieval encaramado sobre un meandro del río Guadalaviar.
  </p>

  <h2>Qué ver</h2>
  <figure>
    <img src="img/murallas.webp" alt="Murallas de piedra que ascienden por la ladera sobre el pueblo"
         width="1200" height="800" loading="lazy" decoding="async">
    <figcaption>Las murallas medievales rodean el casco histórico.</figcaption>
  </figure>

  <h2>Vídeo de la visita</h2>
  <video controls width="1280" height="720" poster="img/video-albarracin.jpg" preload="none">
    <source src="video/albarracin.webm" type="video/webm">
    <source src="video/albarracin.mp4" type="video/mp4">
    <track src="subtitulos/albarracin-es.vtt" kind="captions" srclang="es" label="Español" default>
    <p><a href="video/albarracin.mp4">Descarga el vídeo (MP4, 24 MB)</a></p>
  </video>

  <h2>Cómo llegar</h2>
  <p>Albarracín está a 38 km de Teruel por la carretera A-1512.</p>
  <iframe
    src="https://www.openstreetmap.org/export/embed.html?bbox=-1.4520,40.4030,-1.4300,40.4130&layer=mapnik&marker=40.4080,-1.4410"
    title="Mapa de situación de Albarracín"
    width="900" height="506"
    loading="lazy">
  </iframe>
</body>
</html>

Como no tienes los ficheros de imagen y vídeo, verás los textos alternativos y los huecos reservados. Sustitúyelos por imágenes propias (o descargadas de Wikimedia Commons) para ver el resultado completo.


12. Rendimiento y accesibilidad: lista de comprobación

Rendimiento

Buena práctica Por qué
Redimensiona y comprime todas las imágenes Las imágenes suelen ser la mayor parte del peso de una página
Usa AVIF o WebP, con respaldo si lo necesitas Mismo aspecto, mucho menos peso
SVG para logos e iconos Nítidos a cualquier tamaño y muy ligeros
Siempre width y height Evitan los saltos de contenido (CLS)
loading="lazy" en imágenes e iframes fuera de la primera pantalla Ahorra datos y acelera la carga inicial
fetchpriority="high" en la imagen principal y nunca lazy en ella Mejora el LCP (tiempo en mostrar el elemento principal)
srcset y sizes en imágenes grandes El móvil no descarga imágenes de escritorio
preload="metadata" o "none" en vídeos No descarga megas que quizá nadie vea
Vídeo en lugar de GIF animado Hasta 10 veces menos peso

Accesibilidad

Buena práctica Para quién
alt en todas las imágenes (vacío si son decorativas) Usuarios de lectores de pantalla
No metas texto importante dentro de imágenes Lectores de pantalla, traductores, zoom, buscadores
Subtítulos (captions) en vídeos con diálogo Personas sordas o en entornos sin sonido
Transcripción de audios y podcasts Personas sordas; también mejora el SEO
Nada de autoplay con sonido Usuarios de lectores de pantalla, todo el mundo
Controles de pausa en contenido en movimiento Personas con trastornos de atención o vestibulares
title en todos los iframe Usuarios de lectores de pantalla
Dirección en texto junto a los mapas Todo el mundo

💡 Consejo: Ejecuta Lighthouse después de añadir imágenes y vídeos: te avisará de imágenes sin alt, sin dimensiones, demasiado pesadas o en formatos antiguos, e incluso te dirá cuántos KB podrías ahorrar.


13. Ejercicios

Ejercicio 1: Galería con textos alternativos

Crea una página con una galería de 6 fotos de tu ciudad (descárgalas de Wikimedia Commons o Unsplash). Cada imagen debe tener width, height, un alt descriptivo y adecuado al contexto, y loading="lazy" excepto la primera. Envuelve cada imagen en un figure con su figcaption, sin repetir el texto del alt. Añade también una imagen decorativa (un separador) con alt vacío.

Ejercicio 2: Comparativa de formatos

Toma una fotografía y una captura de pantalla con texto. Con Squoosh, exporta cada una en JPEG, PNG, WebP y AVIF con calidad similar. Crea una página con una tabla (o una lista) que muestre cada versión junto con su peso en KB, y escribe una conclusión: ¿qué formato elegirías para cada tipo de imagen y por qué?

Ejercicio 3: Imagen responsive con srcset

Genera 4 versiones de la misma foto (400, 800, 1200 y 1600 píxeles de ancho). Insértala con srcset y sizes de modo que ocupe el 100 % del ancho en pantallas de hasta 700 px y 700 px en pantallas mayores. Comprueba en la pestaña Network de DevTools (con el modo dispositivo y distintos tamaños, y la caché desactivada) qué versión descarga el navegador en cada caso.

Ejercicio 4: Dirección de arte con picture

Prepara dos recortes de una misma foto: uno horizontal (16:9) y otro cuadrado (1:1). Usa picture para mostrar el cuadrado en pantallas de menos de 600 px y el horizontal en las demás. Añade además versiones WebP de ambos con su JPEG de respaldo.

Ejercicio 5: Reproductor de vídeo con subtítulos

Graba un vídeo corto con el móvil (o descarga uno con licencia libre) y conviértelo a MP4 y WebM. Insértalo con póster, controles, preload="metadata" y dos pistas de subtítulos (español e inglés) escritas por ti en WebVTT con al menos 4 entradas cada una. Ábrelo con Live Server y comprueba que puedes cambiar de idioma.

Ejercicio 6: Página de contacto con mapa y vídeo

Crea una página de contacto para un negocio ficticio con: la dirección en texto, un mapa de OpenStreetMap o Google Maps en un iframe con title y loading="lazy", y un vídeo de presentación de YouTube incrustado con youtube-nocookie.com, sin atributos obsoletos y con proporción 16:9 flexible mediante CSS.

Ejercicio 7: Iconos SVG propios

Dibuja con SVG en línea tres iconos sencillos de 24 × 24 (una casa, un sobre y una estrella) usando solo rect, circle, polygon y line, con fill="currentColor" o stroke="currentColor". Úsalos en un menú de tres enlaces (Inicio, Contacto, Favoritos), ocultando los iconos a los lectores de pantalla. Cambia el color del enlace con un style y comprueba que los iconos cambian también.

Ejercicio 8: Auditoría multimedia

Toma la página del ejercicio 1 y pásale Lighthouse en modo móvil. Después introduce estos errores a propósito: elimina el alt de una imagen, quita width y height de otra y sustituye una imagen por su versión original sin comprimir. Vuelve a pasar Lighthouse, anota qué avisos aparecen y cómo cambia la puntuación, y corrige todo.


Resumen

Concepto Sintaxis / idea clave
Imagen <img src="..." alt="..." width="..." height="...">
alt Describe la función o el contenido; alt="" si es decorativa; nunca omitirlo
width / height Dimensiones reales: evitan saltos (CLS)
Carga diferida loading="lazy" (no en la imagen principal)
Prioridad fetchpriority="high" en la imagen principal
Decodificación decoding="async"
Formatos Fotos: AVIF/WebP/JPEG. Transparencia: WebP/PNG. Logos e iconos: SVG. Animación: vídeo
Densidad srcset="a.jpg 1x, b.jpg 2x"
Ancho variable srcset="a.jpg 400w, b.jpg 800w" + sizes="(max-width: 600px) 100vw, 50vw"
Formatos con respaldo <picture><source type="image/avif" srcset="..."><img ...></picture>
Dirección de arte <source media="(min-width: 1000px)" srcset="...">
Figura <figure> + <figcaption>
Audio <audio controls> + <source src="..." type="audio/mpeg">
Vídeo <video controls poster="..." width height> + <source>
Subtítulos <track src="x.vtt" kind="subtitles" srclang="es" label="Español" default>
Autoplay Solo con muted (y playsinline en iOS); nunca con sonido
Iframe <iframe src="..." title="..." loading="lazy">
YouTube youtube-nocookie.com/embed/ID, allowfullscreen, sin frameborder
Seguridad iframe sandbox="allow-scripts allow-forms", allow="..."
SVG en línea <svg viewBox="0 0 w h"> con rect, circle, path, fill="currentColor"
SVG accesible Decorativo: aria-hidden="true". Informativo: role="img" + <title>