mcpField
M
modern-css

modern-css

github.com/caidanwデザイン・UI1161 回インストール11 週間前に更新
リポジトリ

modern-css について

CSSを作成・レビューする開発者向けのガイダンススキルです。ブラウザー対応状況や旧環境の要件を踏まえ、最新のネイティブCSS技術を提案します。

主な機能

  1. 01古い記述に代わる最新CSS技術
  2. 02ブラウザー対応状況に基づく技術分類
  3. 03フォールバックと段階的拡張の指針
  4. 04レイアウト、セレクター、色、タイポグラフィを網羅

活用シーン

  1. 01古いCSSパターンのリファクタリング
  2. 02新しいUIに使うCSS技術の選定
  3. 03新しいCSSの採用前に対応ブラウザーを確認

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/caidanw/skills --skill modern-css

インストール後、Claude Code で/modern-cssを入力して読み込まれたか確認します。

詳細

モダン CSS

CSS の仕様は大きく進化しました。絶対配置による中央揃え、padding-top を使ったアスペクト比、JavaScript のスクロールリスナー、Sass の色関数といった古いハックには、今ではすっきりとしたネイティブの代替手段があります。このスキルを使えば、常にモダンな手法を優先できます。

参考資料: modern-css.com — すべての手法はこのサイトを参考にしています。ライブデモや詳しい解説は、各ページをご覧ください。

サポートデータ: ブラウザーのサポート率は、caniuse.com による世界のユーザー利用率を示しており、最終更新日は2026 年 2 月です。ブラウザーのアップデートに伴い数値は変動するため、プロジェクトで正確さが重要な場合は、caniuse でご確認ください。

このスキルの使い方

CSS を記述またはレビューする際は、次のようにしてください。

  1. 広く利用可能な段階の手法(サポート率 90% 以上)は、確認せずに必ず使用してください。古いパターンを見つけた場合は、モダンな同等手法にリファクタリングしてください。
  2. 新たに利用可能な段階の手法(サポート率 80~90%)は、提案してください。新たに利用可能になったことを伝え、ユーザーに判断してもらいます。必要に応じてフォールバックも提示してください。
  3. 利用範囲が限られる手法(サポート率 80% 未満)を使う前には、必ず確認してください。ブラウザーのサポート状況について警告し、段階的な拡張方法やフォールバックを提案してください。
  4. ユーザーに古いブラウザーの要件(古い Safari、企業内ブラウザーなど)がある場合は、広く利用可能な手法であっても、使用前に確認してください。サポート率は最新のブラウザーを前提としているためです。フォールバックには @supports を使用してください。

既存のコードに古い CSS パターンがある場合は、それを指摘し、モダンな代替手段とその利点を簡潔に説明してください。


広く利用可能(サポート率 90% 以上) — 常に使用

これらの手法は十分に確立されており、すべてのモダンブラウザーで動作します。ためらわずに使用してください。

レイアウト
要素の中央揃え — place-items: center
/* OLD: absolute + transform hack (5 declarations, 2 selectors) */
.parent { position: relative; }
.child {
  position: absolute;
  top: 50%; left: 50%;
  transform: translate(-50%, -50%);
}

/* MODERN: grid centering (2 declarations, 1 selector) */
.parent {
  display: grid;
  place-items: center;
}

参考資料 →

要素間の間隔 — gap
/* OLD: margin hacks with :last-child override */
.grid > * { margin-right: 16px; }
.grid > *:last-child { margin-right: 0; }

/* MODERN: gap on the container */
.grid {
  display: flex;
  gap: 16px;
}

参考資料 →

アスペクト比 — aspect-ratio
/* OLD: padding-top percentage hack */
.wrapper { padding-top: 56.25%; position: relative; }
.inner { position: absolute; inset: 0; }

/* MODERN: aspect-ratio property */
.video-wrapper {
  aspect-ratio: 16 / 9;
}

参考資料 →

位置指定の短縮形 — inset
/* OLD: four separate properties */
.overlay { top: 0; right: 0; bottom: 0; left: 0; }

