グローバルナビゲーションへ

本文へ

フッターへ

お役立ち情報Blog



:not()否定擬似クラスを使ってCSSセレクタに!(否定条件)を追加しよう

CSSコーディングをしていると、

  • 一番下の行には線をつけないでください
  • 3つ目の要素は背景画像をとってください

といったように、要素の「位置」や「順番」に応じて装飾を除外するような要求を出されることがたくさんあると思います。

CSSセレクタは原則として「当てはまる条件」を連ねて要素を絞り込んでいくものですが、:not()擬似クラスを利用することで「否定条件」をセレクタに追加することができます。

CSSは柔軟な言語なので:not()擬似クラスを利用しなくても問題を解決する様々な方法がありますが、コードに「否定」を明言することで可読性の向上に一役買ってくれるなかなか便利な機能です。

本記事で簡単な使い方と従来のセレクタとの比較についてご紹介いたしますので、ぜひ最後までお付き合いください。

:not()擬似クラスとは

:not() – CSS: カスケーディングスタイルシート | MDN

:not()擬似クラスは選択対象の要素から特定の条件に一致する要素を除外することができるセレクタで、「否定擬似クラス(negation pseudo-class)」と呼ばれています。

例えば、「n番目の要素だけ色を変えない」といったような、特定の条件の要素を除外したセレクタ指定をする際に活用できます。
ただし、このような条件を満たすセレクタを記述するにあたり、:not()擬似クラスは必須ではありません。

<style>
/** :not() 擬似クラスを使わない場合 **/
ul > li {
  color: red;
}
ul > li:nth-child(3) {
  color: inherit;
}

/** :not() 擬似クラスを使った場合 **/
ul > li:not(:nth-child(3)) {
  color: red;
}
</style>

いかがでしょうか?どちらも同じ結果になりますが、:not()擬似クラスを使ったほうがコード量を少なくすることができますね。

しかし、上記例からもわかるように、:not()擬似クラスを使わなくても別のセレクタからスタイルを上書き(リセット)することで対処することが可能ですし、実際に、このような運用をするケースはたくさんあると思います。(著者もよくやっています)

このような修正は、各々の要求自体は単純なことが多く、上記のように:nth-child()擬似クラスを利用したり、除外対象となる要素に個別にクラスを設定することで要素を特定し、別途、上書きするような形で対応すれば問題は解決します。

しかし、この類の修正は単体で見れば簡単なものですが、デザインの影響を受けやすいので頻繁に発生し、数が多くなりがちなのがネックなところ。ちりも積もればなんとやらで、いつの間にか管理コストが膨れ上がってて、ちょっとした修正に時間をとられるようになってしまいます。

:not()擬似クラスですべてを解決することはできませんが、コード量を少なく保つことはメンテナンス性の向上に寄与すると著者は考えています。なんでも:not()擬似クラスを使えばいいとは思いませんが、コーディングの際の選択肢の1つとして覚えておいて損はないと思います。

対象ブラウザ

CSS selector: Negation pseudo-class selector (:not()) | Can I use… Support tables for HTML5, CSS3, etc

:not()擬似クラスはかなり昔から全ブラウザでサポートされており、モダンブラウザはもちろん、IE9でも問題なく利用できました。

過去のコードをメンテナンスする際にも使われている可能性は十分にありますので、基本的な使い方は押さえておきたいところです。

:not()擬似クラスの使い方

それでは:not()擬似クラスの基本的な使い方を見ていきます。

<style>
.container >:not(p) {
  color: blue;
}
</style>

<div class="container">
  <div>テキストがはいります </div>
  <div>テキストがはいります </div>
  <p>テキストがはいります </p>
  <p>テキストがはいります </p>
  <div>テキストがはいります </div>
  <span>テキストがはいります </span>
</div>

とてもサンプルっぽいコードになりましたが、「p要素以外の文字色を青」にする例です。:not()擬似クラスに指定した要素(p要素)にはスタイルが適用されていないのがわかると思います。

