wandres.dev
LAYOUTS · plantillas compartidas

Construir un layout con slot

El elemento slot como hueco donde se proyecta el contenido de cada página. La mecánica de composición, el contenido por defecto de un slot vacío, la idea de los slots con nombre y cómo una página consume el layout envolviendo su contenido.

⏱ 14 min

Un layout sin <slot /> es un marco sin cuadro: estructura vacía que no sabe dónde poner nada. El <slot /> es la pieza que convierte un componente cualquiera en un envoltorio útil, el hueco reservado donde aterriza el contenido de la página que lo use. Construir un layout es, en esencia, decidir dónde va ese hueco y qué lo rodea.

🎯 Al terminar esta lección sabrás
  • Escribir un layout mínimo con un <slot /> funcional dentro de su estructura.
  • Entender la proyección: cómo el contenido de la página llega hasta el hueco del layout.
  • Aprovechar el contenido por defecto de un <slot /> para regiones opcionales.
  • Consumir un layout desde una página envolviendo su contenido entre etiquetas.

El hueco donde entra la página

El <slot /> es un elemento marcador de posición. Cuando una página escribe <Base>...</Base>, todo lo que ponga entre la etiqueta de apertura y la de cierre —lo que Astro llama los hijos del componente— se renderiza exactamente donde el layout haya colocado su <slot />. El layout no sabe qué contenido va a recibir; solo reserva el sitio. La página no sabe cómo es el marco; solo entrega su interior. Cada uno ignora al otro, y esa ignorancia mutua es lo que hace la composición robusta.

Conviene fijar el vocabulario, porque volverá una y otra vez. Al layout se le llama el componente envolvente; a lo que la página coloca entre sus etiquetas, los hijos o el contenido proyectado; y al acto de que esos hijos aparezcan dentro del layout, proyección. Son tres nombres para una sola mecánica: el contenido de fuera se proyecta en el hueco de dentro.

Este patrón no es invención de Astro: es la proyección de contenido de los Web Components estándar, y el primo hermano de la prop children de React. En todos los casos la idea es la misma —un componente reserva un hueco y quien lo usa lo rellena—, pero en Astro ocurre en tiempo de compilación y no cuesta ni un byte de JavaScript en el cliente. El <slot /> es una costura del build, no un mecanismo del navegador.

Construir el layout paso a paso

Un layout mínimo pero completo tiene el documento entero y un único <slot /> en el punto donde debe entrar el contenido, casi siempre dentro del <main>.

---
// src/layouts/Base.astro
---
<!doctype html>
<html lang="es">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>Mi sitio</title>
  </head>
  <body>
    <header>
      <nav><a href="/">Inicio</a> · <a href="/blog">Blog</a></nav>
    </header>
    <main>
      <slot />
    </main>
    <footer>© 2026 Mi sitio</footer>
  </body>
</html>

Cada parte cumple un papel. El <!doctype html> y el <html> establecen el documento; el <head> reúne los metadatos; la cabecera y el pie son el marco visible constante; y el <slot /> dentro del <main> es la única grieta por la que entra lo que cambia. Fíjate en que el <slot /> se escribe autocerrado, igual que una etiqueta HTML vacía: no envuelve nada por sí mismo, solo señala una posición.

flowchart LR
PAG[contenido de la pagina] --> SLOT[slot dentro del main]
SLOT --> OUT[documento html final]
MARCO[cabecera head y pie] --> OUT
style SLOT fill:#89b4fa,color:#11111b
style OUT fill:#a6e3a1,color:#11111b

La posición del <slot /> importa tanto como su existencia. Ponlo dentro del <main> y el contenido de cada página quedará envuelto por la semántica de contenido principal, con la cabecera antes y el pie después. Muévelo fuera del <main> y romperías esa estructura. El layout no solo decide qué rodea al contenido, sino con qué etiquetas lo rodea, y esa decisión afecta a la accesibilidad y al SEO de todas las páginas a la vez.

Contenido por defecto y el slot vacío

Un <slot /> puede no estar vacío. Si escribes contenido entre sus etiquetas, ese contenido actúa como valor por defecto: se muestra solo cuando quien usa el layout no entrega nada para ese hueco. En cuanto la página aporta hijos, el contenido por defecto desaparece y es reemplazado por completo.

<main>
  <slot>
    <p>Esta página todavía no tiene contenido.</p>
  </slot>
</main>

