Módulo del sitio · Migas de pan

Las Migas de pan: dónde estás y cómo volver

La línea fina bajo el header de las páginas internas. En un vistazo dicen en qué parte del sitio estás y dejan saltar a cualquier nivel superior, sin recurrir al botón «atrás» del navegador.

Esta página no es una ficha técnica más: es el módulo entero, abierto y explicado. Qué problema resuelve y por qué se gana su lugar bajo el header, de qué piezas se compone, dónde encaja en el layout y cómo está construido —el recorrido completo, del criterio de diseño a la implementación.

Con una diferencia respecto a los módulos del chrome: las migas no son globales (como el topbar o el header) ni de contenido editorial (como el hero). Son la RUTA del visitante en la jerarquía. Cada página la declara una sola vez en su prop breadcrumbs, y de ahí salen a la vez la barra visible (con microdata) y el JSON-LD BreadcrumbList, que el layout emite una única vez —jamás duplicado—.

Definición

¿Qué son las migas de pan?

La ruta de la página: una línea de eslabones que muestran, desde la home hasta donde estás, el camino jerárquico del sitio.

Las migas de pan (breadcrumbs) son una línea breve y discreta que aparece bajo el header en las páginas internas. Listan, de izquierda a derecha, los niveles del sitio que llevan a la página actual: Inicio › Sección › Subsección › Página. Cada nivel superior es un enlace; el último, la página donde estás, no enlaza —ya estás ahí—.

Su nombre nace de cuento: las migajas que deja Hansel para volver a casa. La metáfora encaja: no son un menú ni una decoración —son el rastro que el visitante puede seguir hacia atrás—. Por eso reflejan la JERARQUÍA del sitio, no el historial del navegador: si llegaste a una página desde otra rama, las migas siguen mostrando su sitio natural en el árbol, no de dónde venías.

Función e importancia

¿Para qué sirven?

Hacen tres trabajos a la vez: ubicar al visitante en la jerarquía, darle un camino rápido de vuelta a cualquier nivel y alimentar el rastro que el buscador muestra en los resultados.

Su función es resolver, en una sola línea, dos preguntas que cualquier visitante trae cuando aterriza en una página interna —sea por un menú, por Google o por un enlace compartido—: «¿dónde estoy?» y «¿cómo subo un nivel?». Sin migas, esas dos respuestas obligan a explorar el menú o a darle al botón «atrás» con suerte; con ellas, son una mirada.

Y de propina, hacen un tercer trabajo invisible al ojo. La misma ruta, expresada como BreadcrumbList en el JSON-LD, le dice a Google la posición de la página dentro de la estructura del sitio. Cuando el motor cumple sus requisitos, esa cadena aparece bajo el título en los resultados, en lugar de la URL cruda —más limpio, más legible, mejor clic—. Una pieza pequeña con peso fuera de proporción a su tamaño.

Orientación de un vistazo

En las páginas internas, las migas responden la pregunta que el visitante trae sin formularla: «¿dónde estoy parado dentro del sitio?». Una sola línea, leída en un segundo, ubica la jerarquía y ahorra explorar el menú para entenderlo.

Camino de vuelta sin penalizar

Cada nivel superior es un enlace, así que dejan saltar a la categoría o a la home sin usar el botón «atrás» del navegador. Bajan la fricción para explorar laterales del sitio y suelen mejorar las páginas vistas por sesión.

Jerarquía legible para el buscador

El BreadcrumbList del schema (JSON-LD) le dice a Google la posición de la página dentro de la estructura. Cuando se cumplen los requisitos, ese rastro aparece bajo el título en los resultados, en lugar de la URL cruda.

Anatomía

¿Qué llevan las migas?

Cuatro piezas: la raíz (Inicio), cada eslabón intermedio (categoría, subcategoría), el separador entre ellos y la página actual al final.

Cada pieza tiene un papel claro. La raíz ancla la ruta a la home —el punto de partida que todos esperan—; los eslabones intermedios son enlaces que dejan saltar a cualquier nivel superior; el separador es una flecha decorativa que marca la dirección de la jerarquía; y el último eslabón es la página actual: ni enlace ni separador después, porque ya llegaste.

