svelte-styling について
svelte-styling は、Svelte 5 コンポーネントのスタイルを扱うリファレンススキルです。スコープ付き・グローバル CSS、カスタムプロパティ、class の処理、style: ディレクティブ、キーフレームを例とトラブルシューティングとともに解説します。
主な機能
- 01スコープ付き・グローバル CSS のパターン
- 02CSS カスタムプロパティの使い方
- 03class 属性とディレクティブ
- 04style: ディレクティブの動作
- 05スコープ付き・グローバルキーフレーム
- 06スタイル問題のトラブルシューティング
活用シーン
- 01コンポーネントのスタイルが適用されない原因の特定
- 02コンポーネント間での CSS 値の受け渡し
- 03挿入した HTML へのグローバルスタイル適用
- 04キーフレームや Tailwind クラスの問題解決
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ full-stack-skills/ svelte-skills --skill svelte-stylingインストール後、Claude Code で/svelte-stylingを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
agents/openai.yamlexamples/global-patterns.mdnested-style.mdREADME.mdscoped-keyframes.mdscoped-styles.mdstyle-directive.mdtailwind.mdreferences/class-directive.mdcss-custom-properties.mdglobal-reference.mdREADME.mdscoped-deep.mdscoped-keyframes.mdspecificity.mdstyle-directive.md詳細
Svelte スタイリングリファレンス(Svelte 5)
このスキルでは、Svelte コンポーネントのスタイリングシステムについて、スコープ付きスタイル、グローバルスタイル、CSS カスタムプロパティ、class の処理、style: ディレクティブ、ネストされた <style>、スコープ付き keyframes を含めて説明します。
このスキルを使用する場面
ユーザーが Svelte コンポーネントのスタイルを記述する、スタイルの分離を処理する、CSS 変数を渡す、style: ディレクティブを使用する、アニメーションの keyframes を扱う、または Svelte コンパイラーのスタイル処理を理解する必要がある場合に使用します。
重要:スコープ付きスタイル
<style> ブロック内の CSS はデフォルトでスコープ化され、現在のコンポーネント内の要素にのみ影響します。
<style>
p { color: burlywood; }
.container { padding: 1em; }
</style>
コンパイル時に、Svelte はスコープ内のセレクターにハッシュクラス(svelte-123xyz など)を自動的に追加します。
特異性(Specificity)
スコープ付きセレクターでは、特異性が +0-1-0 追加されます(スコープクラスによる)。そのため、同じセレクターを使うグローバルスタイルより優先される場合があります。
/* 全局 */
p { color: blue; }
/* 组件内(scoped,优先级更高) */
p { color: red; }
:where() によるラップ
同じスコープクラスをセレクター内に複数回含める必要がある場合、特異性に寄与するのは最初の出現箇所のみです。後続の箇所は :where(.svelte-xyz123) でラップされ、特異性には寄与しません。これにより、深いセレクター(.a .b .c など)の特異性が過剰に高くなるのを防ぎます。
スコープ付き Keyframes
@keyframes の名前も自動的にスコープ化され、同じコンポーネント内の animation: name 参照は一致するように書き換えられます。
<style>
@keyframes bounce {
0%, 100% { transform: translateY(0); }
50% { transform: translateY(-20px); }
}
.animated { animation: bounce 1s; } /* 编译为 bounce-svelte-abc123 */
</style>
スタイルが適用されない場合
- 要素が子コンポーネントによってレンダリングされている(スコープはコンポーネント境界を越えません)
{@html}の内容(スコープクラスがありません)- クラス名が動的またはプログラムによって追加されており、セレクターで
:global(...)を使用していない - セレクターがテンプレート内に実際に存在する要素に一致しない
style=""属性または JS でスコープ付き keyframe 名を使用している(-global-で解決します)
重要:グローバルスタイル
:global(...) 単一セレクター
<style>
:global(body) { margin: 0; } /* 全局 body */
div :global(strong) { color: goldenrod; } /* 嵌套全局 */
p:global(.big.red) { font-weight: bold; } /* 带条件 */
</style>
:global(selector)— セレクター全体がスコープの対象外になります。parent :global(child)— 親はスコープを保持し、子は保持しません(最も一般的な形式)。tag:global(.class.class)— 要素はスコープクラスを保持しますが、トリガークラスをテンプレート内に記述する必要はありません(サードパーティライブラリが実行時に追加するクラスに適しています)。
:global { ... } ブロック(複数のセレクター)
<style>
:global {
p { margin: 1em; }
.theme-dark { --bg: #111; }
}
.parent :global {
.foo .bar { color: red; } /* .parent 是 scoped,.foo .bar 是全局 */
}
</style>
:global ブロック内のセレクターはそのまま出力され、特異性が低下することはありません。.foo .bar 自体の特異性のみが適用されます。
グローバル Keyframes
keyframe 名の前に -global- を付けます。
<style>
@keyframes -global-my-animation-name {
0% { opacity: 0; }
100% { opacity: 1; }
}
</style>
コンパイル後、-global- プレフィックスは削除され、my-animation-name になります。他のコンポーネント、<style> 属性、JS から参照できます。
コンパイラーが書き換えるのは、同じ
<style>ブロック内のanimation参照のみです。style="..."属性、{@html}の内容、JS、style:colorディレクティブ内の keyframe 名は書き換えられません。これらの箇所では-global-付きの名前が必要です。
重要:CSS カスタムプロパティ
カスタムプロパティを渡す
<Slider bind:value --track-color="black" --thumb-color="rgb(255 0 0)" />
コンパイル時に、Svelte はインライン style を保持するために svelte-css-wrapper(SVG では <g>)をラップします。
<svelte-css-wrapper style="display: contents; --track-color: black; --thumb-color: rgb(255 0 0)">
<Slider ... />
</svelte-css-wrapper>
ラッパー要素は
display: contentsを持ちますが、>子セレクターによる照合には引き続き含まれます。必要に応じて子孫セレクターを使用してください。
コンポーネント内での読み取り
<style>
.track { background: var(--track-color, #aaa); }
.thumb { background: var(--thumb-color, blue); }
</style>
CSS カスタムプロパティはカスケード可能
値を直接渡す必要はありません。親要素が CSS 変数を定義していれば、子コンポーネントから読み取れます。
/* 全局 */
:root { --primary: #ff3e00; }
重要:style: ディレクティブ
style: ディレクティブは style="..." 属性の省略記法で、プロパティごとに 1 つのディレクティブを指定します。
<div style:color="red">A</div>
<div style:color={myColor}>B</div>
<div style:color>C</div>
複数のスタイル
<div style:color style:width="12rem" style:--columns={columns}>...</div>
CSS カスタムプロパティ
style:--var で CSS 変数を設定します。
<div style:--columns={columns} style:--gap="1rem">...</div>
!important 修飾子
style:color|important="red" → style="color: red !important" にコンパイルされます。
優先順位
style: ディレクティブは同じ要素の style="" 属性より優先されます。style="" 内で !important を使用している場合も同様です。
<div style:color="red" style="color: blue !important">This will be red</div>
数値の単位
数値に単位は自動的に追加されません。
<div style:width={10}>...</div>
<div style:width="{10}px">...</div>
重要:class 属性
Svelte 5.16+ の class 属性は、オブジェクトと配列をサポートします(clsx で処理されます)。
オブジェクト形式
<div class={{ cool: isCool, large: isLarge }}>...</div>
配列形式
<div class={[faded && 'saturate-0 opacity-50', large && 'scale-200']}>...</div>
混在形式
<Button class={['btn', props.class]} />
型安全性
<script lang="ts">
import type { ClassValue } from 'svelte/elements';
let { class: cls }: { class: ClassValue } = $props();
</script>
<div class={['original', cls]}>...</div>
5.16 より前の falsy の動作
歴史的な理由により、class={false} は class="false" としてシリアライズされますが、class={undefined} / class={null} の場合は属性が出力されません。今後の Svelte バージョンでは、すべての falsy 値で class が省略されるようになります。
重要:class: ディレクティブ(非推奨)
Svelte 5.16+ では、class: ディレクティブの代わりに class={} のオブジェクト/配列形式を使用することを推奨します。
<div class={{ cool, lame: !cool }}></div>
<div class:cool class:lame={!cool}></div>
重要:ネストされた <style> 要素
1 つのコンポーネントに指定できる最上位の <style> ブロックは1 つだけですが、<style> タグをネストできます(スコープ処理は行われず、そのまま DOM に挿入されます)。
<div>
<style>
/* 原生 style 标签,无作用域,规则全局生效 */
div { color: red; }
</style>
</div>
使用例:
{#if}によるテーマトークンの切り替え(変数を切り替えに応じて追加・削除)- CSS が付属するサードパーティコンポーネント
- 動的なテーマ変数
- メール/SVG テンプレート
注意: ネストされた <style> 内の @keyframes 名はグローバルで、書き換えられません。複数のコンポーネントで同じ keyframe 名を使用すると競合します。
重要:{@html} とスコープ付きスタイル
{@html} で挿入された内容にはスコープクラスがないため、スコープ付きセレクターは一致しません。:global(...) で解決します。
<style>
:global(.highlight) { color: red; }
</style>
警告: 完全に制御できない HTML のスタイリングに :global(...) を使用しないでください。XSS のリスクがあります。
クイック修正
| 問題 | 解決策 |
|---|---|
| スタイルが適用されない | スコープハッシュに上書きされていないか確認します。:global を使用します |
| コンポーネントにスタイルが渡らない | スコープ付きセレクターではなく、CSS カスタムプロパティ(--var)を使用します |
| 親コンポーネントから子コンポーネントのスタイルを上書きできない | --var で値を渡すか、:global を使用します(非推奨) |
| グローバルスタイルがコンポーネントのスコープ付きスタイルに上書きされる | スコープ化により特異性が +0-1-0 増加します。:where() を使用するか、グローバルセレクターの特異性を高めます |
| Tailwind クラスが適用されない | JIT が動的に連結されたクラス名を検出できません。class={[...]} の配列マッピングまたは safelist を使用します |
動的な style="animation: x" から keyframe が見つからない | keyframe がスコープ化されています。@keyframes -global-x を使用します |
style: が適用されない | 式の構文を確認します。数値には単位が必要です |
> .child が一致しない | 親から --var を渡す際に svelte-css-wrapper が追加されています。子孫セレクターに変更します |
| slot の内容にスタイルが適用されない | 親コンポーネントからスタイルを指定するには ::slotted(selector) を使用します |
注意点
- スコープ付きスタイルの分離 — ハッシュクラスによって実現されており、スタイルが実際に「隠される」わけではありません(ページのソースを確認すると表示されます)
- スコープ付きセレクターの特異性は +0-1-0 — 同じ形のグローバルセレクターより常に高くなります
@keyframesの名前もスコープ化されます —style="animation: name"ではスコープ化された名前を見つけられません(-global-を使用してください){@html}の内容はスコープ化の影響を受けません — 挿入された HTML にはスコープクラスがありません- CSS 変数にスコープ化は不要です —
var(--custom)はそのままスコープとカスケードをまたいで使用できます svelte-css-wrapper要素 — 親から--varが渡されると挿入され、>子セレクターを壊します:globalは特異性を下げません — スコープからは外れますが、specificity からは外れません- ネストされた
<style>はグローバルです — Svelte コンパイラーを経由せず、そのまま DOM に挿入されます - コンパイラーが
animationを書き換えるのは同じ<style>ブロック内だけです — それ以外の場所では-global-が必要です <style>属性と JS 内のスコープ化された keyframe 名 — 書き換えられません
FAQ
Q: 子コンポーネントの内部にスタイルを適用するにはどうすればよいですか?
A: 方法は 2 つあります。① 親コンポーネントから CSS カスタムプロパティを渡す(推奨)。② :global を使う(グローバルに影響し、カプセル化が損なわれます)。
Q: Svelte のコンパイル後、class 名はどのようになりますか?
A: svelte-123xyz のようなハッシュで、コンポーネントごとに一意です。
Q: スコープ付きスタイルはグローバルスタイルより優先されますか?
A: はい。スコープ付きスタイルは特異性が +0-1-0 高くなります。同じ形のグローバルな p は、スコープ付きの p より優先度が低くなります。
Q: CSS 変数ではなく :global を使うのはどのような場合ですか?
A: 値を渡すのではなく、セレクター自体(位置や対象)を制御する必要がある場合に :global を使います。ほとんどの「値を渡す」場面では、CSS 変数のほうが適しています。
Q: class:[...] 配列内の falsy 値が文字列にならないのはなぜですか?
A: Svelte は clsx のルールに従い、false/null/undefined/""/0 を除外します。class={false} の場合にのみ class="false" になります(これは以前の動作で、5.16+ では配列形式の動作が変更されています)。
Q: ネストされた <style> 内のルールがグローバルなのはなぜですか?
A: ネストされた <style> は Svelte コンパイラーのスコープ処理を経ず、そのまま DOM に挿入されます。ブラウザーは通常の <style> と同じように解析します。
Q: スコープ付き keyframe を外部から実行できますか?
A: できません。スコープ付き keyframe 名はコンパイル時に書き換えられるため、外部から名前だけで参照することはできません。@keyframes -global-name を使ってください。
Q: style: ディレクティブと style="..." 属性を同時に使うとどうなりますか?
A: style: が優先されます。style="" で !important を使っていても同様です。これは Svelte 5 の設計です。
Q: bg-${color}-500 のようなテンプレート文字列で動的な Tailwind クラスを指定できますか?
A: 確実には動作しません。JIT ではクラス名全体を認識できないためです。検索テーブル({ red: 'bg-red-500', ... })または safelist を使ってください。
例
| ファイル | 説明 |
|---|---|
| examples/README.md | すべてのサンプルファイルを説明付きで一覧表示するエントリーポイント |
| examples/scoped-styles.md | スコープ付きスタイル、特異性、:where() のテクニック、スタイルが適用されない場合、コンパイル後の出力、svelte-css-wrapper |
| examples/scoped-keyframes.md | @keyframes のスコープ化、-global- プレフィックス、アニメーションの共有、JS からの実行、prefers-reduced-motion |
| examples/global-patterns.md | :global(...) の単一、複合、ネスト、ブロック形式、および CSS カスタムプロパティとの使い分け |
| examples/style-directive.md | style:property、style:--var、|important、式、複数のスタイル、値の型変換 |
| examples/nested-style.md | テンプレート内の生の <style> タグ、{#if}/{#each} のスタイルフラグメント、ライフサイクル、注意点 |
| examples/tailwind.md | Tailwind CSS、任意の値、カスタムプロパティによる動的なテーマ設定、safelist、twMerge |
リファレンス
| ファイル | 説明 |
|---|---|
| references/README.md | すべてのリファレンスファイルを説明付きで一覧表示するエントリーポイント |
| references/scoped-deep.md | スコープ化の仕組み、ハッシュ生成、:where() によるラップ、ネストされた <style>、エッジケースの詳細 |
| references/scoped-keyframes.md | スコープ付き keyframe、-global- プレフィックス、コンポーネント間での共有、書き換えルール |
| references/global-reference.md | カスケードと変換の例を含む、:global(...) の単一、ネスト、ブロック、複合形式の完全なリファレンス |
| references/specificity.md | 特異性の相互作用、:where() / :is() / :not()、上書きの方法、カスケード順序 |
| references/style-directive.md | すべての style: 形式、style:--var のシリアライズ、|important、値の型変換、優先順位 |
| references/css-custom-properties.md | CSS カスタムプロパティ:受け渡し、読み取り、カスケード、動的な更新 |
| references/class-directive.md | class と class: ディレクティブの違い、ClassValue 型、clsx のパターン |