- Authors

- Name
- Youngju Kim
- @fjvbn20031
- はじめに
- 1. 2025年(ねん)のCSS:新機能(しんきのう)まとめ
- 2. Flexboxマスター
- 3. Gridマスター
- 4. Flexbox vs Grid 決定(けってい)ガイド
- 5. Container Queries 詳細(しょうさい)
- 6. モダンCSSセレクタ
- 7. CSSアニメーション総(そう)まとめ
- 8. Tailwind CSS v4
- 9. CSS-in-JS比較(ひかく)
- 10. レスポンシブデザインパターン
- 11. CSSアーキテクチャ
- 12. 面接質問(めんせつしつもん)とクイズ
- 参考資料(さんこうしりょう)
はじめに
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 比較表(ひかくひょう)
| 基準(きじゅん) | Flexbox | Grid |
|---|---|---|
| 次元(じげん) | 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:バリアントはCSSprefers-color-schemeベースに変更(へんこう)- PostCSSプラグインの代(か)わりにViteプラグインを推奨(すいしょう)
9. CSS-in-JS比較(ひかく)
9.1 主要(しゅよう)ライブラリ比較(ひかく)
| 特性(とくせい) | styled-components | Emotion | Panda CSS | vanilla-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アニメーションのパフォーマンス最適化方法(さいてきかほうほう)は?
transformとopacityのみアニメーションすればGPU合成(ごうせい)レイヤーで処理(しょり)され、リフロー/リペイントを回避(かいひ)できます。will-changeでブラウザにヒントを与(あた)えますが、乱用(らんよう)するとメモリの無駄遣(むだづか)いです。width、height、topなどの変更(へんこう)はレイアウト再計算(さいけいさん)を発生(はっせい)させるので避(さ)けましょう。
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の変更(へんこう)はリフローを発生(はっせい)させます。transform、opacity、filterは合成(ごうせい)(composite)段階(だんかい)でGPUが処理(しょり)します。
Q5: Tailwind CSS v4で設定(せってい)ファイルはどう変(か)わりましたか?
正解(せいかい): tailwind.config.jsの代(か)わりに、CSSファイル内(ない)の@themeブロックで設定(せってい)します。CSS変数(へんすう)ベースでテーマを定義(ていぎ)し、コンテンツパスも自動(じどう)検出(けんしゅつ)されます。
参考資料(さんこうしりょう)
- MDN - CSS Grid Layout
- MDN - Flexbox
- MDN - Container Queries
- CSS Tricks - A Complete Guide to Grid
- CSS Tricks - A Complete Guide to Flexbox
- Tailwind CSS v4 Documentation
- Chrome - View Transitions API
- Chrome - Scroll-Driven Animations
- web.dev - CSS :has()
- Panda CSS Documentation
- vanilla-extract Documentation
- web.dev - Learn CSS
- State of CSS 2024
- CSS Nesting Specification