/* MODERN: inset shorthand */
.overlay {
  position: absolute;
  inset: 0;
}

参考資料 →

スティッキーヘッダー — position: sticky
/* OLD: JS scroll listener + getBoundingClientRect */
// add/remove .fixed class based on scroll position

/* MODERN: sticky positioning */
.header {
  position: sticky;
  top: 0;
}

参考資料 →

レスポンシブ画像 — object-fit
/* OLD: background-image with background-size */
.card-image {
  background-image: url(...);
  background-size: cover;
  background-position: center;
}

/* MODERN: object-fit on an img element */
img {
  object-fit: cover;
  width: 100%;
  height: 200px;
}

参考資料 →

利用可能なスペースを埋める — stretch
/* OLD: calc workaround */
.full { width: calc(100% - 40px); }

/* MODERN: stretch keyword */
.full { width: stretch; }
/* fills container, respects margins */

参考資料 →

スクロールチェーンの防止 — overscroll-behavior
/* OLD: JS wheel event preventDefault */
// modal.addEventListener('wheel', e => e.preventDefault(), { passive: false })

/* MODERN: overscroll-behavior */
.modal-content {
  overflow-y: auto;
  overscroll-behavior: contain;
}

参考資料 →

スクロールバーによるレイアウトシフトの防止 — scrollbar-gutter
/* OLD: force scrollbar or hardcode padding */
body { overflow-y: scroll; }

/* MODERN: reserve scrollbar space */
body { scrollbar-gutter: stable; }

参考資料 →

グリッドテンプレート領域 — 名前付き領域
/* OLD: grid line numbers or floats */
.item { grid-column: 1 / 3; grid-row: 2; }

/* MODERN: named grid areas */
.layout {
  display: grid;
  grid-template-areas:
    "header header"
    "sidebar main"
    "footer footer";
}
.header { grid-area: header; }

参考資料 →

モーダルダイアログ — <dialog> 要素
/* OLD: fixed overlay + JS open/close/ESC/focus-trap */
.overlay { position: fixed; z-index: 999; }

/* MODERN: native dialog with ::backdrop */
dialog { padding: 1rem; }
dialog::backdrop { background: rgb(0 0 0 / .5); }
/* JS: dialog.showModal() / dialog.close() */

参考資料 →

方向に応じたレイアウト — 論理プロパティ
/* OLD: physical properties + RTL overrides */
margin-left: 1rem;
padding-right: 1rem;
[dir="rtl"] .box { margin-right: 1rem; }

/* MODERN: logical properties */
margin-inline-start: 1rem;
padding-inline-end: 1rem;
border-block-start: 1px solid;

参考資料 →

レスポンシブコンポーネント — @container
/* OLD: viewport-based media queries */
@media (min-width: 768px) {
  .card { grid-template-columns: auto 1fr; }
}

/* MODERN: container queries */
.wrapper { container-type: inline-size; }
@container (width > 400px) {
  .card { grid-template-columns: auto 1fr; }
}

参考資料 →

スクロールスナップ — scroll-snap
/* OLD: Slick/Swiper carousel or touch handlers */
// $('.carousel').slick({ ... })

/* MODERN: CSS scroll snap */
.carousel {
  scroll-snap-type: x mandatory;
  overflow-x: auto;
}
.carousel > * { scroll-snap-align: start; }

参考資料 →

セレクター
親要素の選択 — :has()
/* OLD: JavaScript el.closest('.parent').classList.add(...) */

/* MODERN: :has() parent selector */
.card:has(img) {
  grid-template-rows: auto 1fr;
}

参考資料 →

グループ化セレクター — :is()
/* OLD: repeat the full selector for each match */
.card h1, .card h2, .card h3, .card h4 { margin-bottom: 0.5em; }

/* MODERN: :is() grouping */
.card :is(h1, h2, h3, h4) { margin-bottom: 0.5em; }

リファレンス →

詳細度の低いリセット — :where()
/* OLD: class-based resets with specificity issues */
.reset ul, .reset ol { margin: 0; }

