learning-front

Nivel 1 · HTML y CSS: la estructura y la piel

Imágenes, listas y tablas

Los tres elementos que completan el vocabulario HTML básico: cómo incrustar imágenes con un alt que de verdad ayuda, cómo marcar listas eligiendo entre ul y ol con criterio, y cuándo y cómo construir una tabla de datos correcta.

Ya tienes texto y enlaces en la ficha. La página funciona, pero aún parece un documento de texto: le faltan imágenes para poner cara a los héroes, listas para organizar la información en grupos, y tablas para mostrar datos que se relacionan entre sí. Esos tres elementos son el vocabulario que cierra el HTML básico.

Seguimos con la ficha de Tracer. Al terminar el capítulo tendrá imagen, lista de habilidades y una tabla de estadísticas del equipo: Tracer, Reinhardt y Mercy.

Imágenes: <img>, src y alt#

La imagen en HTML es un elemento vacío —sin contenido y sin cierre— que le dice al navegador dónde está el fichero y qué muestra:

html
<img src="tracer.png" alt="Tracer apuntando con su pistola de pulso" />
<!-- src="tracer.png" es la ruta al fichero de imagen
     alt="..." describe lo que muestra la imagen para quien no puede verla -->
  • src (source) es la ruta al fichero: puede ser relativa (tracer.png, img/heroes/tracer.webp) o una URL completa. Sin src, no hay imagen.
  • alt es el texto alternativo. Es el atributo más importante de <img> y, sin embargo, el que más se descuida.

El alt tiene dos modos, y elegir bien importa#

La regla de fondo es que el alt debe transmitir la misma información que transmitiría la imagen si se pudiera ver. De ahí que haya dos situaciones distintas:

Alt informativo — cuando la imagen aporta algo que no está ya en el texto:

html
<img src="tracer.png" alt="Tracer apuntando con su pistola de pulso" />
<!-- alt informativo: describe la imagen porque esa información no está en otro sitio -->

El alt describe lo que muestra la imagen. Si no carga (red lenta, ruta rota, imagen bloqueada), aparece ese texto. Si el usuario tiene lector de pantalla, lo oye en voz alta.

Alt decorativo — cuando la información ya está en el texto cercano:

html
<!-- el nombre ya está aquí en texto -->
<h1>Tracer</h1>
<!-- la descripción también ya está -->
<p>Heroína de daño. Rápida y escurridiza.</p>
<!-- alt="" vacío: la imagen es decorativa, no repite información -->
<img src="tracer.png" alt="" />

Aquí el <h1> y el <p> ya describen a Tracer: la imagen es decorativa. Con alt="" vacío el lector de pantalla sabe que debe saltársela. Si pusiéramos el mismo texto del encabezado, el usuario lo oiría dos veces. Y si omitiéramos el atributo alt por completo, muchos lectores de pantalla leerían la ruta del fichero, que no informa de nada.

La pregunta que guía la decisión es: ¿quitando la imagen, pierde el usuario alguna información que no esté en el texto? Si sí, alt informativo. Si no, alt="".

width y height: reservar el hueco#

html
<img src="tracer.png" alt="..." width="120" height="120" />

Cuando el navegador no sabe el tamaño de la imagen antes de descargarla, dibuja la página sin ese hueco. Cuando llega la imagen, la inserta y recoloca todo lo que había debajo: ese salto brusco del contenido se llama layout shift y es molesto. Con width y height en el HTML, el navegador reserva el espacio desde el principio aunque la imagen tarde.

Los formatos más comunes son jpg (fotos), png (transparencias), svg (iconos y gráficos vectoriales) y webp (más compacto que jpg o png para fotos). En este capítulo no entran los detalles de cada uno; lo que importa es que <img> funciona igual con todos.

Listas: <ul>, <ol> y <li>#

Una lista en HTML no es solo “varios elementos seguidos”: es una agrupación con un significado. Hay dos tipos, y la elección entre ellos es la primera decisión que hay que tomar:

  • <ul> (unordered list) — lista sin orden: los elementos forman un conjunto en el que cambiar el orden no cambia el significado.
  • <ol> (ordered list) — lista con orden: la secuencia importa. Cambiar el orden cambia el resultado.

En ambas, cada elemento de la lista va en un <li> (list item):

html
<!-- ul: las habilidades de Tracer en cualquier orden son las mismas habilidades -->
<ul>
  <li>Parpadeo</li>
  <li>Retroceso</li>
  <li>Bomba de pulso</li>
</ul>

<!-- ol: los pasos de la combo de Reinhardt en este orden concreto -->
<ol>
  <li>Golpe de martillo</li>
  <li>Embestida</li>
  <li>Terremoto</li>
