El documento HTML
En resumen: Un documento HTML es texto con etiquetas y atributos del que el navegador construye un árbol de elementos; los elementos semánticos como header, nav, main y footer dicen qué es cada parte.
Problema
El precio es un enlace
Un compañero hizo la página de un producto. La abres y el precio está en azul y subrayado, y un clic en «Añadir al carrito» te lleva a otros panes. El código no tiene ningún enlace alrededor del precio.
Consola
El navegador no muestra ningún error y la consola está vacía. Pulsa «Añadir al carrito»: la consola dice que es un enlace a /bread. El error está en la línea 9: la <a> se abre pero nunca se cierra. El navegador no muestra el texto línea por línea. Primero construye con él otra cosa, y esa otra cosa es la razón de que el precio sea un enlace.
La idea
Elementos, etiquetas, atributos
HTML es texto que dice qué hay en la página. Cada pieza es un elemento: un encabezado, un párrafo, un enlace, un botón. Un elemento empieza con una etiqueta de apertura y termina con una de cierre:
<a href="/cart">Carrito</a><a …>es la etiqueta de apertura, y</a>es la de cierre: el mismo nombre con una/.href="/cart"es un atributo: un nombre y un valor dentro de la etiqueta de apertura. Dice algo sobre el elemento: aquí, adónde lleva el enlace.- «Carrito» es el contenido: el texto entre las dos etiquetas.
Los elementos van unos dentro de otros. Un párrafo <p> puede contener un enlace, y <body> contiene todo lo que ves. Algunos elementos no tienen contenido y por eso no tienen etiqueta de cierre: <meta>, <img>, <input>, <br>.
Todo el documento tiene siempre el mismo marco:
<!doctype html><html lang="es"> <head> <meta charset="utf-8"> <title>Pan Dobrudzha</title> </head> <body> … </body></html><!doctype html> dice que es HTML moderno. lang="es" indica el idioma: un lector de pantalla elige su voz según él, y el navegador separa las palabras según él. <head> contiene información sobre la página: la codificación y el título de la pestaña del navegador. <body> contiene lo que ves.
La idea
Del texto al árbol
El navegador no dibuja el texto. Lo lee con un parser y construye un árbol: cada elemento es un nodo, y los elementos que contiene son sus hijos. Cada elemento tiene exactamente un padre. Este árbol se llama DOM (Document Object Model). CSS y JavaScript trabajan con él, no con el texto.
El parser lleva la cuenta de qué elementos están abiertos en cada momento. Una etiqueta de apertura crea un nodo nuevo, hijo del último elemento abierto. Una etiqueta de cierre cierra el elemento, y el parser vuelve al padre.
Si falta una etiqueta de cierre, el parser no se detiene. HTML tiene una regla para cada error, y el navegador decide por su cuenta dónde cerrar. A veces decide distinto de lo que tenías en mente.
Míralo
Mira cómo se construye el árbol
El código es el problema de antes, en corto. Fíjate en qué elementos están abiertos a la derecha.
<body> <h1>Pan</h1> <p>Mira también <a href="/bread">otros</p> <p>Precio: 1,80 €</p> <button>Añadir</button></body>Paso a paso, en palabras
- El parser lee el código de arriba abajo. <body> abre un elemento: aquí es la raíz del árbol. A la derecha están los elementos que están abiertos ahora mismo.
- <h1> pasa a ser hijo del elemento abierto, <body>. </h1> lo cierra en la misma línea, y el parser vuelve a <body>.
- <p> es hijo de <body>, y <a> es hijo de <p>. Ahora hay tres elementos abiertos: body, p, a.
- No hay </a>. </p> cierra el párrafo, y <a> no puede quedarse fuera de él, así que se cierra también. Pero el parser lo recuerda: en el código el enlace nunca se cerró.
- Antes del siguiente contenido el parser vuelve a abrir la <a> recordada, ahora como hija de <body>. Este enlace no está en el código. El nuevo <p> entra en él.
- El botón también entra en el enlace.
- El camino desde el botón hacia arriba: button, a, body. El precio y el botón están dentro de un enlace, y un clic en ellos lleva a /bread. La corrección es un </a> en la línea 3.
La segunda <a> no está en el código, pero sí en el árbol. El navegador muestra el árbol, no el texto. Por eso, cuando una página se ve rara, miras el árbol: en el navegador es el panel Elements de las herramientas para desarrolladores (F12). Ahí está la segunda <a>, y en el código fuente (Ver código fuente) no está.
Pruébalo
Arregla el enlace
Corrige el código para que la página tenga exactamente un enlace: «otros panes». Pulsa «Comprobar»: la comprobación cuenta los enlaces de la página.
Consola
Solución
index.html<!doctype html>
<html lang="es">
<head>
<meta charset="utf-8">
<title>Pan Dobrudzha</title>
</head>
<body>
<h1>Pan Dobrudzha</h1>
<p>Mira también <a href="/bread">otros panes</a></p>
<p>Precio: 1,80 €</p>
<button type="button">Añadir al carrito</button>
</body>
</html>
Faltaba el </a> de la línea 9. Con él el enlace termina antes de </p>, y el parser no tiene nada que volver a abrir. El precio y el botón vuelven a ser hijos de <body>.
Pruébalo
Encuentra el error
¿Por qué «Entrega en 2 días hábiles» está en negrita?
Elige la línea con el error.
El <strong> de la línea 3 no está cerrado. </p> lo cierra junto con el párrafo, pero el parser lo recuerda y lo vuelve a abrir alrededor del párrafo siguiente. Debe ser <strong>1,80 €</strong></p>.
Pruébalo
Completa
¿Qué atributo dice adónde lleva el enlace?
<nav>
<a ="/cart">Carrito</a>
</nav>href (hypertext reference): la dirección a la que lleva el enlace.
La idea
Elementos con significado
Una página puede estar hecha solo de elementos <div>. Entonces el navegador sabe que hay cajas, pero no qué es cada una. Una persona reconoce el menú por su lugar y su aspecto. Un lector de pantalla, un buscador y el teclado solo ven el árbol.
Por eso HTML tiene elementos semánticos: elementos cuyo nombre dice qué es el contenido.
<header>: la parte de arriba de la página: el logotipo y el menú.<nav>: la navegación, el grupo de enlaces a las otras páginas.<main>: el contenido principal. Uno por página.<article>: algo completo que tiene sentido por sí solo: un producto, un pedido, una entrada.<footer>: la parte de abajo de la página: entrega, contacto, condiciones.<h1>…<h6>: los encabezados.<h1>es el encabezado de la página.
Se ven igual que un <div>. La diferencia es que un lector de pantalla anuncia «navegación» y «contenido principal», y quien usa el teclado salta a ellos con una sola tecla. <div> y <span> quedan para cajas sin significado: un grupo que CSS tiene que colocar.
Míralo
La página con significado
El mismo producto con elementos semánticos. El segundo archivo tiene un poco de CSS para que las partes se vean. El módulo siguiente trata de eso.
Consola
La comprobación del ejemplo encuentra las partes por su rol: <header> es «cabecera» (banner), <nav> es «navegación», <main> es «contenido principal», <footer> es «pie de página» (contentinfo). Un lector de pantalla las ve igual.
Pruébalo
Dale significado
La página está hecha solo de elementos <div>. Cámbialos por elementos semánticos: la parte de arriba, el menú, el contenido principal, el producto y la parte de abajo. El nombre del producto es el encabezado de la página.
Consola
Solución
index.html<!doctype html>
<html lang="es">
<head>
<meta charset="utf-8">
<title>Leche fresca 3% · La tienda</title>
</head>
<body>
<header>
<a href="/">La tienda</a>
<nav>
<a href="/bread">Pan</a>
<a href="/milk">Leche</a>
<a href="/cart">Carrito</a>
</nav>
</header>
<main>
<article>
<h1>Leche fresca 3%</h1>
<p>Precio: 2,40 €</p>
<button type="button">Añadir al carrito</button>
</article>
</main>
<footer>Entrega en 2 días hábiles</footer>
</body>
</html>
top pasa a ser <header>, menu pasa a ser <nav>, content pasa a ser <main>, product pasa a ser <article>, y bottom pasa a ser <footer>. El nombre del producto pasa a ser <h1>: es el encabezado de la página. La comprobación busca el botón dentro del article, el menú por el rol «navegación» y el encabezado por el nivel 1. Las clases ya no hacen falta.
Más precisamente, para curiosos
El parser y los errores. Las reglas para los errores forman parte del estándar (el HTML Living Standard), así que todos los navegadores construyen el mismo árbol con el mismo HTML roto. El parser guarda las <a>, <strong>, <em>, <b> e <i> sin cerrar en una lista (la lista de elementos de formato activos) y las vuelve a abrir. Por eso un error así «se derrama» por la página.
Cerradas por sí solas. Algunas etiquetas cierran otras sin que haya un error: <p> cierra un <p> abierto, y <li> cierra un <li> abierto. Así que <li>Pan<li>Leche son dos elementos de lista. Escribimos las etiquetas de cierre porque entonces el código dice lo mismo que el árbol.
Atributos. Los nombres de las etiquetas y de los atributos no dependen de las mayúsculas y minúsculas (<A HREF> es <a href>), pero escribimos en minúsculas. Algunos atributos no tienen valor: <input required>. Las comillas alrededor de un valor se pueden omitir, pero con ellas es más seguro.
<section> y <aside>. <section> es una parte con un encabezado, un trozo de algo más grande. <aside> es contenido al lado del principal: productos relacionados, un anuncio.
Ejercicio
Mi pedido
Haz desde cero la página del pedido 1042. Arriba: un enlace «La tienda» y un menú con dos enlaces: «Mis pedidos» y «Carrito». El contenido principal: el encabezado «Pedido 1042», el estado «enviado» y dos productos, cada uno con su nombre como encabezado de segundo nivel y debajo la cantidad con el precio (pan: 2 × 1,80 €, leche: 1 × 2,40 €), y luego «Total: 6,00 €». Abajo: «Devoluciones hasta 14 días después de la entrega».
Consola
Solución
index.html<!doctype html>
<html lang="es">
<head>
<meta charset="utf-8">
<title>Pedido 1042 · La tienda</title>
</head>
<body>
<header>
<a href="/">La tienda</a>
<nav>
<a href="/orders">Mis pedidos</a>
<a href="/cart">Carrito</a>
</nav>
</header>
<main>
<h1>Pedido 1042</h1>
<p>Estado: <strong>enviado</strong></p>
<article>
<h2>Pan Dobrudzha</h2>
<p>2 × 1,80 €</p>
</article>
<article>
<h2>Leche fresca 3%</h2>
<p>1 × 2,40 €</p>
</article>
<p>Total: <strong>6,00 €</strong></p>
</main>
<footer>Devoluciones hasta 14 días después de la entrega</footer>
</body>
</html>
Cada producto es un <article> con su propio encabezado <h2>: es un todo por sí solo. El encabezado de la página es uno, <h1>. El total es un párrafo en <main>, y la regla de devoluciones está en el <footer>. La comprobación busca por rol y por nivel de encabezado, así que un <div class="title"> no pasa, por mucho que se parezca a un encabezado.
Test
Ponte a prueba
Lecciones relacionadas
Sección «Lecciones relacionadas»- Continúa en: Texto, enlaces, imágenes, tablas · Formularios · Accesibilidad · Selectores y la cascada
- Ejercicios sobre el tema: HTML: la estructura de la página