Skip to content
Published on

モダンCSS完全攻略2025:Flexbox、Grid、Container Queries、Tailwind CSSまで

Authors

はじめに

2025年(ねん)のCSSはかつてないほど強力(きょうりょく)になりました。Container Queries、CSS Nesting、:has()セレクタ、View Transitions API、Scroll-Driven Animationsなど、長年(ながねん)開発者(かいはつしゃ)が待(ま)ち望(のぞ)んでいた機能(きのう)が、すべての主要(しゅよう)ブラウザでサポートされています。

JavaScriptなしで純粋(じゅんすい)なCSSだけで実現(じつげん)できる範囲(はんい)が爆発的(ばくはつてき)に広(ひろ)がり、Tailwind CSS v4はOxideエンジンでビルド速度(そくど)を10倍(ばい)改善(かいぜん)し、ユーティリティファーストパラダイムを次(つぎ)のステージに進化(しんか)させました。

この記事(きじ)では、FlexboxからGrid、Container Queries、モダンセレクタ、アニメーション、Tailwind CSS v4、CSS-in-JS比較(ひかく)、レスポンシブパターン、CSSアーキテクチャまで、モダンCSSのすべてを体系的(たいけいてき)に解説(かいせつ)します。


1. 2025年(ねん)のCSS:新機能(しんきのう)まとめ

1.1 CSS Nesting(ネイティブネスト)

Sassなしで直接(ちょくせつ)CSSでネストが可能(かのう)になりました。

/* ネイティブCSS Nesting */
.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 (width >= 768px) {
    display: grid;
    grid-template-columns: 1fr 2fr;
  }
}

1.2 :has() リレーショナルセレクタ

親要素(おやようそ)を子(こ)の条件(じょうけん)で選択(せんたく)できる革命的(かくめいてき)なセレクタです。

/* 画像を含むカードのスタイル変更 */
.card:has(img) {
  grid-template-rows: 200px 1fr;
}

/* 無効な入力があるフォーム */
form:has(:invalid) .submit-btn {
  opacity: 0.5;
  pointer-events: none;
}

/* チェックされたチェックボックスの兄弟要素 */
input:checked + label {
  color: green;
}

1.3 Container Queriesプレビュー

メディアクエリがビューポート基準(きじゅん)なら、Container Queriesは親(おや)コンテナ基準(きじゅん)です。

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

@container card (min-width: 400px) {
  .card {
    display: grid;
    grid-template-columns: 200px 1fr;
  }
}

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

1.4 CSS Layers (@layer)

カスケードの優先順位(ゆうせんじゅんい)を明示的(めいじてき)に制御(せいぎょ)します。

/* レイヤー順序宣言(後が優先) */
@layer reset, base, components, utilities;

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

@layer base {
  body { font-family: system-ui; line-height: 1.6; }
}

@layer components {
  .btn { padding: 0.5rem 1rem; border-radius: 4px; }
}

@layer utilities {
  .mt-4 { margin-top: 1rem; }
}

2. Flexboxマスター

2.1 Flexbox基本(きほん)コンセプト

Flexboxは1次元(じげん)レイアウトシステムで、主軸(しゅじく)(main axis)と交差軸(こうさじく)(cross axis)を基(もと)に動作(どうさ)します。

.flex-container {
  display: flex;

  /* 方向 */
  flex-direction: row;          /* デフォルト:横 */
  flex-direction: column;       /* 縦 */
  flex-direction: row-reverse;  /* 横逆順 */

  /* 折り返し */
  flex-wrap: nowrap;    /* デフォルト:1行 */
  flex-wrap: wrap;      /* 複数行許可 */

  /* 短縮形 */
  flex-flow: row wrap;
}

2.2 整列(せいれつ)プロパティ完全(かんぜん)ガイド

.flex-container {
  /* 主軸整列 */
  justify-content: flex-start;    /* 開始 */
  justify-content: center;        /* 中央 */
  justify-content: space-between; /* 両端配置、均等間隔 */
  justify-content: space-around;  /* 均等間隔(両端半分) */
  justify-content: space-evenly;  /* 完全均等間隔 */

  /* 交差軸整列 */
  align-items: stretch;     /* デフォルト:伸ばす */
  align-items: center;      /* 中央 */
  align-items: flex-start;  /* 開始 */
  align-items: baseline;    /* テキストベースライン */

  /* 複数行の交差軸整列 */
  align-content: center;
  align-content: space-between;

  /* 間隔 */
  gap: 1rem;
  row-gap: 1rem;
  column-gap: 2rem;
}