Abajo, el ejemplo en vivo —réplica anotada de una ruta real (Inicio › Servicios › Diseño de logotipo)—. Cada punto numerado se desglosa en su tarjeta: qué resuelve y de qué dato del componente sale. A diferencia del hero, los textos no se inventan: son el rastro jerárquico de la página, declarado UNA sola vez en la prop breadcrumbs del layout.

1

Raíz (Inicio)

El primer eslabón, siempre enlazado a la home. Es el punto de partida de la ruta y el «volver al inicio» que todos esperan al inicio de una jerarquía. El componente lo antepone automáticamente: la página solo declara su rastro.

Dato items[0] · href '/'

2

Eslabón intermedio

Cada nivel ancestro entre la home y la página actual (categoría, subcategoría). Son enlaces de verdad: dejan saltar a cualquier nivel superior sin tocar el botón «atrás» del navegador.

Dato items[].href

3

Separador

El icono (›) entre eslabones. Es decorativo —va con aria-hidden— y solo marca la dirección de la jerarquía; nunca es un enlace ni se lee con lector de pantalla.

Dato SVG · aria-hidden

4

Página actual

El último eslabón: la página donde estás. No enlaza (ya estás ahí) y se marca con aria-current="page" para que los lectores de pantalla la anuncien como destino actual.

Dato item sin href · aria-current

Variantes

Otros diseños y aplicaciones

Las de esta plantilla son texto con separador, pero la ruta se viste distinto según el tipo de sitio y la profundidad del catálogo.

No hay un único modelo: hay una misma idea —el rastro jerárquico de una página— que cada tipo de proyecto ajusta a su contexto. Una tienda con catálogo profundo gana con un icono casa y rutas colapsables; una app prefiere cápsulas que se tocan cómodo; un sitio editorial se queda con el clásico texto + chevron, sobrio y sin estorbar la lectura.

Abajo, seis variantes reales —cada una con su réplica en vivo y el tipo de proyecto donde rinde mejor—. Sirven para reconocer cuál encaja con tu caso y ver cómo el mismo molde cambia de cara sin perder su función: orientar y dejar volver.

  • Texto con separador (›)

    Sitio de negocio · Servicios

    La de esta plantilla. Cada nivel es texto, separado por un chevron ligero (›) con aria-hidden. Discretas y universales: el ojo ya las tiene aprendidas, así que no compiten con el contenido. La opción más segura para casi cualquier sitio.

  • Con icono «home» en la raíz

    E-commerce · Catálogo

    El primer eslabón se reemplaza por un icono de casa enlazado a la home; el resto sigue como texto. Compacta la ruta y refuerza el atajo «volver al inicio», que en tiendas grandes es uno de los enlaces más usados de toda la página.

  • Cápsulas (pills)

    SaaS · Paneles

    Cada eslabón vive en una cápsula con fondo suave, separada por un chevron. Da más peso visual y un blanco táctil generoso —cómodo de tocar—; encaja en apps y paneles donde la jerarquía es información operativa, no adorno.

  • Compactas: «atrás + actual»

    Móvil · Detalle de producto

    En móvil, las migas largas se sustituyen por una flecha «atrás» al nivel inmediato superior + el nombre de la página actual. Mantiene el camino de vuelta sin obligar al texto a multilínea; el rastro completo queda para el escritorio.

  • Colapsadas con «…»

    Catálogo profundo · Wiki

    Cuando la jerarquía es muy profunda, los niveles intermedios se colapsan en «…» que se expanden al tocar. Las puntas siempre visibles (Inicio y la página actual) dan contexto sin desbordar la línea.

  • Truncado con tooltip

    Documentación · CMS

    Cada eslabón se trunca con ellipsis si su etiqueta es larga; al pasar el cursor (o con el teclado) aparece el nombre completo en un tooltip. Útil cuando los títulos no se pueden acortar pero la ruta debe caber en una sola línea.

Responsive y móvil

Cómo se comportan en el teléfono

