レイアウト
ページ間で共通のUIを定義する
レイアウトとは?
日常での例え:額縁(フレーム)
額縁
どんな絵を入れても
外枠は同じデザイン
レイアウト
どんなページでも
ヘッダーとフッターは同じ
なぜレイアウトが必要?
レイアウトがないと困ること:
- 全ページにヘッダーのコードをコピペ(10ページあれば10回!)
- ヘッダーを修正→全ファイルを手作業で修正
- 修正漏れでページによってデザインが違う...
レイアウトがあれば:1箇所書くだけで全ページに適用!修正も1箇所だけ。
用語解説
レイアウト:ページの共通部分(枠組み)のこと。ヘッダーやフッターなど。
ヘッダー:ページ上部の共通部分。ロゴやナビゲーションメニューを置く場所。
フッター:ページ下部の共通部分。著作権表示やリンク集を置く場所。
サイドバー:ページ横の共通部分。メニューや補足情報を置く場所。
children:子要素のこと。レイアウトでは「ページの中身」を指す。
レイアウトでできること
✓ ヘッダー、フッター、サイドバーの共通化
✓ ナビゲーションメニューの配置
✓ 認証チェック(ログイン必須ページなど)
✓ ページ遷移時のアニメーション
基本的なレイアウト
+layout.svelte
すべてのページに適用
svelte
<!-- src/routes/+layout.svelte -->
<script>
let { children } = $props();
</script>
<div class="app">
<header>
<nav>
<a href="/">ホーム</a>
<a href="/about">アバウト</a>
<a href="/contact">お問い合わせ</a>
</nav>
</header>
<main>
{@render children()} <!-- ここにページが表示される -->
</main>
<footer>
<p>© 2024 My Website</p>
</footer>
</div>
<style>
.app {
display: flex;
flex-direction: column;
min-height: 100vh;
}
main {
flex: 1;
}
</style>プレビュー
@render children() とは?
Svelte 5の書き方です。ここにページの内容(+page.svelte)が挿入されます。
レイアウトは「枠」、childrenは「中身」と考えてください。
ネストしたレイアウト
レイアウトは入れ子にできる
/dashboard 以下だけ別のレイアウト、という設定ができます。
ディレクトリ構造
レイアウトの継承
text
src/routes/
├── +layout.svelte # 全ページ共通(ヘッダー・フッター)
├── +page.svelte # / (トップページ)
├── about/
│ └── +page.svelte # /about
└── dashboard/
├── +layout.svelte # dashboardだけのレイアウト(サイドバー)
├── +page.svelte # /dashboard
├── settings/
│ └── +page.svelte # /dashboard/settings
└── profile/
└── +page.svelte # /dashboard/profile
/dashboard/* のページは:
1. routes/+layout.svelte(ルート)
2. routes/dashboard/+layout.svelte(ダッシュボード)
の両方が適用されるプレビュー
// /dashboard/settings の表示
[ルートレイアウト]
[ダッシュボードレイアウト]
[settingsページ]
ダッシュボード用レイアウト
サイドバー付きレイアウト
svelte
<!-- src/routes/dashboard/+layout.svelte -->
<script>
let { children } = $props();
</script>
<div class="dashboard-layout">
<aside class="sidebar">
<nav>
<a href="/dashboard">ダッシュボード</a>
<a href="/dashboard/profile">プロフィール</a>
<a href="/dashboard/settings">設定</a>
</nav>
</aside>
<div class="content">
{@render children()}
</div>
</div>
<style>
.dashboard-layout {
display: flex;
min-height: calc(100vh - 120px);
}
.sidebar {
width: 250px;
background: #f3f4f6;
padding: 1rem;
}
.content {
flex: 1;
padding: 1rem;
}
</style>プレビュー
レイアウトのリセット
+page@.svelte
親レイアウトを使わない
text
src/routes/
├── +layout.svelte # 通常のレイアウト
├── +page.svelte # / (レイアウト適用)
└── login/
└── +page@.svelte # /login (レイアウトなし!)
ファイル名を +page@.svelte にすると
ルートレイアウトを含む全レイアウトをリセット
+page@dashboard.svelte なら
dashboardレイアウト以降をリセットプレビュー
+page@.svelte
// ログインページなど
// ヘッダー不要なページに使う
レイアウトでデータを読み込む
+layout.server.ts
レイアウト用のload関数
typescript
// src/routes/+layout.server.ts
export async function load({ cookies }) {
const sessionId = cookies.get('session');
const user = sessionId ? await getUser(sessionId) : null;
return {
user // 全ページで使える
};
}
// src/routes/+layout.svelte
<script>
let { data, children } = $props();
</script>
<header>
{#if data.user}
<span>ようこそ、{data.user.name}さん</span>
<a href="/logout">ログアウト</a>
{:else}
<a href="/login">ログイン</a>
{/if}
</header>
{@render children()}
// 子ページからもアクセス可能
// src/routes/dashboard/+page.svelte
<script>
let { data } = $props();
// data.userにアクセスできる!
</script>プレビュー
// +layout.server.ts のデータは
// 子ページにも引き継がれる
グループ(括弧フォルダ)
(folder) とは?
括弧でフォルダ名を囲むと、URLには影響しないグループを作れます。
レイアウトだけを共有したいページをまとめるのに便利です。
グループの使用例
URLに影響しないフォルダ
text
src/routes/
├── (marketing)/ # URLには含まれない
│ ├── +layout.svelte # マーケティング用レイアウト
│ ├── about/
│ │ └── +page.svelte # /about
│ └── pricing/
│ └── +page.svelte # /pricing
│
├── (app)/ # URLには含まれない
│ ├── +layout.svelte # アプリ用レイアウト
│ ├── dashboard/
│ │ └── +page.svelte # /dashboard
│ └── settings/
│ └── +page.svelte # /settings
(marketing)と(app)で別のレイアウトを適用
でもURLは /about, /dashboard のままプレビュー
(marketing)/about → /about
(app)/dashboard → /dashboard
// 括弧はURLに含まれない
実践的な構成例
一般的なWebサイト構成
よくあるレイアウトパターン
text
src/routes/
├── +layout.svelte # 基本レイアウト(ヘッダー・フッター)
├── +layout.server.ts # 認証情報の取得
│
├── (public)/ # 公開ページ
│ ├── +layout.svelte # シンプルなレイアウト
│ ├── +page.svelte # / (トップ)
│ ├── about/+page.svelte # /about
│ └── contact/+page.svelte # /contact
│
├── (auth)/ # 認証ページ
│ ├── +layout@.svelte # レイアウトリセット(ヘッダーなし)
│ ├── login/+page.svelte # /login
│ └── register/+page.svelte # /register
│
└── (app)/ # ログイン後のページ
├── +layout.svelte # サイドバー付きレイアウト
├── +layout.server.ts # 認証チェック(リダイレクト)
├── dashboard/+page.svelte # /dashboard
├── profile/+page.svelte # /profile
└── settings/+page.svelte # /settingsプレビュー
(public)
ヘッダー + フッター
(auth)
シンプル(ロゴのみ)
(app)
サイドバー + ヘッダー