Kurs Svelte i SvelteKit · Moduł 11: Routing w SvelteKit
Layouts
W tej lekcji4
+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()} <!-- Tu renderuje się strona -->
</main>
<Footer />
<style>
main {
max-width: 1200px;
margin: 0 auto;
padding: 1rem;
}
</style>Layout dostaje zawartość strony jako snippet children i wyświetla ją tagiem {@render children()}. W Svelte 4 służył do tego element <slot />, który w Svelte 5 jest przestarzały.
Alias #lib to w SvelteKit 3 następca $lib: wskazuje folder src/lib (wpis imports w package.json), a moduły JS importujesz z rozszerzeniem, np. #lib/utils.js.
Zagnieżdżone layouty
src/routes/
├── +layout.svelte # Layout główny
├── +page.svelte # Strona główna
└── dashboard/
├── +layout.svelte # Layout dla dashboard (zagnieżdżony)
├── +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>
Zalogowany jako: {data.user.name}
</nav>
{@render children()}Resetowanie layoutu
<!-- src/routes/fullscreen/+page@.svelte -->
<!-- @ resetuje do layoutu root -->
<h1>Strona pełnoekranowa bez layoutu</h1>Kod do tej lekcji: App.svelte
<script>
// Layout i nested layouts
let showSidebar = $state(true);
</script>
<div class="app-layout">
<!-- +layout.svelte (główny) -->
<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 z (warriors)/+layout.svelte -->
<aside class="sidebar">
<h3>Filtr wojowników</h3>
<ul>
<li><a href="/warriors?status=all">Wszyscy</a></li>
<li><a href="/warriors?status=alive">Żywi</a></li>
<li><a href="/warriors?status=dead">Walhalla</a></li>
</ul>
</aside>
{/if}
<!-- +page.svelte -->
<main class="page">
<button onclick={() => showSidebar = !showSidebar}>
{showSidebar ? 'Ukryj' : 'Pokaż'} sidebar
</button>
<h2>Zawartość strony</h2>
<p>Tutaj layout renderuje stronę: <code>{'{@render children()}'}</code></p>
<div class="structure">
<pre>
src/routes/
├── +layout.svelte ← Header (wspólny)
├── +page.svelte ← Home
└── warriors/
├── +layout.svelte ← Sidebar (dla warriors)
└── +page.svelte ← Lista wojowników
</pre>
</div>
</main>
</div>
<!-- Footer z głównego layoutu -->
<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>Hasła z dokumentacji w tej lekcji
Widzisz błąd w tej lekcji?
Sprawdź się
Odpowiedz na pytania z tej lekcji. Wybierz odpowiedź, a od razu zobaczysz, czy jest poprawna.
1. Jak w +layout.svelte (Svelte 5) wyświetlasz zawartość strony?