上記例では:not()擬似クラスに対して「pタグ(要素セレクタ)」を指定しましたが、

  • 要素セレクタ(divとかpとか)
  • IDセレクタ(#hogehogeとか)
  • クラスセレクタ(.hogehogeとか)
  • 属性セレクタ([name=”hogehoge”]とか)
  • 擬似クラス(:fist-childとか)
  • ユニバーサルセレクタ((*)アスタリスク)

を利用して否定条件を指定することが可能です。 普段のコーディングで使うセレクタは大体利用可能ですが、「疑似要素」など一部のものが使えませんので注意しましょう。

それではもう少し具体的に、どのようなケースで:not()擬似クラスを利用できるか確認していきます。

一番最初の要素、一番最後の要素を除外したい

著者がコーディングをしていてよく出くわすのは「一番最初の要素」もしくは、「一番最後の要素」を除外したいときです。
今回は「一番最後の要素の除外」でよくある、「リスト要素の下線の有無」を例に考えます。

border-bottomプロパティを利用して下線を引くのが一般的なやり方だと思いますが、このような指定では全ての要素に下線がついてしまいます。このままでいいケースもありますが、デザインによっては「一番下の線はとってください」と言われることもしばしば。

このような要件への対処方法はいくつかありますが、よく使われる3パターンを比較します。

:last-child擬似クラスで対応

先述した例と同じ考え方です。おそらくこのやり方が一番使われているのではないでしょうか。
border-bottomプロパティを全ての要素に適用した上で、:last-child擬似クラスを同じセレクタに適用して最後の要素だけ下線を無効にする方法です。

/** :last-child擬似クラスで対応 **/
.container ul > li {
  border-bottom: 1px solid #dfdfdf;
  padding: 1em 0;
}
.container ul > li:last-child {
  border-bottom: none;
}

「CSSを上書き」という行為は直感的ではありますが、数が増えると全体を把握するのが困難になるという問題も合わせもっています。また、セレクタの詳細度が高くなりますので、何かしらのコーディング規約にそって詳細度を管理している場合は注意が必要です。

CSSの上書きが一概に悪いとは言えませんが、他のセレクタで代用できる場合は検討の余地があると思います。

次兄弟結合子で対応

著者がよく使っていたのはこちらです。「次兄弟結合子」というと戸惑いますが、「+」記号、つまり隣接する兄弟要素を参照する演算子です。

/** 次兄弟結合子で対応 **/
.container ul > li {
  padding: 1em 0;
}
.container ul > li + li {
  border-top: 1px solid #dfdfdf;
}

打ち消しよりも幾分コードがスッキリして見えませんか?「一番最後の要素に下線をつけない」という条件に対して、「2つ目以降の要素の上に線をつける」という形で要求を満たしています。発想の転換(条件の置き換え)ですね。

個人的にはとても合理的な対応だと思っているのですが、「下線を引く」という要件に対してborder-topプロパティを使うという点がしっくり来ない人もいるようです。(当社比)
慣れの問題かもしれませんが、可読性に少し難あり、といったところでしょうか。

ちなみに、次兄弟結合子の使い方として、「* + *」のように記述することで「二番目以降の要素」もしくは「最初の要素以外の要素」を参照することができますが、この見た目がフクロウの顔に見えることから「フクロウ演算子、フクロウセレクタ」と呼ばれることもあります。覚えておくといいことあるかもしれません。

:not()擬似クラスで対応

本記事の本題、:not()擬似クラスを利用した方法です。

/** :not()擬似クラスで対応 **/
.container ul > li {
  padding: 1em 0;
}
.container ul > li:not(:last-child) {
  border-bottom: 1px solid #dfdfdf;
}

:last-child擬似クラスも併用する形にはなりますが、「CSSの打ち消し」ではなく、「セレクタから除外」という形で利用しています。また、一番最後の要素を除外していますので、「下線を引く」という要件に対してborder-bottomプロパティを使うという方法で要求を満たすこともできています。

:last-child擬似クラスと:not()擬似クラスの併用ということで、両者の使い方を知る必要はありますが、3パターンの中では一番効率よく、また可読性も担保できる記述方法ではないかと思います。

さいごに

いかがでしたでしょうか。:not()擬似クラスを利用した否定条件の使い方についてご紹介しました。

「否定擬似クラス」という名の通り、セレクタに否定条件を指定できる数少ない方法の1つです。否定条件を使わなくても「上書き」や「条件の置き換え」といった手段でコーディングは可能ですが、否定条件を使うことでより効率的なコーディングを意識することは重要だと著者は考えています。(まだまだできていませんが…)

本記事がみなさんのコーディングのお役に立てれば幸いです。

この記事を書いた人

なかもと
なかもとソリューション事業部 マークアップエンジニア
企画・営業部を経て、システムエンジニア、マークアップエンジニアとしてweb サイト制作、webアプリケーション開発の上流から下流まで幅広く携わる。ユーザビリティ、アクセシビリティを意識したセマンティックなマークアップとより良いユーザー体験を追及して日々奔走中。三度の飯よりwebが好き。
この記事のカテゴリ

FOLLOW US

最新の情報をお届けします