ハコヅミを作る #24:ヘッダーにアイコンを付け、全部の画面にフッターを出す
前回(#23)で一覧のカードを整えたので、今回は画面の「枠」のほうを直します。
- ヘッダーのメニューに、アイコンを付ける(#118)
- 全部の画面に、共通のフッターを出す(#119)
- 編集画面の一番下に、「一覧へ戻る」リンクをそろえる(#117)
どれも、Issue を作る前にサンプル画像を見て決めました(#22からの進め方です)。
ヘッダー:メモの「トップページのアイコン」はどれのこと?
/issue に渡したメモは、こうでした。
トップページのアイコンが小さすぎて見にくいので改善したい その他のメニューも文字だけではく白色のシンプルなアイコンと一緒に文字を表示して
1行目の「トップページのアイコン」は、2通りに読めます。トップページに並ぶ大きなメニューのタイルの絵か、ヘッダーの左上の小さなロゴ(トップページへのリンク)か、です。
Claude Code は、「ヘッダーの見直し」という1行目から、ヘッダーの左上のロゴのことだと読みました。そのうえで、読み方を「決めてほしい点」に書き、サンプルでもロゴを大きくして見せてくれました。読み違いがあっても、画像を見ればすぐ分かります。

ヘッダーの見比べ(左から、今/案A:アイコンの下に文字/案B:アイコンの右に文字)
- 案A:アイコンの下に文字。スマホの幅でも、5つが1列に均等に並ぶ
- 案B:アイコンの右に文字。スマホの幅では入りきらず、「プラン」が2行目に回る
案A にしました。トップページの大きなタイルは、今回は見直さず、今の絵のままにしています。
アイコンは、パッケージを足さずに写す
アイコンには、Lucide の線画を使いました。ただ、アイコンのパッケージは入れていません。使うのは5つだけなので、SVG のパスを部品(MenuIcon.svelte)に写して、出典とライセンス(ISC)をファイルの先頭に書いています。
依存を増やさないのは、CLAUDE.md の決まりの1つです(「依存パッケージは増やさない。追加するときは理由を PR に書く」)。コンテナ(ふた付きの箱)だけはちょうどよい形がなかったので、Lucide の線の太さと角の丸めに合わせて描いてもらいました。
アイコンは飾りなので、読み上げられないようにしています(aria-hidden="true")。リンクの名前は今までどおり「ギア」などの文字だけで、E2E でもそれを確かめています。
フッター:何を載せるか
フッターのメモは、提案を頼む形にしました。
通常フッターに表示するとしたら、○Cマーク、プライバシーポリシーのリンク、利用規約のリンクぐらい? こちらは提案して(画面イメージと一緒に)
返ってきた提案は、今は © だけにする、でした。
| 載せるもの | いつ載せるか | 理由 |
|---|---|---|
| ©(© 2026 Jiru-Labo) | 今 | 決まった文字で、用意するものがない |
| 利用規約 | ページができたとき | 中身を書く必要がある |
| プライバシーポリシー | ページができたとき | Google Fonts や画像の保存(R2)について書く必要がある |
| お問い合わせ | 方法が決まったとき | メールかフォームか、まだ決めていない |
中身のないページへのリンクを置くと、押した先が「準備中」になります。それなら、ないほうがよい、という判断です。どちらも一般に公開する前には必要なので、そのときに足します。

フッターの見比べ(左から、案A:明るい背景、線で区切る/案B:ヘッダーと同じ緑/案C:© だけ)。リンクは見た目を比べるための仮のもの
見た目は、ヘッダーと同じ緑の 案B にしました。上下を同じ色で挟むと、画面の枠がはっきりします。
包まずに並べると、ページの幅が縮む
中身が短い画面でも、フッターを画面の一番下に出すには、ページ全体を画面の高さ以上にして、縦に並べます(Tailwind では flex min-h-dvh flex-col)。
ここで1つ、つまずきました。ヘッダー・中身・フッターを、そのまま縦の flex に並べると、中身の幅が縮みます。

左:中身をそのまま並べたとき(フォームが縮む)/右:中身を1つの div で包んだとき
ハコヅミのページの中身は、左右の余白を margin-inline: auto で取っています(.page)。flex の中では、左右が auto の余白を持つ要素は、引き伸ばされずに中身の幅まで縮みます。
気づいたのは実装のときですが、あとで見返すと、Issue を作る前に撮ったサンプル画像でも、案A〜C のどれもフォームが細くなっていました。見た目を選ぶことに気を取られて、見落としていたわけです。実装では、中身を flex-1 の div で包み、flex の子にしないようにしています(この記事の見比べの画像は、包んだ形で撮り直しています)。
<!-- src/routes/+layout.svelte -->
<div class="flex min-h-dvh flex-col">
<AppHeader />
<div class="flex-1">
{@render children()}
</div>
<AppFooter />
</div>
この理由は、あとで「包まなくてもよさそう」と消されないよう、コードのコメントと CLAUDE.md に書いています。
フッターを、画面に固定しない理由
マージの前に、こう聞かれました。
フッターは固定して、ヘッダーとフッターの間のエリアのみスクロールとした方がいいかと思ったが、それだと問題がありそう?
Claude Code の答えは、「今の中身(© だけ)なら、固定しないほうがよい」でした。
- 中身を見られる範囲が狭くなる。スマホのヘッダー(アイコン付きで約 115px)とフッター(約 45px)が、いつも場所を取る。積み込みながらリストを見る場面で効いてくる
- 常に見えている必要がない。画面に固定するのは、何度も押すもの(下に並ぶタブのメニューなど)。© は一度見れば十分
- 「間だけスクロール」は、スマホのブラウザと相性が悪い。iPhone の Safari でアドレスバーが縮まない、画面の上端をタップして一番上に戻れない、「戻る」でスクロールの位置が戻らない、キーボードを出したときに固定したフッターが入力欄に重なる、など
いつでも見えていてほしいものがあるなら、フッターより、ヘッダーを上に固定するほうが役に立つ、という提案もありました。今はどちらも固定していません。
編集画面の一番下を、キャンプの画面にそろえる
キャンプの画面は、一番下に「キャンプ一覧へ」のリンクと「削除」ボタンが並んでいます。ほかの編集画面(ギア・消耗品・コンテナ・プラン)は、「削除」ボタンだけでした。
この一番下の段を、UI 部品 BackAndDelete にまとめ、5つの画面で同じものを使うようにしました(#117)。渡すのは、戻り先・リンクの文字・削除の確認の文の3つだけです。
できあがり

スマホの幅(左から、ギアの一覧/コンテナの登録/ギアの編集画面の一番下)

広い幅では、ロゴが左、メニューが右
手元の E2E が落ちた:テストのデータがたまって4桁に
#117 の全部の E2E を手元で流したとき、今回の変更と関係のないテストが2件落ちました。「幅 375px で、ヘッダーやタブが画面からはみ出さない」ことを確かめるテストです。
原因は、手元の D1 にたまったテストのデータでした。E2E を流すたびにギアが増え、「所有」が 1,437 件になっていました。ギアの一覧のタブの件数が4桁になり、8px だけはみ出していたのです。
- CI は毎回空の D1 で流すので、起きない
- 手元の D1 を作り直す(Notion から取り込んだ 56 件に戻す)と、通った
- 実際にギアが 1,000 件を超えることはまずないので、画面は直していない
#20で E2E の時間が延びたのも、たまったデータが原因でした。たまったデータは、遅くするだけでなく、テストの結果も変えます。同じことがこのあとも1回起きたので、手元で流す前に D1 を作り直すコマンドを足すことを考えています。
おわりに
- メモの言葉が2通りに読めるときは、読み方を書いてもらい、サンプル画像で確かめる
- アイコンは、使う分だけ写せば、パッケージを足さずに済む
- 中身のないページへのリンクは置かない。用意ができてから足す
- 縦の flex に、左右が auto の余白の要素を直接置くと縮む。包んでから並べる
- フッターの固定は、見た目より、スマホのブラウザでの使い勝手で決める
次回は、キャンプの日付の出し方と、おすすめ度・感想を足した話です。