La pantalla del teléfono no perdona una ruta larga. Por debajo de 640 px las migas dejan de fluir en multilínea y eligen un patrón: scroll horizontal, truncado, colapso o «atrás + actual».

En escritorio las migas viven cómodas en una sola línea, con espacio de sobra. En el teléfono, una ruta de cuatro o cinco eslabones se parte en dos y tres líneas si la dejas fluir —y de paso roba altura al contenido—. Por eso conviene elegir, según el sitio, una estrategia: hacerlas scrollables, truncar cada eslabón, colapsar el medio o cambiar al patrón compacto «← atrás + página actual».

Las cuatro están abajo, cada una con su vista en el teléfono y una receta comentada lista para adaptar. La que ya trae el componente de esta plantilla es la primera (flex-wrap natural en dos líneas, que es lo más seguro cuando la ruta es corta). Las otras tres se aplican como capa adicional en proyectos con catálogos profundos o títulos largos.

1 · Una sola línea con scroll

Si la ruta no cabe, en lugar de partirse en varias líneas se vuelve scrollable en horizontal —como una app—. Se ocultan las barras de scroll para que el efecto quede limpio y se mantiene la inercia táctil en iOS.

CSS · scroll horizontal sin barra
/* MIGAS MÓVIL · una sola línea con scroll horizontal
   Si los eslabones no caben, la lista se desliza en horizontal en
   lugar de partirse en varias líneas. La barra de scroll se oculta
   para que el efecto quede como en una app, sin línea gris. */

.breadcrumb__list {
  display: flex;
  flex-wrap: nowrap;                      /* no multilínea */
  overflow-x: auto;
  scrollbar-width: none;                  /* Firefox */
  -webkit-overflow-scrolling: touch;      /* inercia iOS */
}
.breadcrumb__list::-webkit-scrollbar { display: none; }   /* WebKit */
.breadcrumb__item { white-space: nowrap; }                /* no parte la etiqueta */

2 · Truncar eslabones largos

Cada enlace recibe un ancho máximo (≈ 14 caracteres) y, si su etiqueta se pasa, se corta con «…». El nombre completo queda accesible en el atributo title y se ve al pasar el cursor o con el teclado.

CSS · ellipsis por eslabón
/* MIGAS MÓVIL · truncar eslabones largos con ellipsis
   Cada enlace tiene un ancho máximo y, si su texto se pasa,
   se corta con «…». El nombre completo queda en el atributo
   title para verlo al pasar el cursor o con teclado. */

@media (max-width: 600px) {
  .breadcrumb__link,
  .breadcrumb__current {
    max-width: 14ch;            /* ~14 caracteres por eslabón */
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    display: inline-block;
    vertical-align: bottom;
  }
}

3 · Colapsar el medio

Cuando la jerarquía es profunda, los niveles intermedios se ocultan tras un «…» que se expande al tocar. Las puntas (Inicio y la página actual) quedan siempre visibles: contexto suficiente sin saturar la pantalla. Se resuelve con <details> nativo, sin JavaScript.

HTML · <details> colapsando el medio
<!-- MIGAS MUY PROFUNDAS · colapsar el medio con «…»
     Con <details> nativo, sin una línea de JavaScript: las puntas
     (Inicio y la página actual) siempre visibles; los intermedios
     se expanden al tocar el «…». Accesible y progresivo. -->
<nav aria-label="Migas de pan">
  <ol class="breadcrumb__list">
    <li><a href="/">Inicio</a></li>
    <li aria-hidden="true">›</li>

    <li>
      <details class="bc-colapso">
        <summary aria-label="Ver niveles intermedios">…</summary>
        <a href="/productos">Productos</a>
        <a href="/productos/uniformes">Uniformes</a>
        <a href="/productos/uniformes/escolares">Escolares</a>
      </details>
    </li>

    <li aria-hidden="true">›</li>
    <li><span aria-current="page">Primaria</span></li>
  </ol>
</nav>

4 · «← Atrás + página actual»

En catálogos y detalle de producto, la ruta larga se reemplaza en móvil por una flecha al nivel inmediato superior y, a la derecha, el nombre de la página actual. Mantiene el camino de vuelta sin pedirle al texto que ocupe dos líneas. El rastro completo regresa en escritorio.

