Communitygithub.com

karero/website-design-system

見た目と視覚的なパフォーマンスを担当するレイヤーです。モバイルグラフィック、ダークモード、テーマトークンを管理します。

website-design-system とは?

このスキルは、Webサイトの**見た目と視覚的なパフォーマンス**を一貫して管理するための設計システムです。具体的には、モバイルグラフィック、ダークモード、テーマトークンを担当し、`BRAND.md`ファイルとCSSカスタムプロパティによるトークン定義を維持します。画像アセットの生成には別の`image`スキルを使用します。ダークモードはCSSカスタムプロパティを用いたトークンベースで、初回描画前のFOUC対策スクリプトによりスムーズに切り替わり、両テーマでWCAG AA基準のコントラスト比を満たします。モバイルファーストのレスポンシブデザインを採用し、画像はWebP/AVIF形式で適切にサイズ・遅延読み込みを行い、alt属性を必須とします。また、多言語翻訳時のテキスト長変化に対応するため、フレキシブルな幅設計、ハイフネーション、ワードラップの設定を推奨します。テーブルはスタック型とフィギュア型の2種類を定義し、アクセシビリティテストで検証します。メールアドレスはスクレイパー対策のためにビルド時にエンコードし、`EmailLink`コンポーネントを使用します。すべての変更は指定されたブレークポイントでレイアウトが崩れず、パフォーマンス指標が確認された時点で完了とみなされます。

対応~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/karero/croftweaver/tree/HEAD/skills/website-design-system

お気に入りのAIに質問する

このエージェントスキルを事前に読み込んだ状態で新しいチャットを開きます。

ドキュメント

ウェブサイトデザインシステム

見た目と視覚的なパフォーマンスを担当するレイヤーです。モバイルグラフィック、ダークモード、テーマトークンを管理します。BRAND.md(テンプレート:new-websiteスキルのtemplates/brand.md)と、そのスキルのtemplates/astro/src/styles/global.css内のトークンブロックを出力・維持します。画像ルールは以下の通り(Astroのastro:assetsによるWebP/AVIF対応)。images.spec.tsテストでルールが強制されます。画像アセットの生成にはimageスキルを使用してください。

ダークモード(ファーストクラス)

  • トークン、ハードコードされた色は使用しません。 すべての色はCSSカスタムプロパティを通して流れます。ライトモードは:rootのデフォルト、ダークモードは:root[data-theme="dark"]で上書きし、さらにJavaScript無効の訪問者向けに@media (prefers-color-scheme: dark)ブロックも用意します。スターターキットはこの正確な構造を備えています。
  • FOUC防止スクリプト を<head>に配置し、localStorage.themeまたはシステム設定から最初の描画前にdata-themeを設定します(Base.astroに既に組み込み済み)。トグルはlocalStorage.themeに書き込みます(スターターキットにはトグルは含まれていません。追加する場合は、プライバシーページのセクション3にその旨を記載してください)。
  • 両テーマのコントラスト比を確認: すべてのテキスト/背景の組み合わせがWCAG AA(本文4.5:1、大文字/UI 3:1)を満たします。ライトモードで合格する色でもダークモードでは不合格になることがよくあります。アクセシビリティテストはライト+ダークの全組み合わせで実行されるため、両方を確認してください。

モバイル&レスポンシブグラフィック

  • モバイルファースト: 360pxからデザイン。タップターゲットは44px以上。水平スクロールは禁止。360 / 768 / 1280pxで確認してください(preview_resize)。
  • モダンなフォーマット: 写真にはJPEG/PNGではなくWebP(またはAVIF)を使用します。
  • 表示サイズに合わせ、元画像に合わせない。 80pxのスロットに2000pxの画像を配信しないでください。幅のバリエーションを生成し、srcset/sizes(または<picture>)を使用します。
  • レイアウトシフトを防ぐ: 明示的なwidth/height属性を設定し、画像読み込み前にボックスを確保します(CLS / LCPを保護)。Astroの<Image>は自動的に設定します。images.spec.tsでは属性の存在が必須です(CSSのみのaspect-ratioではテストに合格しません)。
  • 遅延読み込み vs 即時読み込み: ファーストビュー以下の画像はloading="lazy"。LCP/ヒーロー画像はfetchpriority="high"で即時読み込みします(遅延読み込みはしないでください)。
  • すべての画像にaltテキスト(純粋に装飾的な場合のみalt="")。
  • フォント: woff2をセルフホストし、font-display: swapを設定。ファーストビューで使用する1~2種類のフォントのみプリロードします。フォントの遅延読み込みによるレイアウトシフトを避けます。

