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を切替 |