CSS · alterna patrón con @media
/* En el teléfono, oculta los niveles intermedios y muestra
   solo el botón ← + la página actual. En escritorio reaparece
   la ruta completa. Mismo HTML, dos comportamientos. */

@media (max-width: 600px) {
  .breadcrumb__list { justify-content: space-between; }
  .breadcrumb__item:not(:first-child):not(:last-child),
  .breadcrumb__sep { display: none; }       /* solo padre + actual */
  .breadcrumb__item:first-child a::before {
    content: '← ';                          /* flecha atrás */
  }
}

Posición

¿Dónde se colocan?

En las páginas internas, justo bajo el header y antes del hero o del título. Una sola vez por página; nunca en la home, donde no aportan.

El orden del armado es deliberado y se respeta en todo el sitio. PageLayout apila el chrome siempre igual: primero el topbar (la barra utilitaria), debajo el header (marca y navegación), enseguida las migas y, recién entonces, el contenido. Las migas viven en una franja sutil —fondo de superficie con un hilo de borde inferior—, lo bastante presentes para encontrarse, lo bastante calladas para no competir con el hero.

No van en la home: ahí no hay nivel superior y serían ruido. Tampoco encima del header o intercaladas con el contenido: su sitio es la franja entre el chrome y el cuerpo, donde el ojo ya las espera. En esta plantilla, basta con que la página pase la prop <code>breadcrumbs</code> al layout: si está, se pinta la barra y se emite el BreadcrumbList; si no, ninguno de los dos aparece —cero ruido en páginas que no las necesitan—.

Módulos cercanos en el chrome: header (la barra justo encima), topbar (la franja utilitaria del tope) y encabezado de sección (el primer título dentro del contenido).

Implementación

Cómo están construidas

Una sola declaración por página alimenta dos consumidores: el componente visible (con microdata) y el JSON-LD BreadcrumbList, emitido una única vez por el layout.

Las migas viven en Breadcrumbs.astro y se pintan automáticamente cuando una página declara la prop breadcrumbs en su layout. Esa prop es una lista mínima: cada entrada lleva un label y, salvo la última (la página actual), un href. El componente antepone la raíz «Inicio» en el visual, así que la página no necesita repetirla; el último eslabón —sin href— se marca con aria-current="page" y queda en color de tinta, sin enlace.

Aquí entra una regla dura del proyecto (B3, anti-patrón confirmado en otros codebases): el BreadcrumbList del JSON-LD se emite UNA sola vez. Lo hace buildSchema() en lib/seo.ts cuando recibe la prop, no el componente visual —si los dos lo emitieran, el rich result de Google se duplicaría y los validadores marcarían error—. Por eso la barra del Breadcrumbs.astro lleva microdata (itemtype/itemprop) en el HTML, suficiente para acompañar el JSON-LD sin chocar con él.

Astro · la prop breadcrumbs de la página
---
// Cada página declara SU rastro UNA sola vez en la prop breadcrumbs.
// El componente antepone «Inicio» en el visual y buildSchema arma el JSON-LD.
import PageLayout from '@layouts/PageLayout.astro'
---

<PageLayout
  title="Diseño de logotipo — Servicios"
  description="…"
  pageType="service"
  breadcrumbs={[
    { label: 'Servicios', href: '/servicios' },
    { label: 'Diseño de logotipo' },        // sin href = página actual
  ]}
>
  {/* …contenido de la página… */}
</PageLayout>
HTML · barra visible con microdata
<!-- BARRA VISIBLE · ol con microdata schema.org/BreadcrumbList
     El último <li> NO tiene <a> y va con aria-current="page".
     El separador es SVG decorativo (aria-hidden), nunca un enlace. -->