テキスト長のレスポンシブ対応(翻訳コピー)

  • 翻訳テキストは長くなります。 ドイツ語(および他の多くの言語)は、英語の同等コピーよりも一般的に20~35%長くなります。英語のプレースホルダーテキストに合わせてサイズ設定されたボタン、ナビリンク、またはカードは、実際の翻訳コピーに置き換えられた瞬間に静かにオーバーフローしたり、折り返しが醜くなったり、切り詰められたりします。
  • フレキシブルな幅を優先します。 翻訳テキストを保持する要素には、英語の文字列に合わせた固定widthではなく、min-width / flex / gridのauto/frサイジングを使用します。
  • オーバーフロー ≠ 幅: フレキシブルなサイジングだけでは、単一の長い複合名詞(例:Datenschutzerklärung)が狭いカラムからはみ出すのを防げません。そのためには、hyphens: auto(lang属性により言語ごとに正しく適用。Base.astroで既に設定済み)に加え、フォールバックとしてoverflow-wrap: break-wordが必要です。スターターキットのglobal.cssは両方をbodyに設定しています。テーブルのセルではハイフネーションをオフにします(テーブルを参照)。
  • ナビリンクやボタンラベルの処理として、white-space: nowrap + text-overflow: ellipsisだけに依存しないでください。 ナビリンクを切り詰めることは、通常許容されるUXではありません(訪問者はどこに移動するのかわからなくなります)。切り詰めが許容されるトレードオフとなるコンテンツ(例:テーブルセル)には問題ありませんが、ナビゲーションには適していません。
  • 英語のプレースホルダーではなく、実際の翻訳ラベルで確認してください。 サイトがastro-i18n-setupのLanguageSwitcher.astroやバイリンガル/マルチリンガルナビを出荷する場合、英語のプレースホルダーだけでなく、すべての言語で実際に出荷されたコピーを使用して、360/768/1280(preview_resize)でレイアウトを確認してください。

テーブル

すべてのテーブルに1つのスタイル。ページはテーブル用のレイアウトCSSを持ちません。スターターキットのsrc/styles/tables.css(Base.astroによってglobal.cssの後にインポートされる)に存在し、tests/tables.spec.tsがそれをチェックします。このセクションより前に作られたサイトは、tables.cssをコピーし、レイアウトにインポート行を追加し、最初に各ページの独自のテーブルCSSを削除します。

セルの内容によって区別される2種類があります。

  • stack(文章): 40rem以上のテーブル。40rem以下では各行が積み重なり、行ヘッダーがタイトル、各セルがカラム名の下に配置されます。4カラムの散文は320pxを共有できません。
  • figures(短い数字、数値セルにclass="num"を付与): スマートフォンでもテーブルを維持し、320pxに収まる必要があります。収まらなくなった場合はstackにします。スクロールバーは修正策ではありません。stack figuresを組み合わせると、積み上げレイアウトでのフィギュアの見え方になります。

すべてのテーブルのマークアップ:

<div class="table-wrap stack" role="region" aria-label="テーブルの説明" tabindex="0">
  <table role="table">
    <thead role="rowgroup"><tr role="row">
      <th scope="col" role="columnheader">{cols[0]}</th><th scope="col" role="columnheader">{cols[1]}</th>
    </tr></thead>
    <tbody role="rowgroup">{rows.map((r) => (
      <tr role="row"><th scope="row" role="rowheader">{r.item}</th><td role="cell" data-label={cols[1]}>{r.text}</td></tr>
    ))}</tbody>
  </table>
