ミニマルモダンUI:完成したように感じられるミニマルサイト
個人サイト、ポートフォリオ、ランディングページ、ブログ向け:控えめで細部にこだわる、コンテンツファーストな小規模サイト向けです。ウェブアプリ、プロダクトインターフェース、ダッシュボード、ツールには向きません。これらが抱える問題(アプリの状態、データ密度、複雑なフォーム)には別のガイダンスが必要です。
ここにあるものはすべてプレーンなHTML、CSS、そして少量のバニラJSです。そのため、どんなスタックやスタックレスにも適合します。プロジェクトですでにビルドやテンプレート設定がある場合はそれを使用してください。原則は変わりません。
これはテンプレートではなく、コンパスです。各ルールは理由と出発点を示し、テーマやユーザーの好みに合わせて調整します。必須とマークされた項目は、数少ない省略できないものです。
参考ファイル(必要なときに読む):
- references/snippets.md:コピーペースト可能な構成ブロック(トークン、ベース、散文、投稿リスト、フォーム、モーション)。
- references/interface-checklist.md:VercelのWebインターフェースガイドラインを元にした、インタラクション、フォーム、コンテンツ、パフォーマンスの詳細チェックリスト。
- references/ship-checklist.md:SEO、ソーシャルプレビュー、RSS、アナリティクス、ホスティング。
- references/lessons.md:実際のプロジェクトからの落とし穴とブラウザ検証のヒント。
- references/templates.md:10のCarrdランディングページテンプレートからの測定値(Carrdのテンプレート番号、例:#304で引用)。目を校正するための参照データであり、ルールではありません。
1. ワークフロー
- ジョブを理解する。 誰のサイトか、誰のために、訪問者がすべきことや学ぶべき唯一のこと、必要なページ、そして「完了」の意味。答えがビルドを変える場合に尋ねる:最終的なドメイン、訪問者を追跡するかどうか、コピーの所有者、既存のコンテンツ(投稿、プロジェクト)を持ち込むかどうか。
- 方向性を決める(§2) そしてそれを書き留める:プロジェクトノート(CLAUDE.md、AGENTS.md、またはREADME)に、カラートークン、タイプペアリング、スペーシングと半径のスケール、モーションパーソナリティを記述し、後続のセッションで一貫性を保つ。
- 最初のページの前に共有部分を設定する(§3) :トークン、ベーススタイル、レイアウトプリミティブ、コンポーネント、そしてヘッダー、フッター、
<head>の1つのソース。すべてのページ(最初のページを含む)はこれらから構築される。 - まず実際のコピーを入れる。 プレースホルダーテキストはレイアウトの問題を隠す。ページレシピ(§4)に従う。
- 静的に、レスポンシブに、アクセシブルに構築し、次にモーションを追加し、最後に磨きをかける。
- 出荷する(§11) 、ブラウザで検証する(§12) 、次に抑制のパス(§13) を行う。
- 小さく、目に見えるステップで反復する。 一度に1つの変更を行い、それを確認し、推測する代わりに好みの判断を仰ぎ、何が検証され何がされなかったかを率直に述べ、要求された場合のみコミットまたは公開する。
2. 方向性を選ぶ
ミニマルがデフォルト:コンテンツファースト、アクセント1つ、十分なスペース、ボックスよりもヘアライン、小さなモーション。すべての要素に意味があるべきで、意味のない装飾は削除する。
| ファミリー | 見た目 | 適合しやすいもの |
|---|---|---|
| 静かなライト | ほぼ白、ニュートラルサンセリフ、ヘアライン区切り、1つの鮮明なアクセント | 個人サイト、ブログ、執筆 |
| 静かなダーク | ほぼ黒、ライトウェイトの大きなタイプ、1つのアクセント、メタデータに等幅フォント | エンジニアリングおよび個人サイト、ローンチ |
| エディトリアル | 見出しまたは本文にセリフ、広めのメジャー、アウトラインされたボタン | 長文執筆、書籍、カルチャー;技術系の読者には古臭く見える可能性があるので、まずライブで見せること |
| ソフトグロー | 静かなベースに1つの微妙なグラデーションまたは放射状グロー、オプションで曇りガラス風の表面 | 温かみが必要なランディングページ |
| ワンボールドブロック | 静かなベースに1つの縁まで広がるカラーブロックまたは額縁入り写真 | ポートフォリオ、イベント、個人ブランド |
- トーンは目新しさに勝る。 真面目なテーマには落ち着いて信頼できるものが求められ、遊び心のあるフォントや派手な効果は通常拒否される。
- 観客の慣習に合わせる。 技術系の観客は、ほぼ白またはほぼ黒の上にニュートラルなサンセリフと1つの鮮明なアクセントを期待する傾向がある。他の観客にはそれぞれの慣習がある。複数の方向性を提案する場合、フォントや用紙の色だけでなく、レイアウトとサーフェス(リストページ、スティッキースプリット、カードグリッド、1つのカラーブロック)を変えて、ユーザーが実際の選択肢から選べるようにする。
- 好みが不明な場合は、ライブで試す。 実際のページでフォント、アクセント、またはスペーシングを切り替えて、ユーザーの反応を見る。数ラウンドを予想する。
- ユーザーの好みはこのガイドよりも優先される。 ユーザーが方向性を受け入れるか拒否したら、それをプロジェクトノートに書き、ここでのデフォルトよりもそれに従う。
3. 共有スタイルとコンポーネント
2ページ目は最初のページのように見えるべきである。なぜなら、同じ部品から構築され、スタイルがコピーされたからではないからだ。
- トークンのソースは1つ。 色、タイプスケール、スペーシング、半径、影、モーションタイミングはすべて1つのファイル内のカスタムプロパティである。ページとコンポーネントはトークンを使用し、生の値は決して使用しない:ページのスタイル内の16進数コードや1回限りのピクセルサイズは修正すべきバグである。
- ページではなくコンポーネントをスタイリングする。
.btn、.card、.field、.prose、.post-list、.site-headerであり、.about .blue-boxではない。バリアントは修飾子(.btn--outline)であり、編集されたコピーではない。ページスタイルはコンポーネントを配置するだけで、短く保つ。 - CSSをレイヤー化する:トークン→ベース→レイアウトプリミティブ→コンポーネント→ページ配置。
@layerで宣言することで、ページルールがコンポーネントを密かに上書きしないようにする(スニペット参照)。 - 共有クロームは1回記述する。 ヘッダー、ナビゲーション、フッター、
<head>、サイトスクリプトは1つのソースから来る:プロジェクトのインクルード、パーシャル、テンプレート、または小さなビルドスクリプト。手動でコピーしたヘッダーはずれる;2ページのサイトでコピーが避けられない場合は、その旨を伝え、変更のたびにすべてのコピーを再確認する。aria-current="page"を使用して、ナビゲーション内の現在のページをマークする。 - マークアップによる動作。 1つのサイトスクリプトがデータ属性とクラスを通じてリビールとディスクロージャーを処理するため、新しいページはページごとのJSを必要としない。
- インベントリを維持する。 プロジェクトノートにコンポーネントをリストする(名前、目的、バリアント)。新しいページでは、まず再利用する;新しいものはすべて共有ファイルとリストに追加され、ページには追加されない。各状態とテーマのすべてのコンポーネントを示す
styleguide.htmlは、変更後のクイックチェックとして役立つ。 - 今日はシングルページ? それでもトークンとコンポーネントをページスタイルから分離する;次のページはアセンブリになる。
4. ページレシピ
ランディングページ
- ヒーロー:1つの見出し、1文のリード、最初のビューポート内の主要なアクション(またはサインアップフォーム自体)。
- 次に、訪問者の質問に順番に答えるセクション:それが何か、どのように機能するか(番号付きステップと1つの小さな画像)、証明(短い引用、ロゴ、実際の数字)、FAQ、フッター。
- ピッチを繰り返さない:ヒーローがフォームを保持している場合、それを再述する閉じるブロックは何も追加しない。
個人サイト / ポートフォリオ
- 名前とその人のしていることの1行、次に短いセクション:仕事またはプロジェクト、執筆、概要、連絡先。
- プロジェクトや投稿にはカードグリッドよりもヘアライン付きのリストが適している;画像は額縁入りの1枚で十分。
- 連絡先はプレーンなリンク(メール、プロフィール)であり、ユーザーがフォームを要求しない限りフォームではない。
ブログインデックス
- カードではなくリスト:タイトル、日付(
<time datetime>)、オプションで1行の概要。投稿が多くなったら年ごとにグループ化する。行全体がリンクであり、デッドゾーンはない。 - ストックサムネイルはなし。ページネーションまたは1つの長いページのどちらも機能する;どちらかをノートに明記する。
ブログ投稿
- 約60~72文字の読みやすいカラム、本文17~19px、行間1.6~1.75(§5)。
- 上部にタイトル、日付、オプションの読了時間;アンカーと
scroll-margin-topを持つ見出し;長い投稿にのみ目次。 - キャプション付きの図はテキストより幅を広げてもよい;コードブロックは内部でスクロールし、ページ全体をスクロールさせることはない。
- 次のステップで終了する:前/次の投稿またはさらにいくつかの投稿の短いリスト、およびRSSリンク。
全タイプに共通
- ヘッダー:ナビゲーションか、何もなし。 ブランドの反対側にある孤独なボタンは未完成に見える。
- フッターは下部に、短いページでも(フルハイトのフレックスカラム)、その下に余分なマージンがないようにする。
- すべての状態をデザインする:空(まだ投稿がない)、非常に長いタイトル、画像がない、サイトのルックで404ページ。
5. タイポグラフィ
- 1つまたは2つのファミリー:ニュートラルな本文用の書体(システムスタックで十分)に加えて、多くても1つの表示用書体。日付、コード、メタデータ用の等幅フォントは、価値がある場合のみ3つ目の書体とする。
- 見出しは、モダンで大きく、軽く、タイトなトラッキングで読める:ヒーローでは約40~72px、ウェイト300~500、レタースペーシング−0.02~−0.05em(ネオグロテスクの場合)、行間1.1~1.25、
clamp()でサイズ設定。 - 短いページ(個人サイト、ブログインデックス)のセクション見出し:約1.25倍の本文(約20px)、セミボールド、テキストカラー。かすんだ大文字のラベルは弱すぎる;表示サイズはヒーローと競合する。
- 読みやすいテキスト。 17~19px、行間1.6~1.75、60~72chのメジャー、段落間は約1emのスペース。二次テキストは小さいサイズではなく、ミュートカラーを使用する。
- きれいな行:見出しには
text-wrap: balance、段落にはtext-wrap: prettyを使用して、取り残された単語を避ける。 - タイポグラフィの詳細:引用符(“ ”)、省略記号(…)、数字と単位の間の改行しないスペース(
10 MB)、リスト内の日付と数字にはtabular-nums。ブランド名と製品名をtranslate="no"とマークして、ブラウザの翻訳がそれらを変更しないようにする。 - ワードマーク:セクション見出しの隣で自立できる大きさ(多くの場合1.2~1.6倍);1つの単語内のウェイトコントラスト(ライト+エクストラボールド)は手頃に個性を加える。
- 両端揃えテキストは、
langが設定されhyphens: autoの場合のみ、狭いカラムでは決して使用しない。
6. 色とサーフェス
:rootのトークン:背景、サーフェス、テキスト、ミュート、ヘアラインカラー、1つのアクセント(オプションで2番目のグラデーションストップ)、オンアクセントカラー。- コントラスト(必須)。 本文テキストは、実際のサーフェス上で少なくとも4.5:1(WCAG 2)であり、半透明またはグラデーションのサーフェスの最も明るい箇所で確認する。ライトウェイトの表示タイプにはさらに必要。APCAは細いタイプのための有用なセカンドオピニオンであり、代替ではない。常にリンクの色を設定する;ブラウザのデフォルトの青はほとんどすべてのデザインで間違って見える。
- 少数の小さなマークのためのアクセント:見出しの1つの単語、リンク、ホバーとフォーカス、現在のナビゲーションアイテム。大きな色のブロックではなく、リストの番号付けにも使用しない。
- サーフェス:デフォルトはフラットでヘアライン付き。影を使用する場合は、2つのレイヤー(ソフトなアンビエントともう1つのタイトな直接光)を持つ;境界線は半透明にして、どの背景でもエッジが鮮明に保たれるようにする。内部半径はそのコンテナの半径より決して大きくならない。色付きの背景では、境界線と影をその色相に tint する。
- ホバーとフォーカスは、静止状態と比較してコントラストを上げる。
- ライト、ダーク、またはその両方。 早い段階で決定する。1つの固定スキームで十分:
color-schemeとtheme-colorを一致させる。両方の場合は、prefers-color-scheme: darkの下で同じトークンを再定義し(トグルがある場合は[data-theme]のオーバーライドも追加)、それぞれのスキームでコントラスト、影、画像、コードブロックを確認する。 - 背景:ソリッド、または1つの優しいグラデーションかグロー;パターンは10%以下のコントラストでのみ使用する。2つの派手なものを決して組み合わせない。
7. モーション
モーションは、何が変わったか、どこを見ればよいかを人が理解するのに役立つべきである。これらのサイトでは、少ない方が通常は良い。
- デフォルト:メインコンテンツのロード時の短いフェードイン(数ピクセルの上昇)と、ホバー/フォーカスフィードバック。これだけのページでも、完全で落ち着いた結果になる。
- スクロールリビールはオプションであり、控えめに保つ:不透明度と6~20pxの移動、
ease、0.3~1秒、約25%表示されたときに1回再生。距離に応じてカスケード(見出しが最も動かず、ボタンが最も動く);100~150msの間隔、最大6~8アイテム。長文の読み物コンテンツでは決して使用しない。 - まずCSS、次にWeb Animations API、そして本当に必要な場合のみJSライブラリ。
opacityとtransformのみをアニメーション化し、トランジションするプロパティを明示的にリストし(transition: allは決して使用しない)、モーションが物理的に始まる場所にtransform-originを設定する。SVGの場合は、transform-box: fill-boxを持つ<g>をアニメーション化する。- 中断可能:固定されたタイムラインではなくトランジションなので、ホバーアウトや2回目のクリックがスムーズに逆転する。
- ホバー/フォーカス:ボタンは約1.02~1.06倍にスケールするか、浮き上がる;ナビゲーションとテキストリンクは左からスライドインする2pxの下線を取得し、
:focus-visibleでも同様。 - アンビエントモーション:多くても1つのスローなループ、またはなし。ループするメディアはミュートされた
<video>であり、GIFではない。5秒を超えるモーションには一時停止コントロールが必要。 - ガラスのちらつき(Chrome):
backdrop-filter要素の子をフェードさせたり、そのブラーをアニメーション化したりしない(レッスン参照)。
8. インタラクションパターン
- リンクはリンクである。 ナビゲーションには
<a>を使用して、新しいタブ、リンクのコピー、中クリックが機能するようにする。デッドゾーンなし:行がクリック可能に見える場合、そのすべてがクリック可能である。 - フォーム(サインアップ、連絡先):すべてのフィールドにラベルが付いている;正しい
type、name、autocomplete、inputmode;メールのスペルチェックオフ;まずネイティブバリデーション。ペーストやキーストロークをブロックせず、ユーザーが試す前に送信を無効にしない。エラーはフィールドの隣に表示され、問題の修正方法を説明し、送信時に最初のエラーにフォーカスが移動する。詳細はインターフェースチェックリストを参照。 - 送信:ボタンはラベルを維持し、スピナーを取得する。約200ms後にのみ表示され、その後少なくとも約400ms間表示されることで、高速な応答がちらつかないようにする(スニペット参照)。成功はフォームを明確な次のステップに置き換える。
- ディスクロージャー(FAQ、「もっと見る」):
<button aria-expanded aria-controls>、grid-rowsトリックでアニメーション化、JSが実行されている場合のみ閉じた状態。 - インラインヘルプをツールチップより優先する。 まずテキストで説明する。ツールチップが必要な場合、
titleに依存しない;ホバーとフォーカスでカスタムツールチップを使用し、最初のツールチップの前に短い遅延を入れ、隣接する要素間の移動時には遅延を入れない。 - コピー:訪問者の言葉でページが提供するものを説明する;ボタンはそれが何をするかを正確に述べる(「送信」ではなく「ニュースレターを購読」);エラーメッセージは回復方法を述べる。
9. 品質ベースライン(必須)
- モーション軽減:
prefers-reduced-motion: reduceでは、リビールは即座に表示され、ループとスムーススクロールはオフになる。 - JSなしでも安全:隠れてから表示される状態は
.jsクラスの背後にあるため、JSが失敗しても何も見えなくならない。 - キーボードとフォーカス:「スキップナビゲーション」リンク、論理的な見出しレベル、
…
[truncated for translation]