JavaScriptなしで、transform / perspective / layered shadows と CSSカスタムプロパティ だけで
“パッ”と目を引く3Dカードを作成してみましょう。
さらに Shadow DOM 内でも同じ見た目を再現できるよう、::part() と変数で拡張可能にします。
ゴール(できあがりイメージ)
-
マウスホバーでわずかに傾く3D表現
-
斜めに流れるハイライト(きらめき)
-
ライト/ダークどちらでも映える配色
-
prefers-reduced-motion でアニメ控えめ
-
Shadow DOM対応:
::part()と CSS変数で外部からのテーマ変更OK
デモ:CSSとHTMLだけで作る3DカードUI
💡 マウスを乗せるとカードがわずかに傾き、立体的な効果が確認できます。
最小HTML(ライトDOM版)
コアCSS(ライトDOM版)
Shadow DOM に対応させる考え方
ポイントは 「パーツを切り出す」 と 「CSS変数でテーマ化」。
外側(ライトDOM)から Shadow DOM 内を直接スタイルできないため、コンポーネント作者がpartを付与し、利用者は::part()で装飾、色や半径は CSS変数で調整します。
Web Component 側(作者向け:影DOM内のテンプレ)
※ここでは概念を示すための HTMLスケッチ です。実際の ShadowRoot 作成は JS が必要ですが、スタイル設計の指針としてご覧ください。
利用者側(外部)からのテーマ上書き例
まとめ:
作者は Shadow DOM 内で CSS変数とpart名を定義
利用者は ホストへ変数指定し、必要なら
::part()でピンポイント調整
デザインバリエーション(クラス追加だけ)
アクセシビリティと実用Tips
-
ボタン/リンクのヒット領域は最低44×44pxを意識(
paddingで確保) -
prefers-reduced-motionに配慮(すでに対応) -
コントラスト:
oklchやcolor-mix()で暗所・明所どちらも読みやすく -
画像の
altを適切に -
フォールバック:古い環境では
oklchが未対応 → 代替色を上書き可能に
よく使うCSSカスタムプロパティ(外から上書きOK)
| 変数名 | 役割 | 例 |
|---|---|---|
| --card-bg | 背景色 | #fff / #111 |
| --card-fg | 文字色 | #111 / #eee |
| --card-accent | CTAなどの強調色 | oklch(0.78 0.17 30) |
| --card-radius | 角丸 | 12px / 20px |
| --card-shadow-1 | 影レイヤ(近) | 0 1px 2px rgba(0,0,0,.2) |
| --card-shadow-2 | 影レイヤ(遠) | 0 8px 24px rgba(0,0,0,.12) |
| --card-border | 境界線 | 1px solid rgba(0,0,0,.06) |
| --card-tilt | 傾き(通常) | rotateX(5deg) rotateY(-6deg) |
| --card-tilt-hover | 傾き(ホバー) | rotateX(6.5deg) rotateY(-10deg) |
| --card-gloss | ハイライト | linear-gradient(120deg, transparent 30%, rgba(255,255,255,.4) 45%, transparent 60%) |
| --card-gloss-size | ハイライトサイズ | 200% 200% |
トラブルシュート
-
立体感が弱い →
--card-tiltと影(--card-shadow-2)を強める -
グロスが強すぎる →
--card-glossの不透明度を上げる(=白を薄く) -
画面酔い →
prefers-reduced-motion環境で確認、もしくはカードに.is-outlineを付与 -
Shadow DOM で色が変わらない → 変数は ホスト(custom element)側に定義しているか確認
まとめ
| 項目 | ポイント |
|---|---|
| 3D表現 | transformとperspectiveで奥行きを演出 |
| 輝き | ::beforeのグラデとbackground-positionで流し込み |
| 配色 | oklchとcolor-mixでライト/ダーク両対応 |
| アクセシビリティ | prefers-reduced-motionと十分なヒット領域 |
| Shadow DOM | 作者はpart公開&変数化/利用者は::part()と変数上書き |
| 拡張 | クラス追加でelevated/glass/outlineを切替 |
