Módulo 03: Imágenes y multimedia
Objetivos del módulo
- Insertar imágenes con
imgy 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
srcsetysizes - Usar
pictureysourcepara dirección de arte y formatos modernos con alternativa - Asociar pies de foto con
figureyfigcaption - Incrustar audio y vídeo nativos, con varias fuentes, póster y subtítulos
- Incrustar contenido externo (YouTube, mapas) con
iframede 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
alten voz alta. - La imagen no carga (conexión lenta, ruta incorrecta): se muestra el texto en su lugar.
- Los buscadores indexan la imagen: el
altles dice qué contiene.
📘 Concepto: Un buen
altresponde 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, escribealt=""(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
widthyheight, 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
widthyheightlas 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
srcsettú das el menú (las versiones disponibles y su tamaño) y consizesdas 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 asume100vw(todo el ancho de la ventana) y puede descargar imágenes más grandes de lo necesario. Consizes="auto"yloading="lazy", los navegadores que lo soportan calculan el tamaño automáticamente, pero no todos lo admiten todavía: indicasizesde forma explícita.
⚠️ Importante: Las versiones de
srcsetdeben 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 (lossourcesolo le cambian el fichero), así que es el que llevaalt,width,heightyloading.
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>
figcaptionpuede ir al principio o al final delfigure, pero solo puede haber uno.- Un
figurepuede 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:
figcaptionyaltno son lo mismo. Elaltsustituye a la imagen para quien no la ve; elfigcaptioncomplementa 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
autoplayen 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
autoplayfuncione, 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ñadecontrolso 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.vttpor seguridad. Usa Live Server. Además, el fichero.vttdebe 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-scriptsyallow-same-originpara contenido de tu propio dominio: el contenido podría eliminar el propiosandboxy 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-OptionsoContent-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.widthyheightdefinen el tamaño en pantalla. Si cambiaswidtha 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.htmlreú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> |