/* MODERN: :where() has zero specificity */
:where(ul, ol) {
  margin: 0;
  padding-inline-start: 1.5rem;
}

リファレンス →

キーボード操作時のみのフォーカス — :focus-visible
/* OLD: :focus fires on mouse click too, so people remove outlines (a11y fail) */
:focus { outline: 2px solid blue; }

/* MODERN: :focus-visible only shows for keyboard navigation */
:focus-visible {
  outline: 2px solid var(--focus-color);
}

リファレンス →

色
フォームコントロールのスタイリング — accent-color
/* OLD: appearance: none + rebuild the entire control */
input[type="checkbox"] { appearance: none; /* 20+ lines of custom styles */ }

/* MODERN: accent-color */
input[type="checkbox"],
input[type="radio"] {
  accent-color: #7c3aed;
}

リファレンス →

知覚的に均一な色 — oklch()
/* OLD: hex/rgb with guess-and-check for each shade */
--brand: #4f46e5;
--brand-light: #818cf8;
--brand-dark: #3730a3;

/* MODERN: oklch — adjust lightness, keep perceived hue */
--brand: oklch(0.55 0.2 264);
--brand-light: oklch(0.75 0.2 264);
--brand-dark: oklch(0.35 0.2 264);

リファレンス →

広色域カラー — display-p3 / oklch
/* OLD: sRGB only — washed out on P3 displays */
.hero { color: rgb(200, 80, 50); }

/* MODERN: oklch or display-p3 for vivid colors */
.hero { color: oklch(0.7 0.25 29); }
/* or: color(display-p3 1 0.2 0.1) */

リファレンス →

すりガラス効果 — backdrop-filter
/* OLD: pseudo-element with blurred background image */
.card::before { content: ''; background-image: url(bg.jpg); filter: blur(12px); z-index: -1; }

/* MODERN: backdrop-filter */
.glass {
  backdrop-filter: blur(12px);
  background: rgba(255, 255, 255, .1);
}

リファレンス →

タイポグラフィ
可変タイポグラフィ — clamp()
/* OLD: multiple media queries for each breakpoint */
h1 { font-size: 1rem; }
@media (min-width: 600px) { h1 { font-size: 1.5rem; } }
@media (min-width: 900px) { h1 { font-size: 2rem; } }

/* MODERN: clamp for fluid scaling */
h1 { font-size: clamp(1rem, 2.5vw, 2rem); }

リファレンス →

複数行テキストの切り詰め — line-clamp
/* OLD: JS to slice text by chars/words and add "..." */

/* MODERN: line-clamp */
.card-title {
  display: -webkit-box;
  -webkit-line-clamp: 3;
  line-clamp: 3;
}

リファレンス →

ドロップキャップ — initial-letter
/* OLD: float hack with manual line-height */
.drop-cap::first-letter { float: left; font-size: 3em; line-height: 1; }

/* MODERN: initial-letter */
.drop-cap::first-letter { initial-letter: 3; }

リファレンス →

フォントの読み込み — font-display: swap
/* OLD: invisible text until font loads (FOIT) */
@font-face { font-family: "MyFont"; src: url(...); }

/* MODERN: font-display swap shows fallback immediately */
@font-face {
  font-family: "MyFont";
  src: url("MyFont.woff2");
  font-display: swap;
}

リファレンス →

可変フォント — すべてのウェイトを1つのファイルに
/* OLD: separate @font-face for each weight */
@font-face { font-weight: 400; src: url("Regular.woff2"); }
@font-face { font-weight: 700; src: url("Bold.woff2"); }

/* MODERN: one variable font file */
@font-face {
  font-family: "MyVar";
  src: url("MyVar.woff2");
  font-weight: 100 900;
}

リファレンス →

アニメーション
独立したトランスフォーム
/* OLD: rewrite entire transform shorthand to change one value */
.icon { transform: translateX(10px) rotate(45deg) scale(1.2); }

