テーマ設定#
デフォルトのサイトテンプレートには、小さくも明確な意図を持ったデザインシステムが付属しています。OKLCH パレット、流動的な Utopia の型・スペーススケール、システムフォント、auto/light/dark テーマ、アイコンセット、そして控えめな背景画像を備えた中央寄せのヒーロー。すぐに使え、CSS を一行も書かずに完成度の高い見た目が手に入ります。
このページでは、テーマがどう構成されているか、そして最もよくオーバーライドしたくなる部分をどう上書きするかを説明します。
トークンモデル#
すべての色は、3 つのレイヤーのいずれかに属する CSS カスタムプロパティであり、それぞれが上位のレイヤーの上に構築されています。
- プリミティブ — 1 本のニュートラルランプ。
--color-gray-50から--color-gray-950まで、加えて--color-white/--color-black。生の色の値が存在するのはここだけです。デフォルトテーマは純粋なニュートラルグレーのランプを使います。この 11 個の値を変更すれば、あらゆる面(サーフェス)とテキストの色がそれに従います。ほかに触るファイルはありません。 - ロール — 「ブランド」。
--color-primary、--color-secondary、--color-accent。それぞれに-fg(その上に乗るテキスト)と-hoverのバリアントがあります。デフォルトではこれらをグレーにマッピングしています。ロールを色のランプ(たとえば赤)に向ければ、すべてのボタン・リンク・フォーカスリングがスキンし直されます。グレー以外のロールは light と dark で異なる値を持つことができます。 - セマンティック — サーフェス + テキスト。
--color-bg、--color-surface、--color-fg、--color-border、コールアウト系のトークンなどで、ランプ上にマッピングされます。コンポーネントはロールとセマンティックを参照し、ランプを直接参照することはありません。
ダークモードは、同じランプを反転したステップに再マッピングしたものです。ダーク専用の色の値は存在せず、ロールとサーフェスをグレーランプの反対側の端に向ける小さなブロックがあるだけです(--color-bg → 暗いグレー、--color-fg → 明るいグレー。エレベーションは反転するので、「浮き上がった」サーフェスはより明るくなります)。ランプを一度変更すれば、両方のテーマが一緒に更新されます。
トークンのアーキテクチャ(名前、レイヤー構成、スケール)はプロジェクトの docs/internal/STYLES.md にあります。テーマごとの色の値はテーマのスタイルシート(templates/default/style.css)にあります。
利用可能なテーマ#
ページ全体に適用される 5 つのパレットがバンドルされており、それぞれに light と dark のバリアントがあります(light/dark/auto モードは独立した選択肢のままです)。Ovellum がデフォルトで、残りはピッカーと同様にアルファベット順に並びます。
| テーマ | 備考 |
|---|---|
| Ovellum | モノクロ、純粋なニュートラルグレーのランプ(palette: 'default')。このサイトが使っているテーマです。 |
| E-ink | 温かみのある紙 + インクの黒、最大コントラストのモノクロ — 電子書籍リーダーのような見た目。色のアクセントはなく、site.font: 'serif' と特に相性が良いです。 |
| Flexoki | 温かみのあるインキーな紙のトーン。Flexoki にちなんでいます。 |
| Nord | 北極のブルーグレー — Snow Storm の light、Polar Night の dark、Frost のアクセント。 |
| Solarized | Ethan Schoonover のベーストーン。クリームの light、深いティールの dark。 |
各パレットは、上記のトークンモデルが約束するとおりに実装されています。ロールが指す同じ 11 ステップのグレーランプをスキンし直すので、dark バリアントは反転ランプの再マッピングから自動的に得られます。サーバーレンダリングされるデフォルトは site.palette で設定します。訪問者はトップバーの外観コントロールから実行時に切り替えられます(localStorage に保存され、描画前に適用されます)。コードブロックのシンタックステーマは独立しており、site.codeTheme で選択できます。
タイポグラフィ#
フォント#
フォントのロールは CSS 変数です。--font-sans(本文 + 見出し)、--font-mono(コード)、--font-serif(serif オプション)。実際に使われる本文フォントは --font-body で、site.font から設定され、訪問者がライブで上書きできます。
デフォルトは システムフォントのみを読み込みます — 即座に最初の描画が行われ、ウェブフォントの往復がありません。
組み込みのフォントピッカー#
site.font は 4 つの値を取り、外観コントロールは同じセットをライブのフォントピッカーとして公開します。
| 値 | フォント | ウェブフォントを読み込む? |
|---|---|---|
'sans' | システムの sans-serif スタック(デフォルト) | いいえ |
'serif' | システムの serif(Georgia など) | いいえ |
'inter' | Inter | はい — バンドル済み、オンデマンド |
'geist' | Geist | はい — バンドル済み、オンデマンド |
Inter と Geist はテンプレートの中に同梱されており(/assets/fonts/ から配信)、ホスティングするものは何もありません。それらの @font-face ルールは仕様上 レイジー です。ファイルが取得されるのは、ページが実際にそのファミリーでレンダリングされるとき、つまり site.font がそれに設定されているか、訪問者がそれを選んだときだけです。だからデフォルトのサイトはウェブフォントゼロで高速なまま保たれ、コストはオプトインしたときだけ支払われます。(コードはどちらにしても等幅のままです。)
バンドルされている両ファミリーは SIL Open Font License 1.1 の下にあり、これはソフトウェア内での再配布を許可しています。だから Ovellum はそれらを同梱でき、あなたのビルドはライセンスの懸念なくそれらを配信できます。
自分のフォントを持ち込む#
バンドルされた 2 つ以外のファミリーを使うには、トークンを上書きするだけです — 単なる CSS 変数の変更です。Google Fonts のリンクよりもセルフホスティングを推奨します。第三者への接続を避けられ、訪問者の IP をフォント CDN に送るというプライバシー / GDPR の懸念も避けられます。そして昔の「共有ブラウザキャッシュ」の論拠はもはや成り立ちません(ブラウザはキャッシュをサイトごとに分割するようになりました)。
まずライセンスを確認してください。 セルフホスティングとはあなたがフォントファイルを配信するということなので、ライセンスがウェブ埋め込みを許可しているものだけを使ってください。Open Font License(OFL)のファミリー — バンドルされている Inter や Geist のような — は常に安全です。一部の「無料」フォントは自分のサイトに埋め込むのは無料でも、再配布が許可されていない場合があります。それらを自分でセルフホストするのは構いませんが、責任はあなたにあります。
- フォント(と小さなスタイルシート)を
publicDirに置きます —content/public/は出力ルートにコピーされるので、content/public/fonts/…は/fonts/…で、content/public/site.cssは/site.cssで配信されます。 - そのスタイルシート(
site.headExtraから参照)の中で、@font-faceを定義して--font-sansを上書きします。ファミリーに対応する等幅フォントが付属していれば--font-monoも上書きします。なければシステムスタックのままにしておきます。
/* content/public/site.css → served at /site.css */
@font-face {
font-family: 'My Font';
src: url('/fonts/my-font.woff2') format('woff2');
font-weight: 100 900; /* variable weight axis */
font-display: swap;
}
:root {
--font-sans: 'My Font', ui-sans-serif, system-ui, sans-serif;
}
<!-- site.headExtra (ovellum.config.*) -->
<link rel="preload" href="/fonts/my-font.woff2" as="font" type="font/woff2" crossorigin>
<link rel="stylesheet" href="/site.css">
本文・見出し・プローズは --font-sans を自動的に拾います。headExtra のスタイルシートはテーマの CSS の後に読み込まれるので、その :root の上書きが勝ちます。preload は取得をウォームアップします。(このようなトークンの上書きはピッカーのデフォルトを上書きします — システムスタックではなく、あなたのフォントがベースラインになります。)
読みやすいテキストサイズ#
外観コントロールには、5 段階のテキストサイズスケールも備わっています(2 段階小さく、真ん中がデフォルト、2 段階大きい)。段階的な「A」のランプとしてレンダリングされ、Kindle や Safari リーダーのサイズステッパーのようです。これは --ov-text-scale を介してモジュラー型スケール全体(本文とすべての見出し)を比例的にスケールし、<html data-text-size> に書き込まれ、訪問者ごとに記憶されます。
外観コントロール#
トップバー右端のパレットアイコンは、5 つのコントロールを備えた小さなパネルを開きます(モバイルではメニューシートにインライン展開されます)。
- モード —
auto(prefers-color-schemeで OS に追従)、light、またはdark。<html data-theme>に書き込まれます。 - テーマ — バンドルされた 5 つのパレットのいずれか(それぞれ独自のライングリフを持つ)。
<html data-palette>に書き込まれます。 - カラー — CTA ボタンのほか、リンク、フォーカスリング、「このページの内容」インジケーターを駆動するプライマリカラー。ホバー状態はそこから自動的にミックスされます。6 つのプリセット、ネイティブのカスタムカラーピッカー、そして先頭のデフォルトスウォッチ(テーマ自身のプライマリ — Ovellum ではダークチャコール — に戻します)があります。
- テキストサイズ — 読みやすさの型をスケールする 5 段階の「A」ランプ。
<html data-text-size>に書き込まれます。 - フォント — Sans-Serif(デフォルト)/ Serif / Inter / Geist。
<html data-font>に書き込まれます。Inter と Geist はオンデマンドで読み込まれます(上記のフォントを参照)。
すべての選択は localStorage に保存され、描画前に適用されるので、再訪問時に間違った色がちらつくことはなく、訪問者の選択はページやセッションをまたいで追従します。
初回訪問時のデフォルトは config で設定します。
{
"site": {
"defaultTheme": "dark",
"palette": "nord",
"accent": "oklch(57% 0.16 255)"
}
}
accent は任意の CSS の色の値を取り、訪問者が自分の色を選ぶまでプライマリ + アクセントのロールを駆動します。未設定の場合、各テーマは自身のプライマリを使います(Ovellum のものはモノクロのチャコールです)。
トップバー#
デフォルトのトップバーは 3 カラムのグリッドです。左にブランド、右寄せのナビ、そしてコントロールのクラスター(検索スロット + 外観コントロール + モバイルメニューボタン)。
ブランドはデフォルトではサイトタイトルです。site.logo(単色の SVG/PNG へのパス — テーマに応じて反転するモノクロのシルエットとしてレンダリングされます)で、その前にオプションのマークを追加できます。未設定のままにすればタイトルが単独で表示されます。ファビコンはデフォルトでルートの /favicon.ico で、site.favicon で上書きできます。
site.topbarNav でナビ項目を追加します。
{
"site": {
"topbarNav": [
{ "label": "Guides", "href": "/guides/manual-mode/" },
{ "label": "Reference", "href": "/reference/config/" },
{ "label": "GitHub", "href": "https://github.com/you/repo", "external": true }
]
}
}
外部リンク(external: true または任意の http(s):// URL)は、rel="noopener" と小さな外部リンクアイコンとともに新しいタブで開きます。720px 未満ではナビがハンバーガーに折りたたまれ、トップバーの下にアンカーされた全幅のシートを開きます — 追加の設定は不要です。
ヒーロー#
ランディングページのヒーロー(site.landing.enabled が true のとき)は中央寄せで、擬似要素を介して適用される 2 つの重なった背景レイヤーを持ちます。これにより画像はサイトに同梱されません。
- 24px のドット状 SVG パターン(テーマに応じた塗り、端でフェードするようにマスクされる)。
- アクセントカラーの放射状スポットライトグラデーション(低い不透明度)。
ヒーローのタイポグラフィは clamp() を使い、メディアクエリの森なしにモバイルからデスクトップまでスケールします。タイトルの最大幅は 16ch、サブタイトルは 56ch です。
アイコン#
テンプレートは全体を通じて Lucide のアイコンを使っています。各アイコンは stroke="currentColor" と stroke-width="2" を持つインライン SVG なので、すべてのテーマで周囲のテキストから色を自動的に拾います。アイコンフォントも、別のリクエストもありません。
現在のバンドルで利用可能なアイコン:
menu、close、sun、moon、monitor、chevron-down、github、external-link、search、check。
新しいものを追加するには、packages/site/src/icons.ts に 1 つの import を追加し、REGISTRY マップに 1 つのエントリを追加するだけです。パッケージは Lucide の残りをツリーシェイクするので、各アイコンがバンドルに追加するのはおよそ 100 バイトです。
Lucide v1 はブランドマークを削除した(商標の懸念)ため、
githubは Lucide のストローク言語に合わせて手作りした例外です。もっと多くのブランドロゴが必要なら、simple-icons が標準的な相棒です。
デフォルトテーマのカスタマイズ#
今のところ、最もシンプルなオーバーライドは後続のスタイルシートです。CSS ファイルを content/ に置き(静的アセットとしてそのまま通過します)、ページから参照するか、あるいは — より良いのは — のちにプラグインシステム経由でテンプレートを拡張することです(計画中、未実装)。
ロールをスキンし直す — リンクとアクセントがどこでもそれに従います(これはグレー以外の色なので light と dark で異なります)。
:root {
--color-accent: oklch(55% 0.20 320); /* magenta */
--color-accent-fg: var(--color-white);
--color-accent-hover: oklch(48% 0.22 320);
}
:root[data-theme='dark'] {
--color-accent: oklch(72% 0.18 320);
--color-accent-fg: var(--color-gray-950);
--color-accent-hover: oklch(80% 0.16 320);
}
あるいは、グレーランプを上書きして UI 全体のトーンを変える — すべてのサーフェス、テキスト、(グレーの)ロールが一度にシフトし、コンポーネントごとの編集は不要です。
:root {
/* e.g. a warmer 'stone'-style neutral */
--color-gray-100: oklch(97% 0.004 60);
--color-gray-900: oklch(20.5% 0.006 60);
/* …override whichever steps you use */
}
content/css/override.css として保存し、各ページのフロントマターから将来の extraStyles フィールド(計画中)経由で参照します。
オーバーライドのパターンはまだ正式化の途上です — 今のところ、色の調整以上のことをしたければデフォルトテンプレートをフォークすることを想定してください。プラグイン / テンプレートオーバーライドの API はロードマップに載っています。
ランディングページのテーマ設定#
site.landing を有効にしている場合、ランディングは同じトークンを継承します。ヒーロー、フィーチャーカード、トラストストリップは、ほかのすべてのコンポーネントと同様に --color-fg、--color-bg、--color-accent、--color-border を読みます。ヒーローのスポットライトの色味は --color-accent に自動的に従うので、アクセントを変えればヒーローの雰囲気も自動的にスキンし直されます。
コードブロックのテーマ#
コードブロックはビルド時に shiki でレンダリングされます。各テーマは CSS 変数を通じて出力される { light, dark } のペアです — 同じ HTML が両方のカラースキームを提供し、<html> の [data-theme] を切り替えるとランタイムコストゼロでパレットが入れ替わります。
site.codeTheme で 1 つ選びます。
{
"site": {
"codeTheme": "nord"
}
}
| 値 | Light | Dark | 備考 |
|---|---|---|---|
'github' | github-light | github-dark | デフォルト。Ovellum のデフォルトに合います。 |
'nord' | min-light | nord | Nord は shiki では dark のみ。クリーンで低彩度の light のために min-light とペアにしています。 |
'solarized' | solarized-light | solarized-dark | Ethan Schoonover の solarized。 |
今日バンドルされているもの vs. 計画中のもの#
現在利用可能:
- デフォルトの light + デフォルトの dark。
prefers-color-schemeによる OS への自動追従。- 描画前のテーマスクリプト(ちらつきなし)。
renderIcon(name)ヘルパーを備えた Lucide ベースのアイコンレジストリ。- モバイルシート付きの右寄せトップバーナビ(720px 未満でハンバーガー)。
- ドットノイズ + アクセントスポットライトの背景を持つ中央寄せのヒーロー。
- ネストされたページで記事の上に表示されるパンくずリスト。
- 記事の上に表示されるページごとのメタ行(読了時間 + 最終更新日)。
- クロームを取り除き記事を広げるプリント用スタイルシート。
- カスタム 404 レイアウト(狭いカラム、大きな見出し、クロームなし)。
- すべてのコードブロックのコピーボタン。
ロードマップ:
- ページテーマを名前で切り替える
site.themeconfig(Nord、Dracula など)。各テーマはトークンモデルに従い、独自のグレーランプ + ロール値に加え、反転ランプの dark ブロックを同梱します。今日はデフォルトのページテーマのみが同梱されています。site.codeThemeはすでにシンタックスパレットを切り替えます。 - 完全にカスタムなテンプレートのためのプラグイン API。
- 一度きりのページ固有 CSS のためのページごとの
extraStyles。
それらが実現するまでは、本格的なカスタマイズの推奨パスは次のとおりです。
templates/default/ディレクトリをフォークする。- あなたのフォークを指す独自の
ovellum.config.tsを実行する。 - Ovellum がテンプレートを更新したら、リベースし直す。
これは v1 のための意図的な制約です — カスタマイズの表面が安定すれば、API はよりコミットしやすくなります。