Skip to content
LayoutsView the code for this module.

In the last module we went over routing to our pages, and up to this point, we've treated our pages as standalone components: upon navigation, the existing page is destroyed, and a new one takes its place. But this is not necessarily the case. Oftentimes, there are elements that should be displayed on every page. For example, you may want a header and footer to always exist throughout the app. Thankfully with SvelteKit, this is very intuitive to do. Instead of adding these to every single page file, we can use layout components.

Pages can be wrapped in a layout component using the <slot> tag, which indicates where the child component should be placed within the parent layout. If you're unfamiliar with slots, you can check out one of my previous modules in this course on the topic.

To create a layout component that applies to every page, in our routes folder, we need to create a file called __layout.svelte, which you may remember making back when we covered CSS. This layout component needs to contain a single <slot> tag, but we can add whatever markup, styles, and behavior we want as well.

Within our layout file we have some html and tailwind classes that are creating our header and shopping cart, as well as some logic to show and hide our cart. This means that every single page in our application will display our header, and will also be able to open and close our shopping cart. If we check out some different routes we can confirm this. Now, we can put anything we want in this file, the only rule is that it must contain a slot tag for our pages to be inserted into. Just remember, whatever you add to this layout will be shown on every page in your app.

We can also create nested layouts similar to how we used nested routes. Each folder within our routes folder can have its own layout. In our example, we created a root layout that will be applied to every page in our app, but we can also create a layout file in our product folder that will only be applied to the pages within the folder. Let's create a __layout.svelte file in our product folder to add a suggested items section to these pages.

// product/__layout.svelte
<script>
  import CollectionCard from '$lib/CollectionCard.svelte';
  import { setContext } from 'svelte';
  let newItems = [
    {
      name: 'Graphic T',
      src: 'https://cdn.shopify.com/s/files/1/0434/0285/4564/products/Front-NoModel_ec3be051-d579-4c03-b55b-64449d0b0445.png?v=1623255893',
      price: '$60.00',
    },
    {
      name: 'Jacket',
      src: 'https://cdn.shopify.com/s/files/1/0434/0285/4564/products/bomber-jacket-0.png?v=1622902777',
      price: '$80.00',
    },
  ];
  setContext('newItemsContext', newItems);
</script>

<slot />
<div class="pb-40">
  <CollectionCard />
</div>

Now if we check this out in our browser, we only see our root layout, but if we navigate to /product/cup, we see both the root layout as well as our product layout. It is important to remember that adding a nested layout will not cancel out the root layout, it will display both.

Now, what if we want to add this new nested layout only to certain pages within the product directory, but not all of them? For instance, if we wanted to apply it to our [name].svelte page and our /apparel/index.svelte page, but no other pages within the product folder.

In this case, we can used named layouts. To create a named layout, you create a layout file like we did before, but after layout, we add a dash (-) and then the name of our layout. In this case, we can add -product to our layout file name like this __layout-product.svelte.

Named layouts act just like normal layouts, so this means it is still important to make sure it contains a slot tag. Now, if we were to route to /product/cup, we'd notice that this new named layout is still not being displayed on the page. This is because we are not applying this new named layout to any of the pages. In order to use this new layout, we need to reference the layout name, ‘product', in the file name of the page we want to apply it to. In this case, we should add @product to the end of our [name].svelte page, as well as our /apparel/index.svelte page like this: /products/[name]@products.svelte, /products/apaprel/index@products.svelte . Now, these two pages will also display the new named layout, but no other pages will.

It's important to keep scope in mind when using named layouts. Named layouts can only be applied to components in the same sub tree. In our example, we could apply our /src/products/__layout.svelte to any page within the product folder, but we could not apply it to our root index page, since it is not within the product subtree.

Now, what if we have a page where we don't want to inherit any of the parent layouts? In this case, we can create a named layout at the root of out project containing nothing but an empty slot tag. I'll create one called ‘root' like this.

// routes/__layout-root.svelte

<slot />

Since this is in the root of our routes folder, we can reference this layout from any file, and that page will have no layout. If we update the name of our t-shirt.svelte page within our apparel folder to be t-shirt@root.svelte, and then navigate to it, we see that there is no layout being inherited. Even layouts themselves can inherit from named layouts. In our example, what if we wanted our default layout in our product folder to not inherit its parent layout, we can reference our named root layout in this layout (/product/__layout@root.svelte), and now only what we directly add to this layout will be displayed.

The last thing to go over in this module is error pages. If a page fails to load, SvelteKit will render an error page. For example, it we try to route to a page that doesn't exist, we will get this default error page. When a page fails to load, SvelteKit will render the error page within the layout, if one exists. If you do not supply an error page, SvelteKit will use the default one, which we see here.

You can customize this page by creating error components alongside your layout and page components. Just like for layouts, each folder within the routes folder can have an error page. we create these error components by naming a file __error.svelte. Let's create an error page in the root of our routes folder.

// __error.svelte

<h1>There was an error loading this page</h1>

This is the root error page, which means it will be displayed for all pages unless a different error page is specified.

That covers everything layout related. We now have an efficient way to share specific components, styles, and logic throughout our app without destroying it on each page change. In the next module, we will learn about SvelteKit endpoints.