Contenedores y semántica
Hasta ahora hemos visto cómo marcar texto, imágenes, listas y formularios. Pero una página web no es solo una lista de párrafos: tiene una cabecera, una navegación, un área de contenido principal, quizás una barra lateral, un pie de página. Esta lección trata de cómo se organiza todo eso.
El flujo del documento
El navegador renderiza los elementos HTML en el orden en que aparecen en el código siguiendo dos direcciones: los elementos inline fluyen de izquierda a derecha dentro de cada línea; cuando una línea se llena, se abre la siguiente. Los elementos de bloque, en cambio, se apilan de arriba a abajo, cada uno en su propia línea. Esto se llama flujo normal del documento.
"Cuando una línea se llena" significa cuando el texto alcanza el borde derecho de su contenedor. El contenedor de todo el contenido es el <body>, que por defecto ocupa el ancho completo de la ventana. El texto se redistribuye automáticamente: si el usuario estrecha la ventana, el navegador reajusta los saltos de línea en tiempo real.
Esto también explica uno de los problemas más frecuentes en CSS: el scroll horizontal indeseado. Aparece cuando algún elemento es más ancho que su contenedor, desbordándolo. Las causas habituales son una imagen sin max-width: 100%, un elemento con un ancho fijo mayor que la ventana, o una palabra larga sin espacios (una URL, un identificador técnico) que no tiene punto de corte natural. Para este último caso existe overflow-wrap: break-word, que fuerza el corte en medio de la palabra si no queda otra opción.
Las técnicas de layout que veremos en las siguientes sublecciones (modelo de caja, flexbox, grid) trabajan sobre este flujo: algunas lo modifican, otras lo reemplazan completamente.
Elementos de bloque e inline
Cada elemento HTML tiene un comportamiento de flujo por defecto:
Elementos de bloque (block): ocupan todo el ancho disponible y comienzan en una línea nueva. El siguiente elemento baja. Ejemplos: <p>, <h1>-<h6>, <ul>, <div>, <section>, <article>.
Elementos inline (en línea): solo ocupan el espacio que necesita su contenido y no provocan salto de línea. Fluyen dentro del texto. Ejemplos: <span>, <a>, <strong>, <em>, <img>.
<p>
Este es un párrafo con <strong>texto en negrita</strong>
y un <a href="#">enlace</a> que fluyen dentro del texto.
</p>
<p>Este segundo párrafo baja porque <code><p></code> es un elemento de bloque.</p>
Las reglas de anidamiento reflejan esto: no se puede poner un elemento de bloque dentro de un elemento inline. Por eso <p><div>...</div></p> es HTML inválido (aunque el navegador lo corrija silenciosamente).
<div> y <span>
<div> y <span> son los contenedores genéricos de HTML. No tienen ningún significado semántico: solo sirven como ancla para aplicar CSS o JavaScript.
<div>es un contenedor de bloque. Se usa para agrupar bloques de contenido y aplicarles estilo o comportamiento colectivo.<span>es un contenedor inline. Se usa para marcar fragmentos de texto dentro de un párrafo.
<div class="tarjeta">
<h2>Título</h2>
<p>Texto con una <span class="destacado">palabra marcada</span> en verde.</p>
</div>
.tarjeta {
border: 1px solid #ddd;
padding: 1rem;
border-radius: 6px;
}
.destacado {
color: #84ba3f;
font-weight: bold;
}
Antes de HTML5, <div> era la única herramienta para estructurar páginas. Una página típica de aquella época era una jerarquía de <div id="header">, <div id="nav">, <div id="content">... Todo funcionaba, pero el código no decía nada sobre el significado de cada bloque.
Etiquetas semánticas HTML5
HTML5 introdujo etiquetas que hacen lo mismo que <div> a nivel de presentación, pero con un significado declarado. Benefician al SEO (los motores de búsqueda entienden mejor la estructura) y a la accesibilidad (los lectores de pantalla pueden navegar por secciones).
<header> contiene la cabecera de una página o sección: logo, título, navegación principal. Puede aparecer varias veces en la misma página (una por sección). No confundir con <head>, que contiene metadatos y no se renderiza.
<nav> marca un bloque de enlaces de navegación. No todos los grupos de enlaces son <nav>: solo los conjuntos de enlaces de navegación principales (menú del sitio, paginación, tabla de contenidos).
<main> encierra el contenido principal de la página, el que es único en esa URL. Solo debe haber uno por página. No incluye navegación repetida, encabezados comunes ni pies de página.
<article> marca contenido que tiene sentido por sí solo y podría redistribuirse de forma independiente: un post de blog, una noticia, una reseña, un comentario. La prueba es: ¿tendría sentido este bloque fuera de contexto? Si sí, es un <article>.
<section> agrupa contenido temáticamente relacionado dentro de una página o artículo, normalmente con su propio encabezado. Si el bloque no necesita un título, probablemente sea mejor un <div>.
<aside> contiene contenido relacionado con el contenido principal pero no esencial para entenderlo: una barra lateral, un recuadro de información adicional, publicidad relacionada.
<footer> contiene información al final de una página o sección: copyright, enlaces legales, información de contacto, autor.
<body>
<header>
<h1>Mi blog</h1>
<nav>
<ul>
<li><a href="/">Inicio</a></li>
<li><a href="/archivo">Archivo</a></li>
<li><a href="/contacto">Contacto</a></li>
</ul>
</nav>
</header>
<main>
<article>
<h2>El título del artículo</h2>
<section>
<h3>Introducción</h3>
<p>Primer apartado del artículo...</p>
</section>
<section>
<h3>Desarrollo</h3>
<p>Segundo apartado...</p>
</section>
</article>
<aside>
<h3>Artículos relacionados</h3>
<ul>...</ul>
</aside>
</main>
<footer>
<p>© 2026 Mi blog. <a href="/privacidad">Privacidad</a></p>
</footer>
</body>
¿Cuándo usar cada una?
La regla práctica es: usa semántica cuando existe una etiqueta que describe con precisión el propósito del bloque. Usa <div> cuando necesitas un contenedor para CSS sin significado semántico propio.
Dicho de otro modo: si vas a escribir <div class="header">, probablemente debería ser <header>. Pero si vas a escribir <div class="columna-izquierda"> o <div class="tarjeta">, no hay una semántica mejor y <div> es la elección correcta.
No hay que obsesionarse: un <div> bien nombrado en una página bien estructurada es mejor que etiquetas semánticas mal usadas.
La propiedad display
CSS permite cambiar el tipo de flujo de cualquier elemento con la propiedad display. Los valores más usados:
/* Convierte un elemento inline en bloque */
span { display: block; }
/* Convierte un elemento de bloque en inline */
div { display: inline; }
/* Comportamiento mixto: respeta dimensiones como bloque, fluye como inline */
img { display: inline-block; }
/* Elimina el elemento del flujo (no ocupa espacio) */
.oculto { display: none; }
/* Activa flexbox en el contenedor */
.fila { display: flex; }
/* Activa grid en el contenedor */
.rejilla { display: grid; }
display: inline-block es especialmente útil: permite aplicar width, height, padding vertical y margin vertical (que los elementos inline ignoran) sin provocar un salto de línea.
Recapitulación
- El flujo normal sigue dos ejes: los elementos inline fluyen de izquierda a derecha dentro de cada línea; los elementos de bloque se apilan de arriba a abajo, cada uno en su propia línea.
<div>es un contenedor de bloque genérico.<span>es su equivalente inline. No tienen significado semántico.- Las etiquetas semánticas HTML5 (
<header>,<nav>,<main>,<article>,<section>,<aside>,<footer>) describen el propósito del bloque, mejorando SEO y accesibilidad. - Usa semántica cuando hay una etiqueta que encaja. Usa
<div>cuando solo necesitas un contenedor para CSS. displaypermite cambiar el comportamiento de flujo de cualquier elemento:block,inline,inline-block,none,flex,grid.
Tu proyecto
Reestructura proyecto.html envolviendo el contenido en las etiquetas semánticas apropiadas. El aspecto visual no cambia, pero la estructura pasa a ser correcta:
<body>
<header>
<nav class="nav-principal">...</nav>
<h1 id="presentacion">Laura Suárez</h1>
<h2>Arquitecta</h2>
<p>Párrafo de presentación...</p>
</header>
<main>
<section id="proyectos">...tabla de proyectos...</section>
<section id="servicios">...lista de servicios...</section>
</main>
<footer id="contacto">
...formulario de contacto...
</footer>
</body>
En la próxima lección: el modelo de caja: cómo el navegador calcula el espacio que ocupa cada elemento, y las propiedades padding, margin y border.