Svelte and SvelteKit course Β· Module 11: SvelteKit Routing
Layouts
In this lesson4
+layout.svelte
<!-- src/routes/+layout.svelte -->
<script>
import Header from '#lib/components/Header.svelte';
import Footer from '#lib/components/Footer.svelte';
let { children } = $props();
</script>
<Header />
<main>
{@render children()} <!-- The page renders here -->
</main>
<Footer />
<style>
main {
max-width: 1200px;
margin: 0 auto;
padding: 1rem;
}
</style>The layout receives the page content as the children snippet and shows it with the {@render children()} tag. In Svelte 4 the <slot /> element did this job; in Svelte 5 it is deprecated.
The #lib alias is the SvelteKit 3 successor of $lib: it points to the src/lib folder (an imports entry in package.json), and you import JS modules with their extension, for example #lib/utils.js.
Nested layouts
src/routes/
βββ +layout.svelte # Main layout
βββ +page.svelte # Home page
βββ dashboard/
βββ +layout.svelte # Layout for dashboard (nested)
βββ +page.svelte # /dashboard
βββ settings/
βββ +page.svelte # /dashboard/settings<!-- src/routes/dashboard/+layout.svelte -->
<script>
import Sidebar from './Sidebar.svelte';
let { children } = $props();
</script>
<div class="dashboard-layout">
<Sidebar />
<div class="content">
{@render children()}
</div>
</div>Layout data
// src/routes/+layout.js
export function load() {
return {
user: { name: 'Ragnar' }
};
}<!-- src/routes/+layout.svelte -->
<script>
let { data, children } = $props();
</script>
<nav>
Logged in as: {data.user.name}
</nav>
{@render children()}Resetting layout
<!-- src/routes/fullscreen/+page@.svelte -->
<!-- @ resets to root layout -->
<h1>Fullscreen page without layout</h1>Code for this lesson: App.svelte
<script>
// Layout and nested layouts
let showSidebar = $state(true);
</script>
<div class="app-layout">
<!-- +layout.svelte (main) -->
<header class="header">
<h1>Viking App</h1>
<nav>
<a href="/">Home</a>
<a href="/warriors">Warriors</a>
<a href="/ships">Ships</a>
</nav>
</header>
<div class="main-content">
{#if showSidebar}
<!-- sidebar from (warriors)/+layout.svelte -->
<aside class="sidebar">
<h3>Warrior filter</h3>
<ul>
<li><a href="/warriors?status=all">All</a></li>
<li><a href="/warriors?status=alive">Alive</a></li>
<li><a href="/warriors?status=dead">Walhalla</a></li>
</ul>
</aside>
{/if}
<!-- +page.svelte -->
<main class="page">
<button onclick={() => showSidebar = !showSidebar}>
{showSidebar ? 'Hide' : 'Show'} sidebar
</button>
<h2>Page content</h2>
<p>This is where the layout renders the page: <code>{'{@render children()}'}</code></p>
<div class="structure">
<pre>
src/routes/
βββ +layout.svelte β Header (shared)
βββ +page.svelte β Home
βββ warriors/
βββ +layout.svelte β Sidebar (for warriors)
βββ +page.svelte β Warrior list
</pre>
</div>
</main>
</div>
<!-- Footer from main layout -->
<footer class="footer">
<p>Β© 2024 Viking App - Powered by SvelteKit</p>
</footer>
</div>
<style>
.app-layout {
font-family: 'Georgia', serif;
min-height: 100vh;
display: flex;
flex-direction: column;
background: #0a1628;
color: #b8d4f7;
}
.header {
background: #1e3a5f;
padding: 1rem 2rem;
display: flex;
justify-content: space-between;
align-items: center;
}
.header h1 {
margin: 0;
color: #ffd700;
font-size: 1.5rem;
}
.header nav {
display: flex;
gap: 1rem;
}
.header a {
color: #b8d4f7;
text-decoration: none;
}
.main-content {
flex: 1;
display: flex;
}
.sidebar {
width: 200px;
background: rgba(74, 144, 217, 0.1);
padding: 1rem;
border-right: 1px solid #4a90d9;
}
.sidebar h3 {
color: #4a90d9;
font-size: 1rem;
margin-top: 0;
}
.sidebar ul {
list-style: none;
padding: 0;
}
.sidebar li {
margin: 0.5rem 0;
}
.sidebar a {
color: #b8d4f7;
text-decoration: none;
}
.page {
flex: 1;
padding: 2rem;
}
button {
padding: 0.5rem 1rem;
background: #1e3a5f;
color: #b8d4f7;
border: 1px solid #4a90d9;
border-radius: 4px;
cursor: pointer;
margin-bottom: 1rem;
}
h2 {
color: #4a90d9;
}
code {
background: rgba(0,0,0,0.5);
padding: 0.2rem 0.5rem;
border-radius: 4px;
}
.structure pre {
background: rgba(0,0,0,0.5);
padding: 1rem;
border-radius: 4px;
font-size: 0.85rem;
}
.footer {
background: #1e3a5f;
padding: 1rem;
text-align: center;
font-size: 0.9rem;
}
</style>Docs entries used in this lesson
Spotted a mistake in this lesson?
Check yourself
Answer the questions from this lesson. Pick an answer to see right away whether it is correct.
1. How do you show the page content inside +layout.svelte (Svelte 5)?