El problema: HTML básico no te consigue trabajo
Cuando empiezas con HTML, aprendes <div>, <p>, <form> y crees que con eso ya vas. Haces un formulario, funciona, lo subes a tu portfolio y esperas que alguien lo vea.
El problema es que cualquier desarrollador con algo de experiencia abre el inspector del navegador y ve el HTML. Si está lleno de divs sin sentido y formularios sin validación, da igual que visualmente esté bonito. Aquí es donde la mayoría se atasca sin saber por qué.
¿Qué vamos a aprender?
- Formularios HTML que validan sin JavaScript
- Atributos ARIA para accesibilidad real
- HTML semántico: cuándo usar
<section>,<article>,<nav> - Por qué importa en tu CV y en el trabajo
- Errores que cometen todos los principiantes
Formularios HTML: validación nativa sin JavaScript
La mayoría de principiantes hacen formularios así:
<form>
<input type="text" name="email">
<input type="text" name="telefono">
<button>Enviar</button>
</form>
Funciona. Pero cuando alguien escribe un número de teléfono en el campo de email, o lo deja vacío y le da a enviar, no pasa nada. Ahí empieza el lío: añades JavaScript para validar, luego más JavaScript para el teléfono, y acabas con 50 líneas de código para algo que HTML ya hace solo.
Mira esto:
<form>
<label for="email">Tu email:</label>
<input
type="email"
id="email"
name="email"
required
placeholder="tu@email.com"
>
<label for="telefono">Teléfono:</label>
<input
type="tel"
id="telefono"
name="telefono"
pattern="[0-9]{9}"
required
>
<button type="submit">Enviar</button>
</form>
¿Ves la diferencia? Ahora:
type="email"→ Valida automáticamente que sea un emailrequired→ El usuario DEBE rellenar el campopattern="[0-9]{9}"→ Solo acepta 9 números<label>→ Accesible para pantallas lectoras
❌ Error común: poner type="text" para todo
Es lo primero que hace todo el mundo, yo incluido. El problema es que pierdes toda la validación nativa del navegador. Con type="email" el navegador ya comprueba que hay una @ y un dominio. Con type="text" te comes cualquier cosa.
Tipos de input avanzados que no conocías
HTML5 trae inputs que hacen validación sola:
<!-- Email con validación nativa -->
<input type="email" required>
<!-- Número con rango -->
<input type="number" min="18" max="65">
<!-- Fecha -->
<input type="date" >
<!-- Color (abre selector de color) -->
<input type="color">
<!-- URL con validación -->
<input type="url" required>
<!-- Archivo (para subir) -->
<input type="file" accept=".jpg,.png">
<!-- Selector con sugerencias -->
<input list="paises">
<datalist id="paises">
<option>España</option>
<option>México</option>
<option>Argentina</option>
</datalist>
Todo esto funciona sin JavaScript. El navegador lo maneja automáticamente.
HTML Semántico: cuándo usar qué etiqueta
Esto me costó pillarlo. Al principio todo era <div class="header">, <div class="nav">, <div class="article">. Funciona visualmente igual. Pero semántica significa que el HTML describe QUÉ es el contenido, no solo CÓMO se ve. Y eso importa para SEO, para accesibilidad, y para que otro desarrollador entienda tu código sin querer matarte.
<!-- ❌ MAL: Divs para todo -->
<div class="header">
<div class="nav">
<a href="/">Inicio</a>
</div>
</div>
<div class="main">
<div class="article">
<h1>Título</h1>
</div>
</div>
<!-- ✅ BIEN: Etiquetas semánticas -->
<header>
<nav>
<a href="/">Inicio</a>
</nav>
</header>
<main>
<article>
<h1>Título</h1>
</article>
</main>
Cuándo usar cada etiqueta semántica
- <header> - Encabezado de la página o sección (logo, nav principal)
- <nav> - Navegación principal (menú)
- <main> - Contenido principal de la página (solo UNO por página)
- <article> - Contenido independiente (un post, un comentario, una noticia)
- <section> - Agrupar contenido relacionado dentro de un artículo
- <aside> - Contenido relacionado pero secundario (sidebar, publicidad)
- <footer> - Pie de página (copyright, links legales)
Regla de oro: si puedes preguntar "¿esto es un artículo completo?" y la respuesta es sí, usa <article>. Si es solo una sección dentro de un artículo, usa <section>.
Accesibilidad: ARIA y atributos que importan
La accesibilidad es donde más se nota si alguien sabe HTML o solo lo ha visto por encima. Un botón con solo un icono ✕ sin texto, para un lector de pantalla no dice nada. Literalmente lee "✕". Así de fácil es romper la accesibilidad sin darte cuenta.
Los atributos ARIA (Accessible Rich Internet Applications) le dicen a los lectores de pantalla qué hace cada elemento:
<!-- Botón con etiqueta accesible -->
<button aria-label="Cerrar menú">✕</button>
<!-- Alertas dinámicas -->
<div role="alert">Error: Completa todos los campos</div>
<!-- Carrusel accesible -->
<div role="region" aria-label="Imágenes destacadas">
<!-- Contenido -->
</div>
<!-- Campos con descripción oculta -->
<label for="password">Contraseña:</label>
<input id="password" type="password" aria-describedby="pwd-hint">
<small id="pwd-hint">Mínimo 8 caracteres</small>
❌ Error común: alt="" en todas las imágenes
O peor: alt="imagen". Un lector de pantalla lee eso literalmente. Si la imagen muestra un formulario de registro, el alt debería ser algo como "Formulario de registro con campos de nombre y email". Si es solo decorativa, vacío está bien. Pero ponlo vacío a propósito, no porque no supiste qué poner.
Un formulario profesional juntando todo
Ahora vamos a juntar formularios, semántica y accesibilidad en un ejemplo real:
<form>
<fieldset>
<legend>Tus datos personales</legend>
<div>
<label for="nombre">Nombre completo:</label>
<input
type="text"
id="nombre"
name="nombre"
required
minlength="3"
>
</div>
<div>
<label for="email">Email:</label>
<input
type="email"
id="email"
name="email"
required
>
</div>
<div>
<label for="edad">Edad:</label>
<input
type="number"
id="edad"
name="edad"
min="13"
max="120"
>
</div>
</fieldset>
<fieldset>
<legend>Preferencias</legend>
<div>
<input type="checkbox" id="newsletter" name="newsletter">
<label for="newsletter">Recibir newsletter</label>
</div>
</fieldset>
<button type="submit">Enviar</button>
</form>
El <fieldset> agrupa campos relacionados y <legend> les da nombre. Un lector de pantalla cuando llega al campo de email sabe que está dentro de "Tus datos personales". Sin eso, simplemente lee "Email" sin contexto de nada.
El siguiente paso: añade JavaScript solo donde HTML no llega
La validación nativa de HTML cubre el 80% de los casos. Para el otro 20% — comparar que dos contraseñas coincidan, validar en tiempo real mientras escribes, mostrar mensajes de error personalizados — ahí sí tiene sentido añadir JavaScript.
Pero empieza siempre por el HTML. Es más rápido, funciona sin JavaScript activado, y es lo que hace que tu código sea mantenible.
🎯 ¿Quieres añadir validación JavaScript encima de esto?
Ya tienes la base de HTML bien hecha. El siguiente post te enseña a añadir validaciones más complejas con JavaScript sin tirar lo que has aprendido aquí.
👉 Validaciones de formularios con JavaScriptMensajes de error personalizados, validación en tiempo real y más.
📚 Si llegaste aquí sin tener claro el HTML básico
👉 Empieza por HTML5 para principiantesMejor tener la base antes de lo avanzado. Sin prisas.