</div>
  • カラム名はリストに1度だけ記述し、ヘッダーとすべてのdata-labelに使用します。スタックされたセルのラベルはそのカラムのヘッダーと等しくなければならず、テストで両者が比較されます。figuresテーブルには、セルごとのロールやdata-labelは必要ありません。
  • スタックされたテーブルはもはやdisplay: tableではありません。ロールは、レイアウトが変更されたときにブラウザがテーブルをドロップした場合のフォールバックです。実際にそれらが機能するかどうかはチェックされません。Chromiumでは、実際のテーブルで測定したところ、アクセシビリティツリーはロールがなくてもテーブルを維持していました。
  • セル内に単独で存在するリンクにclass="tap"を付けると、スマートフォン上で44pxのタップターゲットになります。nowrapは短い値(1, 3, 6など)を1行に保持します。long-head(stackと併用)は、行ヘッダーが文章の場合に最初のカラムを広げます。
  • セル内の単語はハイフネーションされません。bodyのhyphens: autoは狭い最初のカラムを断片("An-thropic")に圧縮するため、ブロックはそこにhyphens: manualを設定します。
  • 外部から取得したテーブルを含むページで、マークアップを適用できない場合は、理由とともにTABLE_EXEMPTに追加します。PAGESは変更しないでください。サイトマップとllms.txtのチェックでは、すべてのライブルートがそれに含まれている必要があります。

tables.spec.tsがチェックする内容:すべてのテーブルは、いずれかの種類の.table-wrap内にあり、そのリージョン、ラベル、tabindexを持ち、すべてのヘッダーセルにscope="col"があり、すべての行の最初のセルとして<th scope="row">があり、残りは<td>であること。スタックされたテーブルにはロールと、各セルにヘッダーと等しいラベルがあること。360pxおよび320pxで、どのページもテーブルも横スクロールしないこと。641px以上では、スタックされたテーブルは再びテーブルになり、ヘッダー行が表示され、単語が分割されていないこと(これはoverflow-wrap: anywhereのようにカラムが単語を圧縮できるようにするルールをキャッチします)。どのセルにもhyphens: autoがないこと。また、ホームページに追加するフィクスチャでCSSをテストし、両方のテーマでaxeを使用するため、テーブルがなくてもブロックが機能することを証明します。ヘッドレスChromiumはハイフネーションしないため、ハイフンガードは計算されたスタイルを読み取り、レイアウトは読み取りません。SafariとVoiceOverはチェックされません。

メールアドレスの難読化(クローラーからアドレスを隠す)

プレーンテキストのメールアドレスやmailto:your@addrをHTMLソースに決して配置しないでください。スクレイパーがそれを収集し、数時間以内にスパムに使用します。すべてのアドレスは、**EmailLink.astro**コンポーネント(new-websiteスキルのtemplates/astro/内のsrc/components/EmailLink.astro、およびそのlib/obfuscate.tsヘルパー)を通してレンダリングします。アドレスはビルド時に反転されbase64エンコードされ、ブラウザで再構築されるため、提供されるHTMLには読み取り可能なアドレスは含まれません。JavaScript無効の訪問者には、引き続き使用可能な「name [at] domain [dot] com」ヒントが表示されます。

<EmailLink address="[email protected]" subject="お問い合わせ" text="メールを送信" />

ルール:ビルドされたHTML内に生のmailto:リンクとリテラルの@アドレスをゼロにする — website-qaがこれをチェックします。収集されたくない電話番号についても同様の考え方を適用します。

ブランドトークン

BRAND.mdのパレットをトークンブロックに反映し、同期を維持します。以下を定義します:ブランド(固定)、およびテーマごとのheading/ink/muted/accent/link/line/bg/bg-soft/surface。アクセントカラーとリンクカラーは、両方のテーマで背景に対してAAに合格する必要があります。そのため、各テーマは独自のものを持っています。オプションのwebsite-brand-kitはチェックとともにミラーリングを行います。その入力はBRAND.mdのテーブルを読み取り、すべてのテキストカラーを両テーマのすべての背景に対して4.5:1に保ち、値をglobal.cssの3つのすべてのカラーブロック(ライト、ダーク、JavaScript無効の訪問者向けのダークブロック)に書き込みます。手動で行う場合も、3つのブロックすべてを一緒に変更してください。

完了条件

BRAND.mdが記入され、トークンブロックと一致していること。画像はWebP形式で、サイズ設定され、遅延/即時読み込みが正しく行われ、alt属性があること。アクセシビリティテスト(ライト+ダーク)がパスしていること。レイアウトが360/768/1280pxでシフトなく保持されていること。すべてのテーブルがstackまたはfiguresであり、tables.spec.tsがパスしていること。パフォーマンス数値(FCP/LCP)がwebsite-qaで確認されていること。レイアウトは、デフォルトのロケールだけでなく、出荷されるすべての言語の実際の(プレースホルダーではない)コピーでも、360/768/1280pxで保持されていること。

Individual skills in this repo

This repo contains 2 individual skills — each has its own dedicated page.

関連スキル