Cuando ya sabemos crear componentes en Astro y sabemos utilizar las props y los slots, es hora de comenzar a crear layouts. Según la complejidad de nuestra página, necesitaremos menos o más layouts. Es posible que necesites varios o simplemente uno.
¿Qué es un layout?
Un layout no es más que un componente de Astro, sólo que es algo especial porque contiene toda la estructura HTML de una página. De esta forma, es muy fácil reutilizar su código y no andar repitiéndolo en todas las páginas del sitio web.
Los layouts funcionan exactamente igual que los componentes, sólo que se colocan en una carpeta aparte en
src/layouts
, pero se importan y utilizan de la misma forma.
¿Cuál es el problema?
Tenemos la siguiente página de src/pages/index.astro
. El problema que tenemos actualmente, es que en cada página que creamos, tendríamos que repetir la estructura <html>
, <head>
, etc... y a parte de incómodo, no es muy práctico.
Para solucionarlo utilizaremos layouts. Partamos del siguiente código:
---
import SiteHeader from "../components/SiteHeader.astro";
import SiteNav from "../components/SiteNav.astro";
import SiteFooter from "../components/SiteFooter.astro";
const title = "Página principal";
const description = "Una larga y detallada descripción de mi página.";
---
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
<meta name="viewport" content="width=device-width" />
<meta name="generator" content={Astro.generator} />
<title>{title}</title>
<meta name="description" content={description} />
</head>
<body>
<SiteHeader />
<SiteNav />
<h2>{title}</h2>
<main>
<p>Contenido de la página web en cuestión.</p>
</main>
<SiteFooter />
</body>
</html>
Nos interesa crear las páginas src/pages/services/index.astro
y src/pages/about/index.astro
pero no queremos tener que repetirlo prácticamente todo en cada página, puesto que sólo van a cambiar ciertas cosas como el contenido de <body>
, y el title
y description
en cada página.
Creando layouts
Así pues, lo primero que haremos es crear una carpeta src/layouts
donde crearemos un componente BaseLayout.astro
. Este fichero va a contener la estructura (layout) de mi tipo de página. Metemos todo, salvo el contenido de <body>
:
---
import SiteHeader from "../components/SiteHeader.astro";
import SiteNav from "../components/SiteNav.astro";
import SiteFooter from "../components/SiteFooter.astro";
const { title, description } = Astro.props;
---
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
<meta name="viewport" content="width=device-width" />
<meta name="generator" content={Astro.generator} />
<title>{title}</title>
<meta name="description" content={description} />
</head>
<body>
<slot />
</body>
</html>
Como puedes ver, en el interior de <body>
añadimos un <slot>
. Esto hará que podamos importar el layout como un componente y meter en su interior el contenido de la página en cuestión. Veamos ahora como quedaría nuestra página src/pages/index.astro
:
---
import BaseLayout from "../layouts/BaseLayout.astro";
import SiteHeader from "../components/SiteHeader.astro";
import SiteNav from "../components/SiteNav.astro";
import SiteFooter from "../components/SiteFooter.astro";
const title = "Mi página principal";
const description = "Descripción larga y detallada de la página principal.";
---
<BaseLayout title={title} description={description}>
<SiteHeader />
<SiteNav />
<h2>{title}</h2>
<main>
<p>Contenido de la página web en cuestión.</p>
</main>
<SiteFooter />
</BaseLayout>
Observa que los title
y description
se definen en la zona superior del frontmatter y representan información sobre la página en la que estamos. Luego, esa información es enviada al layout por props. Fíjate que el layout se importa como un componente normal (lo es) sólo que se suele colocar en src/layouts
porque es un componente especial que define la estructura de la página completa.
Esto hace que podamos crear diferentes layouts si necesitamos estructuras diferentes, o queremos simplemente cambiar y probar un diseño diferente de forma fácil y rápida.
Ahora, cada una de nuestras nuevas páginas sólo debe importar el layout concreto y definir en su interior el contenido de la página, algo mucho más rápido y práctico que escribir todo el código HTML.