</ol>

El navegador pinta <ul> con viñetas y <ol> con números, pero eso es el estilo por defecto: el CSS puede cambiarlo. La distinción que importa es la del significado, no el aspecto.

Una lista puede anidarse dentro de otro <li> para crear subniveles:

html
<!-- lista exterior: las categorías de héroe -->
<ul>
  <!-- un elemento de la lista exterior... -->
  <li>Héroes de daño
    <!-- ...que contiene a su vez otra lista (anidada) -->
    <ul>
      <!-- elemento de la lista interior -->
      <li>Tracer</li>
      <!-- otro elemento de la lista interior -->
      <li>Soldier: 76</li>
    <!-- cierra la lista interior -->
    </ul>
  <!-- cierra el elemento "Héroes de daño" -->
  </li>
  <!-- otro elemento de la lista exterior con su sublista -->
  <li>Héroes de apoyo
    <!-- segunda lista anidada -->
    <ul>
      <!-- elemento de la sublista -->
      <li>Mercy</li>
      <!-- otro elemento de la sublista -->
      <li>Ana</li>
    <!-- cierra la segunda sublista -->
    </ul>
  <!-- cierra el elemento "Héroes de apoyo" -->
  </li>
<!-- cierra la lista exterior -->
</ul>

Listas de descripción: parejas de término y dato#

A veces lo que tienes no es una secuencia de elementos, sino parejas de un término y su valor: las estadísticas de un héroe (Partidas: 120, Victorias: 78), las características de un producto o los campos de una ficha. Para eso hay una tercera lista, la lista de descripción <dl> (description list):

html
<!-- description list: contenedor de parejas término–valor -->
<dl>
  <!-- dt = el término (la etiqueta) -->
  <dt>Partidas</dt>
  <!-- dd = el valor que corresponde al término de arriba -->
  <dd>120</dd>
  <!-- otro término -->
  <dt>Victorias</dt>
  <!-- su valor -->
  <dd>78</dd>
  <!-- tercer término -->
  <dt>Winrate</dt>
  <!-- su valor -->
  <dd>65%</dd>
<!-- cierra la lista de descripción -->
</dl>

Cada término va en un <dt> (description term) y su valor en el <dd> (description details) que lo sigue. Un mismo <dt> puede tener varios <dd> si un término tiene varios valores. Frente a escribir “Partidas: 120” en un párrafo suelto, el <dl> deja explícito en el HTML qué es etiqueta y qué es dato: un lector de pantalla los anuncia como pares, y tú puedes estilar el término y el valor por separado.

Tablas: datos que se relacionan entre sí#

Una tabla sirve para presentar datos tabulares: información que tiene sentido precisamente porque cruza filas y columnas. La tabla de estadísticas del equipo —héroe, rol, partidas, victorias— es el ejemplo perfecto.

Lo que no es una tabla: un bloque de texto con columnas por aspecto. Las tablas se usaron durante años para maquetar páginas enteras (columnas, cabeceras, pie). Eso ya no se hace; hoy existe CSS para eso. Una tabla HTML es solo para datos.

Las piezas de una tabla#

html
<!-- contenedor de toda la tabla -->
<table>
  <!-- título de la tabla, asociado a ella -->
  <caption>Estadísticas del equipo — temporada actual</caption>
  <!-- zona de cabeceras de columna -->
  <thead>
    <!-- una fila (table row) -->
    <tr>
      <!-- celda de cabecera de columna (scope="col") -->
      <th scope="col">Héroe</th>
      <!-- cabecera de columna -->
      <th scope="col">Rol</th>
      <!-- cabecera de columna -->
      <th scope="col">Partidas</th>
      <!-- cabecera de columna -->
      <th scope="col">Victorias</th>
      <!-- cabecera de columna -->
      <th scope="col">Winrate</th>
    <!-- cierra la fila de cabeceras -->
    </tr>
  <!-- cierra la cabecera -->
  </thead>
  <!-- zona del cuerpo: los datos -->
  <tbody>
    <!-- fila de datos de un héroe -->
    <tr>
      <!-- cabecera de fila (scope="row"): nombra la fila, no es un dato -->
      <th scope="row">Tracer</th>
      <!-- celda de dato (table data) -->
      <td>Daño</td>
      <!-- celda de dato -->
      <td>120</td>
      <!-- celda de dato -->
      <td>78</td>
      <!-- celda de dato -->
      <td>65 %</td>
    <!-- cierra la fila de Tracer -->
    </tr>
    <!-- otra fila de datos -->
    <tr>
      <!-- cabecera de fila -->
      <th scope="row">Reinhardt</th>
      <!-- celda de dato -->
      <td>Tanque</td>
      <!-- celda de dato -->
      <td>90</td>
      <!-- celda de dato -->
      <td>51</td>
      <!-- celda de dato -->
      <td>57 %</td>
    <!-- cierra la fila de Reinhardt -->
    </tr>
    <!-- otra fila de datos -->
    <tr>
      <!-- cabecera de fila -->
      <th scope="row">Mercy</th>
      <!-- celda de dato -->
      <td>Apoyo</td>
      <!-- celda de dato -->
      <td>200</td>
      <!-- celda de dato -->
      <td>130</td>
      <!-- celda de dato -->
      <td>65 %</td>
    <!-- cierra la fila de Mercy -->
    </tr>
  <!-- cierra el cuerpo -->
  </tbody>