/* MODERN: individual transform properties */
.icon {
  translate: 10px 0;
  rotate: 45deg;
  scale: 1.2;
}
/* animate any one without touching the rest */

リファレンス →

型付きカスタムプロパティ — @property
/* OLD: custom properties are strings, can't animate */
:root { --hue: 0; }
.wheel { transition: --hue .3s; } /* ignored */

/* MODERN: @property makes them animatable */
@property --hue {
  syntax: "<angle>";
  inherits: false;
  initial-value: 0deg;
}
.wheel {
  background: hsl(var(--hue), 80%, 50%);
  transition: --hue .3s;
}

リファレンス →

レスポンシブなクリップパス — shape()
/* OLD: clip-path: path() uses fixed px coordinates */
.shape { clip-path: path('M0 200 L100 0...'); }

/* MODERN: shape() uses responsive units */
.shape { clip-path: shape(from 0% 100%, ...); }

リファレンス →

ワークフロー
CSSネスティング — プリプロセッサー不要
/* OLD: requires Sass/Less compiler */
// .nav { & a { color: #888; } }

/* MODERN: native CSS nesting */
.nav {
  & a { color: #888; }
}
/* plain .css file, no build step */

リファレンス →

カスケードレイヤー — @layer
/* OLD: specificity wars and !important */
.page .card .title.special { color: red !important; }

/* MODERN: cascade layers control order */
@layer base, components, utilities;
@layer utilities {
  .mt-4 { margin-top: 1rem; }
}

リファレンス →

テーマ変数 — カスタムプロパティ
/* OLD: Sass variables compile to static values */
$primary: #7c3aed;
.btn { background: $primary; }

/* MODERN: CSS custom properties update at runtime */
:root { --primary: #7c3aed; }
.btn { background: var(--primary); }

リファレンス →

ダークモードのデフォルト — color-scheme
/* OLD: manually restyle every form control for dark mode */
@media (prefers-color-scheme: dark) { input, select, textarea { ... } }

/* MODERN: color-scheme tells the browser to handle it */
:root { color-scheme: light dark; }

リファレンス →

遅延レンダリング — content-visibility
/* OLD: IntersectionObserver to defer rendering */
// new IntersectionObserver((entries) => { /* render */ }).observe(el)

/* MODERN: content-visibility auto */
.section {
  content-visibility: auto;
  contain-intrinsic-size: auto 500px;
}

リファレンス →


新たに利用可能(サポート率80~90%)— ユーザーに提案

これらの手法は、主要なブラウザーで新たに利用可能になりました。ユーザーに提案し、 サポート率を伝え、必要に応じて代替策を提示してください。

レイアウト
ドロップダウンメニュー — [popover](86%)
/* OLD: display:none + JS toggle + click-outside + ESC */
.menu { display: none; }
.menu.open { display: block; }

/* MODERN: popover attribute */
/* <button popovertarget="menu">Toggle</button> */
/* <div id="menu" popover>...</div> */
#menu[popover] { position: absolute; }

リファレンス →

サブグリッド — ネストされたグリッドを親のトラックに揃える(88%)
/* OLD: duplicate parent track definitions in child */
.child-grid { grid-template-columns: 1fr 1fr 1fr; }

/* MODERN: subgrid inherits parent tracks */
.child-grid {
  display: grid;
  grid-template-columns: subgrid;
}

リファレンス →

カスタマイズ可能なセレクト — appearance: base-select(86%)
/* OLD: Select2 or Choices.js replacing native select */

/* MODERN: base-select unlocks full styling */
select, select ::picker(select) {
  appearance: base-select;
}

注:サポートは急速に拡大しています。現在の状況は caniuseで確認してください。 リファレンス →

ホバー時のツールチップ — popover=hint + interestfor(86%)



<button interestfor="tip">Hover me</button>
<div id="tip" popover=hint>Tooltip content</div>

リファレンス →

アニメーション
登場時のアニメーション — @starting-style(85%)
/* OLD: requestAnimationFrame to add class after paint */
// requestAnimationFrame(() => el.classList.add('visible'))

/* MODERN: @starting-style defines entry state */
.card {
  transition: opacity .3s, transform .3s;
  @starting-style {
    opacity: 0;
    transform: translateY(10px);
  }
}

リファレンス →

display: none のアニメーション — transition-behavior: allow-discrete(85%)
/* OLD: wait for transitionend, use visibility + opacity + pointer-events */

/* MODERN: allow-discrete enables display transitions */
.panel {
  transition: opacity .2s, display .2s;
  transition-behavior: allow-discrete;
}
.panel.hidden { opacity: 0; display: none; }

リファレンス →

ページ遷移 — View Transitions API(89%)
/* OLD: Barba.js or React Transition Group */

/* MODERN: View Transitions API */
/* JS: document.startViewTransition(() => updateDOM()); */
.hero { view-transition-name: hero; }
/* Style with ::view-transition-old(hero) / ::view-transition-new(hero) */

リファレンス →

色
色の混合 — color-mix()(89%)
/* OLD: Sass mix($blue, $pink, 60%) */

/* MODERN: color-mix in CSS */
background: color-mix(in oklch, #3b82f6, #ec4899);

リファレンス →

色のバリエーション — 相対色構文(87%)
/* OLD: Sass lighten($brand, 20%) — compile-time only */

/* MODERN: relative color syntax — runtime */
.btn {
  background: oklch(from var(--brand) calc(l + 0.2) c h);
}
/* change --brand and all derivatives update */

リファレンス →

ダークモードの色 — light-dark()(83%)
/* OLD: duplicate values in prefers-color-scheme media query */
@media (prefers-color-scheme: dark) { color: #eee; }

/* MODERN: light-dark() function */
color: light-dark(#111, #eee);
color-scheme: light dark;

リファレンス →

セレクター
フォームの検証 — :user-invalid / :user-valid(85%)
/* OLD: JS blur listener to add .touched class */
// el.addEventListener('blur', () => el.classList.add('touched'))

/* MODERN: :user-invalid only fires after interaction */
input:user-invalid { border-color: red; }
input:user-valid { border-color: green; }

リファレンス →

ワークフロー
スコープ付きスタイル — @scope(84%)
/* OLD: BEM naming (.card__title) or CSS Modules */

/* MODERN: @scope limits selectors to a root */
@scope (.card) {
  .title { font-size: 1.25rem; }
  .body { color: #444; }
}
/* .title only matches inside .card */

リファレンス →

範囲スタイルクエリ(88%)
/* OLD: multiple style() blocks for each value */
@container style(--p: 51%) {}
@container style(--p: 52%) {}

/* MODERN: range comparisons */
@container style(--progress > 50%) {
  .bar { ... }
}

リファレンス →

タイポグラフィ
バランスの取れた見出し — text-wrap: balance(87%)
/* OLD: manual <br> tags or Balance-Text.js */

/* MODERN: text-wrap balance */
h1, h2 { text-wrap: balance; }

リファレンス →


対応が限定的(サポート率80%未満)— 使用前に確認してください

これらは最先端のCSS機能です。使用する前に必ずユーザーに確認し、ブラウザーのサポート状況について警告したうえで、フォールバックまたはプログレッシブエンハンスメントの方法を提案してください。

レイアウト
モーダルの制御 — commandfor(72%)

<button onclick="document.querySelector('#dlg').showModal()">Open</button>


<button commandfor="dlg" command="show-modal">Open</button>
<dialog id="dlg">...</dialog>

フォールバック:小さなJS onclickハンドラーを使ってdialog.showModal()を呼び出します。 リファレンス →

ダイアログのライトディスミス — closedby="any"(72%)



<dialog closedby="any">Click outside to close</dialog>

フォールバック:::backdropにクリックリスナーを追加してdialog.close()を呼び出します。 リファレンス →

アンカー配置 — position-anchor + anchor()(77%)
/* OLD: Popper.js / Floating UI for tooltip positioning */

/* MODERN: CSS anchor positioning */
.trigger { anchor-name: --tip; }
.tooltip {
  position-anchor: --tip;
  top: anchor(bottom);
}

フォールバック:Floating UIを使うか、JSによる絶対配置を使用します。 リファレンス →

カルーセルの制御 — ::scroll-button / ::scroll-marker(72%)
/* OLD: Swiper.js or Slick carousel */

/* MODERN: native scroll markers and buttons */
.carousel::scroll-button(right) { content: "→"; }
.carousel li::scroll-marker { content: ''; }

フォールバック:CSSのスクロールスナップと、JSで実装したカスタムボタンを使用します。 リファレンス →

コーナー形状 — corner-shape: squircle(67%)
/* OLD: clip-path polygon with 20+ points */

/* MODERN: corner-shape property */
.card {
  border-radius: 2em;
  corner-shape: squircle;
}

フォールバック:標準のborder-radiusまたはSVGのclip-pathを使用します。 リファレンス →

アニメーション
スクロール駆動アニメーション — animation-timeline: view()(78%)
/* OLD: IntersectionObserver + GSAP or AOS.js */

/* MODERN: CSS scroll-driven animations */
@keyframes reveal {
  from { opacity: 0; translate: 0 40px; }
  to   { opacity: 1; translate: 0 0; }
}
.reveal {
  animation: reveal linear both;
  animation-timeline: view();
  animation-range: entry 0% entry 100%;
}

フォールバック:IntersectionObserverを使い、.visibleクラスを切り替えます。 ポリフィル:scroll-timeline リファレンス →

高さの自動アニメーション — interpolate-size: allow-keywords(69%)
/* OLD: JS to measure scrollHeight, set px, then transition */

/* MODERN: interpolate-size enables height:auto transitions */
:root { interpolate-size: allow-keywords; }
.accordion { height: 0; overflow: hidden; transition: height .3s ease; }
.accordion.open { height: auto; }

フォールバック:大きな値を使ったmax-heightか、JSによる計測を使用します。 リファレンス →

スタッガードアニメーション — sibling-index()(72%)
/* OLD: nth-child custom property for each item */
li:nth-child(1) { --i: 0; }
li:nth-child(2) { --i: 1; }

/* MODERN: sibling-index() function */
li {
  transition-delay: calc(0.1s * (sibling-index() - 1));
}

フォールバック:CSSカスタムプロパティとnth-childを使用します。 リファレンス →

スティッキー/スナップ要素のスタイル — スクロール状態コンテナクエリ(50%)
/* OLD: JS scroll listener checking element position */

/* MODERN: @container scroll-state() */
@container scroll-state(stuck: top) {
  .header { box-shadow: 0 2px 8px rgb(0 0 0 / .1); }
}

フォールバック:IntersectionObserverを使ってクラスを切り替えます。 リファレンス →

タイポグラフィ
テキストの垂直方向の中央揃え — text-box(79%)
/* OLD: uneven padding hacks for optical centering */
.btn { padding: 10px 20px; padding-top: 8px; /* hack */ }

/* MODERN: text-box trims leading/trailing space */
h1, button {
  text-box: trim-both cap alphabetic;
}

フォールバック:手動でパディングを調整します。 リファレンス →

自動で拡張するテキストエリア — field-sizing: content(73%)
/* OLD: JS input listener resizing on every keystroke */

/* MODERN: field-sizing */
textarea {
  field-sizing: content;
  min-height: 3lh;
}

フォールバック:JSの自動リサイズハンドラーを使用します。 リファレンス →

セレクター
スクロールスパイ — :target-current(48%)
/* OLD: IntersectionObserver with 15+ lines of JS */

/* MODERN: :target-current pseudo-class */
nav a:target-current {
  color: var(--accent);
}

代替策:IntersectionObserver を使って .active クラスを切り替えます。 参考 →

ワークフロー
CSS 関数 — @function(67%)
/* OLD: Sass @function */
// @function fluid($min, $max) { @return clamp(...); }

/* MODERN: native CSS @function */
@function --fluid(--min, --max) {
  @return clamp(...);
}

代替策:Sass 関数または繰り返しの clamp() 式を使います。 参考 →

型付き属性値 — 型を指定した attr()(42%)
/* OLD: JS reading dataset to set styles */
// el.style.width = el.dataset.pct + '%';

/* MODERN: attr() with type() */
.bar { width: attr(data-pct type(<percentage>)); }

代替策:JS でデータ属性を読み取り、インラインスタイルを設定します。 参考 →

インライン条件分岐 — if()(35%)
/* OLD: JS classList toggle */
// el.classList.toggle('primary', isPrimary)

/* MODERN: CSS if() function */
.btn {
  background: if(style(--variant: primary): blue; else: gray);
}

代替策:クラスの切り替えと CSS カスタムプロパティを使います。 参考 →


基本原則

CSS を記述する際は、次の基本原則に従ってください。

  1. JavaScript よりネイティブ CSS — CSS で実現できるなら、JS は使いません。カルーセルライブラリよりスクロールスナップ、切り替えスクリプトよりポップオーバー、モーダルライブラリよりダイアログを使います。
  2. 物理プロパティより論理プロパティ — left/right/top/bottom の代わりに inline/block を使います。どの書字方向でもレイアウトが機能します。
  3. 固定ブレークポイントより内在サイズ — clamp()、min()、max()、コンテナクエリ、flex/grid の自動サイズ調整を使います。コンテンツにレイアウトを決めさせます。
  4. プリプロセッサ変数よりカスタムプロパティ — CSS カスタムプロパティは実行時に更新でき、JS と連携し、カスケードします。Sass 変数はコンパイル時に消去されます。
  5. 詳細度ハックよりカスケードレイヤー — @layer を使ってカスケードを整理します。詳細度の競争に勝つために !important や深いネストを使うのはやめましょう。
  6. 段階的な機能強化 — モダンな機能は代替策とともに使います。@supports を使って、利用可能になったばかりの機能や利用が限定されている機能を、対応状況の確認を通じて有効にします。
    /* fallback for older browsers */
    .card { display: flex; flex-wrap: wrap; }
    
    /* modern upgrade */
    @supports (container-type: inline-size) {
      .wrapper { container-type: inline-size; }
      @container (width > 400px) { .card { flex-direction: row; } }
    }
    

すぐに使える選択ガイド

したいこと...これを使います
要素を中央に配置するdisplay: grid; place-items: center
子要素を均等に配置するflex/grid の gap
アスペクト比を維持するaspect-ratio: 16 / 9
スクロール時にヘッダーを固定するposition: sticky; top: 0
レスポンシブなコンポーネントを作る@container クエリ
モーダルを作る<dialog> 要素
ドロップダウンを作る[popover] 属性 🟡
子要素に基づいて親要素を選択する:has() セレクター
キーボードフォーカス時のみスタイルを設定する:focus-visible
流動的なフォントサイズを設定するclamp(min, preferred, max)
複数行のテキストを省略するline-clamp: N
見出しの折り返しを整えるtext-wrap: balance 🟡
スクロールに合わせてアニメーションするanimation-timeline: view() ⚠️
ページ遷移を実装するView Transitions API 🟡
表示時にアニメーションさせる@starting-style 🟡
1 色からカラーパレットを作る明度を調整した oklch()
2 色を混ぜるcolor-mix(in oklch, ...) 🟡
ダークモードの色を設定するlight-dark() + color-scheme 🟡
スタイルをコンポーネントにスコープする@scope (.component) 🟡
カスケードの順序を制御する@layer
セレクターをネストするネイティブ CSS ネスト & selector
カスタムプロパティに型を設定する@property
ツールチップを配置するCSS アンカーポジショニング ⚠️

マーカーなし = 広く利用可能(90% 以上、常に使用できます)。 🟡 = 新たに利用可能(80~90%、ユーザーに提案してください)。⚠️ = 利用が限定的(80% 未満、事前に確認してください)。

コメント