2.3 子要素(こようそ)プロパティ

.flex-item {
  /* 拡大比率(残りスペース分配) */
  flex-grow: 1;

  /* 縮小比率 */
  flex-shrink: 0;  /* 縮小防止 */

  /* 基本サイズ */
  flex-basis: 200px;

  /* 短縮形: grow shrink basis */
  flex: 1 0 200px;
  flex: 1;         /* = 1 1 0% */
  flex: auto;      /* = 1 1 auto */
  flex: none;      /* = 0 0 auto */

  /* 個別整列 */
  align-self: center;

  /* 順序 */
  order: -1;  /* 先頭へ */
}

2.4 Flexbox実践(じっせん)パターン

/* パターン1:完全な上下左右中央揃え */
.center-everything {
  display: flex;
  justify-content: center;
  align-items: center;
  min-height: 100vh;
}

/* パターン2:Sticky Footer */
.page-layout {
  display: flex;
  flex-direction: column;
  min-height: 100vh;
}
.page-layout main {
  flex: 1;
}

/* パターン3:同じ高さのカード */
.card-grid {
  display: flex;
  flex-wrap: wrap;
  gap: 1rem;
}
.card-grid .card {
  flex: 1 1 300px;
  display: flex;
  flex-direction: column;
}
.card-grid .card .content {
  flex: 1;
}

/* パターン4:ナビゲーションバー */
.navbar {
  display: flex;
  align-items: center;
  gap: 1rem;
}
.navbar .logo { margin-right: auto; }
.navbar .actions { display: flex; gap: 0.5rem; }

3. Gridマスター

3.1 Grid基本(きほん)コンセプト

CSS Gridは2次元(じげん)レイアウトシステムで、行(ぎょう)と列(れつ)を同時(どうじ)に制御(せいぎょ)します。

.grid-container {
  display: grid;

  /* 列定義 */
  grid-template-columns: 200px 1fr 200px;       /* 固定-フレキシブル-固定 */
  grid-template-columns: repeat(3, 1fr);         /* 3等分 */
  grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));  /* レスポンシブ */
  grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));   /* レスポンシブ+伸張 */

  /* 行定義 */
  grid-template-rows: auto 1fr auto;

  /* 間隔 */
  gap: 1rem;
  row-gap: 1rem;
  column-gap: 2rem;
}

3.2 Grid Template Areas

視覚的(しかくてき)にレイアウトを定義(ていぎ)する強力(きょうりょく)な方法(ほうほう)です。

.page-layout {
  display: grid;
  grid-template-areas:
    "header  header  header"
    "sidebar content aside"
    "footer  footer  footer";
  grid-template-columns: 200px 1fr 200px;
  grid-template-rows: auto 1fr auto;
  min-height: 100vh;
}

.header  { grid-area: header; }
.sidebar { grid-area: sidebar; }
.content { grid-area: content; }
.aside   { grid-area: aside; }
.footer  { grid-area: footer; }

/* モバイルでは単一列 */
@media (max-width: 768px) {
  .page-layout {
    grid-template-areas:
      "header"
      "content"
      "sidebar"
      "aside"
      "footer";
    grid-template-columns: 1fr;
  }
}

3.3 auto-fill vs auto-fit

/* auto-fill:空のトラックを維持(最小サイズで空の列を作成) */
.grid-fill {
  grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
}

/* auto-fit:空のトラックを縮小(アイテムが残りスペースを埋める) */
.grid-fit {
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
}

アイテムが少(すく)ない場合(ばあい)に違(ちが)いが現(あらわ)れます。auto-fillは空(から)の列(れつ)を残(のこ)し、auto-fitは既存(きそん)のアイテムが伸(の)びてスペースを埋(う)めます。

3.4 Subgrid

親(おや)Gridのトラックを子(こ)に継承(けいしょう)する機能(きのう)です。

.parent-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 1rem;
}

.child-grid {
  grid-column: span 3;
  display: grid;
  grid-template-columns: subgrid;  /* 親の列トラックを継承 */
  gap: 1rem;
}

3.5 メディアクエリなしのレスポンシブGrid

/* 完璧なレスポンシブカードグリッド - メディアクエリ不要 */
.responsive-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(300px, 100%), 1fr));
  gap: 1.5rem;
}

