wandres.dev
PROPS Y SLOTS · componer componentes

Named slots: varios huecos con nombre

Cómo definir múltiples huecos nombrados con slot name, dirigir cada fragmento hijo a su destino con el atributo slot en el padre, combinar los huecos con nombre con el slot por defecto que recoge lo no marcado, y construir con ellos un patrón de tarjeta con cabecera, cuerpo y pie reutilizable con cualquier contenido.

⏱ 15 min

Un solo hueco basta para envolver, pero no para estructurar. Cuando un componente necesita varias zonas —una cabecera arriba, un cuerpo en medio, un pie abajo—, el slot por defecto se queda corto: no distingue qué fragmento va a cada sitio. Los named slots resuelven el problema dando nombre a cada hueco, de modo que el padre pueda dirigir cada parte de su contenido al lugar exacto que le corresponde. Es el salto de la envoltura simple a la plantilla estructurada, donde el componente ofrece una forma con varias zonas nombradas.

🎯 Al terminar esta lección sabrás
  • Definir varios huecos nombrados en un componente con <slot name="cabecera" />.
  • Dirigir cada fragmento hijo a su hueco con el atributo slot="cabecera" en el padre.
  • Combinar los huecos con nombre con el slot por defecto que recoge lo no marcado.
  • Construir un patrón de tarjeta con cabecera, cuerpo y pie que se reutiliza con cualquier contenido.

Declarar huecos con nombre

Un slot con nombre es un <slot /> con un atributo name. Ese nombre lo convierte en un destino direccionable: una zona con identidad propia dentro del componente, distinta de las demás.

---
// src/components/Tarjeta.astro
---
<article class="tarjeta">
  <header>
    <slot name="cabecera" />
  </header>
  <div class="cuerpo">
    <slot />
  </div>
  <footer>
    <slot name="pie" />
  </footer>
</article>

Tarjeta declara tres aberturas distintas. Dos llevan nombre —cabecera y pie— y una no lo lleva: es el slot por defecto, el mismo de la lección anterior. Cada zona queda encajada en su propia estructura —la cabecera dentro del <header>, el pie dentro del <footer>— de modo que el componente no solo separa el contenido en regiones, sino que envuelve cada región con la etiqueta semántica que le toca.

ℹ️
Los nombres de slot son cadenas libres

El nombre de un hueco es una cadena cualquiera: cabecera, pie, acciones, barra-lateral. No hay una lista fija ni nombres reservados, salvo default, que designa siempre al slot sin nombre. Elige nombres que describan el papel de la zona y no su aspecto: acciones envejece mejor que botones-abajo, porque el papel perdura aunque el diseño cambie. Un buen nombre de slot documenta el contrato de forma tan bien como un buen nombre de prop documenta el de datos.

Dirigir contenido: el atributo slot

Del lado del padre, cada fragmento hijo elige su destino con el atributo slot, cuyo valor debe coincidir con el nombre del hueco. Lo que no lleve ese atributo cae en el slot por defecto.

---
// src/pages/precios.astro
import Tarjeta from '../components/Tarjeta.astro';
---
<Tarjeta>
  <h3 slot="cabecera">Plan Pro</h3>
  <p>Todo lo del plan base, más analíticas e integraciones.</p>
  <a slot="pie" href="/alta">Contratar</a>
</Tarjeta>

El <h3> lleva slot="cabecera", así que aterriza en <slot name="cabecera" />; el <a> lleva slot="pie" y va al pie. El <p>, que no declara ningún slot, cae en el hueco por defecto y forma el cuerpo. Cada hijo se enruta por su atributo, y el reparto queda explícito en el punto de uso: leyendo la página se sabe qué va a cada zona sin abrir el componente.

El orden en que escribes los hijos no altera su destino: un fragmento con slot="pie" va al pie aunque lo pongas primero en la página. El atributo manda sobre la posición en el código, lo que te deja ordenar el marcado del padre por claridad —cabecera, cuerpo, pie— sin atarlo a que ese orden coincida con el de las zonas declaradas en el hijo.

Cuando una zona necesita varios elementos, no hace falta inventar un contenedor solo para colgarle el atributo slot. <Fragment> agrupa varios nodos bajo un mismo destino sin dejar rastro en el HTML.

<Tarjeta>
  <Fragment slot="cabecera">
    <h3>Plan Pro</h3>
    <span class="insignia">Nuevo</span>
  </Fragment>
</Tarjeta>
💡
Fragment agrupa una zona sin dejar rastro

La regla es la misma que ya viste con Fragment: la forma corta agrupa y nada más, pero en cuanto un grupo necesita un atributo —aquí, slot="cabecera"— hay que usar la forma nombrada <Fragment slot="...">. Así varios elementos comparten un mismo destino sin que un contenedor artificial se cuele en la zona del componente y le rompa la maquetación.

El patrón tarjeta y la reutilización

Estas tres zonas forman un patrón clásico de interfaz, y su fuerza está en que la estructura permanece fija mientras el contenido varía. La misma Tarjeta produce una ficha de precio, un artículo de blog o un aviso, porque cada padre rellena las zonas con lo que necesita sin tocar el componente.

🔠

cabecera (con nombre)

Hueco nombrado para el titular. Vive dentro del <header> de la tarjeta y se rellena con slot="cabecera".

📄

cuerpo (por defecto)

El slot sin nombre: recoge todo lo que el padre no marca. Es el contenido principal de la pieza.

🔻

pie (con nombre)

Hueco nombrado para acciones o notas. Vive dentro del <footer> y se rellena con slot="pie".

