お知らせ・ブログ一覧へ戻る

CSSが一部だけ効かないときに見るところ|全部反映されないのとは原因が違う


CSSが一部だけ効かないときに見るところ|全部反映されないのとは原因が違う

CSSが一部だけ効かないときに見るところ|全部反映されないのとは原因が違う

CSSを修正した。同じファイルに書いた変更のうち、いくつかはちゃんと反映されている。それなのに、特定の指定だけが効かない。

この「一部だけ効かない」という症状は、「全部効かない」とは原因がまったく別です。全部効かないなら、疑うべきはファイルの配信元やキャッシュで、これは別記事「WordPressでCSSを直したのに反映されないとき|キャッシュより先に確かめる配信元」で手順をまとめています。一方、一部でも反映されているなら、ファイルは間違いなくブラウザまで届いています。キャッシュを何度クリアしても状況は変わりません。

原因はCSSの適用ルールにあります。あなたが書いた指定が、別の場所にある指定に「優先順位で負けている」のです。この記事では、負けている箇所を1分で特定する手順、優先順位が決まる仕組み、直し方の選び方、そしてこの問題が起きにくいCSSの書き方をまとめます。

結論:開発者ツールで「打ち消し線」を見る

最初にやることは1つだけです。ブラウザの開発者ツール(ChromeならF12、Macは Command+Option+I)を開き、変わらない要素を右クリックして「検証」を選びます。右側の「Styles(スタイル)」欄に、その要素に関係するCSSが優先順位の高い順に並びます。

ここで自分が書いた指定を探し、状態を見ます。見え方は3パターンしかありません。

見え方 意味 次にやること
打ち消し線が付いている 別の指定に負けている 上に表示されている「勝った指定」を確認する
一覧に出てこない セレクタが要素に当たっていない クラス名の打ち間違い・HTML構造の違いを疑う
打ち消し線なしで有効なのに見た目が変わらない 別の仕組みの問題 親要素からの継承、レイアウト、別プロパティを疑う

実務で圧倒的に多いのは1つ目です。打ち消し線が付いた指定の上を見ると、勝った側のセレクタと、それがどのファイルの何行目にあるかまで表示されています。つまり「誰に負けたか」は開発者ツールが答えを全部出してくれます。分からないのは「なぜ負けたか」の方なので、次でその仕組みを説明します。

なぜ後から書いたのに負けるのか:優先順位は2段階で決まる

CSSの優先順位は、次の2段階で決まります。

  1. 詳細度(セレクタの具体性)を比べる。詳細度が高い方が勝つ
  2. 詳細度が同点なら、後から読み込まれた方が勝つ

多くの人は2番だけを知っています。「CSSは後に書いた方が勝つ」という理解です。これは同点のときにしか成立しません。詳細度に差があれば、ファイルのどこに書こうが、どのファイルに書こうが、順番は一切関係なく詳細度の高い方が勝ちます。「あとから追記したのに変わらない」の正体は、ほぼこれです。

詳細度の数え方