min()関数(かんすう)を使(つか)うと、コンテナが300pxより狭(せま)い場合(ばあい)でもオーバーフローなく動作(どうさ)します。


4. Flexbox vs Grid 決定(けってい)ガイド

4.1 比較表(ひかくひょう)

基準(きじゅん)FlexboxGrid
次元(じげん)1次元(行または列)2次元(行と列同時)
コンテンツ vs レイアウトコンテンツ優先レイアウト優先
整列方向(せいれつほうこう)主軸/交差軸行/列独立制御
アイテム配置(はいち)ソース順序基準自由な配置可能
適切(てきせつ)な使用場面(しようばめん)ナビゲーション、カード内部ページレイアウト、ダッシュボード
gap対応(たいおう)対応対応
折(お)り返(かえ)しflex-wrap自動トラック配置

4.2 いつどちらを使(つか)うか

Flexboxを選(えら)ぶ場合(ばあい):

  • 一方向(いちほうこう)(横(よこ)または縦(たて))にアイテムを配置(はいち)
  • コンテンツサイズに基(もと)づくフレキシブルなレイアウト
  • ナビゲーションバー、ボタングループ、カード内部(ないぶ)レイアウト
  • アイテム間(かん)の均等(きんとう)な間隔(かんかく)

Gridを選(えら)ぶ場合(ばあい):

  • 行(ぎょう)と列(れつ)の両方(りょうほう)を制御(せいぎょ)する必要(ひつよう)がある
  • 明確(めいかく)なレイアウト構造(こうぞう)(ヘッダー、サイドバー、メイン)
  • アイテムの重(かさ)ね合(あ)わせや自由(じゆう)な配置(はいち)
  • ダッシュボード、ギャラリー、ページ全体(ぜんたい)レイアウト

組(く)み合(あ)わせて使(つか)う:

  • Gridでページ全体(ぜんたい)構造(こうぞう)、Flexboxでコンポーネント内部(ないぶ)レイアウト
/* Grid + Flexbox の組み合わせ */
.dashboard {
  display: grid;
  grid-template-columns: 250px 1fr;
  grid-template-rows: 60px 1fr;
  min-height: 100vh;
}

.dashboard .toolbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 1rem;
}

.dashboard .sidebar-nav {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}

5. Container Queries 詳細(しょうさい)

5.1 基本(きほん)構文(こうぶん)

/* コンテナ宣言 */
.widget-container {
  container-type: inline-size;  /* インライン軸(通常は幅)基準 */
  container-name: widget;       /* オプションの名前 */
}

/* コンテナクエリ */
@container widget (min-width: 500px) {
  .widget {
    flex-direction: row;
  }
}

@container widget (max-width: 499px) {
  .widget {
    flex-direction: column;
  }
}

5.2 container-typeの種類(しゅるい)

/* inline-size:インライン軸(通常は幅)のみクエリ可能 */
.container { container-type: inline-size; }

/* size:幅と高さの両方をクエリ可能(コストが高い) */
.container { container-type: size; }

/* normal:クエリ不可、名前のみ使用(スタイルクエリ用) */
.container { container-type: normal; }

5.3 @container vs @media

/* @media:ビューポート基準 - 画面全体の幅 */
@media (min-width: 768px) {
  .card { flex-direction: row; }
}

/* @container:親コンテナ基準 - 再利用可能 */
@container (min-width: 400px) {
  .card { flex-direction: row; }
}

Container Queriesの核心的(かくしんてき)な利点(りてん)は**コンポーネントの再利用性(さいりようせい)**です。同(おな)じカードコンポーネントがサイドバーでは縦(たて)、メインエリアでは横(よこ)に自動(じどう)で切(き)り替(か)わります。

5.4 コンテナクエリ単位(たんい)

.widget {
  /* cqw:コンテナ幅の1% */
  font-size: clamp(0.875rem, 3cqw, 1.25rem);

  /* cqh:コンテナ高さの1% */
  padding: 2cqw;

  /* cqi:コンテナインラインサイズの1% */
  /* cqb:コンテナブロックサイズの1% */
  margin-inline: 5cqi;
}

6. モダンCSSセレクタ

6.1 :has() 詳細(しょうさい)

/* テキスト入力にフォーカスがあるときフォームのボーダーを変更 */
form:has(input[type="text"]:focus) {
  border-color: blue;
}