Para ver la reutilización en acción, la misma tarjeta sirve para un contenido por completo distinto sin cambiar una línea de su código: una noticia con imagen en la cabecera y una fecha en el pie.

<Tarjeta>
  <img slot="cabecera" src="/portada.jpg" alt="Portada del artículo" />
  <p>Astro 7 estabiliza el renderizado en el servidor y afina los islands.</p>
  <time slot="pie" datetime="2026-07">Julio de 2026</time>
</Tarjeta>

Fíjate en el reparto de responsabilidades. La tarjeta decide el orden de las zonas, sus etiquetas semánticas y su estilo; el padre decide qué contenido llena cada una. Rediseñar la tarjeta —mover el pie, cambiar el <header>— afecta a todos sus usos a la vez, y ninguno se rompe, porque el contrato entre ambos es un mapa de nombres, no un acuerdo sobre el contenido concreto.

Reglas de emparejamiento

El sistema es simple, pero tiene esquinas que conviene conocer para no perseguir fantasmas cuando una zona aparece vacía.

⚠️
El nombre debe coincidir exactamente

El emparejamiento entre slot="cabecera" y <slot name="cabecera" /> es una comparación literal de cadenas. Un desajuste —slot="cabezera", una mayúscula de más, un guion donde había un espacio— no lanza ningún error: el fragmento apunta a un hueco que no existe y, sencillamente, se descarta. Si una zona sale vacía, sospecha antes que nada de una diferencia de una letra entre el nombre declarado y el usado.

Del emparejamiento se derivan tres reglas más. Varios fragmentos con el mismo slot se concatenan en el orden del documento, así que puedes mandar dos elementos a una zona sin agruparlos. Todo lo que no lleve atributo slot se acumula en el hueco por defecto. Y si el padre proyecta contenido sin marca pero el componente no declara un <slot /> por defecto, ese contenido no tiene dónde ir y se pierde sin aviso.

<Tarjeta>
  <h3 slot="cabecera">Plan Pro</h3>
  <span slot="cabecera" class="insignia">Nuevo</span>
  <p>Ambos elementos anteriores se concatenan dentro del header, en este orden.</p>
</Tarjeta>
flowchart TD
H[h3 con slot cabecera] --> SC[slot name cabecera dentro del header]
P[p sin atributo slot] --> SD[slot por defecto dentro del cuerpo]
A[a con slot pie] --> SP[slot name pie dentro del footer]
style H fill:#89b4fa,color:#11111b
style SP fill:#a6e3a1,color:#11111b
📝
Reenviar un hueco a otro nivel

Una capa intermedia puede dejar pasar una zona nombrada sin tocar su contenido escribiendo <slot name="pie" slot="pie" />: el primer atributo declara el hueco que recibe y el segundo lo reenvía al hueco homónimo del componente que envuelve. Así la proyección se encadena a través de varios niveles, que es justo como los layouts anidados propagan sus zonas hacia dentro. No hace falta para el caso común, pero explica cómo un hueco puede viajar más allá del primer componente que lo recibe.

Los named slots son la API de forma de un componente

Una interface Props declara la API de datos de un componente: qué valores acepta, de qué tipo, cuáles son obligatorios. Los slots con nombre declaran algo distinto y menos reconocido, su API de forma: el conjunto de zonas que la pieza ofrece para ser rellenadas. Cuando escribes <slot name="cabecera" />, <slot /> y <slot name="pie" />, no pides datos; publicas un mapa de posiciones —aquí el encabezado, aquí el cuerpo, aquí el pie— que cualquier padre puede ocupar como quiera. Ese mapa es un contrato tan real como el de las props, pero opera sobre la estructura en vez de sobre los valores. La consecuencia de diseño es profunda. Un componente que resuelve todas sus variantes con props tiende a hincharse: cada caso nuevo añade una bandera booleana, una rama, un parámetro más, hasta que su interfaz se vuelve un panel de control imposible. Un componente que expone zonas nombradas se mantiene delgado porque no intenta prever el contenido de cada zona, solo garantiza que existan y dónde están. La tarjeta no sabe si su cabecera lleva un título, un logotipo o un vídeo; solo promete que habrá una cabecera, envuelta en su <header>, colocada antes del cuerpo. Diseñar con named slots es, por tanto, un ejercicio de identificar las juntas naturales de una pieza —los lugares donde el contenido legítimamente varía— y darles nombre, en vez de parametrizar cada relleno posible. Las props dicen qué necesito saber para funcionar; los slots con nombre dicen qué espacios ofrezco para que me completes. Un buen componente reparte con criterio entre ambos idiomas: pide por props lo poco que debe interpretar y abre por slots las muchas zonas que solo debe alojar. Cuando esa frontera está bien trazada, la pieza se reutiliza en contextos que su autor jamás imaginó, porque su contrato describe una forma, no un contenido.

⚔️ Diseña una tarjeta de tres zonas
  1. Crea Tarjeta.astro con tres huecos: <slot name="cabecera" /> dentro de un <header>, un <slot /> por defecto para el cuerpo y <slot name="pie" /> dentro de un <footer>.
  2. Úsala desde una página mandando un <h3> a cabecera, un párrafo al cuerpo sin atributo slot y un enlace a pie; comprueba en el HTML que cada pieza cae en su zona.
  3. Manda dos elementos a cabecera con el mismo slot="cabecera" y confirma que se concatenan dentro del <header> en el orden en que los escribiste.
  4. Escribe slot="cabezera" con una errata a propósito y observa que ese fragmento desaparece sin error: la prueba de que el emparejamiento es literal.