Imágenes, Tablas y Formularios

Aprendé a mostrar imágenes, organizar datos en tablas y crear formularios para recolectar información del usuario.

Imágenes

La etiqueta <img> inserta una imagen en la página. Es una etiqueta vacía — no tiene etiqueta de cierre — y requiere dos atributos obligatorios: src (la ruta de la imagen) y alt (texto alternativo).

<!-- Imagen desde una URL externa -->
<img src="https://picsum.photos/300/200" alt="Foto aleatoria">

<!-- Imagen desde un archivo local -->
<img src="fotos/perfil.jpg" alt="Foto de perfil">

<!-- Con ancho y alto explícitos -->
<img src="logo.png" alt="Logo de la empresa" width="200" height="100">

<!-- Imagen con título (tooltip al pasar el mouse) -->
<img src="foto.jpg" alt="Paisaje" title="Tomada en Patagonia">
alt es obligatorio

El atributo alt describe la imagen para lectores de pantalla (accesibilidad) y se muestra cuando la imagen no carga. Si la imagen es puramente decorativa, usá alt="" — vacío pero presente.

Rutas de archivos

<!-- Misma carpeta que el HTML -->
<img src="foto.jpg" alt="...">

<!-- Subcarpeta -->
<img src="imagenes/foto.jpg" alt="...">

<!-- Carpeta superior -->
<img src="../foto.jpg" alt="...">

<!-- Ruta absoluta desde la raíz del sitio -->
<img src="/assets/img/foto.jpg" alt="...">

Imagen como enlace

<!-- Envolver la imagen en un <a> la convierte en enlace -->
<a href="https://ejemplo.com">
    <img src="banner.jpg" alt="Visitá nuestro sitio">
</a>

Figure y figcaption

Para imágenes con descripción, HTML5 ofrece las etiquetas semánticas <figure> y <figcaption>:

<figure>
    <img src="grafico.png" alt="Gráfico de ventas 2026">
    <figcaption>Fig. 1 — Evolución de ventas durante 2026.</figcaption>
</figure>
Formatos de imagen más usados

JPG para fotos (compresión alta, sin transparencia). PNG para gráficos y logos (soporta transparencia). SVG para iconos e ilustraciones vectoriales. WebP para web moderno (mejor compresión que JPG/PNG).

Probá el Ejemplo 1: Imágenes

Tablas

Las tablas organizan datos en filas y columnas. Están pensadas para datos tabulares — nunca para hacer layouts de página (eso es tarea del CSS).

Estructura básica

<table>
    <thead>                          <!-- Encabezado de la tabla -->
        <tr>                         <!-- Fila (table row) -->
            <th>Nombre</th>          <!-- Celda de encabezado (table header) -->
            <th>Edad</th>
            <th>Ciudad</th>
        </tr>
    </thead>
    <tbody>                          <!-- Cuerpo de la tabla -->
        <tr>
            <td>Ana García</td>      <!-- Celda de datos (table data) -->
            <td>28</td>
            <td>Córdoba</td>
        </tr>
        <tr>
            <td>Carlos López</td>
            <td>35</td>
            <td>Buenos Aires</td>
        </tr>
    </tbody>
    <tfoot>                          <!-- Pie de tabla (opcional) -->
        <tr>
            <td colspan="3">Total: 2 usuarios</td>
        </tr>
    </tfoot>
</table>

<table>

Contenedor de la tabla

<thead> / <tbody> / <tfoot>

Secciones semánticas

<tr>

Fila (table row)

<th> / <td>

Encabezado / Dato

colspan y rowspan — combinar celdas

<table>
    <thead>
        <tr>
            <th colspan="2">Nombre Completo</th>  <!-- ocupa 2 columnas -->
            <th>País</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>Ana</td>
            <td>García</td>
            <td rowspan="2">Argentina</td>  <!-- ocupa 2 filas -->
        </tr>
        <tr>
            <td>Carlos</td>
            <td>López</td>
            <!-- la celda Argentina ya cubre esta fila -->
        </tr>
    </tbody>
</table>
scope en <th> — accesibilidad

Agregá scope="col" a los encabezados de columna y scope="row" a los de fila. Los lectores de pantalla lo usan para asociar celdas con sus encabezados.

Probá el Ejemplo 2: Tablas

Formularios

Los formularios permiten al usuario enviar datos. La etiqueta <form> agrupa todos los campos. Los atributos action y method definen a dónde y cómo se envían los datos.

<form action="/procesar.php" method="POST">
    <!-- campos aquí -->
    <button type="submit">Enviar</button>
</form>
AtributoValorDescripción
actionURLA dónde se envían los datos
methodGET / POSTGET: datos en la URL. POST: datos ocultos en el cuerpo
novalidate—Desactiva la validación nativa del navegador
autocompleteon / offActiva o desactiva el autocompletado

Campos de texto y contraseña

<!-- Texto simple -->
<label for="nombre">Nombre:</label>
<input type="text" id="nombre" name="nombre" placeholder="Escribí tu nombre">