La semántica es la de un respaldo, no la de un añadido: el contenido por defecto y el de la página nunca conviven. O uno, o el otro. Esto es útil para regiones opcionales de un layout —una barra lateral que a veces no se rellena, un aviso que solo aparece si la página no puso el suyo— donde quieres una alternativa sensata en lugar de un hueco en blanco.

💡
Un slot vacío no molesta

Si una página no pone nada donde el layout espera contenido y el <slot /> tampoco tiene respaldo, simplemente no se renderiza nada en ese punto. No hay error ni marcado sobrante: el hueco desaparece limpiamente. Puedes diseñar layouts con <slot /> opcionales sin temer que ensucien la salida cuando queden sin usar.

📝
Más de un hueco: los slots con nombre

Un layout puede reservar varios huecos distintos dándoles nombre con <slot name="cabecera" />, y la página los rellena marcando su contenido con el atributo correspondiente. Así un layout puede recibir, por ejemplo, un título arriba y un pie de página propio, cada uno en su sitio. No lo necesitas para el caso común —un solo <slot /> sin nombre basta para el contenido principal— pero saber que existe te dice que la proyección no se limita a un único hueco cuando un diseño lo pida.

Cómo una página usa el layout

Del otro lado, la página importa el layout como cualquier componente y envuelve su contenido entre las etiquetas de apertura y cierre. Todo lo que quede dentro se convierte en los hijos que aterrizarán en el <slot />.

---
// src/pages/index.astro
import Base from '../layouts/Base.astro';
---
<Base>
  <h1>Bienvenido</h1>
  <p>Este párrafo aterriza en el slot del layout.</p>
</Base>

Observa la inversión que se ha producido. La página ya no abre un <html>, ni declara un <head>, ni dibuja una cabecera: ha delegado todo eso en el layout. Se ha encogido hasta su esencia —lo único que la distingue de cualquier otra ruta— y el marco se lo pone Base desde fuera. Comparada con la página del capítulo anterior, cargada de armazón repetido, esta dice exactamente lo que tiene que decir y ni una etiqueta más.

⚠️
Un solo documento por página

El <html>, el <head> y el <!doctype html> deben vivir en el layout, no en la página, y aparecer una sola vez en el resultado. Si la página que usa el layout también abriera su propio <html>, obtendrías un documento anidado dentro de otro: HTML inválido que los navegadores intentarán reparar con resultados impredecibles. La regla es simple: el layout es dueño del documento; la página solo aporta su interior.

La composición invierte quién manda sobre la estructura

El <slot /> encarna un cambio de mando que va más allá de ahorrar tecleo. En un mundo sin composición, cada página es soberana: se construye a sí misma de arriba abajo, decide su propio <html> y carga con la responsabilidad de acertar en cada detalle del armazón. Con el <slot />, la soberanía se invierte: la página deja de ser el documento y pasa a ser un fragmento que otro compone. Es el layout quien manda sobre la estructura, y la página se limita a proveer su contenido cuando se lo piden. Esta inversión —el control de la forma sube al envoltorio, y el detalle particular baja al envuelto— es el mismo principio que rige la composición en toda la programación moderna: funciones que reciben funciones, componentes que reciben hijos, decoradores que envuelven a lo decorado. Lo poderoso es que ninguna de las dos partes necesita conocer a la otra. El layout puede rediseñarse entero —cambiar la cabecera, mover el <slot />, reorganizar el <body>— sin tocar una sola página, porque su contrato con ellas es un único hueco, no un acuerdo detallado. Y la página puede reescribirse sin saber en qué marco vivirá, porque solo entrega contenido. Cuando entiendes el <slot /> no como “el sitio donde va el texto” sino como “la frontera donde se acuerda quién controla qué”, empiezas a diseñar sistemas donde las piezas se recombinan sin fricción, y ese es el rendimiento real de la composición: no menos código, sino menos acoplamiento.

⚔️ Levanta tu primer marco con hueco
  1. Escribe src/layouts/Base.astro con un documento HTML completo y un único <slot /> dentro del <main>; asegúrate de que el <!doctype html> y el <head> viven ahí y no en las páginas.
  2. Crea src/pages/index.astro, importa Base y envuelve un <h1> y un párrafo entre <Base> y </Base>; visita / y confirma que tu contenido aparece dentro del marco.
  3. Da al <slot /> un contenido por defecto y crea una página que use el layout sin poner nada dentro: comprueba que se muestra el respaldo.
  4. Rediseña la cabecera del layout —añade un enlace, cambia el texto— y verifica que todas las páginas lo heredan sin que hayas tocado ninguna de ellas.