Master CSS 入門
クラスでインターフェースを作り、生成される CSS をたどり、プロジェクトで共有する値を定義します。
このページの内容
Master CSS は、マークアップでインターフェースのスタイルを指定し、CSS で共通スタイルを定義するための CSS フレームワークです。要素を作る場所にクラスを書き、プロジェクト全体で共有する値やパターンはスタイルシートに置きます。Master が、そのクラスに必要な CSS を生成します。
付属の色、余白、文字組みから使い始められます。最初のコンポーネントを作る前に、テーマ全体を設計する必要はありません。
#CSS とユーティリティでインターフェースを作る
このカードは、ネイティブのコンポーネントクラスとユーティリティを組み合わせています。.action は CSS でボタンの基本スタイルを定義し、w-full、mt-md、bg-blue-60 はこのカードで使う幅、マージン、色を指定します。ほかのマークアップでは、プリセットのユーティリティでレイアウト、余白、文字組みを整えています。
インストールを終えたら、アプリのスタイルシートでプリセットのインポートより後にこの例の CSS を追加し、連携ツールがスキャンするソースファイルに HTML を置いてください。
@import '@master/css';CSS とユーティリティで作るカード
@layer components { .action { display: flex; align-items: center; justify-content: center; min-height: 2.75rem; padding: var(--spacing-xs) var(--spacing-md); border-radius: var(--radius-md); font-size: var(--text-sm); font-weight: var(--font-weight-regular); line-height: var(--text-sm--line-height, normal); letter-spacing: var(--text-sm--letter-spacing, normal); text-decoration-line: none; outline-offset: 3px; &:focus-visible { outline: 2px solid; } }}<article class="overflow-hidden w-full (max-width:22.5rem) mx-auto r-lg bg-surface-raised shadow-sm"> <img src="/building.jpg" width="640" height="360" alt="Sunlit facade of a contemporary building" class="block w-full h-auto (aspect-ratio:16/9) object-cover"> <div class="p-lg"> <p class="m(0) text-2xs font-regular tracking-widest uppercase fg-text-blue">Launch panel</p> <h2 class="mt-xs mb(0) text-md font-regular fg-text-strong">Build the first screen in markup</h2> <p class="mt-xs mb(0) text-sm leading-lg fg-text-muted">Start with local classes, then promote repeated values into your project theme when the interface settles.</p> <a class="action w-full mt-md bg-blue-60 fg-white bg-blue-70:hover bg-blue-80:active outline-blue-60:focus-visible" href="/guide/installation" target="_top">Start building</a> </div></article>生成された CSS
@layer components { .action { min-height: 2.75rem; padding: var(--spacing-xs) var(--spacing-md); border-radius: var(--radius-md); font-size: var(--text-sm); font-weight: var(--font-weight-regular); line-height: var(--text-sm--line-height, normal); letter-spacing: var(--text-sm--letter-spacing, normal); outline-offset: 3px; justify-content: center; align-items: center; text-decoration-line: none; display: flex; &:focus-visible { outline: 2px solid; } }}@layer theme { :root, :host { --color-zinc-40: oklch(68.6% .0028 265); --color-zinc-60: oklch(48.6% .003 265); --color-zinc-90: oklch(24.6% .0022 265); --color-zinc-100: oklch(15% .0016 265); --color-blue-30: oklch(72.87% .1468 249.3); --color-blue-60: oklch(51.83% .2687 266.1); --color-blue-70: oklch(46.26% .3057 266.7); --color-blue-80: oklch(42.89% .2907 266.3) } :root, :host { --color-surface-raised: light-dark(var(--color-white), var(--color-zinc-90)); --color-text-strong: light-dark(var(--color-zinc-100), var(--color-white)); --color-text-muted: light-dark(var(--color-zinc-60), var(--color-zinc-40)); --color-text-blue: light-dark(var(--color-blue-60), var(--color-blue-30)) } :root, :host { --color-white: oklch(100% 0 none) } :root, :host { --tracking-widest: .12em; --leading-lg: 1.8; --font-weight-regular: 400; --font-size-2xs: .625rem; --font-size-sm: .875rem; --font-size-md: 1rem; --text-2xs: var(--font-size-2xs); --text-2xs--line-height: 1.5; --text-2xs--letter-spacing: 0; --text-sm: var(--font-size-sm); --text-sm--line-height: 1.5; --text-sm--letter-spacing: 0; --text-md: var(--font-size-md); --text-md--line-height: 1.6; --text-md--letter-spacing: 0; --radius-md: .375rem; --radius-lg: .5rem; --spacing-xs: .5rem; --spacing-md: 1rem; --spacing-lg: 1.5rem } :root, :host { --shadow-sm: 0 0 0 1px light-dark(oklch(0% 0 none / .04), oklch(100% 0 none / .05)), 0 1px 1px -.5px light-dark(oklch(0% 0 none / .045), oklch(0% 0 none / .3)), 0 2px 2px -1px light-dark(oklch(0% 0 none / .04), oklch(0% 0 none / .26)), 0 4px 4px -2px light-dark(oklch(0% 0 none / .04), oklch(0% 0 none / .24)) }}@layer utilities { .text-2xs { font-size: var(--text-2xs); line-height: var(--text-2xs--line-height, normal); letter-spacing: var(--text-2xs--letter-spacing, normal) } .text-md { font-size: var(--text-md); line-height: var(--text-md--line-height, normal); letter-spacing: var(--text-md--letter-spacing, normal) } .text-sm { font-size: var(--text-sm); line-height: var(--text-sm--line-height, normal); letter-spacing: var(--text-sm--letter-spacing, normal) } .bg-blue-60 { background-color: var(--color-blue-60) } .bg-surface-raised { background-color: var(--color-surface-raised) } .r-lg { border-radius: var(--radius-lg) } .shadow-sm { box-shadow: var(--shadow-sm) } .fg-text-blue { color: var(--color-text-blue) } .fg-text-muted { color: var(--color-text-muted) } .fg-text-strong { color: var(--color-text-strong) } .fg-white { color: var(--color-white) } .block { display: block } .font-regular { font-weight: var(--font-weight-regular) } .h-auto { height: auto } .tracking-widest { letter-spacing: var(--tracking-widest) } .leading-lg { line-height: var(--leading-lg) } .m\(0\) { margin: calc(0 * 1px) } .mx-auto { margin-inline: auto } .mt-md { margin-top: var(--spacing-md) } .mt-xs { margin-top: var(--spacing-xs) } .mb\(0\) { margin-bottom: calc(0 * 1px) } .object-cover { object-fit: cover } .overflow-hidden { overflow: hidden } .p-lg { padding: var(--spacing-lg) } .uppercase { text-transform: uppercase } .w-full { width: 100% } .\(aspect-ratio\:16\/9\) { aspect-ratio: 16/9 } .\(max-width\:22\.5rem\) { max-width: 22.5rem } .bg-blue-70\:hover:hover { background-color: var(--color-blue-70) } .outline-blue-60\:focus-visible:focus-visible { outline-color: var(--color-blue-60) } .bg-blue-80\:active:active { background-color: var(--color-blue-80) }}プレビューは、表示されている CSS と HTML を組み合わせて動作します。.action はこの例の @layer components 内で定義され、Master はマークアップのクラスからユーティリティルールを生成します。ボタンに共通する形状やフォーカス表示は .action に置き、このインスタンスの青い色と全幅の指定はマークアップに残します。
p-lg を p-md に変えてみてください。ボタンの基本スタイルを変えずに、カードのコンテンツのパディングを小さくできます。
画像 URL は、アプリが /building.jpg を配信することを想定しています。自分の画像と代替テキストに置き換え、リンク先もアプリ内のページに変更してください。
#クラスから CSS をたどる
カードの p-lg を見てみましょう。プリセットは p- をパディングに、lg を余白トークン --spacing-lg に結び付けます。Master は、その CSS 変数を宣言から参照するクラスセレクターを生成します。
クラスがスタイルを選び、トークンが値を与える
対応する名前が各部分を結び付けます。p-lg がルールを選び、var(--spacing-lg) が共通の値を読み取ります。図は該当する宣言だけを示しており、下の完全な出力にはレイヤーも含まれます。
テキストによる説明
- クラスの一致. HTML の p-lg クラスが、生成された .p-lg セレクターに一致します。青い括弧と線が、この二つの記述を結んでいます。
- 共通の値. プリセットは --spacing-lg を 1.5rem と定義しています。紫の括弧と線が、その定義と padding: var(--spacing-lg) 内の参照を結んでいます。
- ブラウザーでの結果. ブラウザーは CSS 変数を解決し、四辺に 1.5rem のパディングを適用します。生成ルールは値を宣言にコピーせず、変数への参照を保持します。
生成された CSS
@layer theme { :root, :host { --spacing-lg: 1.5rem }}@layer utilities { .p-lg { padding: var(--spacing-lg) }}ブラウザーは、一致する要素に padding: var(--spacing-lg) を適用します。プリセットの値では、四辺とも 1.5rem です。テーマで共通の値を変えても、クラス名は変わりません。
ほかのクラスは、別の種類の指定を表します。w-full は width: 100% を指定する固定ユーティリティで、bg-blue-70:hover はホバー状態を追加します。構文チュートリアルでは、動く例を使って値、セレクター、条件を学べます。
#一緒に変える値を定義する
複数の要素でプロジェクトの設定を共有するときは、テーマトークンを追加します。主要なアクションの色なら、アプリのスタイルシートでインポートより後に --color-brand を定義し、マークアップで bg-brand を使います。
@theme { --color-brand: #2563eb;}<a class="inline-flex px-md py-xs r-md bg-brand fg-white" href="/guide/installation">Start building</a>生成された CSS
@layer theme { :root, :host { --color-white: oklch(100% 0 none) } :root, :host { --radius-md: .375rem; --spacing-xs: .5rem; --spacing-md: 1rem } :root, :host { --color-brand: #2563eb }}@layer utilities { .bg-brand { background-color: var(--color-brand) } .r-md { border-radius: var(--radius-md) } .fg-white { color: var(--color-white) } .inline-flex { display: inline-flex } .py-xs { padding-block: var(--spacing-xs) } .px-md { padding-inline: var(--spacing-md) }}--color-brand を変えると、それを使う要素も更新されます。トークンを共有するのは、それらの要素を一緒に変える必要があるからです。無関係な二つの色は、値が同じでも同じ名前にする必要はありません。共通の値の定義と上書きはテーマトークンで説明します。
複数の要素でスタイルの規約を共有するなら .action のようなコンポーネントクラスを使い、マークアップを共有するなら UI コンポーネントを使います。クラスリストが長いという理由だけで、新しい CSS 名を付ける必要はありません。スタイルの再利用では、共通トークン、コンポーネントクラス、独自ユーティリティの使い分けを説明します。
配信方式を変えても、クラス体系は変わらない
構文は、どのスタイルを指定するかを表します。レンダリングモードは、その CSS をいつ、どこで生成するかを決めます。
テキストによる説明
同じクラスとその宣言から、ビルドで生成するスタイルシートと、ブラウザーで生成するスタイルシートの二つの配信経路に分かれています。
#静的 CSS から始める
使用するフレームワークで推奨される静的連携を使ってください。ビルド時にソース内の完全なクラス名を見つけて通常の CSS を配信するため、ブラウザーに Master のランタイムやエンジンは不要です。
インタラクティブなインターフェースもそのまま作れます。既知のクラスを切り替える、:hover などのセレクターを使う、進捗や座標などの値を CSS カスタムプロパティで更新するといった方法があります。プレイグラウンド、ビジュアルエディター、配信済みのコンテンツから、未知のクラス名が追加される場合にはランタイムが役立ちます。配信方式の選び方はレンダリングモードを参照してください。
インストールの手順で Master CSS をアプリに接続し、構文チュートリアルで操作状態やレスポンシブ条件に対応するカードを作りましょう。記述中の入力補完や診断には、言語サービスを設定してください。