詳細度は「ID・クラス・要素」の3桁で数えます。

  • ID(#main など)… 100の位
  • クラス・属性・擬似クラス(.btn、[href]、:hover など)… 10の位
  • 要素名(h3、p、a など)… 1の位

例を挙げます。

.site h3 { margin: 0; }          /* クラス1 + 要素1 = 0,1,1 */
.page-heading { margin-top: 64px; }  /* クラス1 = 0,1,0 */

この2つでは、上の指定が勝ちます。.page-heading をファイルの一番最後に書いても負けます。10の位が同じで、1の位で上回られているからです。

もう1つ、直感に反する重要な仕様があります。メディアクエリは詳細度を一切上げません@media (max-width: 760px) の中に書いた指定は「スマホ専用だから強い」わけではなく、中のセレクタの詳細度がそのまま使われます。スマホ表示だけ崩れる原因の定番です(後述します)。

「一部だけ効かない」が生まれる典型3パターン

弊社が実際の制作・保守で繰り返し遭遇してきたパターンは3つです。どれも「ファイルは正しく配信されているのに、特定の指定だけ効かない」という同じ顔で現れます。

パターン1:後から追加した「上書き用CSS」が常に最後に読まれる構成

リニューアルやデザイン調整を重ねたサイトでは、読み込み順の最後に「上書き用」のCSSファイルが足されていることがよくあります。たとえば読み込み順が、

tokens.css → base.css → components.css → parts.css → sections.css → redesign.css

のような6ファイル構成で、最後の redesign.css がデザイン改修時に追加されたファイルだとします。この構成では、途中の parts.css に同じ詳細度の指定を追記しても、redesign.css に同名セレクタがあれば必ず負けます。追記した本人には「正しい場所に正しく書いた」感覚しかないため、原因に気づきにくいのが厄介な点です。

弊社で保守しているサイトでも、この構成で「リンク色の変更」「見出しサイズの調整」「特定要素の非表示」という性質の違う3つの修正が、立て続けに同じ理由で効かなかったことがあります。それぞれ属性セレクタへの変更・クラスの追加・要素名の追加で詳細度を1段上げて解決しましたが、本質的な予防策は後述の「書く前に検索する」です。

パターン2:リセットCSSが個別指定を黙って食う

サイト全体の余白をそろえるために、こういうリセットを書くことがあります。

.site h1, .site h2, .site h3, .site p, .site ul { margin: 0; }

このセレクタの詳細度は「クラス1+要素1=0,1,1」です。その後、個別のセクションで、

.section-heading { margin-top: 64px; }  /* 0,1,0 */

と書くと、詳細度で負けて余白は付きません。指定した margin-top がすべて0になります。

この事故の本当に厄介なところは、「一部だけ生き残る」点です。たとえば .statement p のような「クラス+要素」のセレクタは詳細度0,1,1でリセットと同点になり、後勝ちで生き残ります。結果、同じ感覚で書いた指定のうち、セレクタの書き方によって効くものと効かないものが混在するという、最も原因特定が難しい見え方になります。弊社の実例では、1つの構成変更で6箇所の見出し・本文の余白が同時に消え、一部のセレクタだけ無事でした。

予防策は、リセットを :where() で書くことです。

.site :where(h1, h2, h3, p, ul, li) { margin: 0; }

:where() の中身は詳細度に数えられないため、このリセットは詳細度0,1,0となり、後から書く単一クラスの指定と同点になります。同点なら後勝ちの原則どおり、個別指定が素直に効きます。

パターン3:バリエーション用のクラスが、スマホ用の指定に勝ってしまう

「同じ部品のコンパクト版」のような変化形を作るとき、クラスを重ねたセレクタを書きます。

.product--compact .product-grid { grid-template-columns: 1fr 1fr; }  /* 0,2,0 */

一方、スマホ用の指定はメディアクエリの中に単一クラスで書かれていることが多い。

@media (max-width: 760px) {
  .product-grid { grid-template-columns: 1fr; }  /* 0,1,0 */
}

前述のとおりメディアクエリは詳細度を上げないので、0,2,0対0,1,0でバリエーション側が勝ち、スマホでも2カラムのままになります。弊社が対応したECサイトの例では、この構造でスマホ表示だけ商品画像が潰れ、テキストが右半分に圧縮される崩れが起きていました。PCでは何の問題もないため、PC画面の縮小確認だけでは見つかりません。

バリエーション用の複合クラスを足すときは、スマホ側にも同じ詳細度の打ち消しをセットで書く、と決めておくとこの事故を防げます。

@media (max-width: 760px) {
  .product--compact .product-grid { grid-template-columns: 1fr; }  /* 同じ0,2,0で後勝ち */
}

直し方の選び方:詳細度は「必要最小限だけ」上げる

負けている箇所が特定できたら、直し方は4つあります。上から順に検討してください。

  1. 同じ詳細度のまま、勝った指定より後に書く。読み込み順の最後のファイルに書けるなら、これが一番きれいです
  2. 要素名を1つ足す(.badge → p.badge)。1の位が上がります
  3. クラスを1つ足す(.hero .badge のように親のクラスを重ねる)。10の位が上がります
  4. 属性セレクタを使う(a[href*="line.me"] など)。クラスを足せないHTMLでも10の位を上げられます

避けたいのは、いきなり !important を付けることです。確かにその場では勝てますが、次にその指定を上書きしたくなったとき、もっと強い !important が必要になります。これを繰り返したCSSは、最終的に誰も安全に触れなくなります。!important は「外部ツールが差し込むスタイルにどうしても勝てない」など、詳細度の操作で解決できない場合の最終手段と考えてください。

予防:書く前に「同名セレクタを検索する」

この問題は、直すより予防する方がずっと安上がりです。ルールは1つで済みます。

CSSを追記する前に、同じセレクタ(同じクラス名)がサイト内の他のCSSファイルに存在しないか検索する。

エディタの横断検索(VS Codeなら Command+Shift+F)でクラス名を検索するだけです。ヒットしたら、そのファイルが自分の書くファイルより後に読まれるかを確認し、後に読まれるなら最初から詳細度を1段上げて書く。この10秒の確認で、「書いた→効かない→調べる→書き直す」の往復が丸ごと消えます。

複数人や複数の時期をまたいで改修されてきたサイトほど、CSSファイルの数は増え、読み込み順は複雑になっています。「自分が今書いている場所が読み込み順のどこか」を把握しないまま追記するのは、負ける場所にくじ引きで書いているのと同じです。

補足:@layer を使う構成では詳細度のルール自体が変わる

最後に、新しめの構成での注意点を1つ。Tailwind CSS v4など、カスケードレイヤー(@layer)を使うフレームワークでは、優先順位の第1段階として「レイヤーの外か中か」が判定されます。レイヤーの外に書かれた普通のCSSは、レイヤー内のCSSに対して詳細度と無関係に必ず勝ちます

つまり、:where() で詳細度を0にしたリセットでも、レイヤー外にある時点でフレームワークのユーティリティクラスを全部潰します。弊社でも、無害なはずの :where(a) { color: inherit } という1行が、Tailwind側で指定したリンク色を無効化した実例がありました。フレームワークがリセット(preflight等)を提供している場合、自作のリセットはそもそも書かない・既にあるなら削除するのが正解です。

まとめ

  • 「一部だけ効かない」はキャッシュや配信の問題ではない。CSSの優先順位で負けている。全部効かない場合とは切り分けて考える
  • 特定は開発者ツールの打ち消し線を見るだけ。「誰に負けたか」はツールが表示してくれる
  • 優先順位は「詳細度→同点なら後勝ち」の2段階。詳細度に差があると書いた場所は関係ない。メディアクエリは詳細度を上げない
  • 典型パターンは「最後に読まれる上書き用CSS」「詳細度の高いリセット」「バリエーションクラスがスマホ指定に勝つ」の3つ
  • 直すときは必要最小限だけ詳細度を上げる。!important は最終手段
  • 予防は「書く前に同名セレクタを検索する」の10秒。リセットを自作するなら :where() で詳細度を0にする

自社サイトを自分で触っている方も、制作会社に依頼している方も、「一部は変わったのに、ここだけ変わらない」という症状が出たら、この記事の切り分けをそのまま使ってください。どうしても原因が特定できない場合や、CSSが積み重なって手を入れるのが怖い状態になっている場合は、graciautoでも調査・整理を承っています。

関連記事

2026.08.28

注文通知メールに何を入れておくべきか|店側が受け取る通知の項目設計

2026.08.28

ロゴの背景が白く四角く出るときの確認手順|PNGなら透過されているとは限らない

2026.08.28

業務の自動化で何を聞けば外さないか|依頼の言葉どおりに作ると効果が出ない理由


お知らせ・ブログ一覧へ戻る