<!-- cierra la tabla -->
</table>

Pieza a pieza:

  • <table> — el contenedor de todo.
  • <caption> — el título de la tabla, asociado a ella por el navegador (no es solo texto encima). El lector de pantalla lo anuncia antes de entrar en la tabla.
  • <thead> y <tbody> — separan las cabeceras del cuerpo de datos. No es obligatorio, pero hace el código más fácil de leer y permite que el navegador repita la cabecera si la tabla se imprime en varias páginas.
  • <tr> (table row) — una fila.
  • <th> (table header) — una celda de encabezado: nombra la columna o la fila. El atributo scope dice a qué aplica: scope="col" para cabeceras de columna, scope="row" para cabeceras de fila. Con él, el lector de pantalla asocia cada dato a su cabecera sin ambigüedad.
  • <td> (table data) — una celda de dato.

Pruébalo#

La ficha de Tracer con los tres elementos. La imagen usa un placeholder porque en el playground no hay ficheros de imagen. Edita el alt, cambia un número de la tabla o añade un <li>, y mira el resultado.

Comprueba lo que sabes#

Pregunta 1 de 5

Una imagen tiene un pie de foto justo debajo que ya dice "Tracer, heroína de daño". ¿Qué alt le pones a la imagen?

Tu turno#

Amplía la ficha de Tracer con imagen, lista y tabla, aquí mismo en el playground. La imagen puede ser un placeholder o un nombre de fichero de ejemplo: lo que importa es practicar los atributosalt, width, height— y decidir entre <ul> y <ol> con criterio. Edita el HTML en la pestaña izquierda y comprueba el resultado en el preview. Cuando creas que lo tienes, despliega las soluciones y compáralas con la tuya.

Ejercicio · en esta página

La ficha de Tracer: imagen, lista y tabla

Partiendo del esqueleto que ya conoces, amplía la ficha de Tracer añadiendo: (a) una imagen con el alt correcto, (b) una lista de sus habilidades eligiendo ul u ol según si el orden importa, y (c) una tabla de estadísticas del equipo con Tracer, Reinhardt y Mercy. Para la imagen usa la URL https://placehold.co/120x120 o el nombre "tracer.png" como ejemplo (el fichero no existe; lo que importa es practicar los atributos).

Paso 1: La información se ve

  • La imagen aparece en la página (o el texto del alt si la URL no carga).
  • Las habilidades están en la página, aunque sea como párrafos con guiones.
  • Las estadísticas están en la página, aunque sea como texto suelto.
Ver soluciones
<!doctype html>
<html lang="es">
  <head>
    <meta charset="utf-8" />
    <title>Tracer — Overwatch Team Builder</title>
  </head>
  <body>
    <h1>Tracer</h1>
    <p>Heroína de daño. Rápida y escurridiza: su trabajo es presionar la retaguardia rival.</p>

    <img src="https://placehold.co/120x120" />

    <h2>Habilidades</h2>
    <p>- Parpadeo</p>
    <p>- Retroceso</p>
    <p>- Bomba de pulso</p>

    <h2>Estadísticas del equipo</h2>
    <p>Tracer: Daño, 120 partidas, 78 victorias</p>
    <p>Reinhardt: Tanque, 90 partidas, 51 victorias</p>
    <p>Mercy: Apoyo, 200 partidas, 130 victorias</p>
  </body>
</html>

Por qué este nivel

  • La información está: se ve la imagen (o el placeholder), las habilidades y las estadísticas. Cumple el mínimo.
  • La imagen no tiene alt. Si la URL no carga, el navegador puede mostrar la ruta del fichero; un lector de pantalla no sabe qué hay ahí.
  • Las habilidades son párrafos con guiones: visualmente se parecen a una lista, pero el navegador no sabe que son una lista. No tienen estructura semántica.
  • Las estadísticas son párrafos de texto: para el navegador son frases sueltas, no datos relacionados. No hay forma de navegar por columnas ni de saber que "120" es el número de partidas.