Layouts in Astro

    Tamas Piros
    Tamas Piros
    Share

    This introduction to layouts in Astro is excepted from Unleashing the Power of Astro, available now on SitePoint Premium.

    While each .astro page (route) has the potential to contain a fully-fledged HTML document, it’s inefficient to duplicate that structure, especially when certain elements—such as <meta> and <title> elements—may vary depending on the currently viewed page. (The inefficiency comes from the fact that we would have to potentially add the same HTML structure to each .astro page.)

    Therefore, it’s advisable to establish an overarching layout that can be used across all pages. Although not mandatory, organizing the layout files within the src/layouts folder makes sense, enabling the addition of multiple layout files—such as one for navigation and another for a footer, or even splitting up the layout for parts of the page (for example, a separate layout for the overall page and for the blog).

    Consider the following as an example of a basic website that would encompass common UI elements:

    • layouts/Layout.astro: the primary layout file
    • layouts/Head.astro: a section for custom <head> elements, potentially unique for each page
    • layouts/Nav.astro: a navigation bar
    • layouts/Footer.astro: a footer section

    Common UI elements on a page

    Here’s a glimpse of the layouts/Layout.astro file:

    ---
    import Head from './Head.astro';
    import Nav from './Nav.astro';
    const {
      title = 'Footie is the best',
      description = 'An online football magazine',
    } = Astro.props;
    
    import Footer from './Footer.astro';
    ---
    
    <html lang="en">
      <title>{title}</title>
      <meta name="description" content={description}>
      <body>
        <Nav />
        <div>
          <main>
            <slot />
          </main>
        </div>
        <Footer />
      </body>
    </html>
    

    Note that, in the example above, we’re mixing standard HTML elements with Astro components. The ones that are capitalized (Nav and Footer) are Astro components that are imported in the top part of this sample layout file.

    Astro.props

    There are a few key takeaways here. Take note of the import function and the usage of Astro.props. We can easily import any other component by using the import keyword. The special built-in Astro.props object allows us to send properties to components and access them. In the code above, default values are set if Astro.props lacks the title or description keys (the default values are Footie is the best and An online football magazine). This is good practice, and we’re leveraging JavaScript’s default params feature intermixed with object destructuring. However, if there are props sent, Astro will pick them up. Let’s take a look at this by examining the code below:

    <!-- Uses the defaults -->
    <Layout />
    
    <!-- Sets title to "My Title," while description retains its default value -->
    <Layout title="My Title" />
    

    The first <Layout /> component doesn’t have any props attached to it, so it will resort to using the previously mentioned default values. In the second scenario, however, the title prop is sent with the value of My Title, which means that the page will display the appropriate title.

    Global Object Properties

    Multiple properties are available from the built-in global object Astro.

    Lastly, take note of the <slot /> element, which serves as the insertion point for content from individual .astro pages. More on this shortly.

    Please also pay attention to the <Head> Astro component. Suppose the property and variable holding the value we wish to send to the property share the same name. In that case, we can employ a simpler syntax:

    const title = 'my title';
    
    <Head title={title} />
    <!-- Can be simplified to 👇 -->
    <Head {title} />
    

    Slot

    Finally, let’s talk a bit more about the built-in <slot /> element. Once the layouts are ready, the content from Astro files in the src/pages folder will be injected where the element mentioned above is placed.

    To apply a layout to an Astro file, we need to import it and use it as we’d use any other component:

    ---
    import Layout from '../layouts/Layout.astro';
    ---
    <Layout title="Welcome">
      <p>Some content that will be injected into the "slot"</p>
    </Layout>

    Want to learn more about Astro, the modern all-in-one framework to build faster, content-focused websites? Check out Unleashing the Power of Astro, available now on SitePoint Premium.