Where Does Page Content Go?
The layout wraps pages, but how exactly does page content end up inside the layout? Understanding {@render children()} is key to mastering layouts.
What You’ll Learn
- How
childrenrepresents page content - The rendering flow from page to layout
- Positioning
{@render children()}for different layouts
The Content Flow
When you visit /about, here’s what happens:
- SvelteKit finds
src/routes/about/+page.svelte - SvelteKit also finds
src/routes/+layout.svelte - The page content of
/about/+page.sveltebecomes thechildrensnippet - The layout renders, calling
{@render children()}where appropriate - The page content appears at that exact position
/about request
│
▼
┌─────────────────────────────────┐
│ +layout.svelte │
│ ┌───────────────────────────┐ │
│ │ about/+page.svelte │ │
│ │ (rendered as children) │ │
│ └───────────────────────────┘ │
└─────────────────────────────────┘ Positioning Content
The position of {@render children()} determines where page content appears. You control this:
<!-- Content at the top -->
<script>
let { children } = $props();
</script>
{@render children()}
<footer>Always at bottom</footer> <!-- Content in the middle -->
<script>
let { children } = $props();
</script>
<header>Always at top</header>
{@render children()}
<footer>Always at bottom</footer> <!-- Content in a specific container -->
<script>
let { children } = $props();
</script>
<div class="sidebar">Navigation</div>
<main class="content">
{@render children()}
</main> A Visual Experiment
Let’s make the layout structure visible. Update your layout:
<!-- filename: src/routes/+layout.svelte -->
<script>
import favicon from '$lib/assets/favicon.svg';
let { children } = $props();
</script>
<svelte:head>
<link rel="icon" href={favicon} />
</svelte:head>
<nav>
<a href="/">BookIt</a>
<a href="/services">Services</a>
<a href="/about">About</a>
<a href="/contact">Contact</a>
</nav>
<div style="border: 3px solid blue; padding: 1rem;">
<p style="color: blue;">LAYOUT START</p>
<div style="border: 3px solid green; padding: 1rem;">
{@render children()}
</div>
<p style="color: blue;">LAYOUT END</p>
</div>
Now visit different pages. You’ll see:
- Blue border around everything (the layout)
- Green border around page content (where children renders)
- “LAYOUT START” always at top
- “LAYOUT END” always at bottom
- Each page’s content inside the green box
This visual debugging helps you understand exactly where content lands.
What Children Actually Is
In Svelte 5, children is a snippet — a special type that represents renderable content. When SvelteKit prepares to render a route:
- It compiles the page into a snippet
- It passes that snippet to the layout as
children - The layout decides where to render it
You can think of it like a placeholder that gets filled with actual content.
Multiple Render Points?
You might wonder: can you render children multiple times?
<script>
let { children } = $props();
</script>
<!-- Don't do this -->
{@render children()}
<hr>
{@render children()} Technically this renders the page twice. There’s rarely a good reason to do this — it would show duplicate content and could cause issues with forms or stateful components.
Stick to rendering children exactly once.
The Real Layout
Remove the debug styling and set up a proper structure:
<!-- filename: src/routes/+layout.svelte -->
<script>
let { children } = $props();
</script>
<div class="app">
<!-- Header -->
<header>
<!-- Navigation will go here -->
</header>
<!-- Main content -->
<main>
{@render children()}
</main>
<!-- Footer -->
<footer>
<!-- Footer will go here -->
</footer>
</div> This structure provides:
- A
<header>for navigation (top of every page) - A
<main>for page content (varies per page) - A
<footer>for site-wide footer (bottom of every page)
Common Mistakes
Rendering Inside a Condition Without Fallback
<!-- ❌ Page might not render -->
{#if showContent}
{@render children()}
{/if} If showContent is false, the page content disappears entirely. Be careful with conditional rendering around children.
Nesting Children Incorrectly
<!-- ❌ Confusing structure -->
<div>
<div>
<div>
{@render children()}
</div>
</div>
</div> While this works, excessive nesting makes styling difficult. Keep your layout structure as flat as reasonable.
Summary
The {@render children()} directive is where page content appears within a layout. You control positioning by placing this directive where you want the page to render. The layout wraps, the page fills the designated slot.
Key takeaways:
childrenis a snippet containing the page content{@render children()}renders the page at that exact position- Layout structure (header, main, footer) surrounds the render point
Next Steps
The layout structure is ready. Continue with Add a Site Header to build BookIt’s navigation bar.