/* 空の状態処理 */
.list:has(> :first-child) {
  /* 子がある場合のみ適用 */
}
.list:not(:has(> *)) {
  /* 子がない場合 */
  display: grid;
  place-items: center;
}
.list:not(:has(> *))::after {
  content: "項目がありません";
}

/* ダークモードトグル */
html:has(#dark-mode:checked) {
  color-scheme: dark;
  --bg: #1a1a1a;
  --text: #e0e0e0;
}

6.2 :is()と:where()

/* :is() - 引数の中で最も高い詳細度を継承 */
:is(h1, h2, h3, h4) {
  line-height: 1.2;
  margin-block: 1em 0.5em;
}

/* :where() - 詳細度は常に0(簡単にオーバーライド可能) */
:where(h1, h2, h3, h4) {
  line-height: 1.2;
}

/* 実用的:リセットスタイルに:where()を使用 */
:where(ul, ol) { list-style: none; padding: 0; }
:where(a) { color: inherit; text-decoration: none; }

/* 深いセレクタの簡素化 */
:is(.article, .blog-post, .docs) :is(h1, h2, h3) {
  color: var(--heading-color);
}

6.3 :not() 高度(こうど)な使用法(しようほう)

/* 最後の項目以外にボーダー */
.list-item:not(:last-child) {
  border-bottom: 1px solid #eee;
}

/* 複数条件の結合 */
input:not([type="submit"]):not([type="button"]) {
  border: 1px solid #ccc;
  padding: 0.5rem;
}

/* 無効なアイテムを除外 */
.nav-link:not(.disabled):hover {
  background: #f0f0f0;
}

6.4 CSS Nesting 詳細(しょうさい)

.card {
  background: white;
  border-radius: 8px;

  /* 子選択 */
  & .title { font-weight: bold; }

  /* 修飾子 */
  &.featured { border: 2px solid gold; }
  &:hover { transform: translateY(-2px); }
  &::before { content: ""; }

  /* ネストされたメディアクエリ */
  @media (prefers-color-scheme: dark) {
    background: #2a2a2a;
    color: white;
  }

  /* ネストされたコンテナクエリ */
  @container card (min-width: 400px) {
    display: grid;
    grid-template-columns: 1fr 1fr;
  }
}

7. CSSアニメーション総(そう)まとめ

7.1 View Transitions API

ページ遷移(せんい)やDOM変更時(へんこうじ)に滑(なめ)らかなアニメーションを提供(ていきょう)します。

/* デフォルトView Transitionスタイル */
::view-transition-old(root) {
  animation: fade-out 0.3s ease-out;
}
::view-transition-new(root) {
  animation: fade-in 0.3s ease-in;
}

/* 個別要素に名前を付与 */
.hero-image {
  view-transition-name: hero;
}

/* その要素のトランジションをカスタマイズ */
::view-transition-old(hero) {
  animation: scale-down 0.4s ease-out;
}
::view-transition-new(hero) {
  animation: scale-up 0.4s ease-in;
}

@keyframes scale-down {
  from { transform: scale(1); }
  to { transform: scale(0.8); opacity: 0; }
}
@keyframes scale-up {
  from { transform: scale(0.8); opacity: 0; }
  to { transform: scale(1); }
}
// JavaScriptからView Transitionをトリガー
document.startViewTransition(() => {
  updateDOM(); // DOM変更を実行
});

7.2 Scroll-Driven Animations

スクロール位置(いち)に応(おう)じてアニメーションが進行(しんこう)します。