<!-- Contraseña —oculta los caracteres -->
<label for="pass">Contraseña:</label>
<input type="password" id="pass" name="pass">

<!-- Email — valida el formato automáticamente -->
<input type="email" name="email" placeholder="usuario@ejemplo.com">

<!-- Número -->
<input type="number" name="edad" min="1" max="120">

<!-- Texto largo -->
<label for="bio">Descripción:</label>
<textarea id="bio" name="bio" rows="4" cols="40"></textarea>
label y for/id — siempre relacionados

El for del <label> debe coincidir con el id del campo. Esto hace que al hacer clic en el texto del label el foco vaya al campo — mejora la usabilidad y la accesibilidad.

Tipos de input más usados

<!-- Checkbox —puede seleccionar varios -->
<input type="checkbox" id="acepta" name="acepta" value="si">
<label for="acepta">Acepto los términos</label>

<!-- Radio —solo uno del grupo -->
<input type="radio" id="masculino" name="genero" value="M">
<label for="masculino">Masculino</label>

<input type="radio" id="femenino" name="genero" value="F">
<label for="femenino">Femenino</label>

<!-- Select —lista desplegable -->
<select name="pais">
    <option value="">— Elegí un país —</option>
    <option value="AR">Argentina</option>
    <option value="BR">Brasil</option>
    <option value="UY" selected>Uruguay</option>
</select>

<!-- Fecha -->
<input type="date" name="nacimiento">

<!-- Rango (slider) -->
<input type="range" name="volumen" min="0" max="100" value="50">

<!-- Color -->
<input type="color" name="favorito" value="#264DE4">

<!-- Archivo -->
<input type="file" name="foto" accept="image/*">

<!-- Oculto —no se muestra pero se envía -->
<input type="hidden" name="userId" value="42">
Probá el Ejemplo 3: Tipos de input

Atributos de validación

HTML5 incluye validación nativa sin JavaScript. El navegador verifica estos atributos antes de enviar el formulario:

<!-- required — campo obligatorio -->
<input type="text" name="nombre" required>

<!-- minlength / maxlength — longitud del texto -->
<input type="text" name="usuario" minlength="3" maxlength="20">

<!-- min / max — para números y fechas -->
<input type="number" name="edad" min="18" max="99">
<input type="date" name="fecha" min="2020-01-01" max="2026-12-31">

<!-- pattern — expresión regular -->
<input type="text" name="codigo" pattern="[A-Z]{3}-[0-9]{4}"
       placeholder="Ej: ABC-1234"
       title="Formato: 3 letras mayúsculas, guión, 4 números">

<!-- disabled — deshabilita el campo (no se envía) -->
<input type="text" name="id" value="42" disabled>

<!-- readonly — solo lectura (sí se envía) -->
<input type="text" name="codigo" value="A-001" readonly>
Validación HTML vs validación del servidor

La validación HTML es solo una primera capa de comodidad para el usuario. Siempre validá también en el servidor — cualquiera puede desactivar la validación del navegador o enviar datos directamente a tu endpoint.

Botones

<!-- submit — envía el formulario -->
<button type="submit">Enviar</button>

<!-- reset — limpia todos los campos al valor inicial -->
<button type="reset">Limpiar</button>

<!-- button — sin comportamiento por defecto (para JS) -->
<button type="button" onclick="calcular()">Calcular</button>

<!-- input type submit —equivalente pero sin HTML dentro -->
<input type="submit" value="Enviar">
Preferí <button> sobre <input type="submit">

<button> acepta HTML adentro — podés poner iconos, spans con estilos, etc. <input type="submit"> solo admite texto plano.

fieldset y legend — agrupar campos

<fieldset> agrupa campos relacionados y <legend> le da un título al grupo. Mejora la organización visual y la accesibilidad.

<form action="/registro" method="POST">

    <fieldset>
        <legend>Datos personales</legend>

        <label for="nombre">Nombre:</label>
        <input type="text" id="nombre" name="nombre" required>

        <label for="email">Email:</label>
        <input type="email" id="email" name="email" required>
    </fieldset>

    <fieldset>
        <legend>Contraseña</legend>

        <label for="pass">Contraseña:</label>
        <input type="password" id="pass" name="pass" minlength="8" required>

        <label for="pass2">Repetir contraseña:</label>
        <input type="password" id="pass2" name="pass2" required>
    </fieldset>

    <button type="submit">Registrarse</button>

</form>
Probá el Ejemplo 4: Formulario de registro completo

Buenas Prácticas

  • Siempre alt en las imágenes: vacío alt="" si son decorativas, descriptivo si aportan contenido
  • Definí width y height en imágenes: el navegador reserva el espacio antes de cargar y evita el salto de layout (CLS)
  • Tablas solo para datos tabulares: nunca para maquetar columnas o layouts — para eso usá CSS Flexbox o Grid
  • Siempre usá label con for/id: es clave para usabilidad y lectores de pantalla
  • name en cada campo: sin name el campo no se envía en el formulario
  • Validación HTML como primera capa: completala siempre con validación del lado del servidor
  • method="POST" para datos sensibles: contraseñas, información personal, pagos — nunca GET