Encodera

Thanks for reading!

Donate to the site — we work hard for you.

Contents

Layouts: +layout.svelte

A layout is a shared wrapper for several pages: a header, a menu, a footer. You write it once in a +layout.svelte file, and SvelteKit renders the current page inside it. When moving between pages the layout is not re-rendered from scratch — only the content changes.

The root layout

A layout in the src/routes folder applies to the whole site. If src/routes/+layout.svelte does not exist yet, create it:

<!-- src/routes/+layout.svelte -->
<script>
  let { children } = $props();
</script>
 
<header>
  <nav>
    <a href="/">Home</a>
    <a href="/blog">Blog</a>
    <a href="/about">About</a>
  </nav>
</header>
 
<main>
  {@render children()}
</main>
 
<footer>© 2026 My blog</footer>

Now the menu and the footer appear on /, /blog and /about. The page arrives in the layout as the children snippet — the same technique as in the lesson on snippets.

A nested layout

A layout in a subfolder wraps only that section's pages and is itself rendered inside the root layout. Create src/routes/blog/+layout.svelte:

<!-- src/routes/blog/+layout.svelte -->
<script>
  let { children } = $props();
</script>
 
<div class="blog">
  <aside>
    <a href="/blog/new">Write a post</a>
  </aside>
  {@render children()}
</div>

On /blog and /blog/new a side link "Write a post" appears, but not on the home page. The shared menu from the root layout stays on all pages.

To highlight the menu item of the current page, you need its address. The page object from the $app/state module provides it:

<!-- src/routes/+layout.svelte -->
<script>
  import { page } from '$app/state';
 
  let { children } = $props();
</script>
 
<nav>
  <a href="/" class:active={page.url.pathname === '/'}>Home</a>
  <a href="/blog" class:active={page.url.pathname.startsWith('/blog')}>Blog</a>
</nav>
 
{@render children()}
 
<style>
  .active {
    font-weight: bold;
  }
</style>

On /blog and all nested addresses the "Blog" item becomes bold. page.url is a regular URL object, and page updates on every navigation.

Global styles

The root layout is a good place to include a shared stylesheet: add import '../app.css'; to its <script>, and the styles from src/app.css apply to every page.

Common mistake

Forgetting to render children in a layout. The site opens, the menu is there, but page content is missing at every address. Every +layout.svelte must contain {@render children()}.

Thanks for reading!

Donate to the site — we work hard for you.