/* スクロール進捗インジケーター */
.scroll-indicator {
  position: fixed;
  top: 0;
  left: 0;
  height: 4px;
  background: linear-gradient(to right, #3b82f6, #8b5cf6);
  transform-origin: left;
  animation: grow-width linear;
  animation-timeline: scroll();
}

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

/* 要素がビューポートに入ったときフェードイン */
.fade-in-section {
  animation: fade-in linear both;
  animation-timeline: view();
  animation-range: entry 0% entry 100%;
}

@keyframes fade-in {
  from { opacity: 0; transform: translateY(50px); }
  to { opacity: 1; transform: translateY(0); }
}

7.3 @keyframes vs transition

/* transition:状態変化に適切(AからBへ) */
.button {
  background: #3b82f6;
  transition: background 0.3s ease, transform 0.2s ease;
}
.button:hover {
  background: #2563eb;
  transform: scale(1.05);
}

/* @keyframes:複雑なマルチステップアニメーション */
@keyframes bounce {
  0%, 100% { transform: translateY(0); }
  25% { transform: translateY(-20px); }
  50% { transform: translateY(0); }
  75% { transform: translateY(-10px); }
}

.bounce-element {
  animation: bounce 1s ease-in-out infinite;
}

7.4 パフォーマンス最適化(さいてきか)のヒント

/* GPUアクセラレーションを活用するプロパティ:transform、opacity */
.good-animation {
  /* GPU合成レイヤーを使用 - 高速 */
  transition: transform 0.3s, opacity 0.3s;
}

.bad-animation {
  /* リフロー/リペイントを発生 - 低速 */
  transition: width 0.3s, height 0.3s, top 0.3s;
}

/* will-changeでブラウザにヒント */
.will-animate {
  will-change: transform;
}
/* 注意:乱用するとメモリの無駄遣い。実際のアニメーション直前にのみ使用 */

8. Tailwind CSS v4

8.1 Oxideエンジンの革新(かくしん)

Tailwind CSS v4はRustベースのOxideエンジンで完全(かんぜん)に書(か)き直(なお)されました。

主(おも)な変更点(へんこうてん):

  • ビルド速度(そくど)10倍以上(いじょう)向上(こうじょう)
  • CSS-first設定(tailwind.config.js不要(ふよう))
  • ネイティブContainer Queriesサポート
  • CSS変数(へんすう)ベースのテーマシステム
  • 自動(じどう)コンテンツ検出(けんしゅつ)(content設定不要(ふよう))

8.2 CSS-first設定(せってい)

/* app.css - tailwind.config.jsの代わりにCSSで設定 */
@import "tailwindcss";

@theme {
  --color-primary: #3b82f6;
  --color-secondary: #8b5cf6;
  --font-family-display: "Inter", sans-serif;
  --breakpoint-3xl: 1920px;
}

8.3 Tailwind v4でのContainer Queries

<!-- コンテナ宣言 -->
<div class="@container">
  <!-- コンテナサイズベースのレスポンシブ -->
  <div class="flex flex-col @md:flex-row @lg:grid @lg:grid-cols-3 gap-4">
    <div class="p-4">Item 1</div>
    <div class="p-4">Item 2</div>
    <div class="p-4">Item 3</div>
  </div>
</div>

8.4 Tailwind v4の主要(しゅよう)ユーティリティ

<!-- 新しいグラディエント -->
<div class="bg-linear-to-r from-blue-500 to-purple-500">
  グラディエント背景
</div>

<!-- 3Dトランスフォーム -->
<div class="rotate-x-12 rotate-y-6 perspective-800">
  3D効果
</div>

<!-- 新しいバリアントの組み合わせ -->
<button class="hover:not-disabled:bg-blue-600 disabled:opacity-50">
  スマートボタン
</button>

<!-- グループバリアントの改善 -->
<div class="group">
  <p class="group-has-[img]:text-sm">
    画像がある場合小さいテキスト
  </p>
</div>

8.5 マイグレーションガイド

# v3からv4への自動マイグレーション
npx @tailwindcss/upgrade

主(おも)な変更点(へんこうてん):

  • tailwind.config.jsをCSS @themeブロックに移行(いこう)
  • bg-opacity-*の代(か)わりにbg-blue-500/50形式(けいしき)を使用(しよう)
  • dark:バリアントはCSS prefers-color-schemeベースに変更(へんこう)
  • PostCSSプラグインの代(か)わりにViteプラグインを推奨(すいしょう)

9. CSS-in-JS比較(ひかく)

9.1 主要(しゅよう)ライブラリ比較(ひかく)

特性(とくせい)styled-componentsEmotionPanda CSSvanilla-extract
ランタイムありありゼロランタイムゼロランタイム
バンドルサイズ~12KB~11KB~0KB~0KB
SSRサポート設定必要設定必要ネイティブネイティブ
TypeScript対応対応タイプセーフタイプセーフ
React 19制限的制限的完全完全
サーバーコンポーネント不可不可可能可能

9.2 2025年(ねん)トレンド:ゼロランタイム

React Server ComponentsとストリーミングSSRの登場(とうじょう)により、ランタイムCSS-in-JSは衰退(すいたい)しています。

// Panda CSS - ゼロランタイム
import { css } from '../styled-system/css'

function Button() {
  return (
    <button className={css({
      bg: 'blue.500',
      color: 'white',
      padding: '8px 16px',
      borderRadius: 'md',
      _hover: { bg: 'blue.600' }
    })}>
      クリック
    </button>
  )
}
// vanilla-extract - ビルドタイムCSS
// styles.css.ts
import { style } from '@vanilla-extract/css'

export const button = style({
  background: 'blue',
  color: 'white',
  padding: '8px 16px',
  borderRadius: '4px',
  ':hover': {
    background: 'darkblue',
  },
})

9.3 選択(せんたく)ガイド

  • 新規(しんき)プロジェクト + React 19: Panda CSSまたはvanilla-extract
  • 既存(きそん)のstyled-componentsプロジェクト: 段階的(だんかいてき)マイグレーションを検討(けんとう)
  • ユーティリティファースト志向(しこう): Tailwind CSS v4
  • CSS Modules志向(しこう): vanilla-extract(タイプセーフCSS Modules)

10. レスポンシブデザインパターン

10.1 流体(りゅうたい)タイポグラフィ

/* clamp()を使った流体フォントサイズ */
h1 {
  /* 最小2rem、最大4rem、ビューポートに応じて流動的 */
  font-size: clamp(2rem, 5vw + 1rem, 4rem);
}

p {
  font-size: clamp(1rem, 0.5vw + 0.875rem, 1.25rem);
  line-height: clamp(1.5, 1.2 + 0.5vw, 1.8);
}

/* 流体スペーシング */
.section {
  padding: clamp(1rem, 3vw, 3rem);
  gap: clamp(0.5rem, 2vw, 2rem);
}

10.2 aspect-ratio

/* アスペクト比を維持するレスポンシブ画像/動画 */
.video-wrapper {
  aspect-ratio: 16 / 9;
  width: 100%;
}

.square-avatar {
  aspect-ratio: 1;
  width: 100%;
  border-radius: 50%;
  object-fit: cover;
}

.card-image {
  aspect-ratio: 4 / 3;
  object-fit: cover;
}

10.3 論理的(ろんりてき)プロパティ

多言語(たげんご)対応(たいおう)(RTL/LTR)のための論理的(ろんりてき)プロパティです。

/* 物理的プロパティ(方向固定) */
.old-way {
  margin-left: 1rem;
  margin-right: 1rem;
  padding-top: 2rem;
  padding-bottom: 2rem;
  border-left: 3px solid blue;
  width: 200px;
  height: 100px;
}

/* 論理的プロパティ(方向適応) */
.new-way {
  margin-inline: 1rem;       /* 左右(またはRTLで右左) */
  padding-block: 2rem;       /* 上下 */
  border-inline-start: 3px solid blue;  /* 開始方向 */
  inline-size: 200px;        /* 幅 */
  block-size: 100px;         /* 高さ */
}

10.4 レスポンシブ画像(がぞう)戦略(せんりゃく)

<!-- srcsetとsizesで最適な画像を提供 -->
<img
  srcset="image-400.webp 400w,
          image-800.webp 800w,
          image-1200.webp 1200w"
  sizes="(max-width: 600px) 100vw,
         (max-width: 1200px) 50vw,
         33vw"
  src="image-800.webp"
  alt="レスポンシブ画像"
  loading="lazy"
  decoding="async"
/>

11. CSSアーキテクチャ

11.1 BEM (Block Element Modifier)

/* Block */
.card {}

/* Element(ブロックの一部) */
.card__title {}
.card__body {}
.card__footer {}

/* Modifier(変形) */
.card--featured {}
.card--compact {}
.card__title--large {}

11.2 ユーティリティファースト

<!-- Tailwindスタイル:ユーティリティクラスの組み合わせ -->
<div class="flex items-center gap-4 p-4 rounded-lg bg-white shadow-md
            hover:shadow-lg transition-shadow">
  <img class="w-12 h-12 rounded-full object-cover" src="..." alt="..." />
  <div>
    <h3 class="text-lg font-semibold text-gray-900">ユーザー名</h3>
    <p class="text-sm text-gray-500">説明テキスト</p>
  </div>
</div>

11.3 CSS Modules

/* Button.module.css */
.button {
  padding: 0.5rem 1rem;
  border-radius: 4px;
  font-weight: 600;
}

.primary {
  background: #3b82f6;
  color: white;
}

.secondary {
  background: #e5e7eb;
  color: #374151;
}
// 自動的にユニークなクラス名を生成
import styles from './Button.module.css'

function Button({ variant = 'primary', children }) {
  return (
    <button className={`${styles.button} ${styles[variant]}`}>
      {children}
    </button>
  )
}

11.4 CSS Layers (@layer) アーキテクチャ

/* レイヤー優先順位:後に宣言されたものが優先 */
@layer reset, base, tokens, components, utilities, overrides;

@layer tokens {
  :root {
    --color-primary: #3b82f6;
    --color-surface: #ffffff;
    --space-sm: 0.5rem;
    --space-md: 1rem;
    --radius-md: 8px;
  }
}

@layer components {
  .btn {
    padding: var(--space-sm) var(--space-md);
    border-radius: var(--radius-md);
    background: var(--color-primary);
    color: white;
  }
}

@layer utilities {
  .sr-only {
    position: absolute;
    width: 1px;
    height: 1px;
    clip: rect(0, 0, 0, 0);
    overflow: hidden;
  }
}

12. 面接質問(めんせつしつもん)とクイズ

面接質問(めんせつしつもん)10選(せん)

Q1: FlexboxとGridの違(ちが)いを説明(せつめい)してください。

Flexboxは1次元(じげん)レイアウト(行(ぎょう)または列(れつ))、Gridは2次元(じげん)レイアウト(行(ぎょう)と列(れつ)同時(どうじ))システムです。Flexboxはコンテンツサイズ基準(きじゅん)、Gridはレイアウト構造(こうぞう)基準(きじゅん)です。通常(つうじょう)、全体(ぜんたい)構造(こうぞう)はGrid、内部(ないぶ)コンポーネントはFlexboxを使用(しよう)します。

Q2: Container QueriesがMedia Queriesより優(すぐ)れている点(てん)は?

Media Queriesはビューポートサイズ基準(きじゅん)ですが、Container Queriesは親(おや)コンテナサイズ基準(きじゅん)です。コンポーネントがどこに配置(はいち)されても自(みずか)ら反応(はんのう)できるため、再利用性(さいりようせい)が大幅(おおはば)に向上(こうじょう)します。

Q3: :has()セレクタの用途(ようと)を例(れい)と共(とも)に説明(せつめい)してください。

親要素(おやようそ)を子(こ)の条件(じょうけん)で選択(せんたく)できるリレーショナルセレクタです。例(たと)えばform:has(:invalid)は無効(むこう)な入力(にゅうりょく)があるフォームを選択(せんたく)し、.card:has(img)は画像(がぞう)を含(ふく)むカードのみ選択(せんたく)します。

Q4: CSS Specificity(詳細度(しょうさいど))の計算方法(けいさんほうほう)を説明(せつめい)してください。

インラインスタイル(1000)、IDセレクタ(100)、クラス/属性(ぞくせい)/擬似(ぎじ)クラス(10)、タグ/擬似(ぎじ)要素(ようそ)(1)の順(じゅん)です。:is()は引数(ひきすう)の中(なか)で最(もっと)も高(たか)い詳細度(しょうさいど)を継承(けいしょう)し、:where()は常(つね)に0です。

Q5: CSS-in-JSでゼロランタイムが重要(じゅうよう)な理由(りゆう)は?

ランタイムCSS-in-JSはJavaScript実行中(じっこうちゅう)にスタイルを生成(せいせい)するためパフォーマンスコストが発生(はっせい)します。React Server Componentsでは動作(どうさ)せず、SSR時(じ)にハイドレーション不一致(ふいっち)が起(お)こる可能性(かのうせい)があります。ゼロランタイムはビルド時(じ)にCSSを生成(せいせい)してこの問題(もんだい)を解決(かいけつ)します。

Q6: auto-fillとauto-fitの違(ちが)いは?

auto-fillは空(から)のトラックを維持(いじ)して可能(かのう)な限(かぎ)り多(おお)くの列(れつ)を作成(さくせい)し、auto-fitは空(から)のトラックを縮小(しゅくしょう)して既存(きそん)のアイテムが残(のこ)りのスペースを埋(う)めます。アイテム数(すう)が少(すく)ない時(とき)に違(ちが)いが現(あらわ)れます。

Q7: CSSアニメーションのパフォーマンス最適化方法(さいてきかほうほう)は?

transformopacityのみアニメーションすればGPU合成(ごうせい)レイヤーで処理(しょり)され、リフロー/リペイントを回避(かいひ)できます。will-changeでブラウザにヒントを与(あた)えますが、乱用(らんよう)するとメモリの無駄遣(むだづか)いです。widthheighttopなどの変更(へんこう)はレイアウト再計算(さいけいさん)を発生(はっせい)させるので避(さ)けましょう。

Q8: CSS Layersの目的(もくてき)は?

@layerを使用(しよう)するとカスケードの優先順位(ゆうせんじゅんい)を明示的(めいじてき)に制御(せいぎょ)できます。サードパーティCSS、リセット、コンポーネント、ユーティリティの優先順位(ゆうせんじゅんい)をセレクタの詳細度(しょうさいど)に関係(かんけい)なくレイヤー順序(じゅんじょ)で管理(かんり)します。

Q9: Tailwind CSS v4の主(おも)な変更点(へんこうてん)は?

RustベースのOxideエンジンで10倍(ばい)高速(こうそく)なビルド、CSS-first設定(せってい)(tailwind.config.js不要(ふよう))、ネイティブContainer Queriesサポート、CSS変数(へんすう)ベースのテーマ、自動(じどう)コンテンツ検出(けんしゅつ)などです。

Q10: Subgridとは何(なに)で、いつ使用(しよう)しますか?

Subgridは親(おや)Gridのトラック定義(ていぎ)を子(こ)Gridが継承(けいしょう)する機能(きのう)です。カードグリッドで各(かく)カードのヘッダー、本文(ほんぶん)、フッターを異(こと)なるカード間(かん)で整列(せいれつ)させる場合(ばあい)に便利(べんり)です。

クイズ5問(もん)

Q1: 次(つぎ)のコードで.itemの実際(じっさい)の幅(はば)は?
.container { display: flex; width: 600px; }
.item { flex: 0 1 200px; }
/* 3つの.itemがある場合 */

正解(せいかい): 各(かく)200pxです。flex-grow: 0なので残(のこ)りスペースは分配(ぶんぱい)されず、flex-basis: 200pxで初期(しょき)サイズが設定(せってい)されます。合計(ごうけい)600pxに3つがぴったり収(おさ)まります。

Q2: :is()と:where()の核心的(かくしんてき)な違(ちが)いは?

正解(せいかい): 詳細度(しょうさいど)(Specificity)です。:is()は引数(ひきすう)の中(なか)で最(もっと)も高(たか)い詳細度(しょうさいど)を継承(けいしょう)し、:where()は常(つね)に詳細度(しょうさいど)が0です。:where()はリセットやデフォルトスタイルに適(てき)しています。

Q3: Container Queriesを使(つか)うために親(おや)に必要(ひつよう)なプロパティは?

正解(せいかい): 親要素(おやようそ)にcontainer-type: inline-size(またはsize)を宣言(せんげん)する必要(ひつよう)があります。オプションでcontainer-nameで名前(なまえ)を指定(してい)できます。

Q4: 次(つぎ)のうちGPUアクセラレーションアニメーションでないものは?

a) transform: translateX(100px) b) opacity: 0.5 c) width: 200px d) filter: blur(5px)

正解(せいかい): c) widthの変更(へんこう)はリフローを発生(はっせい)させます。transformopacityfilterは合成(ごうせい)(composite)段階(だんかい)でGPUが処理(しょり)します。

Q5: Tailwind CSS v4で設定(せってい)ファイルはどう変(か)わりましたか?

正解(せいかい): tailwind.config.jsの代(か)わりに、CSSファイル内(ない)の@themeブロックで設定(せってい)します。CSS変数(へんすう)ベースでテーマを定義(ていぎ)し、コンテンツパスも自動(じどう)検出(けんしゅつ)されます。


参考資料(さんこうしりょう)

  1. MDN - CSS Grid Layout
  2. MDN - Flexbox
  3. MDN - Container Queries
  4. CSS Tricks - A Complete Guide to Grid
  5. CSS Tricks - A Complete Guide to Flexbox
  6. Tailwind CSS v4 Documentation
  7. Chrome - View Transitions API
  8. Chrome - Scroll-Driven Animations
  9. web.dev - CSS :has()
  10. Panda CSS Documentation
  11. vanilla-extract Documentation
  12. web.dev - Learn CSS
  13. State of CSS 2024
  14. CSS Nesting Specification