タイトル: CSSの変更が反映されない
SEOタイトル: CSS の変更が反映されない原因と対処法完全ガイド
この本文には実行可能なタグ等が含まれるため、安全のためHTMLソースとして表示しています。本文データは変更していません。
<table border="1" cellpadding="6" cellspacing="0" style="border-collapse:collapse;background:#fffbea;border:1px solid #f4c430;margin:1em 0;width:100%"><tr><td style="background:#f4c430;color:#000;font-weight:bold;padding:8px">この記事の要点</td></tr><tr><td style="padding:10px"><ul><li><strong>CSS の変更が反映されない</strong>原因の 8 割は <strong>ブラウザキャッシュ</strong>。まずは <code>Ctrl+Shift+R</code> (Mac: <code>Cmd+Shift+R</code>) で強制再読込</li><li>直らない場合は <strong>DevTools (F12) を開いて Network タブの "Disable cache"</strong> をチェック</li><li>本番では <strong>クエリ文字列でキャッシュバスター</strong> (<code>style.css?v=20260518</code>) または <strong>ハッシュ付きファイル名</strong> (<code>style.abc123.css</code>) を使う</li><li>Service Worker / CDN (Cloudflare) / リバースプロキシのキャッシュも疑う → <strong>Cloudflare Purge</strong> / <code>Cache-Control: no-cache</code></li><li>反映されているのに「効いていない」場合は <strong>Specificity (詳細度)</strong> の負け → DevTools の Computed タブで打ち消し元を特定し <code>!important</code> または詳細度を上げる</li></ul></td></tr></table>
<h2>原因の切り分けフロー</h2>
<p>まず「<strong>変更が読み込まれていない</strong>」のか「<strong>読み込まれているが効いていない</strong>」のかを切り分けます。</p>
<table border="1" cellpadding="6" cellspacing="0" style="border-collapse:collapse;width:100%">
<thead><tr style="background:#e3f2fd"><th>確認</th><th>方法</th><th>該当する場合</th></tr></thead>
<tbody>
<tr><td>ファイルが新しい内容になっているか</td><td>DevTools → Sources → 該当 CSS を開き、編集行が反映されているか</td><td>古い → キャッシュ (対処 1〜4)</td></tr>
<tr><td>セレクタにマッチしているか</td><td>DevTools → Elements → 該当要素 → Styles に表示されるか</td><td>表示なし → セレクタミス (対処 5)</td></tr>
<tr><td>取り消し線がついているか</td><td>DevTools → Styles で property に取り消し線</td><td>詳細度の負け (対処 6)</td></tr>
<tr><td>Computed 値が違うか</td><td>DevTools → Computed</td><td>別ルールに上書きされている (対処 6)</td></tr>
</tbody>
</table>
<h2>対処1: ブラウザの強制再読込 (スーパーリロード)</h2>
<p>もっとも多いのが<strong>ブラウザの HTTP キャッシュ</strong>です。通常のリロード (F5) では CSS が再取得されない場合があります。</p>
<table border="1" cellpadding="6" cellspacing="0" style="border-collapse:collapse;width:100%">
<thead><tr style="background:#e3f2fd"><th>OS / ブラウザ</th><th>強制再読込</th></tr></thead>
<tbody>
<tr><td>Windows / Chrome / Edge / Firefox</td><td><code>Ctrl + Shift + R</code> または <code>Ctrl + F5</code></td></tr>
<tr><td>Mac / Chrome / Safari</td><td><code>Cmd + Shift + R</code></td></tr>
<tr><td>Chrome (開発時)</td><td>DevTools を開いたままリロードボタンを<strong>右クリック</strong> → 「キャッシュの消去とハード再読込」</td></tr>
</tbody>
</table>
<h2>対処2: DevTools で Disable cache</h2>
<p>開発中は DevTools を開いている間だけキャッシュを完全無効化できます:</p>
<ol>
<li>F12 で DevTools を開く</li>
<li>Network タブを開く</li>
<li>上部の <strong>Disable cache</strong> にチェック</li>
<li>DevTools が開いている間はリロードでキャッシュ無効</li>
</ol>
<h2>対処3: クエリ文字列によるキャッシュバスター</h2>
<p>本番環境ではエンドユーザーのブラウザキャッシュ対策が必須です。<code>?v=...</code> を付けて URL を変えると別リソースとして取得されます:</p>
<pre style="background:#1e293b;color:#e2e8f0;padding:1em;border-radius:6px;overflow-x:auto;line-height:1.5"><code class="language-html"><!-- 固定バージョン (デプロイ時に手動更新) -->
<link rel="stylesheet" href="/css/style.css?v=20260518">
<!-- ファイル変更時刻を埋め込む (PHP の例) -->
<link rel="stylesheet"
href="/css/style.css?v=<?php echo filemtime(__DIR__ . '/css/style.css'); ?>">
<!-- Laravel Mix / Vite の場合 -->
<link rel="stylesheet" href="{{ mix('css/app.css') }}">
<!-- mix-manifest.json により /css/app.css?id=abc123... に展開 --></code></pre>
<h2>対処4: Webpack / Vite / Laravel Mix のハッシュ付きファイル名</h2>
<p>モダンなビルドツールは出力ファイル名にハッシュを含めるのが標準です:</p>
<pre style="background:#1e293b;color:#e2e8f0;padding:1em;border-radius:6px;overflow-x:auto;line-height:1.5"><code class="language-javascript">// vite.config.js
import { defineConfig } from 'vite';
export default defineConfig({
build: {
rollupOptions: {
output: {
// style.abc123.css のようにハッシュ付与
assetFileNames: 'assets/[name].[hash][extname]',
entryFileNames: 'assets/[name].[hash].js',
},
},
},
});
// webpack.config.js
module.exports = {
output: {
filename: '[name].[contenthash].js',
},
plugins: [
new MiniCssExtractPlugin({ filename: '[name].[contenthash].css' }),
],
};</code></pre>
<p>ファイル内容が変わったときだけハッシュが変わるので、<strong>変更時は確実に新 URL</strong>になり、変わらないときは長期キャッシュが効きます。</p>
<h2>対処5: Service Worker / CDN キャッシュ</h2>
<p>PWA で Service Worker が登録されていると、<strong>ブラウザより手前で CSS をキャッシュ</strong>します。Cloudflare 等の CDN も同様です。</p>
<pre style="background:#1e293b;color:#e2e8f0;padding:1em;border-radius:6px;overflow-x:auto;line-height:1.5"><code class="language-javascript">// DevTools の Application タブ → Service Workers → Unregister
// または JS で削除
navigator.serviceWorker.getRegistrations().then(rs => {
rs.forEach(r => r.unregister());
});
// Cache Storage も削除
caches.keys().then(keys => keys.forEach(k => caches.delete(k)));</code></pre>
<p>Cloudflare の場合: ダッシュボード → Caching → Configuration → <strong>Purge Everything</strong>。または URL 単位で <strong>Purge by URL</strong>。</p>
<h2>対処6: 詳細度 (Specificity) の負け</h2>
<p>CSS が読み込まれているのに効かない場合、<strong>他のルールに上書きされている</strong>可能性があります。DevTools の Styles タブで取り消し線がついている property を確認します。</p>
<table border="1" cellpadding="6" cellspacing="0" style="border-collapse:collapse;width:100%">
<thead><tr style="background:#e8f5e9"><th>セレクタ</th><th>詳細度 (a, b, c)</th><th>備考</th></tr></thead>
<tbody>
<tr><td><code>*</code></td><td>0, 0, 0</td><td>ユニバーサルセレクタ</td></tr>
<tr><td><code>p</code> / <code>div</code></td><td>0, 0, 1</td><td>要素セレクタ</td></tr>
<tr><td><code>.btn</code></td><td>0, 1, 0</td><td>クラス / 属性 / 擬似クラス</td></tr>
<tr><td><code>#header</code></td><td>1, 0, 0</td><td>ID</td></tr>
<tr><td><code>style="..."</code></td><td>インライン</td><td>クラスより強い</td></tr>
<tr><td><code>!important</code></td><td>最強</td><td>濫用禁止</td></tr>
</tbody>
</table>
<pre style="background:#1e293b;color:#e2e8f0;padding:1em;border-radius:6px;overflow-x:auto;line-height:1.5"><code class="language-css">/* 詳細度の例 */
.btn { color: red; } /* (0,1,0) */
nav .btn { color: blue; } /* (0,1,1) → 勝つ */
#header .btn { color: green; } /* (1,1,0) → さらに勝つ */
button.btn { color: orange !important; } /* !important で全勝ち */
/* 詳細度を上げる定番テク */
.btn.btn { color: red; } /* (0,2,0) クラス重ね */
body .btn { color: red; } /* (0,1,1) 親要素追加 */</code></pre>
<h2>対処7: その他チェックリスト</h2>
<ul>
<li><strong>セレクタの綴りミス</strong>: <code>.btn-primaly</code> ↔ <code>.btn-primary</code></li>
<li><strong>HTML との不一致</strong>: <code>class="btn primary"</code> に対し <code>.btn-primary</code> は当たらない</li>
<li><strong>シンタックスエラー</strong>: セミコロン抜け / 中括弧不整合で以降のルールが全部死ぬ</li>
<li><strong>CSS 順序</strong>: 後勝ち。<code>style.css</code> の後に <code>override.css</code> を読み込む</li>
<li><strong>SCSS のネスト崩壊</strong>: <code>&:hover</code> の <code>&</code> 抜け</li>
<li><strong>Tailwind の Purge</strong>: 動的クラス名 (<code>bg-${color}-500</code>) は削られる → safelist 設定</li>
</ul>
<h2>キャッシュバスターをデプロイ自動化</h2>
<pre style="background:#1e293b;color:#e2e8f0;padding:1em;border-radius:6px;overflow-x:auto;line-height:1.5"><code class="language-bash"># Git の commit hash をクエリにする例 (PHP)
$ver = trim(shell_exec('git rev-parse --short HEAD'));
echo "<link rel=\"stylesheet\" href=\"/css/style.css?v=$ver\">";
# Nginx で常に no-cache (開発環境)
location ~* \.css$ {
add_header Cache-Control "no-store, must-revalidate";
}
# 本番では逆に長期キャッシュ + ハッシュ付与
location ~* \.[0-9a-f]{8,}\.(css|js)$ {
expires 1y;
add_header Cache-Control "public, immutable";
}</code></pre>
<h2>FAQ</h2>
<p><strong>Q: シークレットウィンドウなら反映される</strong><br />
A: 確実にブラウザキャッシュです。クエリ文字列 or ハッシュ付きファイル名を導入してください。</p>
<p><strong>Q: 自分の PC では反映されないが他人のは反映される</strong><br />
A: ローカルブラウザキャッシュか拡張機能 (広告ブロッカー等) の干渉。<code>Ctrl+Shift+Delete</code> でキャッシュ消去。</p>
<p><strong>Q: <code>!important</code> を付けても効かない</strong><br />
A: 既に <code>!important</code> が上にある or インラインスタイルで上書きされている。DevTools で確認。</p>