Skip to content

CSS チートシート

Web ページのプレゼンテーションを記述するためのスタイルシート言語。

01

セレクタ

基本セレクタ

CSS セレクタはスタイリングのために HTML 要素をターゲットにします。タイプセレクタは要素名(p、div)にマッチします。クラスセレクタ(.)は class 属性にマッチし再利用可能です。ID セレクタ(#)は単一要素にマッチし一意であるべきです。ユニバーサルセレクタ(*)はすべてにマッチします。カンマでグループ化してスタイルを共有します。

css
/* Type selector - all <p> elements */
p { color: #333; }

/* Class selector - elements with class="btn" */
.btn { padding: 8px 16px; }

/* ID selector - element with id="header" */
#header { background: #fff; }

/* Universal selector - all elements */
* { box-sizing: border-box; }

/* Grouping selector */
h1, h2, h3 { font-family: Arial, sans-serif; }

コンビネータ

コンビネータは要素間の関係を定義します。子孫(スペース)はネストされた任意の要素にマッチします。子(>)は直接の子のみにマッチします。隣接兄弟(+)は直後の要素にマッチします。一般兄弟(~)は後のすべての兄弟にマッチします。コンビネータの理解は余分なクラスなしの精密なスタイリングに不可欠です。

css
/* Descendant - any <a> inside .nav */
.nav a { text-decoration: none; }

/* Child - direct <li> children of <ul> */
ul > li { list-style: none; }

/* Adjacent sibling - <p> right after <h1> */
h1 + p { font-size: 1.2em; }

/* General sibling - all <p> after <h1> */
h1 ~ p { color: gray; }

属性セレクタ

属性セレクタは属性値に基づいて要素にマッチします。[attr] は存在にマッチします。[attr=val] は完全一致にマッチします。^= は接頭辞、$= は接尾辞、*= は部分文字列にマッチします。これらはフォーム入力、タイプ別リンク、data 属性を持つ要素を余分なクラスなしでスタイリングするのに強力です。

css
/* Elements with type attribute */
[type] { border: 1px solid #ccc; }

/* Exact match */
[type="text"] { padding: 4px; }

/* Starts with */
a[href^="https"] { color: green; }

/* Ends with */
a[href$=".pdf"] { color: red; }

/* Contains */
a[href*="example"] { font-weight: bold; }

疑似クラス

疑似クラスは状態や位置に基づいて要素を選択します。インタラクティブ::hover、:focus、:active、:visited、:disabled。構造的::first-child、:last-child、:nth-child(n)、:nth-of-type(n)。:not() はセレクタを否定します。:nth-child(odd/even) はゼブラストライプを作成します。:nth-child(3n) は 3 番目ごとの要素を選択します。これらは余分なクラスの必要性を減らします。

css
/* Interactive states */
a:hover { color: red; }
a:visited { color: purple; }
input:focus { border-color: blue; }
input:disabled { background: #eee; }
button:active { transform: scale(0.98); }

/* Structural */
li:first-child { font-weight: bold; }
li:last-child { border: none; }
li:nth-child(odd) { background: #f9f9f9; }
li:nth-child(3n) { color: blue; }
p:not(.highlight) { color: #333; }

疑似要素

疑似要素(::ダブルコロン)は要素の特定部分をスタイルします。::before と ::after は生成コンテンツを挿入します(content プロパティが必要)。::first-letter と ::first-line はテキスト部分をスタイルします。::selection はハイライトされたテキストをスタイルします。::placeholder は入力プレースホルダーをスタイルします。注意:::before/::after はデフォルトでインラインです — ブロック動作には display:block を設定してください。

css
/* First line of a paragraph */
p::first-line { font-weight: bold; }

/* First letter (drop cap) */
p::first-letter { font-size: 3em; float: left; }

/* Insert content before/after */
.quote::before { content: "\201C"; }
.quote::after { content: "\201D"; }

/* Selection styling */
::selection { background: yellow; color: black; }

/* Placeholder styling */
input::placeholder { color: #999; }

詳細度と !important

詳細度はセレクタが競合する時にどのルールが適用されるかを決定します。インラインスタイル > ID > クラス > タイプ。詳細度が同点の場合、最後のルールが勝ちます。!important はすべてを上書きしますがカスケードを壊します — 避けてください。DevTools で詳細度を調査します。メンテナンス性のためクラスベースのセレクタを優先します。クラスの繰り返し(.btn.btn)で詳細度を上げるのはハックです — 避けてください。

css
/* Specificity hierarchy (low to high):
   1. Type selectors (p, div)         = 0,0,0,1
   2. Class selectors (.btn)          = 0,0,1,0
   3. ID selectors (#header)          = 0,1,0,0
   4. Inline styles (style="...")     = 1,0,0,0
   5. !important                      = overrides all
*/

/* ID beats class */
#nav .link { color: red; }   /* wins */
.nav .link { color: blue; }

/* Avoid !important unless necessary */
.critical { color: red !important; }
02

ボックスモデル

Margin と Padding

すべての要素はコンテンツ、パディング、ボーダー、マージンを持つボックスです。パディングはボーダーの内側(背景に影響)、マージンは外側(透明)です。ショートハンド:1 値 = 全辺、2 値 = 上下 左右、3 = 上 左右 下、4 = 上 右 下 左(時計回り)。margin: 0 auto は定義された幅を持つブロック要素を中央揃えします。

css
.box {
  /* TRBL: top right bottom left */
  margin: 10px 20px 10px 20px;

  /* Shorthand: top/bottom  left/right */
  margin: 10px 20px;

  /* All sides */
  padding: 15px;

  /* Individual sides */
  margin-top: 0;
  padding-left: 24px;

  /* Center horizontally (block) */
  margin: 0 auto;
}

Border と Outline

border はパディングの周りに線を追加しレイアウトに影響します。outline はレイアウトに影響せずボーダーの外側に描画します — フォーカスインジケータに便利です。border-radius は角を丸めます(単一値またはコーナーごと:左上 右上 右下 左下)。outline-offset はボーダーとアウトライン間にスペースを追加します。アクセシビリティのために常に可視のフォーカススタイルを提供してください。

css
.box {
  /* Shorthand: width style color */
  border: 2px solid #333;

  /* Individual sides */
  border-bottom: 3px dashed red;
  border-radius: 8px;

  /* Outline (doesn't affect layout) */
  outline: 2px solid blue;
  outline-offset: 4px;
}

/* Remove default focus, add custom */
button:focus {
  outline: none;
  box-shadow: 0 0 0 3px rgba(0,123,255,0.5);
}

Box Sizing

box-sizing: content-box(デフォルト)は width/height がコンテンツのみに適用されることを意味します — パディングとボーダーが合計サイズに追加されます。box-sizing: border-box はパディングとボーダーを width/height に含め、サイジングを予測可能にします。一貫したレイアウトのために常にグローバルに border-box を設定してください。これは最も重要な CSS リセットの一つです。

css
/* Default: width = content only */
.content-box {
  box-sizing: content-box;
  width: 200px;
  padding: 20px;
  border: 5px solid;
  /* Total width: 200 + 40 + 10 = 250px */
}

/* Recommended: width includes padding+border */
.border-box {
  box-sizing: border-box;
  width: 200px;
  padding: 20px;
  border: 5px solid;
  /* Total width: 200px */
}

/* Apply globally */
*, *::before, *::after {
  box-sizing: border-box;
}

Box Shadow

box-shadow はシャドウ効果を追加します:offset-x offset-y blur-radius spread-radius color。正のオフセットはシャドウを右/下に移動します。inset は内側のシャドウを作成します。複数のシャドウはレイヤー化されます(最初 = 最前面)。自然にブレンドする半透明シャドウには rgba を使用します。シャドウは奥行きに最適ですが過度の使用はパフォーマンスを損ないます — 控えめなシャドウを優先してください。

css
/* offset-x offset-y blur spread color */
.card {
  box-shadow: 0 2px 8px rgba(0,0,0,0.1);
}

/* Multiple shadows */
.button {
  box-shadow:
    0 1px 2px rgba(0,0,0,0.1),
    0 4px 8px rgba(0,0,0,0.05);
}

/* Inset shadow */
.input:focus {
  box-shadow: inset 0 1px 3px rgba(0,0,0,0.1);
}

/* No shadow */
.no-shadow { box-shadow: none; }

Display と Visibility

display: none は要素をレイアウトから完全に削除します(スペースなし)。visibility: hidden は非表示にしますがスペースを保持します。opacity: 0 は透明にしますがインタラクティブのままです。block 要素は全幅を取り改行します。inline 要素はテキストに流れます。inline-block はインラインフローとブロック寸法(width、height)を組み合わせます。コンテンツのトグルには display: none を使用します。

css
/* Display types */
div { display: block; }           /* full width, line break */
span { display: inline; }         /* content width, no break */
.inline-block { display: inline-block; } /* inline but block props */
.flex { display: flex; }          /* flex container */
.grid { display: grid; }          /* grid container */
.none { display: none; }          /* removed from layout */

/* Visibility (keeps space) */
.hidden { visibility: hidden; }

/* Opacity (keeps space, can interact) */
.fade { opacity: 0; }
03

色と単位

カラーフォーマット

CSS は複数のカラーフォーマットをサポートします。Hex(#rrggbb)が最も一般的です。RGB/RGBA はアルファ透明度を追加します。HSL(色相 0-360、彩度%、輝度%)は直感的です — 色相を変えて色をシフトし、輝度でシェードを作ります。currentColor は要素の color プロパティを継承します。現代の CSS はより広い色域の oklch() と color() もサポートします。透明度には rgba/hsla を使用します。

css
/* Named colors */
.color { color: red; background: tomato; }

/* Hexadecimal */
.hex { color: #ff6600; }        /* 6-digit */
.hex-short { color: #f60; }     /* 3-digit shorthand */

/* RGB / RGBA */
.rgb { color: rgb(255, 102, 0); }
.rgba { background: rgba(0, 0, 0, 0.5); }

/* HSL / HSLA (hue, saturation, lightness) */
.hsl { color: hsl(20, 100%, 50%); }
.hsla { background: hsla(120, 100%, 50%, 0.3); }

/* Current color keyword */
.box { color: blue; border: 2px solid currentColor; }

長さの単位

px は絶対的で予測可能です。em は親の font-size に相対します(ネスト時に累積)。rem はルート(html)の font-size に相対です — 一貫性がありアクセシビリティに推奨されます。% は親に相対します。vh/vw はビューポートに相対です(100vh = フル高さ)。フォントサイズには rem、レイアウトには %、ボーダー/細かい詳細には px を使用します。

css
/* Absolute units */
.px { font-size: 16px; }     /* 1px = 1/96 inch */
.pt { font-size: 12pt; }     /* 1pt = 1/72 inch */

/* Relative to parent font-size */
.em { font-size: 1.5em; }    /* 1.5x parent */

/* Relative to root font-size (html) */
.rem { font-size: 1.2rem; }  /* 1.2x root (usually 16px) */

/* Relative to parent dimensions */
.pct { width: 50%; }         /* 50% of parent */

/* Viewport units */
.vh { height: 100vh; }       /* 100% of viewport height */
.vw { width: 50vw; }         /* 50% of viewport width */
.vmin { font-size: 2vmin; }  /* 2% of smaller dimension */

CSS 関数

calc() は混合単位で計算します(例:100% - 250px)。min() は最小値を選びます(レスポンシブ max-width に最適)。max() は最大値を選びます。clamp(min, preferred, max) は範囲間でスケールする流体値を作成します — レスポンシブタイポグラフィに完璧です。var() はオプションのフォールバック付きでカスタムプロパティを参照します。これらの関数によりメディアクエリなしで CSS が動的になります。

css
/* calc() - mathematical calculations */
.sidebar { width: calc(100% - 250px); }
.gap { margin: calc(1rem + 10px); }

/* min() / max() - choose smaller/larger */
.responsive { width: min(90%, 1200px); }
.min-width { width: max(300px, 50%); }

/* clamp() - fluid sizing with bounds */
.title { font-size: clamp(1.5rem, 4vw, 3rem); }

/* var() - use custom properties */
.btn { color: var(--primary, #007bff); }

グラデーション

グラデーションは滑らかな色の遷移を作成します。linear-gradient(direction, color1, color2) は方向に進みます(to right、45deg)。radial-gradient は中心点から広がります。conic-gradient は中心の周りを回転します。位置付きのカラーストップを追加できます:linear-gradient(to right, red 0%, blue 50%, green 100%)。グラデーションは色ではなく画像であり、background-image が受け入れられる場所ならどこでも使用できます。

css
/* Linear gradient */
.bg1 {
  background: linear-gradient(to right, #ff0000, #0000ff);
}

/* Diagonal with angle */
.bg2 {
  background: linear-gradient(45deg, #ff0000, #00ff00, #0000ff);
}

/* Radial gradient */
.bg3 {
  background: radial-gradient(circle, #ff0000, #0000ff);
}

/* Conic gradient */
.bg4 {
  background: conic-gradient(red, yellow, green, blue, red);
}

フィルターとブレンドモード

filter は視覚効果を適用します:blur()、brightness()、contrast()、grayscale()、sepia()、hue-rotate()、invert()、opacity()、saturate()。複数のフィルターが連鎖します。mix-blend-mode は要素を背後のものとブレンドします(multiply、screen、overlay など)。backdrop-filter は要素の背後の領域にフィルターを適用します(グラスモーフィズムに最適)。フィルターはパフォーマンスに影響する可能性があります — 控えめに使用してください。

css
/* Filters */
img.bw { filter: grayscale(100%); }
img.blur { filter: blur(5px); }
img.bright { filter: brightness(1.5); }
img.sepia { filter: sepia(0.8); }

/* Multiple filters */
img.vintage {
  filter: sepia(0.5) contrast(1.2) brightness(0.9);
}

/* Blend mode */
.overlay {
  background: rgba(255,0,0,0.5);
  mix-blend-mode: multiply;
}
04

タイポグラフィ

フォントプロパティ

font-family はフォールバックリストを受け入れます — ブラウザが最初に利用可能なものを使用します。常に汎用ファミリー(serif、sans-serif、monospace)で終わらせてください。font-weight は 100(thin)から 900(black)の範囲です。line-height: 1.5 はフォントサイズの 1.5 倍を意味します — 1.4-1.6 が本文の可読性に理想的です。font ショートハンドには最低でも size と family を含める必要があります。

css
body {
  /* Font shorthand: style weight size/line-height family */
  font: italic bold 16px/1.5 Arial, sans-serif;

  /* Individual properties */
  font-family: "Helvetica Neue", Arial, sans-serif;
  font-size: 16px;
  font-weight: 400;  /* 100-900, normal=400, bold=700 */
  font-style: italic; /* normal, italic, oblique */
  line-height: 1.5;
}

テキストスタイリング

text-align は水平配置を制御します。text-decoration は線を追加します(underline、overline、line-through)。text-transform は大文字小文字を変更します。letter-spacing(トラッキング)と word-spacing は文字と単語間の間隔を調整します。white-space: nowrap はテキストの折り返しを防ぎます。垂直配置には vertical-align(インライン)または flexbox/grid 配置(ブロック)を使用します。

css
p {
  text-align: justify;        /* left, right, center, justify */
  text-decoration: underline; /* none, overline, line-through */
  text-transform: capitalize; /* uppercase, lowercase, capitalize */
  text-indent: 2em;           /* indent first line */
  letter-spacing: 0.05em;     /* tracking */
  word-spacing: 0.1em;
  white-space: nowrap;        /* prevent wrapping */
}

a {
  text-decoration: none;
  color: #0066cc;
}

テキストオーバーフローと折り返し

省略記号でテキストを切り詰めるには 3 つのプロパティが必要です:white-space: nowrap、overflow: hidden、text-overflow: ellipsis。overflow-wrap: break-word は長い単語を分割してオーバーフローを防ぎます。word-break: break-all は任意の文字で分割します。text-wrap: balance(新しい)は見出しの行長をバランスさせます。切り詰めを機能させるには常に max-width または width を設定してください。

css
/* Truncate with ellipsis */
.truncate {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 200px;
}

/* Break long words */
.break-word {
  overflow-wrap: break-word;
  word-break: break-all;
}

/* Balance text wrapping (newer) */
h1 {
  text-wrap: balance;
}

Web フォント(@font-face)

@font-face はカスタムフォントを読み込みます。woff2 がモダンフォーマット(最高圧縮)です。フォールバックとして woff を提供します。font-display: swap はフォールバックテキストを即座に表示し、フォント読み込み後に置き換えます(不可視テキストを防ぐ)。常にフォールバックフォントファミリーを宣言してください。Google Fonts は @import または <link> でホストフォントを提供します。パフォーマンスのために重要なフォントをプリロードします。

css
@font-face {
  font-family: 'MyCustomFont';
  src: url('fonts/custom.woff2') format('woff2'),
       url('fonts/custom.woff') format('woff');
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}

body {
  font-family: 'MyCustomFont', Arial, sans-serif;
}

/* Google Fonts import */
@import url('https://fonts.googleapis.com/css2?family=Roboto:wght@400;700&display=swap');

リストとリンクのスタイリング

list-style: none はカスタムナビゲーションやスタイル付きリストのデフォルト箇条書きを削除します。list-style-type は箇条書きを変更します(disc、circle、square、decimal、none)。list-style-position: inside は箇条書きをコンテンツエリア内に配置します。リンクには LVHA 順序が重要です::link、:visited、:hover、:active。これはリンク状態の適切なカスケードを保証します。

css
/* Reset list styles */
ul {
  list-style: none;
  padding: 0;
  margin: 0;
}

/* Custom bullets */
ul.custom {
  list-style-type: square;
  list-style-position: inside;
}

/* Image bullets */
ul.image {
  list-style-image: url('bullet.png');
}

/* Link states (order matters!) */
a:link { color: blue; }
a:visited { color: purple; }
a:hover { color: red; text-decoration: underline; }
a:active { color: orange; }
05

Flexbox レイアウト

Flex コンテナ

display: flex は flex コンテナを作成します。justify-content は主軸に沿ってアイテムを整列させます(row では水平)。align-items は交差軸に沿って整列させます(垂直)。flex-direction は主軸を変更します。flex-wrap はアイテムが新しい行に折り返すことを許可します。gap はアイテム間の間隔を設定します(マージンハックを置き換え)。Flexbox は 1D レイアウト(行または列)に理想的です。

css
.container {
  display: flex;

  /* Main axis alignment */
  justify-content: space-between;
  /* flex-start, center, flex-end, space-around, space-evenly */

  /* Cross axis alignment */
  align-items: center;
  /* flex-start, center, flex-end, stretch, baseline */

  /* Direction */
  flex-direction: row;
  /* row, row-reverse, column, column-reverse */

  /* Wrapping */
  flex-wrap: wrap;
  /* nowrap, wrap, wrap-reverse */

  /* Gap between items */
  gap: 16px;
}

Flex アイテム

flex-grow はアイテムが余分なスペースを共有する方法を制御します(0 = 成長しない、1 = 均等に成長)。flex-shrink はスペースが限られた時にアイテムが縮む方法を制御します。flex-basis は初期サイズを設定します。ショートハンド flex: 1 は flex-grow:1、flex-shrink:1、flex-basis:0% を意味します。align-self は 1 つのアイテムのコンテナの align-items を上書きします。order は DOM を変更せずに視覚的にアイテムを並べ替えます。

css
.item {
  /* Grow: how much space to take (0 = don't grow) */
  flex-grow: 1;

  /* Shrink: how much to shrink when space is tight */
  flex-shrink: 0;

  /* Basis: initial size before growing/shrinking */
  flex-basis: 200px;

  /* Shorthand: flex: grow shrink basis */
  flex: 1 0 200px;

  /* Override align-items for this item */
  align-self: flex-end;

  /* Order (default 0, lower = earlier) */
  order: -1;
}

一般的な Flexbox パターン

Flexbox は中央揃えを簡単にします:justify-content: center + align-items: center。スティッキーフッターには、body を min-height: 100vh の flex カラムにし、メインコンテンツを flex: 1 にします。ナビバーには justify-content: space-between で最初と最後のアイテムを反対側に押します。これらのパターンは flexbox 以前は困難だった一般的なレイアウト問題を解決します。

css
/* Center anything */
.center {
  display: flex;
  justify-content: center;
  align-items: center;
  min-height: 100vh;
}

/* Sticky footer */
body {
  display: flex;
  flex-direction: column;
  min-height: 100vh;
}
.main { flex: 1; }

/* Navbar: logo left, links right */
.nav {
  display: flex;
  justify-content: space-between;
  align-items: center;
}

Flex Direction と Wrap

flex-direction: column は垂直レイアウトを作成します(スタッキングに便利)。flex-wrap: wrap はスペースがなくなった時にアイテムが新しい行に流れることを許可します。flex: 1 1 300px はアイテムが 300px で開始し、スペースを埋めるために成長し、必要に応じて縮むことを意味します。align-content は折り返された行間の間隔を制御します(wrap でのみ動作)。このパターンはレスポンシブカードグリッドを作成します。

css
/* Horizontal (default) */
.row { display: flex; flex-direction: row; }

/* Vertical */
.column { display: flex; flex-direction: column; }

/* Reverse */
.row-rev { display: flex; flex-direction: row-reverse; }

/* Wrap to new lines */
.cards {
  display: flex;
  flex-wrap: wrap;
  gap: 20px;
}
.card { flex: 1 1 300px; } /* grow, shrink, basis */

/* Align wrapped lines */
.cards { align-content: space-between; }

Flexbox 配置の詳細

flex-direction: column では、主軸は垂直で交差軸は水平です — justify-content と align-items は役割を交換します。flex アイテムの margin: auto は利用可能なすべてのスペースを吸収し、完全に中央揃えします。これは justify-content/align-items の代替です。どの軸が「主」でどちらが「交差」かを理解することが flexbox 配置の習得の鍵です。

css
.container {
  display: flex;
  flex-direction: column;

  /* Main axis = vertical (column) */
  justify-content: flex-start;
  /* push items to top, center, bottom, or spread */

  /* Cross axis = horizontal (column) */
  align-items: stretch;
  /* stretch items to full width */
}

/* Center a single item perfectly */
.wrapper {
  display: flex;
  min-height: 100vh;
}
.centered {
  margin: auto; /* centers in both axes */
}
06

CSS Grid レイアウト

Grid コンテナ

display: grid は 2D レイアウトを作成します。grid-template-columns は列サイズを定義します:fr 単位は空きスペースを比例配分します。repeat(3, 1fr) は 3 つの等しい列を作成します。repeat(auto-fit, minmax(250px, 1fr)) は列数を自動調整するレスポンシブグリッドを作成します — これはレスポンシブグリッドの「聖杯」です。gap が間隔のためにマージンを置き換えます。

css
.grid {
  display: grid;

  /* Define columns */
  grid-template-columns: 200px 1fr 200px;
  /* fixed, flexible, fixed */

  /* Or repeat */
  grid-template-columns: repeat(3, 1fr);
  grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));

  /* Define rows */
  grid-template-rows: auto 1fr auto;

  /* Gap (formerly grid-gap) */
  gap: 20px;
  row-gap: 10px;
  column-gap: 20px;
}

Grid アイテムの配置

Grid アイテムは grid-column: span N で複数セルにまたがれます。行番号も使用できます:grid-column: 1 / 3 は行 1 から開始し行 3 で終了することを意味します。行は 1(左/上)から N+1(右/下)に番号付けされます。grid-area はアイテムを名前付きエリアに割り当てます。Grid は精密な 2D 配置を可能にします — アイテムは行と列を同時にまたがれます。

css
.grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 10px;
}

/* Span multiple columns */
.featured {
  grid-column: span 2;
}

/* Explicit placement */
.sidebar {
  grid-column: 1 / 3;  /* start at line 1, end at line 3 */
  grid-row: 1 / 4;
}

/* Named areas */
.header { grid-area: header; }
.sidebar { grid-area: sidebar; }

Grid Template Areas

grid-template-areas は名前付き文字列を使用してレイアウトの視覚的マップを作成します。各文字列は行を表し、各名前は列を表します。アイテムは grid-area を一致する名前に設定して配置されます。これは複雑なレイアウトを作成する最も読みやすい方法です。空のセルには '.' を使用します。同じ名前が複数セルにまたがれます。レスポンシブレイアウトのためにメディアクエリでエリアを変更します。

css
.layout {
  display: grid;
  grid-template-columns: 200px 1fr;
  grid-template-rows: auto 1fr auto;
  grid-template-areas:
    "header header"
    "sidebar main"
    "footer footer";
  gap: 10px;
  min-height: 100vh;
}

.header { grid-area: header; }
.sidebar { grid-area: sidebar; }
.main { grid-area: main; }
.footer { grid-area: footer; }

Grid 配置

Grid には 6 つの配置プロパティがあります。align-items/justify-items はグリッドセル内のアイテムを整列させます。align-content/justify-content はコンテナ内のグリッドトラック全体を整列させます(グリッドが小さい場合のみ可視)。align-self/justify-self はアイテムごとに上書きします。place-items: center は align-items + justify-items のショートハンドです。place-content: center は両方のコンテンツ配置を組み合わせます。

css
.grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);

  /* Align items within their cell (cross axis) */
  align-items: center;  /* start, center, end, stretch */

  /* Justify items within their cell (main axis) */
  justify-items: center;

  /* Align the entire grid (if smaller than container) */
  align-content: center;
  justify-content: center;
}

/* Override for individual item */
.item {
  align-self: end;
  justify-self: start;
}

レスポンシブ Grid(Auto-fit)

repeat(auto-fit, minmax(300px, 1fr)) は利用可能なスペースに基づいて列数を自動調整するグリッドを作成します — アイテムは少なくとも 300px で成長して埋めます。これはカードレイアウトのメディアクエリを排除します。auto-fill は空の列を保持し(アイテムは左に留まる)、auto-fit はそれらを折りたたみます(アイテムは伸びる)。ほとんどのケースで auto-fit を使用します。最適な結果のためにコンテナの max-width と組み合わせます。

css
/* Auto-responsive grid - no media queries needed! */
.cards {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
  gap: 20px;
}

/* Fixed number of columns per breakpoint */
@media (min-width: 768px) {
  .cards {
    grid-template-columns: repeat(2, 1fr);
  }
}
@media (min-width: 1024px) {
  .cards {
    grid-template-columns: repeat(3, 1fr);
  }
}

/* Auto-fill vs auto-fit:
   auto-fit collapses empty tracks
   auto-fill keeps empty tracks */
07

ポジショニング

Position タイプ

static はデフォルト(通常のドキュメントフロー)です。relative は通常位置からオフセットし他の要素に影響しません(配置コンテキストを作成)。absolute はフローから削除し最も近い配置された祖先に相対的に配置します。fixed はビューポートに相対的に配置します(スクロールで固定)。sticky は relative と fixed を切り替えます — 通常スクロールし、しきい値で固定されます。

css
/* Static (default) - normal flow */
.static { position: static; }

/* Relative - offset from normal position */
.relative {
  position: relative;
  top: 10px;
  left: 20px;
}

/* Absolute - positioned relative to nearest positioned ancestor */
.absolute {
  position: absolute;
  top: 0;
  right: 0;
}

/* Fixed - positioned relative to viewport */
.fixed {
  position: fixed;
  bottom: 0;
  width: 100%;
}

/* Sticky - scrolls then sticks */
.sticky {
  position: sticky;
  top: 0;
}

Absolute ポジショニング

absolute ポジショニングには配置された祖先(relative、absolute、fixed、sticky)が必要です。ない場合、ビューポートに相対的に配置します。top/right/bottom/left プロパティは対応するエッジからオフセットします。絶対配置要素を中央揃えするには、top:50%、left:50% と transform: translate(-50%,-50%) を使用します。absolute ポジショニングは要素を通常フローから削除します。

css
/* Parent must be positioned */
.container {
  position: relative;
  width: 400px;
  height: 300px;
}

/* Position relative to container */
.badge {
  position: absolute;
  top: 10px;
  right: 10px;
}

/* Center absolutely positioned element */
.modal {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}

Sticky ポジショニング

position: sticky はハイブリッドです — 要素はしきい値(例:top: 0)に達するまで通常スクロールし、その後固定されます。スティッキーヘッダー、サイドバー、テーブルヘッダーに最適です。要素は親コンテナ内で固定されます(親がスクロールアウトすると固定解除)。祖先に overflow: hidden/auto/scroll があると sticky は動作しません。重なり問題を防ぐため常に z-index を設定してください。

css
/* Sticky header */
.header {
  position: sticky;
  top: 0;
  background: white;
  z-index: 100;
  padding: 1rem;
}

/* Sticky sidebar */
.sidebar {
  position: sticky;
  top: 80px; /* offset for fixed header */
  height: calc(100vh - 80px);
  overflow-y: auto;
}

/* Note: sticky doesn't work if a parent has
   overflow: hidden or overflow: auto */

Z-index とスタッキングコンテキスト

z-index は配置された要素のスタッキング順序を制御します(高い = 上)。配置された要素(static 以外)でのみ動作します。スタッキングコンテキストは z-index 付きの配置要素、opacity < 1、transform、filter で作成されます。スタッキングコンテキスト内では、子の z-index 値はそのコンテキストに相対的です — 子はより高い z-index の親の兄弟より上に表示できません。これは一般的な混乱の源です。

css
/* Higher z-index = closer to viewer */
.modal-overlay {
  position: fixed;
  z-index: 9999;
  top: 0; left: 0; right: 0; bottom: 0;
  background: rgba(0,0,0,0.5);
}

.modal {
  position: fixed;
  z-index: 10000; /* above overlay */
  top: 50%; left: 50%;
  transform: translate(-50%, -50%);
}

/* Stacking context: z-index only works
   within the same stacking context */
.parent { position: relative; z-index: 1; }
.child { position: absolute; z-index: 9999; }
/* child can't exceed parent's stacking level */

Float と Clear(レガシー)

float は flexbox/grid 以前の主要なレイアウト方法でした。要素を通常フローから削除し左/右に押し出し、テキストが周りに回り込みます。clear は要素が float の隣に表示されるのを防ぎます。clearfix ハックはコンテナに float された子を囲ませます。今日では、本来の目的(画像の周りにテキストを回り込ませる)にのみ float を使用してください。レイアウトには flexbox または grid を使用します。

css
/* Float text around an image */
img.float-left {
  float: left;
  margin: 0 1rem 1rem 0;
}

/* Clear floats */
.clear { clear: both; }
.clear-left { clear: left; }
.clear-right { clear: right; }

/* Clearfix hack for containers */
.clearfix::after {
  content: "";
  display: table;
  clear: both;
}

/* Modern alternative: use flexbox or grid */
/* Float is mainly for text wrapping now */
08

レスポンシブデザイン

メディアクエリ

メディアクエリは条件に基づいてスタイルを適用します。min-width(モバイルファースト)が推奨されます — ベーススタイルがモバイルをターゲットし、大きな画面向けに拡張します。max-width(デスクトップファースト)は逆です。その他の条件:prefers-color-scheme(ダーク/ライト)、print、orientation(ポートレート/ランドスケープ)、prefers-reduced-motion。メディアクエリがモバイルで動作するには HTML に viewport メタタグを常に設定してください。

css
/* Mobile-first: base styles first, then min-width */

/* Base (mobile) */
.container { flex-direction: column; }

/* Tablet and up */
@media (min-width: 768px) {
  .container { flex-direction: row; }
}

/* Desktop and up */
@media (min-width: 1024px) {
  .container { max-width: 1200px; margin: 0 auto; }
}

/* Print styles */
@media print {
  .no-print { display: none; }
}

/* Dark mode */
@media (prefers-color-scheme: dark) {
  body { background: #1a1a1a; color: #eee; }
}

流体タイポグラフィ

clamp(min, preferred, max) はビューポートサイズに応じて滑らかにスケールする流体タイポグラフィを作成します — メディアクエリ不要。preferred 値(多くは vw ベース)が min と max の範囲間でスケールします。min() はより小さい値を選びます(レスポンシブ max-width に最適)。このアプローチは必要なメディアクエリの数を減らし、より滑らかなスケーリングを作成します。可読性のために常に合理的な min/max を設定してください。

css
/* clamp() for fluid font sizes */
h1 {
  font-size: clamp(1.5rem, 5vw, 3rem);
  /* min: 1.5rem, preferred: 5vw, max: 3rem */
}

/* Fluid spacing */
.container {
  padding: clamp(1rem, 3vw, 3rem);
}

/* Fluid width */
.content {
  width: min(90%, 1200px);
  margin: 0 auto;
}

/* Viewport-based sizing */
.hero {
  height: 100vh;
  font-size: clamp(2rem, 8vw, 5rem);
}

コンテナクエリ

コンテナクエリ(CSS Containment Module Level 3)はビューポートではなく親コンテナのサイズに基づいて要素をスタイルできます。container-type: inline-size がコンテナを宣言します。@container はコンテナが条件を満たす時にスタイルを適用します。これはメディアクエリよりモジュラーです — コンポーネントは画面ではなくコンテナに適応します。異なるレイアウトコンテキストの再利用可能コンポーネントに最適です。

css
/* Define a container */
.card-container {
  container-type: inline-size;
  /* or: container: sidebar / inline-size; */
}

/* Query the container's size */
@container (min-width: 400px) {
  .card {
    display: flex;
    flex-direction: row;
  }
}

@container (max-width: 399px) {
  .card {
    display: flex;
    flex-direction: column;
  }
}

レスポンシブ画像とメディア

max-width: 100% + height: auto で画像をレスポンシブにします(縮小するが拡大しない)。padding-bottom ハックでレスポンシブな 16:9 動画埋め込みを作成します。モダンな aspect-ratio プロパティはよりクリーンです — 比率を設定するとブラウザが高さを計算します。レイアウトシフト(CLS)を防ぐため画像に常に width と height 属性を設定してください。固定寸法内で画像をクロップするには object-fit: cover を使用します。

css
/* Responsive image */
img {
  max-width: 100%;
  height: auto;
}

/* Responsive video (16:9 aspect ratio) */
.video-wrapper {
  position: relative;
  padding-bottom: 56.25%; /* 9/16 */
  height: 0;
}
.video-wrapper iframe {
  position: absolute;
  top: 0; left: 0;
  width: 100%;
  height: 100%;
}

/* Aspect ratio property */
.box {
  aspect-ratio: 16 / 9;
  width: 100%;
}

モバイルファースト戦略

モバイルファーストはモバイルスタイルをベースとして書き、min-width メディアクエリで大きな画面に向けて段階的に拡張することを意味します。これによりモバイルユーザー(多くは遅い接続)がより少ない CSS をダウンロードします。一般的なブレイクポイント:768px(タブレット)、1024px(デスクトップ)、1440px(大型)。より良いスケーラビリティのために固定 px ではなく相対単位(rem、%、vw)を使用します。ブラウザ DevTools だけでなく実際のデバイスでテストしてください。

css
/* 1. Start with mobile base styles */
.nav { display: none; } /* hidden on mobile */
.menu-toggle { display: block; }

/* 2. Enhance for larger screens */
@media (min-width: 768px) {
  .nav { display: flex; }
  .menu-toggle { display: none; }
}

/* 3. Common breakpoints */
/* Mobile: < 768px */
/* Tablet: 768px - 1023px */
/* Desktop: 1024px - 1439px */
/* Large: >= 1440px */

/* 4. Use relative units */
body { font-size: 1rem; } /* not 16px */
09

トランジションとアニメーション

トランジション

transition はプロパティ値間の滑らかな変化を作成します。構文:transition: property duration timing-function delay。タイミング関数:ease(デフォルト)、linear、ease-in、ease-out、ease-in-out、cubic-bezier()。アニメーション可能なプロパティのみトランジションします。transition: all は避けてください(パフォーマンス)。トランジションは疑似クラスの変化(:hover、:focus)や JavaScript によるクラス変更でトリガーされます。

css
.button {
  background: #007bff;
  transition: background 0.3s ease, transform 0.2s ease;
}

.button:hover {
  background: #0056b3;
  transform: translateY(-2px);
}

/* Transition all properties (use sparingly) */
.card {
  transition: all 0.3s ease;
}

/* Shorthand: property duration timing-function delay */
.box {
  transition: opacity 0.5s ease-in 0.2s;
}

Transform

transform はレイアウトに影響せずに要素を変更します(margin/position とは異なる)。translate は移動し(translateX、translateY、または translate(x,y))。scale はリサイズします(1 = 100%)。rotate は回転します(deg、rad、turn)。skew は歪めます。複数の transform は順番に連鎖します。transform は GPU アクセラレーションされます — パフォーマンスに最適。滑らかな効果のために常に transition と併用します。transform-origin がピボットポイントを変更します。

css
.box {
  transition: transform 0.3s ease;
}

/* Translate (move) */
.box:hover { transform: translate(10px, 20px); }
.box:hover { transform: translateX(50%); }

/* Scale (resize) */
.box:hover { transform: scale(1.1); }

/* Rotate */
.box:hover { transform: rotate(45deg); }

/* Skew */
.box:hover { transform: skew(10deg, 5deg); }

/* Combine transforms */
.box:hover {
  transform: translate(10px, 0) scale(1.1) rotate(5deg);
}

キーフレームアニメーション

@keyframes がアニメーションステップを定義します。0%/from が開始、100%/to が終了。中間ステップ(25%、50%、75%)を追加できます。animation ショートハンド:name duration timing-function delay iteration-count direction fill-mode。infinite は永遠にループします。direction: alternate は偶数反復で逆転します。fill-mode: forwards は最終状態を保持します。アニメーションはトランジションとは異なり自動的に実行されます。

css
@keyframes bounce {
  0%   { transform: translateY(0); }
  50%  { transform: translateY(-20px); }
  100% { transform: translateY(0); }
}

@keyframes fadeIn {
  from { opacity: 0; }
  to   { opacity: 1; }
}

.ball {
  animation: bounce 0.5s ease infinite;
}

.element {
  animation: fadeIn 1s ease forwards;
  /* name duration timing delay iteration direction fill-mode */
}

アニメーションプロパティ

個別のアニメーションプロパティは細かい制御を提供します。animation-iteration-count は数値または infinite にできます。animation-direction: alternate は前進後に後退して再生します(ピンポン効果に最適)。animation-fill-mode: forwards は終了後に終了状態を保持します。animation-play-state: paused はアニメーションを一時停止します — ホバーで一時停止に便利。複数のアニメーションはカンマ区切り:animation: spin 1s, fade 2s;。

css
.spinner {
  animation-name: spin;
  animation-duration: 1s;
  animation-timing-function: linear;
  animation-delay: 0s;
  animation-iteration-count: infinite;
  animation-direction: normal; /* alternate, reverse */
  animation-fill-mode: none;   /* forwards, backwards, both */
  animation-play-state: running; /* paused */
}

@keyframes spin {
  from { transform: rotate(0deg); }
  to   { transform: rotate(360deg); }
}

/* Pause on hover */
.spinner:hover {
  animation-play-state: paused;
}

パフォーマンスと Reduced Motion

滑らかな 60fps アニメーションのために、transform と opacity のみをアニメーションします — これらは GPU アクセラレーションされレイアウト(リフロー)をトリガーしません。width、margin、top などのアニメーションはブラウザに毎フレームレイアウトの再計算を強制し、ジャンクを引き起こします。常に prefers-reduced-motion: reduce を尊重してください — 一部のユーザーは乗り物酔いや前庭障害を経験します。これらのユーザーのために即時トランジションまたはアニメーション無効化を提供します。

css
/* Only animate transform and opacity for performance */
.good {
  transition: transform 0.3s, opacity 0.3s;
}

/* Avoid animating these (cause reflow/repaint): */
/* margin, padding, width, height, top, left */

/* Respect user's motion preference */
@media (prefers-reduced-motion: reduce) {
  * {
    animation-duration: 0.01ms !important;
    transition-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
  }
}
10

変数と高度な関数

カスタムプロパティ(変数)

カスタムプロパティ(CSS 変数)は再利用可能な値を格納します。グローバルアクセスのために :root で定義します。var(--name) で参照します。これらはカスケードし任意のスコープで上書きできます — テーマ(ダーク/ライトモード)に完璧。プリプロセッサ変数とは異なり、動的(実行時に変更)で JavaScript で操作できます。常にフォールバックを提供:var(--primary, #007bff)。これがデザイントークンを管理するモダンな方法です。

css
:root {
  /* Colors */
  --primary: #007bff;
  --primary-dark: #0056b3;
  --text: #333;
  --bg: #fff;

  /* Spacing scale */
  --space-sm: 0.5rem;
  --space-md: 1rem;
  --space-lg: 2rem;

  /* Font sizes */
  --font-base: 16px;
  --font-lg: 1.5rem;
}

.button {
  background: var(--primary);
  padding: var(--space-sm) var(--space-md);
  font-size: var(--font-base);
  color: white;
}

/* Override in a scope */
.dark-theme {
  --bg: #1a1a1a;
  --text: #eee;
}

calc() と数学関数

calc() は px、%、em、rem、vw を含む任意の単位で計算します。レスポンシブレイアウトに不可欠です。calc() はネストできますが不要です — calc(100% - 2rem) / 3 は内側の calc なしで動作します。min() は最小値、max() は最大値、clamp() は値を min と max の間に拘束します。これらの関数により JavaScript やメディアクエリなしで CSS が動的になります。

css
/* Mixed unit calculations */
.sidebar {
  width: calc(100% - 250px);
}

/* With variables */
.box {
  padding: calc(var(--space-md) + 10px);
}

/* Nested calc */
.responsive {
  width: calc(calc(100% - 2rem) / 3);
}

/* min(), max(), clamp() */
.fluid {
  width: min(90%, 1200px);
  font-size: clamp(1rem, 2vw + 1rem, 2rem);
  height: max(200px, 50vh);
}

Object Fit と Position

object-fit は画像/動画がコンテナを満たす方法を制御します(<img> の background-size のようなもの)。cover はコンテナを満たしオーバーフローをクロップします(アバター/サムネイルに最適)。contain はクロップせず全体に収めます(空きスペースができる場合あり)。fill は引き伸ばします(歪む)。object-position は配置を調整します(background-position のような)。これはレスポンシブ画像の background-image ハックの必要性を置き換えます。

css
/* Cover: fill container, crop overflow */
.avatar {
  width: 100px;
  height: 100px;
  object-fit: cover;
  border-radius: 50%;
}

/* Contain: fit entirely, may letterbox */
.preview {
  width: 200px;
  height: 200px;
  object-fit: contain;
  background: #eee;
}

/* Position the image within the frame */
.image {
  object-fit: cover;
  object-position: top center;
}

Background プロパティ

background は強力なショートハンドです。background-size: cover はコンテナを満たし(クロップ)、contain はクロップせず収めます。background-attachment: fixed はパララックス効果を作成します(スクロール中に画像が静止)。複数の背景はカンマでレイヤー化されます(最初 = 最上位レイヤー)。オーバーレイに linear-gradient を背景として使用:background: linear-gradient(rgba(0,0,0,0.5), transparent), url('image.jpg')。

css
.hero {
  /* Shorthand */
  background: url('hero.jpg') center/cover no-repeat fixed;

  /* Individual properties */
  background-image: url('hero.jpg');
  background-size: cover;     /* cover, contain, or px/% */
  background-position: center; /* top, bottom, left, right, or x y */
  background-repeat: no-repeat;
  background-attachment: fixed; /* scroll, fixed, local */

  /* Multiple backgrounds */
  background:
    url('overlay.png') no-repeat center,
    url('hero.jpg') center/cover;
}

CSS ネスティング(モダン)

モダン CSS はネイティブネスティングをサポートします(Sass/Less のように)。& で親セレクタを参照します。ネスティングは可読性を向上させ繰り返しを減らします。メディアクエリはルール内に直接ネストできます。モダンブラウザ(2023+)で良好なサポート。& は疑似クラス(&:hover)とコンビネータ(& > .child)に必要です。深いネスティング(3+ レベル)は詳細度を上げメンテナンス性を下げるため避けてください。

css
/* Native CSS nesting (no preprocessor needed) */
.card {
  background: white;
  border-radius: 8px;

  & .title {
    font-size: 1.5rem;
    font-weight: bold;
  }

  & .body {
    padding: 1rem;

    & p {
      line-height: 1.6;
    }
  }

  &:hover {
    box-shadow: 0 4px 12px rgba(0,0,0,0.1);
  }

  @media (max-width: 768px) {
    padding: 0.5rem;
  }
}
11

CSS カスタムプロパティ(変数)詳細

変数の定義と使用

CSS カスタムプロパティ(変数)は --name で定義し var() で使用します。テーマ値のために :root でグローバル変数を定義します。Sass 変数とは異なり、CSS 変数はライブです — 変更するとすべての使用が即座に更新されます。定義された要素にスコープされ子孫に継承されます。var() は第 2 引数としてフォールバック値を受け入れ、フォールバックは連鎖できます。これにより動的テーマ用のプリプロセッサ変数よりはるかに強力になります。

css
:root {
  --primary: #3498db;
  --spacing: 16px;
  --radius: 8px;
  --max-width: 1200px;
}

.button {
  background: var(--primary);
  padding: var(--spacing);
  border-radius: var(--radius);
  max-width: var(--max-width);
}

/* Fallback values */
color: var(--text-color, #333);
/* Chained fallbacks */
color: var(--text, var(--default, black));

JavaScript での動的テーマ

CSS 変数はプリプロセッサにはできないランタイムテーマを可能にします。<html> に data-theme を設定しテーマごとに変数を上書きします。JavaScript は実行時に変数を読み取り(getComputedStyle)設定(style.setProperty)でき、動的カラーピッカー、ユーザー設定、ライブプレビューを可能にします。これはダークモード、ブランドカスタマイズ、ユーザー選択可能テーマの標準アプローチです。変数はカスケードし継承するため、子要素での上書きはそのサブツリーのみに影響します。

css
/* Define theme variables */
:root {
  --bg: #ffffff;
  --text: #333333;
}

[data-theme="dark"] {
  --bg: #1a1a1a;
  --text: #e0e0e0;
}

body {
  background: var(--bg);
  color: var(--text);
}

/* Toggle theme with JS */
<script>
document.documentElement.setAttribute(
  "data-theme",
  isDark ? "dark" : "light"
);

/* Or set a single variable directly */
document.documentElement.style
  .setProperty("--primary", "#e74c3c");
</script>

スコープ変数と継承

CSS 変数は他のプロパティのように継承します。:root で定義された変数はどこでも利用可能。.card で定義されたものは .card とその子孫のみに影響。このスコープによりコンポーネントレベルのカスタマイズが可能です。メディアクエリ内で変数を上書きしてレスポンシブな変数値を作成できます — 変数自体は @media 条件では使用できませんが、メディアクエリブロック内でその値を変更できます。このパターンはプロパティ宣言を繰り返さないレスポンシブデザインに強力です。

css
:root {
  --padding: 20px;
}

.card {
  --padding: 12px; /* overrides only for .card subtree */
  padding: var(--padding);
}

.card .inner {
  padding: var(--padding); /* inherits 12px from .card */
}

/* Variables in media queries don't work, but... */
.sidebar {
  --width: 250px;
  width: var(--width);
}
@media (max-width: 768px) {
  .sidebar { --width: 100%; }
}

calc() との変数の組み合わせ

CSS 変数と calc() の組み合わせは強力なデザインシステムを作成します。ベースサイズとスケールファクターを定義し、派生サイズを計算します。これにより一貫したタイポグラフィックスケールとスペーシングシステムが可能になります。calc() は混合単位(px、%、em、vw)と変数で動作します。フォールバックなしの変数も使用できます(var(--nav-h, 60px) がデフォルトを提供)。このアプローチはモダンデザインシステムの基盤です — 1 つの変数を変更するとスケール全体が比例調整されます。

css
:root {
  --base-size: 16px;
  --scale: 1.25;
}

h1 { font-size: calc(var(--base-size) * var(--scale) * 2); }
h2 { font-size: calc(var(--base-size) * var(--scale) * 1.5); }
p  { font-size: var(--base-size); }

/* Spacing scale */
:root {
  --space: 8px;
}
.margin { margin: calc(var(--space) * 2); }
.padding { padding: calc(var(--space) * 3); }

/* Mixed units */
.header { height: calc(var(--nav-h, 60px) + var(--content-h)); }

カスタムプロパティの登録(@property)

@property は型(syntax)、初期値、継承フラグ付きでカスタムプロパティを登録します。これにより CSS 変数のアニメーションとトランジションが可能になります — @property なしでは変数は文字列として扱われ補間できません。syntax は <angle>、<color>、<length>、<number>、<percentage>、'*' などの型を受け入れます。これにより変数駆動のグラデーション、transform、色の滑らかなアニメーションが可能になります。Chromium と Safari で良好なサポート、Firefox がサポート追加中。CSS アニメーション機能の大きな進歩です。

css
/* Type-safe custom properties */
@property --angle {
  syntax: "<angle>";
  initial-value: 0deg;
  inherits: false;
}

@property --color {
  syntax: "<color>";
  initial-value: #3498db;
  inherits: false;
}

/* Now animatable! */
@keyframes spin {
  to { --angle: 360deg; }
}

.loader {
  --angle: 0deg;
  animation: spin 1s linear infinite;
  background: conic-gradient(
    from var(--angle),
    var(--color), transparent
  );
}
12

3D Transforms

3D Transform 関数

3D transform は要素に奥行きを追加します。transform 関数としての perspective() は単一要素に適用され、親の perspective プロパティはすべての子に均一に適用されます。rotateX/rotateY/rotateZ は軸の周りを回転し、translateZ は Z 軸に沿って移動します(視点に向かって/離れて)。低い perspective 値はより劇的な 3D 効果を作成します(近い視点)。複数の変換された子にわたって一貫した 3D 空間のために親コンテナに常に perspective を設定します。複数の transform を組み合わせて複雑な 3D 配置を行います。

css
.card {
  transform: perspective(1000px) rotateY(45deg) rotateX(15deg);
}

/* Using the perspective property instead */
.container {
  perspective: 1000px;
}
.container .card {
  transform: rotateY(45deg) rotateX(15deg);
}

/* translateZ moves toward/away from viewer */
.layer {
  transform: translateZ(100px);
}

/* scale3d for 3D scaling */
.box {
  transform: scale3d(1.5, 1.5, 1.5);
}

transform-style と backface-visibility

transform-style: preserve-3d は子要素の 3D 空間を維持します(flat がデフォルトで子を平坦化)。backface-visibility: hidden は回転時に要素の裏側を非表示にします — フリップカード効果に不可欠。古典的なフリップカードは 2 つの絶対配置された面を使用します:前面は前を向き、背面は 180 度事前回転されています。ホバー時に親が 180 度回転し、どちらの面が可視かが切り替わります。これは最も人気のある 3D CSS パターンの一つです。

css
.container {
  perspective: 1000px;
}

.flip-card {
  transform-style: preserve-3d;
  transition: transform 0.6s;
  position: relative;
}

.flip-card:hover {
  transform: rotateY(180deg);
}

.flip-card .front,
.flip-card .back {
  position: absolute;
  inset: 0;
  backface-visibility: hidden;
}

.flip-card .back {
  transform: rotateY(180deg);
}

3D キューブ

3D キューブは 6 つの面で構築され、それぞれが rotate + translateZ で配置されます。translateZ(100px) は面をキューブ幅の半分外側に押し出します。各面は押し出される前にその方向を向くように事前回転されます。キューブコンテナの transform-style: preserve-3d が不可欠 — ないと面が平坦化されます。アニメーションがキューブを X と Y 両軸で回転させます。これは CSS 3D transform の全力を示します。適切なジオメトリのためにキューブサイズの半分に合わせて translateZ を調整します。

css
.scene {
  perspective: 800px;
  width: 200px; height: 200px;
}
.cube {
  position: relative;
  width: 100%; height: 100%;
  transform-style: preserve-3d;
  animation: rotate 8s infinite linear;
}
@keyframes rotate {
  from { transform: rotateX(0) rotateY(0); }
  to   { transform: rotateX(360deg) rotateY(360deg); }
}
.face {
  position: absolute;
  width: 200px; height: 200px;
  opacity: 0.85;
}
.front  { transform: translateZ(100px); background: red; }
.back   { transform: rotateY(180deg) translateZ(100px); background: blue; }
.right  { transform: rotateY(90deg) translateZ(100px); background: green; }
.left   { transform: rotateY(-90deg) translateZ(100px); background: yellow; }
.top    { transform: rotateX(90deg) translateZ(100px); background: purple; }
.bottom { transform: rotateX(-90deg) translateZ(100px); background: orange; }

3D カードチルト効果

カードチルト効果はマウス位置を追跡し、中心からのカーソルオフセットに基づいて 3D でカードを回転させます。計算は回転角を制限するためにオフセットを係数(10)で割ります。mouseleave でカードはフラットにリセットされます。transition が滑らかな動きを作成します。マウスを追うラジアルグラデーションのグレア/シャインオーバーレイを追加すると効果が強化されます。これは商品カードやヒーローセクションの人気のあるインタラクティブ UI パターンです。transform 文字列内の perspective は親 perspective プロパティなしでも 3D レンダリングを保証します。

css
.tilt-card {
  transition: transform 0.1s ease-out;
  transform-style: preserve-3d;
}

/* JavaScript-driven tilt */
<script>
const card = document.querySelector(".tilt-card");
card.addEventListener("mousemove", (e) => {
  const rect = card.getBoundingClientRect();
  const x = e.clientX - rect.left;
  const y = e.clientY - rect.top;
  const centerX = rect.width / 2;
  const centerY = rect.height / 2;
  const rotateX = (y - centerY) / 10;
  const rotateY = (centerX - x) / 10;
  card.style.transform =
    `perspective(1000px) rotateX(${rotateX}deg) rotateY(${rotateY}deg)`;
});
card.addEventListener("mouseleave", () => {
  card.style.transform = "perspective(1000px) rotateX(0) rotateY(0)";
});
</script>

perspective-origin と 3D 間隔

perspective-origin は消失点の位置を設定します(頭を動かすようなもの)。デフォルトは 50% 50%(中央)。移動すると動的な視角が作成されます。パララックス効果では、異なる translateZ 値の要素がコンテナのスクロールまたは回転時に異なる速度で移動します。より奥にある要素(負の translateZ)は perspective の縮小を補償するために scale() が必要です。この技法は JavaScript なしで UI に奥行きを作成します — 純粋な CSS パララックス。スクロール駆動アニメーションと組み合わせて没入型スクロール体験を作成します。

css
.stage {
  perspective: 1200px;
  perspective-origin: 50% 30%; /* x y position of vanishing point */
  transform-style: preserve-3d;
}

.layer-1 { transform: translateZ(0); }
.layer-2 { transform: translateZ(50px); }
.layer-3 { transform: translateZ(100px); }

/* Parallax-like depth */
.depth-bg    { transform: translateZ(-200px) scale(1.2); }
.depth-mid   { transform: translateZ(-100px) scale(1.1); }
.depth-fg    { transform: translateZ(0); }
13

CSS フィルターと Backdrop Filters

フィルター関数

CSS フィルターは要素に視覚効果を適用します。grayscale、sepia、invert は色を変更し、blur は柔らかくし、brightness/contrast/saturate は強度を調整し、hue-rotate は色をシフトします。複数のフィルターは左から右に連鎖します。drop-shadow はアルファ形状に従うため(透明領域にシャドウが付かない)PNG/SVG 画像には box-shadow より優れています。フィルターは GPU アクセラレーションされパフォーマンスが良好です。一般的な用途:画像ギャラリーのホバーでのグレースケール、ヴィンテージ写真効果、アクセシビリティ(ハイコントラストモード)。

css
img.grayscale { filter: grayscale(100%); }
img.blur { filter: blur(5px); }
img.bright { filter: brightness(1.5); }
img.contrast { filter: contrast(200%); }
img.sepia { filter: sepia(80%); }
img.saturate { filter: saturate(2); }
img.hue { filter: hue-rotate(90deg); }
img.invert { filter: invert(100%); }

/* Combine multiple filters */
img.vintage {
  filter: sepia(50%) contrast(110%) brightness(90%) saturate(120%);
}

/* Drop shadow (follows alpha shape) */
img.png-shadow {
  filter: drop-shadow(2px 4px 6px rgba(0,0,0,0.4));
}

backdrop-filter(グラスモーフィズム)

backdrop-filter は要素自体ではなく背後の領域にフィルターを適用し、グラスモーフィズム効果を作成します。効果を可視するために要素は半透明の背景が必要です。blur がすりガラス用の最も一般的な backdrop フィルターです。Safari サポートのために常に -webkit- プレフィックスを含めてください。洗練されたガラス外観のために半透明のボーダーと控えめな box-shadow と組み合わせます。大きなぼかし領域でパフォーマンス問題が発生する可能性があります — 控えめに使用。これは現代 UI デザインの決定的トレンドです(iOS、macOS、Windows Acrylic)。

css
.glass {
  background: rgba(255, 255, 255, 0.2);
  backdrop-filter: blur(10px) saturate(180%);
  -webkit-backdrop-filter: blur(10px) saturate(180%);
  border: 1px solid rgba(255, 255, 255, 0.3);
  border-radius: 16px;
  padding: 24px;
}

.glass-dark {
  background: rgba(0, 0, 0, 0.4);
  backdrop-filter: blur(20px);
  border: 1px solid rgba(255, 255, 255, 0.1);
}

SVG フィルター(url 参照)

CSS filter: url(#id) は組み込み関数を超えた効果のために SVG フィルターを参照します。「ぐにゃぐにゃ」フィルターは要素のブロブのような結合を作成します(ローディングアニメーションやオーガニック UI に人気)。feGaussianBlur + 高アルファ乗数の feColorMatrix がぼかしたエッジを鋭くすることでぐにゃぐにゃ効果を作成します。feTurbulence + feDisplacementMap が波状/歪んだ効果を作成します。SVG フィルターは強力ですがパフォーマンス集約的になる可能性があります。CSS 単独では不可能な効果を可能にします:液体モーフィング、変位、照明、カスタム合成。

css
<!-- Define SVG filter -->
<svg style="display:none">
  <filter id="gooey">
    <feGaussianBlur in="SourceGraphic" stdDeviation="10" />
    <feColorMatrix values="
      1 0 0 0 0
      0 1 0 0 0
      0 0 1 0 0
      0 0 0 20 -10" />
  </filter>
</svg>

<!-- Apply via CSS -->
.gooey-container {
  filter: url(#gooey);
}

<!-- Displacement map for wavy text -->
<filter id="wavy">
  <feTurbulence baseFrequency="0.02" numOctaves="3" />
  <feDisplacementMap in="SourceGraphic" scale="10" />
</filter>

フィルターアニメーション

フィルターはアニメーション化し滑らかにトランジションできます。パルスグロー効果はネオングローのために brightness と drop-shadow を組み合わせます。ホバーでのグレースケールからカラーへの変化は古典的なギャラリーインタラクションです。フィルタートランジションは GPU アクセラレーションされ、box-shadow や background-color のアニメーションよりパフォーマンスが良いです。ただし、blur や複雑なフィルターのアニメーションは高コストな可能性があります — モバイルでテスト。スクロール駆動の hue-rotate は楽しい効果ですが、長いページでパフォーマンス問題を引き起こす可能性があります。最適化のヒントとして will-change: filter を使用します。

css
@keyframes pulse-glow {
  0%, 100% {
    filter: brightness(1) drop-shadow(0 0 5px #3498db);
  }
  50% {
    filter: brightness(1.3) drop-shadow(0 0 20px #3498db);
  }
}

.glow-button {
  animation: pulse-glow 2s ease-in-out infinite;
}

/* Hover filter transition */
.gallery img {
  filter: grayscale(100%);
  transition: filter 0.3s ease;
}
.gallery img:hover {
  filter: grayscale(0%);
}

/* Color shift on scroll (with JS) */
window.addEventListener("scroll", () => {
  const hue = window.scrollY * 0.5;
  document.body.style.filter = `hue-rotate(${hue}deg)`;
});

mix-blend-mode と background-blend-mode

mix-blend-mode は要素のピクセルが背後のコンテンツとどうブレンドされるかを決定します。multiply は暗くし(シャドウやウォーターマークに適しています)、screen は明るくし(グローに適しています)、difference はサイケデリックな効果を作成し、overlay はコントラストのために multiply と screen を組み合わせます。background-blend-mode は同じ要素上の複数の背景レイヤー(画像とグラデーション)をブレンドします。ブレンドモードはクリエイティブな合成、デュオトーン効果、画像上テキストオーバーレイに不可欠です。isolation: isolate がブレンド効果を封じ込める新しいブレンドコンテキストを作成します。

css
/* mix-blend-mode: how element blends with backdrop */
.overlay {
  mix-blend-mode: multiply; /* darken */
}
.overlay-screen {
  mix-blend-mode: screen; /* lighten */
}
.overlay-difference {
  mix-blend-mode: difference; /* invert */
}

/* Common blend modes: multiply, screen, overlay,
   darken, lighten, color-dodge, color-burn,
   hard-light, soft-light, difference, exclusion,
   hue, saturation, color, luminosity */

/* background-blend-mode: blend background layers */
.gradient-texture {
  background-image: url(texture.png),
                    linear-gradient(45deg, red, blue);
  background-blend-mode: multiply;
}
14

コンテナクエリ

コンテナクエリの基礎

コンテナクエリはビューポートではなくコンテナのサイズに応じてコンポーネントが反応できるようにします。container-type: inline-size がインライン(幅)寸法に基づいて要素をクエリコンテナにします。@container ルールはコンテナが条件にマッチする時にスタイルを適用します。これはコンポーネントベースのデザインに革命です — カードコンポーネントがサイドバーでもフル幅メインエリアでも画面サイズに関わらず適応します。これはビューポートサイズにのみ反応するメディアクエリの根本的な制限を解決します。

css
/* Define a container */
.card-container {
  container-type: inline-size;
  /* or: container-type: size; (both dimensions) */
}

/* Query the container's size */
@container (min-width: 400px) {
  .card {
    display: grid;
    grid-template-columns: 1fr 2fr;
  }
}

@container (max-width: 399px) {
  .card {
    display: flex;
    flex-direction: column;
  }
}

名前付きコンテナ

名前付きコンテナは複数がネストされている時に特定のコンテナをターゲットにできます。container-name がコンテナにラベルを付け、@container name (condition) はそのコンテナのみをクエリします。これにより異なるコンテナコンテキストでコンポーネントがネストされる時の競合を防ぎます。container ショートハンドは名前とタイプを組み合わせます:container: panel / inline-size。名前付きコンテナは複数の独立したコンテナクエリが共存する複雑なレイアウトに不可欠です。名前なしでは @container は最も近い祖先コンテナをクエリします。

css
/* Name a container for specific queries */
.sidebar {
  container-type: inline-size;
  container-name: sidebar;
}

.main-content {
  container-type: inline-size;
  container-name: main;
}

/* Query specific container by name */
@container sidebar (min-width: 300px) {
  .widget { display: grid; grid-template-columns: 1fr 1fr; }
}

@container main (min-width: 600px) {
  .article { columns: 2; }
}

/* Shorthand: container: name / type */
.panel {
  container: panel / inline-size;
}

コンテナクエリ単位

コンテナクエリ単位(cqw、cqh、cqmin、cqmax)はビューポート単位(vw、vh)と似ていますがビューポートではなくクエリコンテナに相対です。1cqw = コンテナ幅の 1%。これにより真にコンポーネントレスポンシブなタイポグラフィとスペーシングが可能になります — テキストは画面ではなくコンポーネントの幅でスケールします。clamp() と組み合わせて min/max 範囲付きでコンテナサイズに適応する流体タイポグラフィを得ます。これはコンポーネントが様々なレイアウトコンテキストで動作する必要があるデザインシステムに理想的です。注意:cqh/cqmin/cqmax は container-type: size(両寸法)が必要です。

css
.card {
  container-type: inline-size;
}

.card-title {
  /* cqw: 1% of container width */
  font-size: 5cqw;

  /* cqh: 1% of container height (needs size type) */
  padding: 2cqh;

  /* cqmin: 1% of smaller container dimension */
  margin: 2cqmin;

  /* cqmax: 1% of larger container dimension */
  border-radius: 1cqmax;
}

/* Fluid typography that responds to container */
.headline {
  font-size: clamp(1rem, 8cqw, 3rem);
}

コンテナスタイルクエリ

コンテナスタイルクエリ(実験的、2025 年時点で Chromium のみ)は寸法だけでなくコンテナ上のカスタムプロパティ値をクエリできます。これによりスタイルベースの条件付きレンダリングが可能になります:コンポーネントはコンテナに設定された --theme 変数に基づいて外観を変更できます。container-type: style(またはスタイルクエリには container-type 不要)がこれを有効にします。これはテーマに強力です — 親に変数を設定しすべての子が適応します。完全なブラウザサポートはまだ保留中です。プログレッシブエンハンスメントまたは @supports チェックで使用してください。

css
/* Query custom property values on container */
.card-wrapper {
  container-type: style;
  container-name: card;
}

@container card style(--theme: dark) {
  .card {
    background: #1a1a1a;
    color: #fff;
  }
}

@container card style(--theme: light) {
  .card {
    background: #fff;
    color: #333;
  }
}

/* Set the theme variable */
<div class="card-wrapper" style="--theme: dark">
  <div class="card">...</div>
</div>

レスポンシブコンポーネントパターン

このパターンは配置に適応する真に再利用可能なコンポーネントを作成します。商品カードは狭いコンテナでは垂直レイアウト、中では水平、広いコンテナでは 3 列グリッドを表示します。同じコンポーネントがサイドバー(狭い)、グリッド(中)、ヒーロー(広い)で prop ベースの条件付きロジックなしで動作します。これはコンテナクエリのキラーユースケースです — 真にコンテキスト非依存のコンポーネント。タイポグラフィのコンテナクエリ単位と組み合わせて完全に自己適応するコンポーネントを得ます。

css
/* Component that adapts to any container */
.product-card {
  container-type: inline-size;
  container-name: product;
}

.product-card .layout {
  display: flex;
  flex-direction: column;
  gap: 1rem;
}

/* Medium container: horizontal layout */
@container product (min-width: 350px) {
  .product-card .layout {
    flex-direction: row;
  }
  .product-card .image {
    width: 40%;
  }
}

/* Large container: full feature layout */
@container product (min-width: 600px) {
  .product-card .layout {
    display: grid;
    grid-template-columns: 1fr 2fr 1fr;
  }
  .product-card .actions {
    display: flex;
    flex-direction: column;
  }
}
15

Scroll Snap と Scroll-Driven アニメーション

Scroll Snap の基礎

Scroll snap は要素をスナップポイントに整列させる磁気スクロールを作成します。scroll-snap-type: x/y が軸を設定し、mandatory はスナップを強制し(常にポイントに着地)、proximity は近い時のみスナップします。scroll-snap-align: start/center/end はコンテナ内で子がどこにスナップするかを定義します。フルページスクロールセクション(プレゼンスライドのように)は 100vh セクションで y mandatory を使用します。水平カルーセルは x mandatory を使用します。タッチデバイスで常にテストしてください — コンテンツがビューポートより高い場合、mandatory スナッピングは制限的に感じる可能性があります。より許容的な動作には proximity を使用します。

css
/* Container with scroll snapping */
.gallery {
  scroll-snap-type: x mandatory;
  overflow-x: auto;
  display: flex;
  gap: 1rem;
}

/* Children snap to positions */
.gallery section {
  scroll-snap-align: start;
  flex: 0 0 100%;
  height: 300px;
}

/* Vertical snapping */
.full-page {
  scroll-snap-type: y mandatory;
  height: 100vh;
  overflow-y: scroll;
}
.full-page section {
  scroll-snap-align: start;
  height: 100vh;
}

パディング付き Scroll Snap

scroll-padding はコンテナエッジからスナップポイントをオフセットします — 固定ヘッダーがある場合やスナップアイテムの周りにマージンが必要な場合に便利です。scroll-snap-stop: always は高速スクロールが複数アイテムをスキップするのを防ぎます(1 つずつスナップを強制)。scroll-snap-align: center はアイテムをコンテナの中央にスナップし、カバーフロー効果を作成します。これらのプロパティはスナッピング動作の細かい制御を提供します。画像カルーセルには、スナップ間のアニメーション遷移のために scroll-behavior: smooth と組み合わせます。

css
.carousel {
  scroll-snap-type: x mandatory;
  scroll-padding: 0 20px; /* offset snap points */
  overflow-x: auto;
  display: flex;
  gap: 1rem;
  padding: 0 20px;
}

.carousel .item {
  scroll-snap-align: start;
  scroll-snap-stop: always; /* don't skip items */
  flex: 0 0 80%;
}

/* Center-aligned snapping */
.carousel-center .item {
  scroll-snap-align: center;
  flex: 0 0 60%;
}

Scroll-Driven アニメーション(animation-timeline)

Scroll-driven アニメーション(CSS のみ、JS なし!)はアニメーションをスクロール位置にリンクします。animation-timeline: scroll() はアニメーションをページスクロール進行に結び付けます(上部で 0%、下部で 100%)。animation-timeline: view() は要素がビューポートに入る/出ることに結び付けます。animation-range はスクロールに対してアニメーションが開始/終了する時を定義します(entry、exit、cover、contain)。これにより JavaScript やスクロールイベントリスナーなしでスクロールプログレスバー、スクロール時表示、パララックス効果が可能になります。Chrome 115+ でサポート、他ブラウザにはプログレッシブエンハンスメントを推奨。

css
/* Animate as user scrolls */
@keyframes fade-in {
  from { opacity: 0; transform: translateY(50px); }
  to   { opacity: 1; transform: translateY(0); }
}

.reveal {
  animation: fade-in linear;
  animation-timeline: view();
  animation-range: entry 0% cover 40%;
}

/* Progress bar based on scroll position */
.progress-bar {
  position: fixed;
  top: 0; left: 0;
  height: 4px;
  background: #3498db;
  width: 100%;
  transform-origin: left;
  animation: grow linear;
  animation-timeline: scroll();
}

@keyframes grow {
  from { transform: scaleX(0); }
  to   { transform: scaleX(1); }
}

View Timeline Ranges

View timeline ranges はアニメーションが正確にいつ発生するかを制御します。'entry' は要素がビューポートに入る時、'exit' は出る時、'cover' は entry 開始から exit 終了まで、'contain' は要素が完全に可視の時です。パーセンテージで各範囲内を微調整します。animation-range: entry 10% entry 90% はアニメーションが entry の 10% から entry の 90% まで実行されることを意味します。スティッキーヘッダーには、ピクセル範囲(0 200px)付きの scroll() が絶対スクロール距離に基づいてアニメーションします。これは複雑な JavaScript スクロールハンドラを宣言的 CSS で置き換えます。

css
/* Element animates as it enters viewport */
@keyframes slide-up {
  from { opacity: 0; transform: translateY(100px); }
  to   { opacity: 1; transform: translateY(0); }
}

.section {
  animation: slide-up linear both;
  animation-timeline: view();
  /* Ranges: entry, exit, cover, contain */
  animation-range: entry 10% entry 90%;
}

/* Sticky header that shrinks on scroll */
.header {
  position: sticky;
  top: 0;
  animation: shrink linear both;
  animation-timeline: scroll();
  animation-range: 0 200px;
}
@keyframes shrink {
  to { padding: 0.5rem 1rem; font-size: 0.9em; }
}

scroll-behavior とスムーズスクロール

html(または任意のスクロールコンテナ)の scroll-behavior: smooth はアンカーリンクナビゲーションと scrollIntoView() をジャンプではなく滑らかにアニメーションします。これは JavaScript スムーズスクロールライブラリの 1 行の置き換えです。常に prefers-reduced-motion を尊重してください — 一部のユーザーは乗り物酔いを経験するため、スムーズスクロールを無効にします。scroll-snap-type: proximity(mandatory 対)はスムーズスクロールと自然な感触のためにうまく組み合わさります。block: 'start'/'center'/'end' 付きの scrollIntoView がターゲットの垂直配置を制御します。

css
/* Smooth scrolling for anchor links */
html {
  scroll-behavior: smooth;
}

/* With scroll snap */
html {
  scroll-behavior: smooth;
  scroll-snap-type: y proximity;
}

/* Target specific elements */
.container {
  scroll-behavior: smooth;
  overflow-y: auto;
}

/* JavaScript: scroll to element */
<script>
document.querySelector(".section-3")
  .scrollIntoView({ behavior: "smooth", block: "start" });

/* Scroll to top */
window.scrollTo({ top: 0, behavior: "smooth" });
</script>

/* Respect reduced motion */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
}
16

CSS カウンター

基本カウンター

CSS カウンターは JavaScript なしで要素を自動採番します。counter-reset がカウンターを初期化します(親または任意の祖先で)。counter-increment が増加させます(通常採番される要素で)。counter(name) が content で現在値を表示します。カウンターはドキュメント全体の採番を自動的に処理します。これは見出し、リストアイテム、図、任意の連続コンテンツの採番に理想的です。カウンターはリセットされた要素とその子孫にスコープされます。

css
/* Initialize counter on parent */
body {
  counter-reset: section;
}

/* Increment and display */
h2::before {
  counter-increment: section;
  content: "Section " counter(section) ": ";
  color: #3498db;
  font-weight: bold;
}

/* Result: Section 1: Introduction, Section 2: Methods... */

ネストされたカウンター

ネストされたカウンターは階層的採番(1.1、1.2、2.1 など)を作成します。親見出しでサブカウンターをリセットします(h2 で counter-reset: section)。各 h2 が新しい章を開始し section カウンターをリセットします。各 h3 が現在の章内の section カウンターを増加させます。content プロパティが区切り文字付きで複数の counter() 呼び出しを組み合わせます。これは書籍や技術文書の採番方法を反映します。カウンターは DOM 構造とリセットポイントに基づいて自然にカスケードします。

css
body {
  counter-reset: chapter;
}

h2 {
  counter-reset: section;
  counter-increment: chapter;
}
h2::before {
  content: "Chapter " counter(chapter) ". ";
}

h3 {
  counter-increment: section;
}
h3::before {
  content: counter(chapter) "." counter(section) " ";
}

/* Result: Chapter 1.  / 1.1 / 1.2 / Chapter 2. / 2.1 ... */

カウンタースタイル

counter() は style 引数を受け入れます:decimal(デフォルト)、decimal-leading-zero(01、02)、lower/upper-alpha(a/b または A/B)、lower/upper-roman(i/ii または I/II)。@counter-style が循環シンボル、加法システム、記号表記でカスタムカウンタースタイルを定義します。system: cyclic はシンボルを繰り返し、system: additive はローマ数字のようなシステムを作成します。カスタムカウンタースタイルは国際化リスト、カスタム箇条書き、装飾的採番に強力です。@counter-style のブラウザサポートはモダンブラウザで良好です。

css
/* Different number styles */
ol {
  counter-reset: item;
  list-style: none;
}
li::before {
  counter-increment: item;
  /* decimal, decimal-leading-zero, lower-alpha,
     upper-alpha, lower-roman, upper-roman */
  content: counter(item, upper-roman) ". ";
}

/* Leading zeros: 01, 02, 03... */
li::before {
  content: counter(item, decimal-leading-zero) ". ";
}

/* Custom @counter-style */
@counter-style thumbs {
  system: cyclic;
  symbols: "👍" "👎";
  suffix: " ";
}
.thumbs-list { list-style-type: thumbs; }

counters() 関数(ネスト)

counters() 関数(複数形)は指定された区切り文字でレベルを区切った完全なカウンターパスを文字列として返します。これはネストされたカウンタースコープを自動的に処理します — 各ネストされた ol が新しいカウンタースコープを作成します。counters(nested, '.') は深くネストされたリストに対して 1、1.1、1.1.1 を生成します。これは現在のレベルのみを表示する counter() とは異なります。ネストされたリストのアウトラインスタイル採番、目次、階層メニューに counters() を使用します。区切り文字列は任意の文字(. , - > など)にできます。

css
/* counters() creates full path string */
ol {
  counter-reset: nested;
  list-style: none;
}
li::before {
  counter-increment: nested;
  /* counters() returns all levels separated by a string */
  content: counters(nested, ".") " - ";
  font-weight: bold;
}

/* For nested <ol> elements:
   1 - Top level
   1.1 - Nested
   1.1.1 - Deeper
   2 - Top level again
*/

図とテーブルのカウンター

カウンターはドキュメント内の図、テーブル、数式の自動採番に完璧です。章ごとにリセット(h2 で counter-reset)して採番が各章で再開します。figcaption/caption の ::before 疑似要素が番号を前置します。これによりコンテンツが並べ替えられた時に更新される一貫した自動採番が保証されます。相互参照(「図 3 を参照」)には、CSS カウンターは直接役立ちません — JS または HTML アンカーが必要です。しかし表示採番には、これはクリーンでメンテナンスフリーなソリューションです。

css
body {
  counter-reset: figure table;
}

figure figcaption::before {
  counter-increment: figure;
  content: "Figure " counter(figure) ": ";
  font-weight: bold;
  color: #2c3e50;
}

table caption::before {
  counter-increment: table;
  content: "Table " counter(table) ": ";
  font-weight: bold;
  color: #2c3e50;
}

/* Reset figure counter per chapter */
h2 {
  counter-reset: figure;
}
18

ダークモードとカラースキーム

prefers-color-scheme

prefers-color-scheme: dark はユーザーの OS/ブラウザのダークモード設定を検出します。ライトモード用のテーマ変数を :root で定義し、ダークメディアクエリで上書きします。CSS 変数を使用すると変数値のみを変更します — すべてのコンポーネントが自動的に更新されます。これがダークモードの標準アプローチです。メディアクエリは 'light' と 'no-preference' もサポートします。OS ダークモードの切り替えまたは Chrome DevTools の Rendering タブ(Emulate CSS prefers-color-scheme)でテストします。

css
/* Light mode (default) */
:root {
  --bg: #ffffff;
  --text: #1a1a1a;
  --surface: #f5f5f5;
  --border: #e0e0e0;
  --accent: #3498db;
}

/* Dark mode */
@media (prefers-color-scheme: dark) {
  :root {
    --bg: #1a1a1a;
    --text: #e0e0e0;
    --surface: #2a2a2a;
    --border: #404040;
    --accent: #5dade2;
  }
}

body {
  background: var(--bg);
  color: var(--text);
}

手動テーマトグル

手動テーマトグルには、システム設定を上書きする <html> の data-theme 属性を使用します。ユーザーの選択を localStorage に格納して永続化します。ページ読み込み時、間違ったテーマのフラッシュ(FOUC)を避けるためレンダリング前に localStorage をチェックします。color-scheme: light dark がブラウザにネイティブ UI 要素(スクロールバー、フォームコントロール)を適切なスキームでレンダリングするよう伝えます。最良の UX のため、保存された選択がない時はシステム設定をデフォルトにします:フォールバックとして matchMedia('(prefers-color-scheme: dark)') をチェックします。

css
/* Default to system preference, allow override */
:root {
  color-scheme: light dark;
}

/* Manual dark mode via data attribute */
[data-theme="dark"] {
  --bg: #1a1a1a;
  --text: #e0e0e0;
}

[data-theme="light"] {
  --bg: #ffffff;
  --text: #1a1a1a;
}

/* Toggle button */
<button onclick="toggleTheme()">Toggle Theme</button>
<script>
function toggleTheme() {
  const current = document.documentElement.dataset.theme;
  const next = current === "dark" ? "light" : "dark";
  document.documentElement.dataset.theme = next;
  localStorage.setItem("theme", next);
}
// Load saved preference
const saved = localStorage.getItem("theme");
if (saved) document.documentElement.dataset.theme = saved;
</script>

color-scheme プロパティ

color-scheme プロパティはブラウザにページがサポートするカラースキームを伝え、ネイティブ UI 要素に影響します:スクロールバー、フォームコントロール(入力、ボタン、ドロップダウン)、デフォルトの背景/キャンバス色、::placeholder 色。これがないと、ダークモードでもフォームコントロールがライトに表示される場合があります(不協和なミスマッチ)。:root に color-scheme: light dark を設定してネイティブ要素が自動適応するようにします。これはダークモードの洗練を劇的に向上させる 1 行の修正です。CSS 変数テーマとは別です — ブラウザネイティブレンダリングのみに影響します。

css
:root {
  /* Tell browser this page supports both schemes */
  color-scheme: light dark;
}

/* Force light only */
.light-only {
  color-scheme: light;
}

/* Force dark only */
.dark-only {
  color-scheme: dark;
}

/* This affects native UI: scrollbars, form controls,
   default colors (canvas, text), and form elements */
input, textarea, select {
  /* Will use dark form controls in dark mode */
  color-scheme: dark;
}

ダークモードの画像とメディア

画像はダークモードで特別な扱いが必要です。白背景の図は filter: invert(1) hue-rotate(180deg) で反転できます — hue-rotate が色の歪みを防ぎます。人物の写真は絶対に反転しないでください。目の疲労を減らすため明るさをわずかに下げます。ロゴとアイコンには、ダーク最適化版を提供するために media-query ソース付きの <picture> を使用します。currentColor の SVG は自動的に適応します。背景画像にはメディアクエリでダークモード代替を提供します。可読性のために両モードで画像を常にテストしてください。

css
@media (prefers-color-scheme: dark) {
  /* Invert images that are essentially white-background */
  img[src*="logo"],
  img[src*="diagram"] {
    filter: invert(1) hue-rotate(180deg);
  }

  /* Reduce brightness of photos */
  img.photo {
    filter: brightness(0.85);
  }

  /* Don't invert photos with people */
  img[src*="photo"]:not(.invertable) {
    filter: none;
  }
}

/* Use dark-mode-friendly SVG */
<picture>
  <source srcset="logo-dark.svg"
          media="(prefers-color-scheme: dark)">
  <img src="logo-light.svg" alt="Logo">
</picture>

スムーズなテーマトランジション

すべての要素にカラートランジションを追加するとスムーズなテーマ切り替えアニメーションを作成します。ただし、初期ページ読み込み時にアニメーション色のフラッシュを引き起こす可能性があります。解決策:テーマ切り替え時と初期読み込み時に <html> に .no-transition クラスを追加し、1 フレーム後に削除します。常に prefers-reduced-motion を尊重してトランジションを無効にします。選択的になってください — すべてのプロパティのトランジションはパフォーマンスに影響する可能性があります。色関連プロパティ(background-color、color、border-color、box-shadow)のみトランジションします。

css
/* Transition colors when theme changes */
* {
  transition: background-color 0.3s ease,
              color 0.3s ease,
              border-color 0.3s ease;
}

/* But not during initial load (prevent flash) */
.no-transition * {
  transition: none !important;
}

<script>
// Disable transitions during theme switch
function toggleTheme() {
  document.documentElement.classList.add("no-transition");
  document.documentElement.dataset.theme = newTheme;
  // Re-enable after switch
  requestAnimationFrame(() => {
    document.documentElement.classList.remove("no-transition");
  });
}
</script>

/* Respect reduced motion */
@media (prefers-reduced-motion: reduce) {
  * { transition: none !important; }
}
19

CSS 関数詳細

clamp()、min()、max()

clamp(min, preferred, max) は流体タイポグラフィとスペーシングの聖杯です — preferred 値でスケールしますが min/max 範囲を超えません。min() はより小さい値を選びます(レスポンシブな max-width に最適)。max() はより大きい値を選びます(最小サイズに最適)。これらは連続流体スケーリングを提供して多くのメディアクエリを排除します。clamp の preferred 値は通常ビューポート単位(vw、vh)またはコンテナ単位(cqw)を使用します。これがブレイクポイントなしのレスポンシブデザインのモダンなアプローチです。

css
/* clamp(min, preferred, max) */
h1 {
  font-size: clamp(1.5rem, 5vw, 3rem);
  /* Never smaller than 1.5rem, never larger than 3rem,
     preferred is 5vw */
}

/* min(): use the smaller value */
.container {
  width: min(100% - 2rem, 1200px);
  /* Full width minus padding, but max 1200px */
}

/* max(): use the larger value */
.hero {
  font-size: max(2rem, 4vw);
  /* At least 2rem, grows with viewport */
}

/* Combining for responsive padding */
.card {
  padding: clamp(1rem, 3vw, 2rem);
}

calc() の高度な使用

calc() は混合単位(px、%、em、vw など)で計算します。加算と減算には演算子の周りにスペースが必要です(calc(100%-20px) ではなく calc(100% - 20px))。乗算と除算は長さではなく数値でのみ動作します(calc(10px * 2) は有効、calc(10px * 10px) は無効)。calc() はネストできますが括弧も動作します。CSS 変数と組み合わせて calc() は動的で計算されたデザインシステムを可能にします。固定と流体寸法を組み合わせるレスポンシブレイアウトに不可欠です。

css
/* Mixed units */
.sidebar {
  width: calc(100% - 250px); /* full width minus fixed sidebar */
  height: calc(100vh - 60px); /* viewport minus header */
}

/* Nested calc */
.element {
  margin: calc(calc(100% - 50px) / 2);
  /* Simplified: */
  margin: calc((100% - 50px) / 2);
}

/* With CSS variables */
:root { --gap: 20px; }
.grid {
  gap: calc(var(--gap) * 2);
}

/* Math operations: + - * / */
.padding {
  padding: calc(1rem + 2px);
  width: calc(50% - 10px);
}

attr() 関数

attr() は HTML 属性値を取得し、最も一般的に疑似要素の content で使用されます。CSS のみのツールチップの基盤です(data-tooltip 属性 → ::after content)。attr() は content プロパティでのみ確実に動作します。型キャスト付きの他のプロパティ(width、color など)での attr() の使用(attr(data-size px))は CSS Values Level 5 の一部ですがブラウザサポートは最小限です。今のところ、HTML からの動的値には CSS 変数を使用します:style='--size: 100px' を設定し var(--size) を使用します。

css
/* Display attribute values */
a[href]::after {
  content: attr(href);
}

/* data attributes for tooltips */
.tooltip::after {
  content: attr(data-tooltip);
  display: none;
  position: absolute;
}
.tooltip:hover::after {
  display: block;
}

/* HTML: <div class="tooltip" data-tooltip="Help text">?</div> */

/* Note: attr() for non-content properties is experimental */
/* This doesn't work widely yet: */
/* .box { width: attr(data-width px); } */

フォールバック付き var()

var() は第 2 引数としてフォールバックを受け入れ、変数が定義されていない時に使用されます。フォールバックは連鎖できます:var(--a, var(--b, var(--c, default)))。これによりプログレッシブエンハンスメントとマルチレベルテーマが可能になります。空の変数値(--defined: ;)は「設定済み」のためフォールバックはトリガーされません — これにより条件付き CSS パターンが可能になります。フォールバックには calc() や他の関数を含む任意の有効な CSS 値を含められます。すべてのコンテキストで定義されるとは限らないオプションのテーマ変数にフォールバックを使用します。

css
/* Single fallback */
color: var(--text-color, #333);

/* Chained fallbacks */
color: var(--text, var(--default-text, black));

/* Fallback in shorthand */
background: var(--bg, white) url(image.png);

/* Fallback with calc */
width: calc(100% - var(--sidebar, 250px));

/* Check if variable is set */
:root {
  --defined: ; /* empty space = valid value */
}
.conditional {
  --use-default: var(--defined, initial);
  /* If --defined is empty, --use-default = initial */
}

gradient 関数

CSS グラデーションは画像なしで色間の滑らかな遷移を作成します。linear-gradient(方向 + 色)、radial-gradient(中心から外向き)、conic-gradient(点の周りの回転)の 3 つのタイプがあります。ハードストップ(2 色の同じパーセンテージ)は鋭いバンドを作成します。repeating-linear-gradient はストライプのようなパターンを作成します。グラデーションは複数の背景でレイヤー化できます(カンマ区切り、最初 = 最上位レイヤー)。conic グラデーションは純粋な CSS でパイチャートとカラーホイールを可能にします。グラデーションは解像度非依存で画像ファイルよりパフォーマンスが良いです。

css
/* Linear gradient */
.bg { background: linear-gradient(45deg, #3498db, #e74c3c); }
.bg2 { background: linear-gradient(to right, red, orange, yellow); }

/* Radial gradient */
.radial { background: radial-gradient(circle, white, blue); }
.radial2 { background: radial-gradient(circle at top left, #fff, #000); }

/* Conic gradient */
.pie { background: conic-gradient(red 0% 30%, blue 30% 70%, green 70% 100%); }

/* Repeating gradients */
.stripes { background: repeating-linear-gradient(45deg, #ccc 0 10px, #fff 10px 20px); }

/* Hard color stops (sharp edges) */
.hard { background: linear-gradient(to right, #000 50%, #fff 50%); }

/* Multiple backgrounds */
.multi {
  background:
    linear-gradient(rgba(0,0,0,0.5), transparent),
    url(photo.jpg);
}
20

CSS 変数

変数の定義と使用

CSS カスタムプロパティ(変数)は --name で定義し var() で使用します。グローバルアクセスのために :root で宣言します。Sass 変数とは異なり、ライブです — JavaScript で変数を変更すると使用するすべての要素が即座に更新されます。

css
:root {
  --primary: #3498db;
  --spacing: 16px;
  --radius: 8px;
}

.button {
  background: var(--primary);
  padding: var(--spacing);
  border-radius: var(--radius);
}

フォールバック値

var() は変数が未定義の時のフォールバックとして第 2 引数を受け入れます。フォールバックはネストでき、デフォルトを連鎖できます。カスタムプロパティをサポートしないブラウザのために、最初に通常の値を宣言し、var() で上書きします。

css
.box {
  color: var(--brand, #333);
  background: var(--bg, var(--default-bg, white));
}

/* Provide fallback for older browsers */
.element {
  color: #333;
  color: var(--text-color, #333);
}

JavaScript インタラクション

JavaScript は getComputedStyle().getPropertyValue() で変数を読み取り、setProperty() で設定します。これによりランタイムテーマが簡単になります — いくつかの変数を切り替えるだけでアプリ全体をリスタイルできます。

css
// Read a variable
const color = getComputedStyle(document.documentElement)
  .getPropertyValue('--primary');

// Set a variable on an element
document.documentElement.style.setProperty('--primary', '#e74c3c');

// Toggle a theme
document.documentElement.setAttribute('data-theme', 'dark');

スコープと継承

カスタムプロパティは継承するため、:root に設定された変数はすべての要素にカスケードします。.card で再定義するとそのサブツリーのみ上書きします。このスコープにより詳細度の争いなしのコンポーネントレベルテーマが可能になります。

css
:root { --size: 16px; }

.card {
  --size: 20px; /* Overrides only within .card */
  font-size: var(--size);
}

.card .text { font-size: var(--size); } /* 20px */
.other { font-size: var(--size); }       /* 16px */

レスポンシブ変数

メディアクエリ内で変数を再定義して、ルールを書き直さずにレイアウト全体をブレイクポイントに応答させます。1 つの変数を変更するとそれを使用するすべての要素が適応します — 各プロパティを個別に上書きするよりはるかにクリーンです。

css
:root {
  --container-width: 1200px;
  --font-size: 18px;
}

@media (max-width: 768px) {
  :root {
    --container-width: 100%;
    --font-size: 16px;
  }
}

.container { max-width: var(--container-width); }
body { font-size: var(--font-size); }
21

アニメーションとキーフレーム

@keyframes と Animation ショートハンド

@keyframes がアニメーションの開始(from/0%)と終了(to/100%)状態を定義します。animation ショートハンドは name、duration、timing-function、delay、iteration-count、direction、fill-mode、play-state を組み合わせます。forwards が最終状態を保持します。

css
@keyframes slide-in {
  from { transform: translateX(-100%); opacity: 0; }
  to   { transform: translateX(0); opacity: 1; }
}

.element {
  animation: slide-in 0.5s ease-out forwards;
}

/* Shorthand: name duration timing delay count direction fill-mode */
.bounce {
  animation: bounce 1s cubic-bezier(0.68, -0.55, 0.27, 1.55) 0s infinite alternate;
}

トランジション

トランジションはプロパティ値が変更される時に滑らかに補間します。どのプロパティがトランジションするかとその duration/timing を指定します。transition: all は便利ですがパフォーマンスを損なう可能性があります — 特定のプロパティをリストすることを優先してください。

css
.button {
  background: blue;
  transition: background 0.3s ease, transform 0.2s ease-out;
}

.button:hover {
  background: darkblue;
  transform: scale(1.05);
}

/* Transition all changed properties */
.card { transition: all 0.3s ease; }

タイミング関数

タイミング関数は加速度曲線を制御します。ease-out は速く始まり減速します(入場に適しています)。ease-in は遅く始まり加速します(退場に適しています)。cubic-bezier でカスタム曲線を作成できます。steps() は離散効果を作成します。

css
/* Built-in */
.ease-linear { transition: all 1s linear; }
.ease-out    { transition: all 1s ease-out; }

/* Custom cubic-bezier(x1, y1, x2, y2) */
.custom { transition: all 1s cubic-bezier(0.68, -0.55, 0.27, 1.55); }

/* Steps */
.steps { transition: all 1s steps(5, end); }

アニメーションイベント

JavaScript は animationstart、animationiteration(各ループで発火)、animationend をリッスンできます。animation-play-state プロパティ(paused/running)で再生を制御します。animationend と組み合わせてアニメーションを連鎖します。

css
const el = document.querySelector('.animate');
el.addEventListener('animationstart', () => console.log('Started'));
el.addEventListener('animationiteration', () => console.log('Looped'));
el.addEventListener('animationend', () => console.log('Finished'));

// Pause and resume
el.style.animationPlayState = 'paused';
el.style.animationPlayState = 'running';

パフォーマンス:transform と opacity

60fps パフォーマンスのために transform と opacity のみをアニメーションします — これらはレイアウトをトリガーせずに GPU で実行されます。width、height、top、margin のアニメーションは毎フレームレイアウトの再計算を強制します。ブラウザにヒントを与えるため will-change を控えめに使用します。

css
/* GOOD: GPU-accelerated, cheap */
.fade { transition: opacity 0.3s; }
.move { transition: transform 0.3s; }

/* BAD: triggers layout/paint, expensive */
.resize { transition: width 0.3s, height 0.3s; }

/* Hint the browser to optimize */
.card { will-change: transform; }
22

Transforms 3D

2D Transforms

2D transform は周囲のレイアウトに影響せずに要素を移動、回転、スケール、スキューします。transform は GPU で合成され、アニメーション用にパフォーマンスが高いです。順序が重要です:rotate 後に translate は回転した軸に沿って移動します。

css
.box { transform: translate(50px, 20px); }
.box { transform: rotate(45deg); }
.box { transform: scale(1.5); }
.box { transform: skew(20deg, 10deg); }

/* Combined — order matters */
.combo { transform: translate(100px, 0) rotate(90deg) scale(1.2); }

3D Transforms と Perspective

3D transform は rotateX、rotateY、rotateZ、translateZ、scaleZ を追加します。親の perspective がすべての子に共有消失点を与えます — 値が低いほど 3D 効果が誇張されます。transform-style: preserve-3d がネストされた要素を 3D に保ちます。

css
.scene { perspective: 1000px; }

.card {
  transform: rotateY(45deg);
  transform-style: preserve-3d;
}

/* Perspective on the element itself */
.self { transform: perspective(800px) rotateX(30deg); }

/* Transform origin */
.pivot { transform-origin: top left; transform: rotate(45deg); }

フリップカード効果

古典的なフリップカードはコンテナで preserve-3d を使用し、前面と背面を絶対配置します。backface-visibility: hidden が各面の裏を非表示にします。コンテナがフリップした時に表示されるよう、背面は 180 度事前回転されています。

css
.card { perspective: 1000px; }
.inner {
  position: relative;
  transform-style: preserve-3d;
  transition: transform 0.6s;
}
.card:hover .inner { transform: rotateY(180deg); }
.front, .back {
  position: absolute;
  backface-visibility: hidden;
}
.back { transform: rotateY(180deg); }

6 面のキューブ

3D キューブは 6 つの面から構築され、それぞれが軸に沿って 50px(キューブ幅の半分)外側に移動されます。preserve-3d が面を 3D 空間に配置します。キューブ transform をアニメーションして回転させます。

css
.cube {
  position: relative;
  width: 100px; height: 100px;
  transform-style: preserve-3d;
  transform: rotateX(-20deg) rotateY(30deg);
}
.face { position: absolute; width: 100px; height: 100px; }
.front  { transform: translateZ(50px); }
.back   { transform: rotateY(180deg) translateZ(50px); }
.right  { transform: rotateY(90deg) translateZ(50px); }
.left   { transform: rotateY(-90deg) translateZ(50px); }
.top    { transform: rotateX(90deg) translateZ(50px); }
.bottom { transform: rotateX(-90deg) translateZ(50px); }

Matrix とパフォーマンス

matrix() と matrix3d() は任意の transform を単一の行列として表現します — JavaScript で transform を計算する時に便利です。translateZ(0) または will-change: transform が GPU アクセラレーションを強制し、アニメーションの滑らかさを向上させます。レイヤーの過剰使用は避けてください。

css
/* matrix(a, b, c, d, e, f) encodes translate, rotate, scale, skew */
.transformed { transform: matrix(1, 0, 0, 1, 100, 50); }

/* 3D matrix */
.cube { transform: matrix3d(1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1); }

/* Hardware acceleration hint */
.gpu { transform: translateZ(0); }
23

CSS Grid 詳細

Grid Template Areas

grid-template-areas はグリッドセルに視覚的に名前を付け、レイアウト意図を明確にします。各引用符付き行はグリッド行を表し、同一の名前はセルにまたがります。空のセルにはドット(.)を使用します。エリアは長方形を形成する必要があります — L 字型は無効です。

css
.layout {
  display: grid;
  grid-template-columns: 200px 1fr;
  grid-template-rows: auto 1fr auto;
  grid-template-areas:
    "header header"
    "sidebar main"
    "footer footer";
  gap: 16px;
}
.header { grid-area: header; }
.sidebar { grid-area: sidebar; }
.main   { grid-area: main; }
.footer { grid-area: footer; }

minmax と auto-fit

repeat(auto-fit, minmax(200px, 1fr)) はメディアクエリなしでレスポンシブグリッドを作成します:列は少なくとも 200px で行を埋めるために伸びます。auto-fit は空のトラックを折りたたみ、auto-fill は予約済みとして保持します。

css
.grid {
  display: grid;
  /* Columns auto-fit, each at least 200px, sharing leftover space */
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: 20px;
}

/* Fixed number that wraps */
.wrap {
  grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
}

Grid 配置

Grid 配置は 2 つのレベルで動作します:コンテナ(justify/align-items と justify/align-content)とアイテム(justify/align-self)。justify-* はインライン軸を制御し、align-* はブロック軸を制御します。place-items: center は両方のショートハンドです。

css
.grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  justify-items: center;
  align-items: center;
  justify-content: space-between;
  align-content: center;
}

.item {
  justify-self: end;
  align-self: start;
}

スパニングとライン配置

グリッド行番号でアイテムを配置(1 / 3 は行 1 から行 3 を意味)または span で(span 2)。負の行は末尾からカウントします(-1 が最後の行)。grid-column: 1 / -1 はアイテムを全幅にまたがらせます。

css
.grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
}
.header { grid-column: 1 / -1; }       /* full width */
.sidebar { grid-column: 1 / 3; }       /* columns 1-2 */
.main { grid-column: span 2; }          /* span 2 columns */
.tall { grid-row: 1 / span 2; }         /* span 2 rows */

Subgrid

subgrid は子グリッドが親トラック定義を継承し、ネストされたグリッド間で列や行が完璧に整列します。subgrid なしではネストされたグリッドは独自のトラックを定義しミスアラインする可能性があります。2023 年以降すべてのモダンブラウザでサポートされています。

css
.card {
  display: grid;
  grid-template-rows: auto 1fr auto;
  /* Inherit column tracks from parent */
  grid-template-columns: subgrid;
  grid-column: span 3;
}

.parent {
  display: grid;
  grid-template-columns: repeat(6, 1fr);
}
24

CSS 関数

calc()

calc() は混合単位(px、%、vw、em、rem)で計算します。+ と - の周りに常にスペースを置いてください(calc(100%-20px) は失敗、calc(100% - 20px) は動作)。乗算と除算は片側が単位のない数値である必要があります。

css
.sidebar {
  width: calc(100% - 250px);
  padding: calc(16px + 2vw);
  font-size: calc(14px + 0.5vw);
}

/* Nested calc */
.full { width: calc(calc(100% - 20px) / 2); }

/* With variables */
.box { margin: calc(var(--gap) * 2); }

clamp()

clamp() は値を最小値と最大値の間に拘束し、中間に preferred 値を持ちます。流体タイポグラフィとスペーシングを構築する最もクリーンな方法です — 値はスケールしますが範囲を下回ったり上回ったりしません。

css
/* clamp(MIN, PREFERRED, MAX) */
h1 {
  font-size: clamp(1.5rem, 4vw, 3rem);
}

.sidebar {
  width: clamp(200px, 25vw, 400px);
}

.padding {
  padding: clamp(1rem, 2vw + 1rem, 2rem);
}

min() と max()

min() は最小の引数を返し、max() は最大を返します。clamp(正確に 3 つの値を取る)とは異なり、min/max は任意の数の引数を受け入れます。値を上限するには min() を、下限するには max() を使用します。

css
/* Picks the smallest/largest of comma-separated values */
.box {
  width: min(100% - 32px, 800px);
  font-size: max(16px, 2vw);
}

/* With multiple units */
.responsive {
  padding: min(5vw, 2rem);
  margin: max(1rem, 3vw);
}

フォールバック付き var()

var() の第 2 引数はカスタムプロパティが未定義の時にのみ使用されます。無効な値の場合、プロパティは継承値または初期値にフォールバックします。var() 呼び出しをネストしてフォールバックを連鎖します。

css
.button {
  background: var(--btn-bg, #007bff);
  color: var(--text, var(--default-text, black));
  width: var(--width, 100%);
}

color-mix() と color 関数

color-mix() は指定された色空間(srgb、oklch、lab)で 2 色をブレンドします。ブランドカラーからティントとシェードを導出するモダンな方法です。相対カラー構文(from キーワード)で個別チャネルを調整できます。

css
/* Mix two colors */
.muted { color: color-mix(in srgb, red 30%, blue); }

/* Adjust relative lightness */
.lighter { background: color-mix(in oklch, var(--brand) 70%, white); }
.darker  { background: color-mix(in oklch, var(--brand) 70%, black); }

/* Relative color syntax (newest) */
.tint { background: oklch(from var(--brand) calc(l + 0.1) c h); }
25

Scroll-Driven アニメーション

animation-timeline の基礎

animation-timeline: scroll(root) はアニメーションをページスクロール位置に結び付けます — ユーザーがスクロールするとアニメーションが進行します。JavaScript 不要。これはスクロールイベントリスナーよりはるかに滑らかです。

css
@keyframes grow {
  from { transform: scaleX(0); }
  to   { transform: scaleX(1); }
}

.progress-bar {
  animation: grow linear;
  animation-timeline: scroll(root);
  transform-origin: left;
}

view() Timeline

view() は要素がビューポートに入る/出ることに結び付けられたタイムラインを作成します。animation-range がエントリのどの部分がアニメーションをトリガーするかを制御します。IntersectionObserver なしのスクロール表示効果に完璧です。

css
@keyframes reveal {
  from { opacity: 0; transform: translateY(40px); }
  to   { opacity: 1; transform: translateY(0); }
}

.card {
  animation: reveal linear;
  animation-timeline: view();
  animation-range: entry 0% entry 100%;
}

Scroll-Linked プログレスバー

スクロールすると満たされる固定プログレスバー。animation-timeline: scroll(root) がページスクロールをアニメーション 0-100% 範囲にマッピングします。transform-origin: 0 50% がバーを左から成長させます。

css
body { min-height: 200vh; }
.progress {
  position: fixed;
  top: 0; left: 0;
  height: 4px;
  width: 100%;
  background: linear-gradient(to right, #6366f1, #ec4899);
  transform-origin: 0 50%;
  animation: scale-x linear;
  animation-timeline: scroll(root);
}
@keyframes scale-x {
  from { transform: scaleX(0); }
  to   { transform: scaleX(1); }
}

名前付き Scroll Timeline

アニメーションを特定のスクロール可能要素(ルートでない)に結び付ける必要がある時、コンテナに scroll-timeline-name を定義し animation-timeline で参照します。scroll-timeline-axis がトラックする軸を選びます(block/inline/x/y)。

css
.scroll-container {
  scroll-timeline-name: --cards;
  scroll-timeline-axis: block;
  overflow-y: scroll;
  height: 400px;
}

.card {
  animation: fade-in linear;
  animation-timeline: --cards;
}

@keyframes fade-in {
  from { opacity: 0; }
  to   { opacity: 1; }
}

View Range 調整

animation-range は要素可視性に対してアニメーションがいつ実行されるかを微調整します。cover 0% から cover 100% は要素が入ってから完全に出るまでにまたがります。contain 0% から 100% は完全に内側にある時のみにまたがります。

css
.image {
  animation: parallax linear;
  animation-timeline: view();
  animation-range: cover 0% cover 100%;
}

@keyframes parallax {
  from { transform: translateY(-20%); }
  to   { transform: translateY(20%); }
}

/* Only animate while in view */
.pulse {
  animation: pulse 1s infinite;
  animation-timeline: view();
  animation-range: contain 0% contain 100%;
}
26

CSS Layers

@layer の定義

@layer はスタイルを名前付きカスケードレイヤーにグループ化します。宣言行の順序が優先度を設定します:後のレイヤーが前のレイヤーより優先します。セレクタ詳細度に関わりらず。これにより大規模スタイルシートに予測可能な順序をもたらします。

css
@layer reset, base, components, utilities;

@layer reset {
  * { margin: 0; padding: 0; box-sizing: border-box; }
}

@layer base {
  body { font-family: sans-serif; line-height: 1.6; }
}

@layer utilities {
  .hidden { display: none !important; }
}

レイヤー優先度

レイヤー内では通常の詳細度ルールが適用されます。しかしレイヤー間では後のレイヤーが常に勝ちます — components の単一クラスが base の ID より勝ちます。レイヤー化されていないスタイルはすべてのレイヤー化されたスタイルより優先されます。

css
@layer base, components;

@layer base {
  /* Even though this is more specific, base loses */
  div.button { color: black; }
}

@layer components {
  .button { color: blue; } /* This wins */
}

/* Unlayered styles always beat layered styles */
.button { color: red; }

レイヤーへのインポート

@import ... layer(name) がスタイルシート全体を名前付きレイヤーに配置します。これはサードパーティ CSS を制御するのに不可欠です:Bootstrap を vendor レイヤーに配置し、カスタムスタイル(後のレイヤーまたはレイヤー化なし)が常に勝ちます。

css
@import url("reset.css") layer(reset);
@import url("bootstrap.css") layer(vendor);

@layer reset, vendor, custom;

@layer custom {
  .btn { background: hotpink; }
}

ネストされたレイヤー

レイヤーはネストでき、階層を作成します。framework.theme は framework 内の theme サブレイヤーを指します。ネストされたレイヤーは同じ優先度ルールに従います:framework 内で theme が base より勝ちます。

css
@layer framework {
  @layer base, theme;

  @layer base {
    .btn { padding: 8px; }
  }
  @layer theme {
    .btn { color: navy; }
  }
}

/* Reference nested layer */
@layer framework.theme {
  .btn { color: hotpink; }
}

レイヤー条件ロジック

@layer ブロックは @media と @supports 内にネストでき、レイヤーメンバーシップが条件に適応します。これにより機能固有のスタイルがレイヤー化されていないスペースに漏出するのではなくレイヤー内に整理されます。

css
@layer base, components;

@media (max-width: 600px) {
  @layer components {
    .nav { flex-direction: column; }
  }
}

@supports (display: grid) {
  @layer components {
    .layout { display: grid; }
  }
}
27

Backdrop Filters

backdrop-filter の基礎

backdrop-filter は要素の背後のコンテンツにフィルターを適用し、すりガラス効果を作成します。Safari サポートのために常に -webkit- プレフィックスを含めてください。ぼかしを可視にするために半透明の背景と組み合わせます。

css
.glass {
  background: rgba(255, 255, 255, 0.2);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  border: 1px solid rgba(255, 255, 255, 0.3);
  border-radius: 12px;
}

複数フィルター

スペース区切りで複数のフィルターを連鎖します:blur、brightness、contrast、grayscale、hue-rotate、invert、opacity、saturate、sepia。それぞれが backdrop に適用されます。色合い付き背景と組み合わせてムードを調整します。

css
.vibrant {
  backdrop-filter: blur(8px) saturate(180%) brightness(1.1);
}

.dark-glass {
  background: rgba(0, 0, 0, 0.4);
  backdrop-filter: blur(12px) grayscale(50%);
}

ブレンドモード

mix-blend-mode は要素が背後のコンテンツとどうブレンドされるかを制御します(backdrop-filter とは別)。multiply は暗くし、screen は明るくし、difference は反転します。テキストの可読性に注意してください。

css
.overlay {
  background: rgba(255, 0, 100, 0.3);
  backdrop-filter: blur(4px);
  mix-blend-mode: multiply;
}

.difference {
  background: white;
  mix-blend-mode: difference;
  backdrop-filter: invert(1);
}

パフォーマンスとフォールバック

backdrop-filter は GPU 集約的で、特に大きなぼかし半径では顕著です。サポートのないブラウザのために確実な背景フォールバックを提供し、@supports で拡張します。backdrop-filter のアニメーションは避けてください — 重大なジャンクを引き起こす可能性があります。

css
/* Fallback for unsupported browsers */
.glass {
  background: rgba(255, 255, 255, 0.9);
}

/* Progressive enhancement */
@supports (backdrop-filter: blur(10px)) {
  .glass {
    background: rgba(255, 255, 255, 0.2);
    backdrop-filter: blur(10px);
  }
}

グラスモーフィズムカード

古典的なグラスモーフィズムカードは半透明の背景、backdrop ぼかし、控えめな光のボーダー(エッジ反射をシミュレート)、ソフトなシャドウを組み合わせます。saturate フィルターがガラス越しに見える色をブーストします。

css
.card {
  background: rgba(255, 255, 255, 0.15);
  backdrop-filter: blur(16px) saturate(180%);
  -webkit-backdrop-filter: blur(16px) saturate(180%);
  border: 1px solid rgba(255, 255, 255, 0.3);
  border-radius: 16px;
  padding: 24px;
  box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1);
}

Was this helpful?

Learning path

Learn from scratch

Learn this language from the ground up with structured lessons.