<nav aria-label="Migas de pan">
  <ol itemscope itemtype="https://schema.org/BreadcrumbList">

    <li itemprop="itemListElement" itemscope
        itemtype="https://schema.org/ListItem">
      <a href="/" itemprop="item"><span itemprop="name">Inicio</span></a>
      <meta itemprop="position" content="1" />
    </li>

    <svg aria-hidden="true" viewBox="0 0 24 24"><polyline points="9 18 15 12 9 6"/></svg>

    <li itemprop="itemListElement" itemscope
        itemtype="https://schema.org/ListItem">
      <span aria-current="page" itemprop="name">Diseño de logotipo</span>
      <meta itemprop="position" content="2" />
    </li>

  </ol>
</nav>
TypeScript · BreadcrumbList centralizado (lib/seo.ts)
// lib/seo.ts — breadcrumbSchema(): el JSON-LD BreadcrumbList,
// emitido UNA sola vez por buildSchema() (regla dura B3 del proyecto).
// El componente Breadcrumbs.astro NO emite su propio script para
// evitar el doble BreadcrumbList (anti-patrón).
export function breadcrumbSchema(items: { name: string; path: string }[]) {
  return {
    '@type': 'BreadcrumbList',
    itemListElement: items.map((c, i) => ({
      '@type': 'ListItem',
      position: i + 1,
      name: c.name,
      item: c.path ? new URL(c.path, SITE.url).toString() : undefined,
    })),
  };
}

// En buildSchema():
if (data.breadcrumbs?.length) {
  out.push({ '@context': CTX, ...breadcrumbSchema(data.breadcrumbs) });
}

En concreto: PageLayout recibe breadcrumbs, transforma la lista al formato del schema ({ name, path }) anteponiendo { name: 'Inicio', path: '/' }, la pasa a BaseLayout dentro de schemaData, y a la vez se la entrega al componente visual Breadcrumbs.astro para que pinte la barra.

El componente visual lleva un modo guía opcional (guia={true}) que pinta una ruta de EJEMPLO con marcadores numerados y una leyenda debajo —es lo que viste arriba a escala—, pensado para páginas que documentan el sitio. En producción se usa con guia={false} (lo que hace esta página de la serie): la ruta REAL, sin marcas ni leyendas, con su microdata BreadcrumbList. El JSON-LD se sigue emitiendo donde corresponde: en el <head>, una sola vez por buildSchema().

Buenas prácticas

Qué hacer y qué evitar

La diferencia entre unas migas que orientan y unas que confunden está en un puñado de hábitos —y en no caer dos veces en el mismo error de duplicar el schema—.

Ninguno de estos hábitos es capricho: salen de mirar cómo usa la gente las migas y de los requisitos del rich result en Google. Unas migas que funcionan reflejan la jerarquía del sitio, no el historial; tienen etiquetas cortas y reconocibles; y dejan claro que el último eslabón es la página actual —sin enlace, con aria-current—.

Donde el equipo se tropieza más seguido es en duplicar el BreadcrumbList del JSON-LD: lo emiten en el componente Y en el layout. Google marca duplicado, y a veces no muestra ninguno. La plantilla lo previene de fábrica (el componente NO emite script), pero conviene saberlo si copias trozos a otro proyecto. Abajo, lo que conviene y lo que conviene evitar, enfrentados.

Sí conviene

  • Refleja la JERARQUÍA del sitio, no el historial: Inicio › Categoría › Página, no «la página anterior».
  • Que el último eslabón sea la página actual, sin enlace y con aria-current="page".
  • Mantén etiquetas cortas y reconocibles: «Servicios», no «Nuestros servicios profesionales».
  • Coloca las migas justo debajo del header, antes del hero o del título de la página interna.
  • Define la ruta una sola vez en la prop breadcrumbs; el JSON-LD lo emite buildSchema (regla B3).

Mejor evita

  • No las uses en la home: ahí no aportan, son ruido.
  • No las conviertas en un segundo menú con todas las secciones; son la RUTA de esta página.
  • No emitas el BreadcrumbList JSON-LD desde el componente: ya lo hace el layout (no dupliques).
  • No marques el último eslabón como enlace (ya estás ahí) ni le pongas un separador después.
  • No mezcles las migas con el título de la sección ni con un panel «volver»: cada cosa en su sitio.
¿Necesitas ayuda?