Cheatsheet HTML
Linguagem de marcação para páginas web
HTML
Estructura básica
Documento HTML5 Completo
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, initial-scale=1.0">
<title>Mi Página</title>
</head>
<body>
<h1>Hola Mundo</h1>
</body>
</html>Estructura mínima obligatoria. <!DOCTYPE html> declara HTML5. lang="es" define el idioma. <meta charset> garantiza las tildes correctas. <meta viewport> hace la página responsive.
Body — Contenido Visible
<body>
<header>Encabezado</header>
<main>
<h1>Contenido principal</h1>
<p>Texto visible ao usuario.</p>
</main>
<footer>Pie de página</footer>
</body>El <body> contiene todo el contenido visible. Todo lo que el usuario ve está aquí. Usa etiquetas semánticas como <header>, <main> y <footer> para organizar.
Atributos data-*
<li data-id="42" data-nombre="Ana"
data-activo="true">
Item personalizado
</li>
<!-- JavaScript: -->
<!-- el.dataset.id → "42" -->
<!-- el.dataset.nombre → "Ana" -->Los atributos data-* guardan datos personalizados en el HTML. Accede vía element.dataset.nombre en JavaScript. Útiles para pasar información sin APIs externas.
DOCTYPE
<!DOCTYPE html>
Debe ser siempre la primera línea del archivo. Informa al navegador que el documento es HTML5. Sin él, el navegador entra en quirks mode (modo de compatibilidad antiguo).
Comentarios
<!-- Comentario simples --> <!-- Comentario multi-linea --> <!-- [if IE]> Solo no Internet Explorer <![endif] -->
Los comentarios son ignorados por el navegador. Útiles para documentar el código. No los uses para "esconder" contenido — es visible en View Source. El formato es <!-- texto -->.
Atributos Globales
<div id="app" class="box" style="color:red"
title="Tooltip" hidden tabindex="0"
contenteditable="true" draggable="true"
data-info="extra" lang="es" dir="ltr">
Editable e arrastrable
</div>Los atributos globales funcionan en cualquier etiqueta. hidden oculta, title muestra un tooltip, tabindex define el orden de tab, contenteditable lo hace editable, draggable permite arrastrar.
Elemento html y lang
<html lang="es"> <html lang="pt-BR"> <html lang="en">
El atributo lang define el idioma de la página. Esencial para SEO, lectores de pantalla y traducción automática. Usa códigos ISO 639-1 (pt, en, es).
Div y Span
<div class="container"> <p>Bloco genérico (block-level)</p> </div> <span class="highlight">Inline genérico</span>
<div> es un contenedor de bloque (ocupa toda la línea). <span> es inline (solo ocupa el contenido). Ambos no tienen significado — úsalos con CSS y JavaScript.
Entidades HTML
< = < > = > & = & " = " = espacio © = © ® = ® → = → ♥ = ♥ 😀 = 😀
Las entidades representan caracteres especiales. < y > para < y >. es un espacio que no rompe. Usa códigos numéricos (😀) para emojis.
Head — Metadatos
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, initial-scale=1.0">
<meta name="description" content="Resumen da página">
<title>Título de la Pestaña</title>
<link rel="stylesheet" href="estilo.css">
</head>El <head> contiene metadatos invisibles. El <title> aparece en la pestaña y en Google. El <link> importa CSS. Los metadatos no aparecen en la página.
Atributos id y class
<div id="encabezado" class="caja highlight">
<p id="intro" class="texto grande">
Contenido
</p>
</div>id es único en la página (1 elemento). class puede repetirse y un elemento puede tener varias clases. Usa id para anclas y JS; class para estilos CSS reutilizables.
Texto y formato
Títulos h1 a h6
<h1>Título principal (1 por página)</h1> <h2>Subtítulo de sección</h2> <h3>Sub-sección</h3> <h4>Detalle</h4> <h5>Sub-detalle</h5> <h6>Menor título</h6>
Seis niveles jerárquicos. Usa solo un <h1> por página. No saltes niveles (ej: h2 → h4). La jerarquía es importante para SEO y accesibilidad.
Superíndice y Subíndice
<p>E = mc<sup>2</sup></p> <p>H<sub>2</sub>O</p> <p>10<sup>3</sup> = 1000</p> <p>CO<sub>2</sub> es dióxido de carbono</p>
<sup> eleva el texto (exponentes, notas). <sub> lo baja (fórmulas químicas). Esenciales para notación matemática y científica.
Dirección de Texto y Unicode
<p dir="rtl">Texto da derecha para izquierda</p> <p dir="ltr">Texto normal (izquierda→derecha)</p> <bdo dir="rtl">Texto invertido</bdo> <!-- Unicode directo: --> <p>© 2024 — Café ☕ → 🚀</p>
dir="rtl" invierte la dirección del texto (árabe, hebreo). <bdo> fuerza la dirección. Para caracteres Unicode (emojis, símbolos), basta usar UTF-8 en el <meta charset>.
Párrafo y Saltos
<p>Primero párrafo de texto.</p> <p>Segundo párrafo.<br> Com salto de linea forzada.</p> <hr> <p>Nuevo tema tras linea horizontal.</p>
<p> crea párrafos con espaciado automático. <br> fuerza un salto de línea sin nuevo párrafo. <hr> inserta una separación temática horizontal.
Código y Preformateado
<p>Use <code>console.log()</code> para debug.</p>
<pre><code>
function hola() {
return "Hola";
}
</code></pre>
<kbd>Ctrl</kbd> + <kbd>C</kbd> = copiar
<samp>Output do programa</samp><code> formatea código inline. <pre> preserva espacios y saltos. <kbd> representa teclas. <samp> muestra output de programas. Combina <pre><code> para bloques.
WBR y Hyphenation
<p> http://site.com/muy/<wbr>largo/<wbr>camino </p> <p lang="de"> Straßen­bahn­haltestelle </p> <p style="hyphens: auto" lang="es"> Paralelepípedo es uma palabra larga </p>
<wbr> sugiere un punto de quiebre en URLs largas. ­ es un guion suave (solo aparece si quiebra). hyphens: auto en CSS separa sílabas automáticamente.
Negrita, Cursiva y Énfasis
<strong>Importante (negrita semântico)</strong> <em>Énfasis (itálico semântico)</em> <b>Negrita visual (sem semântica)</b> <i>Itálico visual (termo técnico)</i>
<strong> indica importancia (negrita). <em> indica énfasis (cursiva). <b> y <i> son solo visuales. Prefiere <strong>/<em> para accesibilidad.
Citas
<blockquote cite="https://ejemplo.com"> <p>Cita larga em bloco.</p> </blockquote> <p>Como disse: <q>cita curta inline</q>.</p> <cite>Título da obra</cite>
<blockquote> para citas largas en bloque. <q> para citas cortas inline (añade comillas automáticas). <cite> referencia el título de la obra. El atributo cite guarda la URL de la fuente.
Texto Modificado
<del>Texto removido</del> <ins>Texto insertado</ins> <mark>Texto destacado</mark> <s>Texto incorrecto</s> <u>Subrayado (cuidado com links!)</u> <small>Texto pequeño</small>
<del> muestra texto tachado (removido). <ins> subraya (insertado). <mark> resalta con fondo amarillo. <small> reduce el tamaño. Evita <u> — se confunde con links.
Abreviaturas y Definiciones
<abbr title="HyperText Markup Language"> HTML </abbr> <dfn>HTML</dfn> es a lenguaje de marcado patrón para páginas web. <address> Escrito por <a href="mailto:a@b.com">Ana</a> </address>
<abbr> muestra el significado en un tooltip. <dfn> marca la definición de un término. <address> contiene información de contacto del autor. Todos mejoran la semántica.
Liza
Lista No Ordenada
<ul> <li>HTML</li> <li>CSS</li> <li>JavaScript</li> </ul>
<ul> crea una lista con viñetas (bullets). Cada item usa <li>. Ideal para items sin orden específico. El estilo de la viñeta cambia con list-style-type en CSS.
Listas Anidadas
<ul>
<li>Frontend
<ul>
<li>HTML</li>
<li>CSS
<ul>
<li>Flexbox</li>
<li>Grid</li>
</ul>
</li>
</ul>
</li>
<li>Backend</li>
</ul>Las sublistas van dentro del <li> padre. Puedes mezclar <ul> y <ol>. La indentación visual viene del CSS (margin-left por nivel).
Lista Ordenada
<ol> <li>Abrir o fichero</li> <li>Editar o contenido</li> <li>Guardar</li> </ol> <ol start="5" reversed> <li>Quinto</li> <li>Cuarto</li> </ol>
<ol> crea una lista numerada. start="5" inicia en 5. reversed invierte la cuenta. Úsala para pasos secuenciales o rankings.
Lista con CSS (Sin Marcadores)
<ul style="list-style: none; padding: 0;">
<li>→ Item com flecha</li>
<li>✓ Item com check</li>
<li>★ Item com estrella</li>
</ul>
<!-- Ou com CSS externo: -->
<!-- ul { list-style: none; } -->
<!-- li::before { content: "→ "; } -->list-style: none quita los marcadores. Usa ::before con content para marcadores personalizados. Patrón común en menús de navegación.
Tipo de Numeración
<ol type="1"> <!-- 1, 2, 3 --> <ol type="A"> <!-- A, B, C --> <ol type="a"> <!-- a, b, c --> <ol type="I"> <!-- I, II, III --> <ol type="i"> <!-- i, ii, iii --> <li value="10">Salta para 10</li>
El atributo type define el formato: 1 (numeros), A/a (letras), I/i (romanos). value en un <li> redefine la numeración a partir de ahí.
Lista de Definición
<dl> <dt>HTML</dt> <dd>Lenguaje de marcado</dd> <dt>CSS</dt> <dd>Folha de estilos</dd> <dt>JavaScript</dt> <dd>Lenguaje de programación</dd> </dl>
<dl> crea una lista de definiciones. <dt> es el término. <dd> es la descripción. Ideal para glosarios, FAQs y pares clave-valor.
Enlaces e imágenes
Link Básico
<a href="https://ejemplo.com">Visitar site</a> <a href="/sobre">Página interna</a> <a href="./fichero.pdf">Fichero local</a>
El <a> crea hiperenlaces. href define el destino. Usa URLs absolutas (https://) para sitios externos y relativas (/pagina) para internas.
Descarga de Archivos
<a href="informe.pdf" download> Baixar PDF </a> <a href="datos.csv" download="ventas-2024.csv"> Baixar com nombre personalizado </a>
El atributo download fuerza la descarga en vez de abrir el archivo. Puedes especificar un nombre alternativo. Solo funciona para URLs del mismo dominio (same-origin).
Abrir en Nueva Pestaña
<a href="https://externo.com" target="_blank" rel="noopener noreferrer"> Abrir em nueva pestaña </a>
target="_blank" abre en una nueva pestaña. Siempre añade rel="noopener" por seguridad (impide acceso a window.opener). noreferrer también esconde el referer.
Link como Botón
<!-- Link com apariencia de botón --> <a href="/registro" class="btn btn-primary" role="button"> Registrar </a> <!-- Botón real (sem navegación) --> <button type="button" class="btn"> Clic aqui </button>
Usa <a> para navegación y <button> para acciones (JS). role="button" indica a los lectores de pantalla que el link actúa como botón. No uses <div onclick> — no es accesible.
Anclas (Links Internos)
<a href="#contactos">Ir para contactos</a> <!-- Mais abaixo na página: --> <section id="contactos"> <h2>Contactos</h2> </section> <!-- Link de outra página: --> <a href="/pagina.html#sección">Sección</a>
Los links con #id saltan al elemento con ese id. Funciona en la misma página o en otra (pagina.html#id). Usa scroll-behavior: smooth en CSS para animar.
Rel noopener y nofollow
<a href="https://externo.com" rel="noopener">Seguro</a> <a href="https://spam.com" rel="nofollow">Sem endorsement SEO</a> <a href="https://patrocinado.com" rel="sponsored">Patrocinado</a> <a href="https://ejemplo.com" rel="noopener nofollow">Ambos</a>
rel="noopener" protege contra ataques. nofollow dice a Google que no siga el link (SEO). sponsored marca links pagados. Combina valores separados por espacio.
Email y Teléfono
<a href="mailto:ana@ejemplo.com"> Enviar email </a> <a href="mailto:a@b.com?subject=Hola&cc=x@y.com"> Email com assunto </a> <a href="tel:+351912345678"> Conectar ahora </a>
mailto: abre el cliente de email. Acepta ?subject=, &cc=, &body=. tel: abre el marcador en el móvil. Usa formato internacional con +.
Breadcrumb (Ruta)
<nav aria-label="Breadcrumb">
<ol>
<li><a href="/">Inicio</a></li>
<li><a href="/productos">Productos</a></li>
<li aria-current="page">Detalle</li>
</ol>
</nav>Los breadcrumbs muestran la ubicación en la jerarquía. Usa <nav> con aria-label. aria-current="page" marca la página actual. Mejora SEO y navegación.
Mesas
Tabla Básica
<table>
<tr>
<td>Célula 1</td>
<td>Célula 2</td>
</tr>
<tr>
<td>Célula 3</td>
<td>Célula 4</td>
</tr>
</table><table> crea la tabla. <tr> es una fila. <td> es una celda de datos. Las tablas son para datos tabulares — no para layout.
Pie de Tabla
<table>
<thead>
<tr><th>Producto</th><th>Precio</th></tr>
</thead>
<tbody>
<tr><td>Item A</td><td>10€</td></tr>
<tr><td>Item B</td><td>20€</td></tr>
</tbody>
<tfoot>
<tr><td>Total</td><td>30€</td></tr>
</tfoot>
</table><tfoot> contiene filas de resumen. El navegador puede repetirlo en tablas largas impresas. El orden en HTML puede ser thead → tfoot → tbody (renderiza al final).
Cabecera y Cuerpo
<table>
<thead>
<tr>
<th>Nombre</th>
<th>Edad</th>
</tr>
</thead>
<tbody>
<tr>
<td>Ana</td>
<td>30</td>
</tr>
</tbody>
</table><thead> agrupa la cabecera. <th> es una celda de cabecera (negrita y centrada). <tbody> contiene los datos. Mejora la accesibilidad y permite estilizar secciones.
Agrupar Columnas (colgroup)
<table>
<colgroup>
<col style="background: #f0f0f0">
<col span="2" style="background: #e0e0e0">
</colgroup>
<tr>
<td>Col 1</td>
<td>Col 2</td>
<td>Col 3</td>
</tr>
</table><colgroup> y <col> estilizan columnas enteras. span="2" aplica a 2 columnas. Útil para zebra striping por columna o destacar columnas específicas.
Leyenda (caption)
<table>
<caption>Ventas por trimestre (2024)</caption>
<thead>
<tr>
<th>Trimestre</th>
<th>Valor</th>
</tr>
</thead>
<tbody>
<tr><td>Q1</td><td>10k</td></tr>
</tbody>
</table><caption> da un título descriptivo a la tabla. Debe ser el primer hijo de <table>. Esencial para accesibilidad — los lectores de pantalla anuncian el caption.
Tabla Responsiva
<div style="overflow-x: auto;">
<table>
<tr>
<td>Datos anchos...</td>
<td>Que no caben...</td>
<td>No pantalla mobile</td>
</tr>
</table>
</div>Envuelve la tabla en un <div> con overflow-x: auto. En pantallas pequeñas, aparece scroll horizontal. Alternativa: transformarla en cards con CSS Grid en mobile.
Colspan y Rowspan
<table>
<tr>
<td colspan="2">Ocupa 2 columnas</td>
</tr>
<tr>
<td rowspan="2">Ocupa 2 lineas</td>
<td>Normal</td>
</tr>
<tr>
<td>Normal</td>
</tr>
</table>colspan="2" hace que la celda ocupe 2 columnas. rowspan="2" ocupa 2 filas. Útil para cabeceras agrupadas y celdas de resumen.
Ámbito del Encabezado
<table>
<tr>
<th scope="col">Nombre</th>
<th scope="col">Edad</th>
</tr>
<tr>
<th scope="row">Ana</th>
<td>30</td>
</tr>
</table>scope="col" indica que el <th> es el encabezado de la columna. scope="row" para la fila. Esencial para que los lectores de pantalla asocien los datos al encabezado correcto.
Formularios
Formulario Básico
<form action="/enviar" method="POST"> <label for="nombre">Nombre:</label> <input type="text" id="nombre" name="nombre"> <button type="submit">Enviar</button> </form>
action define el destino de los datos. method es GET (URL) o POST (body). name es obligatorio para que el campo se envíe. <label> con for enlaza al input.
Checkbox y Radio
<label>
<input type="checkbox" name="aceito"
value="sim" checked>
Aceito os termos
</label>
<label>
<input type="radio" name="color"
value="azul">
Azul
</label>
<label>
<input type="radio" name="color"
value="verde" checked>
Verde
</label>checkbox permite selección múltiple. radio solo permite una elección (mismo name). checked premarca. Envuelve con <label> para hacer clic en el texto también.
Input File y Múltiple
<form enctype="multipart/form-data">
<input type="file" name="foto"
accept="image/*">
<input type="file" name="docs"
multiple
accept=".pdf,.doc,.docx">
</form>type="file" permite subir archivos. accept filtra tipos de archivo. multiple permite varios. El <form> necesita enctype="multipart/form-data" para subidas.
Tipos de Input
<input type="text"> <!-- texto --> <input type="email"> <!-- email --> <input type="password"> <!-- contraseña --> <input type="number"> <!-- numero --> <input type="date"> <!-- fecha --> <input type="time"> <!-- hora --> <input type="color"> <!-- color --> <input type="range"> <!-- slider --> <input type="file"> <!-- archivo --> <input type="url"> <!-- URL --> <input type="tel"> <!-- teléfono --> <input type="search"> <!-- búsqueda -->
El type define el comportamiento y el teclado en el móvil. email valida el formato, number muestra un spinner, date abre un calendario. Usa el tipo correcto para mejor UX.
Validación Nativa
<input type="email" required>
<input type="text" minlength="3"
maxlength="50">
<input type="number" min="1" max="100"
step="0.5">
<input type="text"
pattern="[0-9]{9}"
title="9 dígitos">required lo hace obligatorio. minlength/maxlength limitan el tamaño. min/max limitan valores. pattern valida con regex. title muestra una pista en el error.
Autofocus, Placeholder y Readonly
<input type="text" autofocus
placeholder="Buscar...">
<input type="text" readonly
value="No editável">
<input type="text" disabled
value="Desativado">
<input type="hidden" name="token"
value="abc123">autofocus enfoca al cargar (1 por página). placeholder muestra una pista. readonly impide editar pero envía. disabled impide y no envía. hidden es invisible.
Textarea
<label for="msg">Mensaje:</label>
<textarea id="msg" name="mensaje"
rows="5" cols="40"
placeholder="Escribe aqui..."
maxlength="500"></textarea><textarea> permite texto multilínea. rows define la altura inicial. maxlength limita caracteres. El contenido inicial va entre las etiquetas (no uses value).
Fieldset y Legend
<form>
<fieldset>
<legend>Datos Pessoais</legend>
<label>Nombre: <input name="nombre"></label>
<label>Email: <input type="email"
name="email"></label>
</fieldset>
<fieldset disabled>
<legend>Bloqueado</legend>
<input type="text" value="No editável">
</fieldset>
</form><fieldset> agrupa campos relacionados. <legend> da un título al grupo. disabled en el fieldset desactiva todos los campos dentro. Mejora la organización y la accesibilidad.
Select y Datalist
<select name="país">
<option value="">Elija...</option>
<option value="pt" selected>Portugal</option>
<option value="br">Brasil</option>
<optgroup label="Europa">
<option value="es">Espanha</option>
</optgroup>
</select>
<input list="lenguajes">
<datalist id="lenguajes">
<option value="HTML">
<option value="CSS">
</datalist><select> crea un dropdown. <optgroup> agrupa opciones. selected preselecciona. <datalist> da sugerencias en un input de texto (autocompletado nativo).
Botones
<button type="submit">Enviar</button> <button type="button" onclick="salvar()"> Guardar </button> <button type="reset">Limpiar</button> <button disabled>No disponible</button>
type="submit" envía el formulario. type="button" no envía (usa con JS). type="reset" limpia campos. disabled desactiva. Prefiere <button> a <input type="submit">.
HTML semántico
Header y Footer
<header> <h1>Mi Site</h1> <nav>...</nav> </header> <main>Contenido</main> <footer> <p>© 2024 Mi Site</p> </footer>
<header> es la parte superior (logo, nav, título). <footer> es el pie (copyright, enlaces). Pueden existir varios por página (dentro de <article>, <section>). Sustituyen a <div class="header">.
Aside — Contenido Lateral
<main>
<article>Contenido principal</article>
<aside>
<h3>Relacionado</h3>
<ul>
<li><a href="/post1">Post 1</a></li>
<li><a href="/post2">Post 2</a></li>
</ul>
</aside>
</main><aside> contiene contenido complementario (barra lateral, consejos, publicidad). Debe estar relacionado con el contenido principal. No lo uses para contenido no relacionado.
Dialog (Modal Nativo)
<dialog id="modal">
<h2>Título do Modal</h2>
<p>Contenido da caja de diálogo.</p>
<button onclick="this.closest('dialog')
.close()">Cerrar</button>
</dialog>
<button onclick="document
.querySelector('#modal')
.showModal()">Abrir</button><dialog> crea modales nativos sin JS. .showModal() abre con un overlay. .close() lo cierra. Soporta ::backdrop en CSS para estilizar el fondo. Sin dependencias externas.
Nav — Navegación
<nav aria-label="Principal">
<ul>
<li><a href="/">Inicio</a></li>
<li><a href="/sobre">Sobre</a></li>
<li><a href="/contacto">Contacto</a></li>
</ul>
</nav><nav> marca áreas de navegación principal. Usa aria-label si hay múltiples <nav>. No todos los enlaces necesitan estar en un <nav> — solo los principales.
Details y Summary
<details> <summary>Clic para expandir</summary> <p>Contenido oculto que aparece ao clicar no summary.</p> </details> <details open> <summary>Ya abierto</summary> <p>Visible por defecto.</p> </details>
<details> crea un acordeón nativo sin JavaScript. <summary> es el título clicable. open lo muestra expandido por defecto. Ideal para FAQs y contenido opcional.
Template y Slot
<template id="card-template">
<div class="card">
<h3 class="título"></h3>
<p class="texto"></p>
</div>
</template>
<script>
const tpl = document
.querySelector('#card-template');
const clone = tpl.content.cloneNode(true);
clone.querySelector('.título')
.textContent = 'Nuevo';
document.body.appendChild(clone);
</script><template> guarda HTML inerte (no renderiza). Clona con .content.cloneNode(true) en JS. Ideal para listas dinámicas y Web Components. El contenido solo existe cuando se clona.
Main — Contenido Principal
<body>
<header>...</header>
<nav>...</nav>
<main>
<h1>Título da página</h1>
<p>Contenido único desta página.</p>
</main>
<footer>...</footer>
</body><main> contiene el contenido único de la página. Solo puede existir uno por página. No incluyas header, nav o footer dentro. Ayuda a los lectores de pantalla a saltar directo al contenido.
Time y Fecha
<time datetime="2024-01-15">15 de Janeiro</time> <time datetime="2024-01-15T14:30"> 15 Jan, 14:30 </time> <time datetime="PT2H30M">2h 30min</time>
<time> marca fechas/horas de forma legible por máquinas. El atributo datetime usa formato ISO. Mejora el SEO y permite que los navegadores lo añadan al calendario.
Article y Section
<article> <h2>Post: Como usar HTML</h2> <time datetime="2024-01-15">15 Jan</time> <p>Contenido independente...</p> </article> <section> <h2>Comentarios</h2> <p>Sección temática da página.</p> </section>
<article> es contenido independiente (post, noticia, comentario). <section> agrupa contenido temático. Regla: si tiene sentido por sí solo, usa <article>.
Progress y Meter
<progress value="70" max="100">
70%
</progress>
<meter value="0.7" min="0" max="1"
low="0.3" high="0.8"
optimum="1">
70% completo
</meter><progress> muestra el progreso de una tarea. <meter> muestra un valor dentro de un intervalo (como un medidor). low/high/optimum definen zonas de color.
Metadatos y SEO
Title y Description
<head>
<title>Mi Site - Servicios Web</title>
<meta name="description"
content="Criamos sites modernos e
responsivos. Presupuesto gratis.">
</head>El <title> aparece en la pestaña y en los resultados de Google (máx ~60 chars). La meta description es el resumen en los resultados (máx ~160 chars). Esenciales para el SEO.
Favicon e Iconos
<link rel="icon" href="/favicon.ico"
sizes="32x32">
<link rel="icon" href="/icon.svg"
type="image/svg+xml">
<link rel="apple-touch-icon"
href="/apple-icon.png">
<link rel="manifest"
href="/site.webmanifest">rel="icon" define el favicon de la pestaña. apple-touch-icon para iOS (180x180px). manifest enlaza al PWA. Usa SVG para un favicon escalable.
JSON-LD (Schema.org)
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "Organization",
"name": "Mi Empresa",
"url": "https://site.com",
"logo": "https://site.com/logo.png"
}
</script>JSON-LD son datos estructurados para Google. Va en un <script type="application/ld+json">. Permite rich snippets (estrellas, precios, FAQs) en los resultados de búsqueda.
Open Graph (Redes Sociales)
<meta property="og:title"
content="Título do Post">
<meta property="og:description"
content="Resumen atractivo">
<meta property="og:image"
content="https://site.com/img.jpg">
<meta property="og:url"
content="https://site.com/post">
<meta property="og:type"
content="article">Open Graph controla la vista previa al compartir en Facebook, LinkedIn, WhatsApp. og:image debe tener 1200x630px. Sin esto, las redes intentan adivinar el contenido.
Enlazar CSS y JavaScript
<!-- CSS en el head -->
<link rel="stylesheet" href="estilo.css">
<!-- JS con defer (recomendado) -->
<script src="app.js" defer></script>
<!-- JS con async -->
<script src="analytics.js" async></script>
<!-- Módulo ES6 -->
<script type="module"
src="módulo.js"></script>El CSS va en el <head> con <link>. Para JS usa defer (se ejecuta tras el parse, mantiene orden) o async (se ejecuta al cargar, sin orden). type="module" activa los ES modules.
Twitter Card
<meta name="twitter:card"
content="summary_large_image">
<meta name="twitter:title"
content="Título do Post">
<meta name="twitter:description"
content="Resumen do post">
<meta name="twitter:image"
content="https://site.com/img.jpg">Twitter Card controla la vista previa en X/Twitter. summary_large_image muestra una imagen grande. summary muestra una pequeña. Complementa al Open Graph.
Preload y Prefetch
<!-- Preload: recurso crítico -->
<link rel="preload" href="fonte.woff2"
as="font" crossorigin>
<!-- Preconnect: DNS anticipado -->
<link rel="preconnect"
href="https://fonts.googleapis.com">
<!-- Prefetch: próxima página -->
<link rel="prefetch" href="/proxima">
<!-- DNS prefetch -->
<link rel="dns-prefetch"
href="//cdn.ejemplo.com">preload carga recursos críticos con antelación. preconnect anticipa DNS+TCP. prefetch carga recursos de la próxima página en idle. Mejoran los Core Web Vitals.
Canonical y Robots
<link rel="canonical"
href="https://site.com/pagina">
<meta name="robots"
content="index, follow">
<meta name="robots"
content="noindex, nofollow">canonical indica la URL preferida (evita contenido duplicado). robots controla la indexación: index/noindex (aparecer en Google), follow/nofollow (seguir enlaces).
Meta Tags Esenciales
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width,
initial-scale=1.0">
<meta name="author" content="Ana">
<meta name="theme-color"
content="#E34F26">
<meta http-equiv="X-UA-Compatible"
content="IE=edge">charset y viewport son obligatorios. theme-color define el color de la barra en el móvil. author identifica al autor. X-UA-Compatible para compatibilidad con IE.
Accesibilidad
Alt en Imágenes
<img src="grafico.png"
alt="Ventas subiram 20% em 2024">
<!-- Decorativa: alt vacío -->
<img src="linea.png" alt=""
role="presentation">alt describe la imagen para los lectores de pantalla. Sé específico y descriptivo. Para imágenes decorativas, usa alt="" (vacío) — el lector la ignora. Nunca omitas el atributo.
Labels en Formularios
<!-- Método 1: for/id -->
<label for="email">Email:</label>
<input id="email" type="email">
<!-- Método 2: envolver -->
<label>
Nombre:
<input type="text" name="nombre">
</label>
<!-- Sin label visible -->
<input type="search"
aria-label="Buscar">Todo input necesita un label. for/id enlaza explícitamente. Envolver el input en el <label> también funciona. Sin label visible, usa aria-label. Nunca uses solo placeholder.
ARIA Labels
<button aria-label="Cerrar menu">
✕
</button>
<nav aria-label="Navegación principal">
...
</nav>
<input aria-label="Buscar no site"
type="search">aria-label da un nombre accesible a elementos sin texto visible. Úsalo en botones de iconos, inputs sin label visible y navegaciones. No lo uses si ya existe texto visible adecuado.
Skip Links y Landmarks
<a href="#contenido" class="skip-link"> Saltar para o contenido </a> <header>...</header> <nav>...</nav> <main id="contenido"> <h1>Contenido principal</h1> </main>
Los skip links permiten saltar la navegación (teclado). Escóndelos con CSS pero mantenlos accesibles. <main>, <nav>, <header> son landmarks que los lectores usan para navegar.
ARIA States y Properties
<button aria-expanded="false"
aria-controls="menu">
Menu
</button>
<div id="menu" hidden>
...
</div>
<div aria-live="polite">
Actualización dinâmica
</div>
<span aria-hidden="true">★</span>aria-expanded indica el estado abierto/cerrado. aria-controls enlaza al elemento controlado. aria-live anuncia cambios dinámicos. aria-hidden esconde los decorativos.
Contraste y Foco
<!-- ¡No quites el outline! -->
<style>
a:focus-visible {
outline: 3px solid #E34F26;
outline-offset: 2px;
}
/* Ratio mínimo: 4.5:1 */
.texto {
color: #333; /* buen contraste */
}
</style>Nunca uses outline: none sin alternativa. :focus-visible muestra el foco solo para teclado. Contraste mínimo: 4.5:1 para texto normal, 3:1 para texto grande. Prueba con herramientas de contraste.
Roles ARIA
<div role="alert">
Error: campo obligatorio!
</div>
<div role="tablist">
<button role="tab"
aria-selected="true">Tab 1</button>
<button role="tab">Tab 2</button>
</div>
<div role="tabpanel">Contenido</div>role define el papel del elemento. alert anuncia errores. tablist/tab/tabpanel crean pestañas accesibles. Prefiere etiquetas semánticas — usa role solo cuando sea necesario.
Tablas Accesibles
<table>
<caption>Ventas 2024</caption>
<thead>
<tr>
<th scope="col">Mes</th>
<th scope="col">Valor</th>
</tr>
</thead>
<tbody>
<tr>
<th scope="row">Janeiro</th>
<td>10.000€</td>
</tr>
</tbody>
</table>Usa <caption> para el título. <th> con scope asocia encabezados con celdas. Nunca uses tablas para layout. Los lectores de pantalla navegan por <th> y scope.
Consejos y buenas prácticas
Cargar JavaScript (defer/async)
<!-- Recomendado: defer --> <script src="app.js" defer></script> <!-- Async: sin orden garantizado --> <script src="analytics.js" async></script> <!-- Inline al final del body --> <body> ... <script src="app.js"></script> </body>
defer carga en paralelo y se ejecuta tras el parse (mantiene orden). async se ejecuta en cuanto carga (sin orden). Sin atributo, bloquea el parse. Prefiere defer para scripts propios.
Meta Refresh y Redirect
<!-- Redirect tras 0s -->
<meta http-equiv="refresh"
content="0; url=https://nuevo.com">
<!-- Refresh cada 30s -->
<meta http-equiv="refresh"
content="30">http-equiv="refresh" redirige o recarga la página. content="0; url=..." redirige inmediatamente. Prefiere redirects HTTP (301/302) en el servidor para el SEO.
Contenteditable
<div contenteditable="true">
Clic para editar este texto!
</div>
<p contenteditable="plaintext-only">
Solo texto simples
</p>
<!-- JS: obtener contenido -->
<script>
const el = document
.querySelector('[contenteditable]');
el.addEventListener('input', () => {
console.log(el.innerHTML);
});
</script>contenteditable="true" hace editable cualquier elemento. plaintext-only impide el formato. El evento input detecta cambios. La base de los editores rich-text.
Web Components (Básico)
<template id="tpl">
<style>
.card { border: 1px solid #ccc; }
</style>
<div class="card">
<slot></slot>
</div>
</template>
<script>
class MyCard
extends HTMLElement {
connectedCallback() {
const tpl = document
.querySelector('#tpl');
this.attachShadow({ mode: 'open' })
.append(
tpl.content.cloneNode(true));
}
}
customElements
.define('mi-card', MyCard);
</script>
<mi-card>Contenido</mi-card>Web Components crean elementos personalizados. customElements.define() los registra. Shadow DOM aísla los estilos. <slot> recibe contenido. <template> guarda el HTML.
Output y Resultado
<form oninput="resultado.value =
parseInt(a.value) + parseInt(b.value)">
<input type="number" id="a" value="5"> +
<input type="number" id="b" value="3"> =
<output name="resultado"
for="a b">8</output>
</form><output> muestra el resultado de un cálculo. for enlaza a los inputs relacionados. oninput recalcula en tiempo real. Semántico para resultados de formularios.
Atributos Globales Útiles
<div hidden>Escondido</div>
<div inert>
<button>No clicable</button>
</div>
<p spellcheck="true">Editable</p>
<div translate="no">
No traduzir: código
</div>
<input inputmode="numeric"
pattern="[0-9]*">hidden oculta (sin CSS). inert desactiva la interacción y el foco. spellcheck activa la corrección ortográfica. translate="no" impide la traducción. inputmode define el teclado móvil.
Details como FAQ
<h2>Preguntas Frequentes</h2> <details> <summary>O que es HTML?</summary> <p>Lenguaje de marcado para estruturar páginas web.</p> </details> <details> <summary>Es uma lenguaje de programação?</summary> <p>No, es de marcado.</p> </details>
<details>/<summary> crean FAQs sin JavaScript. Cada pregunta es un <summary>, la respuesta va dentro del <details>. Nativo, accesible y sin dependencias.
Validar HTML (W3C)
<!-- Herramientas de validación: --> https://validator.w3.org <!-- VS Code: --> <!-- Extensión: HTMLHint --> <!-- Errores comunes: --> <!-- ✗ <div><p>Texto</div></p> --> <!-- ✓ <div><p>Texto</p></div> --> <!-- ✗ <img src="x.jpg"> --> <!-- ✓ <img src="x.jpg" alt="..."> -->
Valida en validator.w3.org. Errores comunes: etiquetas mal cerradas, <img> sin alt, <div> dentro de <p>, IDs duplicados. El HTML válido mejora el SEO y la accesibilidad.
Imagens e Media
Imagen Básica
<img src="foto.jpg"
alt="Perro corriendo en el parque"
width="400"
height="300"><img> es self-closing (sin cierre). alt es obligatorio para accesibilidad y SEO. Define width/height para evitar layout shifts.
Lazy Loading
<img src="foto.jpg" alt="..." loading="lazy">
<img src="hero.jpg" alt="..." loading="eager">
<!-- iframe también soporta: -->
<iframe src="mapa.html"
loading="lazy"></iframe>loading="lazy" solo carga la imagen cuando está a punto de aparecer en el viewport. loading="eager" carga inmediatamente (default). Ideal para imágenes debajo del fold.
Imagen Responsiva (srcset)
<img src="foto-800.jpg"
srcset="foto-400.jpg 400w,
foto-800.jpg 800w,
foto-1200.jpg 1200w"
sizes="(max-width: 600px) 400px, 800px"
alt="Paisagem">srcset ofrece múltiples resoluciones. sizes dice al navegador el tamaño de exhibición. El navegador elige la mejor imagen. Reduce datos en pantallas pequeñas.
Figure con Leyenda
<figure>
<img src="grafico.png"
alt="Ventas 2024">
<figcaption>
Fig. 1 — Ventas por trimestre
</figcaption>
</figure><figure> agrupa contenido visual con su leyenda. <figcaption> es la descripción. Puede contener imágenes, gráficos, código o citas.
Picture — Arte Directiva
<picture>
<source media="(max-width: 600px)"
srcset="mobile.jpg">
<source media="(max-width: 1024px)"
srcset="tablet.jpg">
<img src="desktop.jpg" alt="Producto">
</picture><picture> sirve imágenes diferentes según la pantalla (art direction). El <source> define condiciones con media. El <img> es el fallback obligatorio.
SVG Inline
<svg width="100" height="100"
viewBox="0 0 100 100">
<circle cx="50" cy="50" r="40"
fill="#E34F26"/>
<text x="50" y="55"
text-anchor="middle"
fill="white">HTML</text>
</svg><svg> inline permite gráficos vectoriales escalables. viewBox define el sistema de coordenadas. Ventaja: estilizable con CSS y animable con JS. Sin pérdida de calidad.
Formatos Modernos (WebP/AVIF)
<picture> <source srcset="foto.avif" type="image/avif"> <source srcset="foto.webp" type="image/webp"> <img src="foto.jpg" alt="Foto"> </picture>
AVIF y WebP son más ligeros que JPEG/PNG. Usa <picture> con type para fallback. El navegador usa el primer formato soportado. Reduce 30-50% del tamaño.
Mapa de Imagen
<img src="mapa.png" alt="Mapa"
usemap="#menu">
<map name="menu">
<area shape="rect"
coords="0,0,100,50"
href="/pagina1" alt="Pág 1">
<area shape="circle"
coords="200,75,50"
href="/pagina2" alt="Pág 2">
</map><map> define áreas clicables en una imagen. usemap enlaza la imagen al mapa. shape puede ser rect, circle o poly. Poco usado hoy — prefiere SVG.
Multimédia e Embed
Vídeo HTML5
<video controls width="640"
poster="capa.jpg">
<source src="video.mp4"
type="video/mp4">
<source src="video.webm"
type="video/webm">
<track src="legendas.vtt"
kind="subtitles"
srclang="es" label="PT">
O su browser no soporta vídeo.
</video><video> reproduce vídeo nativo. controls muestra los botones. poster es la imagen de portada. <source> ofrece formatos. <track> añade subtítulos (.vtt).
Embed y Object
<!-- PDF -->
<embed src="doc.pdf"
type="application/pdf"
width="100%" height="500">
<!-- Fallback con object -->
<object data="doc.pdf"
type="application/pdf"
width="100%" height="500">
<p>PDF no soportado.
<a href="doc.pdf">Baixar</a>
</p>
</object><embed> incrusta contenido externo (PDF, SVG). <object> permite un fallback (contenido entre las etiquetas). Prefiere <iframe> para páginas e <img> para SVG.
Audio HTML5
<audio controls>
<source src="musica.mp3"
type="audio/mpeg">
<source src="musica.ogg"
type="audio/ogg">
O su browser no soporta audio.
</audio>
<!-- Autoplay con mute -->
<audio autoplay muted loop>
<source src="fondo.mp3">
</audio><audio> reproduce audio nativo. controls muestra el reproductor. autoplay solo funciona con muted (política de los navegadores). loop repite. El texto interno es un fallback.
Picture-in-Picture
<video id="video" controls
src="video.mp4"></video>
<button onclick="togglePiP()">
Picture-in-Picture
</button>
<script>
async function togglePiP() {
const v = document
.querySelector('#video');
if (document.pictureInPictureElement) {
await document
.exitPictureInPicture();
} else {
await v.requestPictureInPicture();
}
}
</script>requestPictureInPicture() activa el modo PiP (vídeo flotante). exitPictureInPicture() lo desactiva. El usuario puede seguir viendo el vídeo mientras navega por otra página.
Iframe
<iframe src="https://maps.google.com/..."
width="600" height="400"
title="Mapa da ubicación"
loading="lazy"
sandbox="allow-scripts"
allowfullscreen>
</iframe><iframe> incrusta otra página. title es obligatorio para la accesibilidad. loading="lazy" aplaza la carga. sandbox restringe permisos. allowfullscreen permite pantalla completa.
Canvas (Básico)
<canvas id="lienzo"
width="400" height="200">
Canvas no soportado.
</canvas>
<script>
const ctx = document
.querySelector('#lienzo')
.getContext('2d');
ctx.fillStyle = '#E34F26';
ctx.fillRect(10, 10, 150, 100);
ctx.font = '20px Arial';
ctx.fillText('HTML5', 50, 70);
</script><canvas> crea un área de dibujo mediante JavaScript. getContext("2d") da acceso a la API de dibujo. Úsalo para gráficos, juegos y manipulación de imágenes. Requiere JS para renderizar.
Embed de YouTube y Vimeo
<!-- YouTube -->
<iframe
src="https://www.youtube.com/embed/ID"
title="Título do vídeo"
allow="accelerometer; autoplay;
clipboard-write; encrypted-media;
gyroscope; picture-in-picture"
allowfullscreen
loading="lazy">
</iframe>Usa la URL /embed/ID de YouTube. allow define permisos. title describe el vídeo. loading="lazy" mejora el rendimiento. Añade aspect-ratio: 16/9 en CSS para responsive.