【CSS】:not()疑似クラスの使い方:効かない原因と複数条件の指定

css-not

CSSの:not()疑似クラスは、特定のクラスや状態を除外してスタイルを適用することで、冗長な「打ち消しコード」を減らすことができる便利なセレクタです。

本記事では、基本的な使い方から他の疑似クラスとの組み合わせ、:has()を利用したテクニックまで解説します。

また、CSSに関するカテゴリーページから学びたい内容を決めたい人は、以下のCSSページをご確認ください。

目次

:not()疑似クラスとは:特定の要素を除外する書き方

Webサイトのデザインを整える中で、「この要素以外にスタイルを当てたい」という場面はよくあります。

そんな時に大活躍するのが否定疑似クラスと呼ばれる:not()です。

:not()を一言で説明すると、指定した条件を「除外」するセレクタです。

これまでは「一度全体にスタイルを当ててから、特定の要素だけスタイルを打ち消す(上書きする)」という冗長なコードが一般的でしたが、:not()をマスターすれば、シンプルで保守性の高いCSSを書けます。

ここでは、実務で必須となる:not()セレクタの基本から特定のプロパティを適用させないテクニックを解説します。

:not()疑似クラスとは:特定の要素を除外する書き方
  • クラスや属性を持たない要素を指定する基本
  • first-childhoverなどの疑似クラスとの組み合わせ
  • 複数条件や:has()との組み合わせ

クラスや属性を持たない要素を指定する基本

基本的な使い方として、特定のクラスやID、属性を「持たない」要素の指定です。

例えば、「.is-activeクラスを持たない要素」、「href属性を持たない<a>タグ」、「データ属性を持たない要素」、「中身が空ではない要素」など、クラス以外の除外も行えます。

「打ち消し(上書き)のCSS」を書かないために:not()を使うのがよいです。

例えば、マージンを消すための.no-marginクラスを作る場合、一度全要素にマージンをつけてから.no-margin { margin: 0; }と打ち消すのではなく、最初からli:not(.no-margin) { margin-bottom: 20px; }と記述します。

これにより、ブラウザのレンダリング負荷も下がり、コードも美しくなります。

⭕️ :not() を使えば「上書き用のCSS」を減らすことができる

  • 通常のリスト項目
  • ハイライト項目(除外される)
  • 無効化された項目(除外される)
/* ⭕️ .is-highlight を持たない要素「だけ」に基本色を当てる */
.not-item:not(.is-highlight) {
  color: #6c757d;
}

/* 💡 data-disabled 属性を持たない要素「だけ」をホバー可能にする */
.not-item:not([data-disabled]) {
  cursor: pointer;
}

/* 💡 中身が空ではない(テキストがある)要素「だけ」にパディングをつける */
.not-item:not(:empty) {
  padding: 15px 20px;
  background-color: #f8f9fa;
}
HTMLコード表示
<div class="not-basic-wrapper">
  
  <p class="not-caption">⭕️ :not() を使えば「上書き用のCSS」を減らすことができる</p>

  <div class="not-demo-area">
    
    <ul class="not-list">
      <li class="not-item">通常のリスト項目</li>
      
      <li class="not-item is-highlight">ハイライト項目(除外される)</li>
      
      <li class="not-item" data-disabled="true">無効化された項目(除外される)</li>
      
      <li class="not-item"></li>
    </ul>

  </div>

  <div class="not-code">
    /* ⭕️ .is-highlight を持たない要素「だけ」に基本色を当てる */<br>
    <span class="hl-blue">.not-item:not(.is-highlight)</span> {<br>
      <span class="hl-green">color: #6c757d;</span><br>
    }<br><br>

    /* 💡 data-disabled 属性を持たない要素「だけ」をホバー可能にする */<br>
    <span class="hl-blue">.not-item:not([data-disabled])</span> {<br>
      <span class="hl-green">cursor: pointer;</span><br>
    }<br><br>

    /* 💡 中身が空ではない(テキストがある)要素「だけ」にパディングをつける */<br>
    <span class="hl-blue">.not-item:not(:empty)</span> {<br>
      <span class="hl-green">padding: 15px 20px;</span><br>
      <span class="hl-green">background-color: #f8f9fa;</span><br>
    }
  </div>

</div>
CSSコード表示
.not-basic-wrapper {
  background-color: #f8f9fa;
  padding: 20px;
  border-radius: 8px;
  border: 1px solid #dee2e6;
}

.not-caption {
  font-size: 13px;
  font-weight: bold;
  margin-bottom: 20px;
  color: #198754;
  text-align: center;
}

.not-demo-area {
  background-color: #fff;
  padding: 30px;
  border-radius: 4px;
  border: 1px dashed #adb5bd;
  margin-bottom: 20px;
}

.not-list {
  list-style: none;
  padding: 0;
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.not-item {
  border: 1px solid #ced4da;
  border-radius: 4px;
  font-size: 14px;
  font-weight: bold;
  transition: all 0.2s ease;
}

/* 💡 :not() を使ったスタイリング */
/* .is-highlight を持たない要素の基本色 */
.not-item:not(.is-highlight) {
  color: #6c757d;
}

/* .is-highlight は別のスタイル */
.not-item.is-highlight {
  color: #0d6efd;
  border-color: #0d6efd;
  background-color: #e7f1ff;
}

/* data-disabled を持たない要素だけホバーエフェクト */
.not-item:not([data-disabled]):hover {
  cursor: pointer;
  transform: translateX(5px);
  box-shadow: 0 4px 6px rgba(0,0,0,0.05);
}

/* data-disabled のスタイル */
.not-item[data-disabled] {
  opacity: 0.5;
  background-color: #e9ecef;
}

/* 中身が空ではない(:emptyではない)要素にだけパディングと背景色をつける */
/* 空の要素はペチャンコになって見えなくなります */
.not-item:not(:empty) {
  padding: 15px 20px;
}

/* コードブロック装飾 */
.not-code {
  background-color: #282c34;
  color: #abb2bf;
  padding: 15px;
  border-radius: 4px;
  font-family: monospace;
  font-size: 13px;
  line-height: 1.6;
  border-left: 4px solid #0d6efd;
}

.hl-blue { color: #61afef; font-weight: bold; }
.hl-red { color: #e06c75; font-weight: bold; }
.hl-green { color: #98c379; font-weight: bold; }

first-childやhoverなどの疑似クラスとの組み合わせ

:not()の真骨頂は、他の疑似クラスと組み合わせた時に発揮されます。

例えば、「最初の要素以外」や「最後の要素以外」、「N番目以外」といったリストの装飾です。

さらには、「ホバーされていない要素」、「フォーカスされていない入力欄」、「チェックされていないボタン」、「無効化されていない要素」など状態に対する除外です。

実務で登場頻度が高い組み合わせが、リストの区切り線を引くli:not(:last-child)です。

初心者はli { border-bottom: 1px solid #ccc; }と書き、最後の要素だけli:last-child { border-bottom: none; }と打ち消しますが、これはスマートではありません。

「最後の子要素以外に下線を引く」と書くのが、モダンCSSのスタンダードです。

また、「ホバーされていない要素を暗くする」というギャラリーサイト等で定番のエフェクトも、親要素へのホバーとimg:not(:hover)を組み合わせることで実装できます。

⭕️ 鉄則:打ち消し(border-bottom: none;)を使わず、最初から除外して線を引く

最後の要素以外に下線

  • メニュー 1
  • メニュー 2
  • メニュー 3(線なし)

ホバーされていない要素を暗く

/* ⭕️ 最後の要素(last-child)「以外」に下線を引く */
.menu-item:not(:last-child) {
  border-bottom: 1px solid #dee2e6;
  margin-bottom: 10px;
  padding-bottom: 10px;
}

/* 💡 親要素がホバーされた時、ホバー「されていない」ボタンを半透明にする */
.btn-group:hover .action-btn:not(:hover):not(:disabled) {
  opacity: 0.4;
  transform: scale(0.95);
}

/* 💡 無効化「されていない」ボタンだけホバーを許可する */
.action-btn:not(:disabled):hover {
  background-color: #0d6efd;
  color: white;
}
HTMLコード表示
<div class="not-pseudo-wrapper">
  
  <p class="not-caption">⭕️ 鉄則:打ち消し(border-bottom: none;)を使わず、最初から除外して線を引く</p>

  <div class="not-demo-area" style="display: flex; gap: 40px; justify-content: center; flex-wrap: wrap;">
    
    <div class="not-box" style="width: 100%; max-width: 250px;">
      <p class="not-label">最後の要素以外に下線</p>
      <ul class="not-menu">
        <li class="not-menu-item">メニュー 1</li>
        <li class="not-menu-item">メニュー 2</li>
        <li class="not-menu-item">メニュー 3(線なし)</li>
      </ul>
    </div>

    <div class="not-box" style="width: 100%; max-width: 250px;">
      <p class="not-label">ホバーされていない要素を暗く</p>
      <div class="not-btn-group">
        <button class="not-action-btn">ボタン A</button>
        <button class="not-action-btn">ボタン B</button>
        <button class="not-action-btn" disabled>無効(disabled)</button>
      </div>
    </div>

  </div>

  <div class="not-code">
    /* ⭕️ 最後の要素(last-child)「以外」に下線を引く */<br>
    <span class="hl-blue">.menu-item:not(:last-child)</span> {<br>
      <span class="hl-green">border-bottom: 1px solid #dee2e6;</span><br>
      <span class="hl-green">margin-bottom: 10px;</span><br>
      <span class="hl-green">padding-bottom: 10px;</span><br>
    }<br><br>

    /* 💡 親要素がホバーされた時、ホバー「されていない」ボタンを半透明にする */<br>
    <span class="hl-blue">.btn-group:hover .action-btn:not(:hover):not(:disabled)</span> {<br>
      <span class="hl-green">opacity: 0.4;</span><br>
      <span class="hl-green">transform: scale(0.95);</span><br>
    }<br><br>

    /* 💡 無効化「されていない」ボタンだけホバーを許可する */<br>
    <span class="hl-blue">.action-btn:not(:disabled):hover</span> {<br>
      <span class="hl-green">background-color: #0d6efd;</span><br>
      <span class="hl-green">color: white;</span><br>
    }
  </div>

</div>
CSSコード表示
.not-pseudo-wrapper {
  background-color: #f8f9fa;
  padding: 20px;
  border-radius: 8px;
  border: 1px solid #dee2e6;
}

.not-caption {
  font-size: 13px;
  font-weight: bold;
  margin-bottom: 20px;
  color: #198754;
  text-align: center;
}

.not-demo-area {
  background-color: #e9ecef;
  padding: 30px;
  border-radius: 4px;
  border: 1px dashed #adb5bd;
  margin-bottom: 20px;
}

.not-box {
  background-color: #fff;
  padding: 20px;
  border-radius: 8px;
  border: 1px solid #ced4da;
}

.not-label {
  font-size: 12px;
  font-weight: bold;
  margin-bottom: 15px;
  color: #333;
  text-align: center;
  border-bottom: 2px dashed #e9ecef;
  padding-bottom: 10px;
}

/* 💡 :not(:last-child) のスタイル */
.not-menu {
  list-style: none;
  padding: 0;
  margin: 0;
}

.not-menu-item {
  color: #495057;
  font-weight: bold;
  font-size: 14px;
}

/* ⭕️ 最後の要素以外に下線と余白をつける */
.not-menu-item:not(:last-child) {
  border-bottom: 1px solid #dee2e6;
  margin-bottom: 15px;
  padding-bottom: 15px;
}

/* 💡 :not(:hover) のスタイル */
.not-btn-group {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.not-action-btn {
  padding: 10px 15px;
  border: 2px solid #0d6efd;
  background-color: #fff;
  color: #0d6efd;
  font-weight: bold;
  border-radius: 4px;
  cursor: pointer;
  transition: all 0.3s ease;
}

.not-action-btn[disabled] {
  border-color: #adb5bd;
  color: #adb5bd;
  cursor: not-allowed;
}

/* ⭕️ グループがホバーされた時、ホバーされていない&無効化されていないボタンを暗くする */
.not-btn-group:hover .not-action-btn:not(:hover):not(:disabled) {
  opacity: 0.3;
  transform: scale(0.95);
}

/* ⭕️ 無効化されていないボタンだけホバーエフェクトをつける */
.not-action-btn:not(:disabled):hover {
  background-color: #0d6efd;
  color: white;
  transform: translateY(-2px);
  box-shadow: 0 4px 8px rgba(13, 110, 253, 0.2);
}

リストの作り方を詳しく知りたい人は「【html&css】ul・li・olの使い方とおしゃれなデザインリスト」を一読ください。

複数条件や:has()との組み合わせ

:not()を使って複数の条件を指定する場合、「AかつBではない」のか、「AまたはBではない」のかという論理演算の理解が必須です。

また、最新のCSSでは親要素セレクタ:has()との組み合わせによって、JavaScriptに頼っていた複雑なUI制御がCSSだけで完結するようになりました。

現在のモダンCSSにおけるテクニックが:not(:has(...))の組み合わせです。

例えば、「画像を持っていないカード」に対してだけ特別なパディングを当てたり、特定のクラスが内包されていないセクションだけ背景色を変えたりと「特定の子要素を持たない親要素」をスタイルできるため、HTMLのクラス設計をシンプルに保てます。

⭕️ :not(.a, .b) の複数除外と、:not(:has(…)) の最強コンボ

風景

画像ありカード

画像があるので通常レイアウト。

画像なしカード

画像がない(imgタグを内包していない)ため、:not(:has(img))が発動し、パディングや枠線が自動的に特別仕様になります。
/* 💡 複数条件の除外(OR条件):apple または banana を持たない要素(css not multiple) */
.item:not(.apple, .banana) {
  opacity: 0.5;
}

/* ⭕️ 子要素に を「持たない」カードだけにスタイルを当てる */
.card:not(:has(img)) {
  border: 2px dashed #0d6efd;
  background-color: #e7f1ff;
}

/* 💡 を持たないカードの本文エリアのパディングを広くする */
.card:not(:has(img)) .card-body {
  padding: 40px 20px;
}
HTMLコード表示
<div class="not-advanced-wrapper">
  
  <p class="not-caption">⭕️ :not(.a, .b) の複数除外と、:not(:has(...)) の最強コンボ</p>

  <div class="not-demo-area" style="display: flex; gap: 30px; flex-wrap: wrap; justify-content: center;">
    
    <div class="not-card has-image">
      <img src="https://picsum.photos/id/1015/300/150" alt="風景" class="not-card-img">
      <div class="not-card-body">
        <p class="not-label">画像ありカード</p>
        <span class="not-txt">画像があるので通常レイアウト。</span>
      </div>
    </div>

    <div class="not-card no-image">
      <div class="not-card-body">
        <p class="not-label" style="color: #0d6efd;">画像なしカード</p>
        <span class="not-txt">画像がない(imgタグを内包していない)ため、:not(:has(img))が発動し、パディングや枠線が自動的に特別仕様になります。</span>
      </div>
    </div>

  </div>

  <div class="not-code">
    /* 💡 複数条件の除外(OR条件):apple または banana を持たない要素(css not multiple) */<br>
    <span class="hl-blue">.item:not(.apple, .banana)</span> {<br>
      <span class="hl-green">opacity: 0.5;</span><br>
    }<br><br>

    /* ⭕️ 子要素に <img> を「持たない」カードだけにスタイルを当てる */<br>
    <span class="hl-blue">.card:not(:has(img))</span> {<br>
      <span class="hl-green">border: 2px dashed #0d6efd;</span><br>
      <span class="hl-green">background-color: #e7f1ff;</span><br>
    }<br><br>

    /* 💡 <img> を持たないカードの本文エリアのパディングを広くする */<br>
    <span class="hl-blue">.card:not(:has(img)) .card-body</span> {<br>
      <span class="hl-green">padding: 40px 20px;</span><br>
    }
  </div>

</div>
CSSコード表示
.not-advanced-wrapper {
  background-color: #f8f9fa;
  padding: 20px;
  border-radius: 8px;
  border: 1px solid #dee2e6;
}

.not-caption {
  font-size: 13px;
  font-weight: bold;
  margin-bottom: 20px;
  color: #198754;
  text-align: center;
}

.not-demo-area {
  background-color: #fff;
  padding: 30px;
  border-radius: 4px;
  border: 1px dashed #adb5bd;
  margin-bottom: 20px;
}

/* ベースのカードスタイル */
.not-card {
  width: 100%;
  max-width: 250px;
  background-color: #fff;
  border: 1px solid #ced4da;
  border-radius: 8px;
  overflow: hidden;
  display: flex;
  flex-direction: column;
}

.not-card-img {
  width: 100%;
  height: 120px;
  object-fit: cover;
  display: block;
}

.not-card-body {
  padding: 20px;
  flex-grow: 1;
}

.not-txt {
  font-size: 13px;
  color: #495057;
  line-height: 1.5;
}

/* ⭕️ :not(:has(img)) を使ったスタイリング */
/* imgタグを内包「していない」カードに特別な枠線と背景色をつける */
.not-card:not(:has(img)) {
  border: 2px dashed #0d6efd;
  background-color: #e7f1ff;
}

/* imgタグを内包「していない」カードの中身のパディングを広くする */
.not-card:not(:has(img)) .not-card-body {
  padding: 40px 20px;
}

疑似要素である:has()の使い方を詳しく知りたい人は「【CSS】:has()疑似クラスの使い方:親・子・孫要素の指定や複数条件との組み合わせ」を一読ください。

ユーザーの操作や挙動を禁止する「not」なCSS実装

CSSの役割は、色や形を整えることだけではありません。

WebアプリケーションやリッチなUIを構築する実務においては、「ユーザーの特定の操作を制限・禁止する」という制御が重要になります。

ここでは、要素の疑似クラス(:not())というセレクタの枠組みから視点を変え、ユーザーの挙動を「not」にする代表的なCSSプロパティ群と使い方を解説します。

ユーザーの操作や挙動を禁止する「not」なCSS実装
  • テキストを選択不可・コピペ禁止にする
  • クリック無効や禁止カーソルにする
  • テキストを改行・折り返しさせない

テキストを選択不可・コピペ禁止にする

Webアプリのボタンやドラッグ&ドロップ機能のつまみなど、連続でクリックする要素のテキストが青くハイライトされてしまうと、操作性が悪くなります。

これを防ぎ、テキストを選択不可にするプロパティがuser-select: none;です。

これを指定することで要素を選択できない状態にし、マーク不可にすることが可能です。

user-select: none;は、アコーディオンメニューの開閉ボタン、タブ切り替えボタン、カルーセルの「次へ」ボタンなど「ユーザーがクリックするUIパーツ」にのみ限定して適用するのがよいです。

⭕️ user-select: none は「連打されるUIパーツ」にだけ適用する

❌ user-select指定なし

連続クリックしてみてください
(文字が青くハイライトされてしまいます)

⭕️ user-select: none あり

連続クリックしてみてください
(どれだけ連打してもハイライトされません)
/* ❌ ボタンに指定を忘れると、連打時に文字が選択されてしまう */
.btn-wrong {
  background-color: #6c757d;
  padding: 10px 20px;
}

/* ⭕️ UIボタンには必ず user-select: none; を指定する */
.btn-correct {
  background-color: #0d6efd;
  padding: 10px 20px;
  user-select: none; /* 💡 テキスト選択を禁止する */
  -webkit-user-select: none; /* 💡 Safari用のプレフィックス */
}
HTMLコード表示
<div class="restrict-tech-wrapper">
  
  <p class="restrict-caption">⭕️ user-select: none は「連打されるUIパーツ」にだけ適用する</p>

  <div class="restrict-demo-area" style="flex-direction: column; gap: 30px;">
    
    <div class="restrict-box" style="align-items: flex-start; width: 100%;">
      <p class="restrict-label">❌ user-select指定なし</p>
      <div class="restrict-btn is-selectable">
        連続クリックしてみてください
      </div>
      <small style="margin-top: 5px; color: #6c757d;">(文字が青くハイライトされてしまいます)</small>
    </div>

    <div class="restrict-box" style="align-items: flex-start; width: 100%;">
      <p class="restrict-label" style="color:#0d6efd;">⭕️ user-select: none あり</p>
      <div class="restrict-btn is-not-selectable">
        連続クリックしてみてください
      </div>
      <small style="margin-top: 5px; color: #6c757d;">(どれだけ連打してもハイライトされません)</small>
    </div>

  </div>

  <div class="restrict-code">
    /* ❌ ボタンに指定を忘れると、連打時に文字が選択されてしまう */<br>
    <span class="hl-blue">.btn-wrong</span> {<br>
      <span class="hl-green">background-color: #6c757d;</span><br>
      <span class="hl-green">padding: 10px 20px;</span><br>
    }<br><br>

    /* ⭕️ UIボタンには必ず user-select: none; を指定する */<br>
    <span class="hl-blue">.btn-correct</span> {<br>
      <span class="hl-green">background-color: #0d6efd;</span><br>
      <span class="hl-green">padding: 10px 20px;</span><br>
      <span class="hl-red">user-select: none;</span> /* 💡 テキスト選択を禁止する */<br>
      <span class="hl-red">-webkit-user-select: none;</span> /* 💡 Safari用のプレフィックス */<br>
    }
  </div>

</div>
CSSコード表示
.restrict-tech-wrapper {
  background-color: #f8f9fa;
  padding: 20px;
  border-radius: 8px;
  border: 1px solid #dee2e6;
}

.restrict-caption {
  font-size: 13px;
  font-weight: bold;
  margin-bottom: 20px;
  color: #198754;
  text-align: center;
}

.restrict-demo-area {
  display: flex;
  align-items: center;
  background-color: #e9ecef;
  padding: 30px;
  border-radius: 4px;
  border: 1px dashed #adb5bd;
  margin-bottom: 20px;
}

.restrict-box {
  display: flex;
  flex-direction: column;
}

.restrict-label {
  font-size: 12px;
  font-weight: bold;
  margin-bottom: 10px;
  color: #333;
}

.restrict-btn {
  padding: 12px 24px;
  color: white;
  font-weight: bold;
  border-radius: 4px;
  cursor: pointer;
  display: inline-block;
}

/* ❌ 指定なし */
.is-selectable {
  background-color: #6c757d;
  /* user-select 指定なしのため、ダブルクリック等で選択される */
}

/* ⭕️ 指定あり */
.is-not-selectable {
  background-color: #0d6efd;
  user-select: none; /* 💡 これが鉄則 */
  -webkit-user-select: none;
}

/* コードブロック装飾 */
.restrict-code {
  background-color: #282c34;
  color: #abb2bf;
  padding: 15px;
  border-radius: 4px;
  font-family: monospace;
  font-size: 13px;
  line-height: 1.6;
  border-left: 4px solid #0d6efd;
}

.hl-blue { color: #61afef; font-weight: bold; }
.hl-red { color: #e06c75; font-weight: bold; }
.hl-green { color: #98c379; font-weight: bold; }

クリック無効や禁止カーソルにする

フォームの送信ボタンを「入力が完了するまで押せない状態」にしたい場合、マウスカーソルを「禁止マーク」に変更するcursor: not-allowed; が用いられます。

「禁止マークを出しつつ、クリックも無効化する」UIを作るには、親要素にcursor: not-allowed;を指定し、子要素にpointer-events: none;を指定するという二段構えの手法です。

もしくは、HTML側で<button disabled>を付与し、CSSでbutton:disabled { cursor: not-allowed; }とするのも解決策です。

⭕️ cursor: not-allowed は見た目だけ!クリックを防ぐには pointer-events が必須

❌ 見た目だけ禁止

⭕️ 完全な禁止状態

/* ❌ cursorを変えても、クリックイベント(JS)は発火してしまう */
.btn-wrong {
  opacity: 0.5;
  cursor: not-allowed; /* 💡 マウスカーソルが禁止マークになるだけ */
}

/* ⭕️ ラッパーと本体の「役割分担」で完璧な無効化を作る */
.btn-wrapper {
  cursor: not-allowed; /* 💡 ラッパーが禁止カーソルを表示する役割 */
  display: inline-block;
}
.btn-correct {
  opacity: 0.5;
  pointer-events: none; /* 💡 ボタン本体は一切のクリックを受け付けない */
}
HTMLコード表示
<div class="restrict-tech-wrapper">
  
  <p class="restrict-caption">⭕️ cursor: not-allowed は見た目だけ!クリックを防ぐには pointer-events が必須</p>

  <div class="restrict-demo-area" style="gap: 30px;">
    
    <div class="restrict-box">
      <p class="restrict-label">❌ 見た目だけ禁止</p>
      <button class="restrict-action-btn is-wrong-cursor" onclick="alert('クリックできてしまいました!')">
        未入力(押せないはず)
      </button>
    </div>

    <div class="restrict-box">
      <p class="restrict-label" style="color:#0d6efd;">⭕️ 完全な禁止状態</p>
      
      <div class="restrict-cursor-wrapper">
        <button class="restrict-action-btn is-correct-disabled" onclick="alert('これは表示されません')">
          未入力(完全に無効)
        </button>
      </div>
      
    </div>

  </div>

  <div class="restrict-code">
    /* ❌ cursorを変えても、クリックイベント(JS)は発火してしまう */<br>
    <span class="hl-blue">.btn-wrong</span> {<br>
      <span class="hl-green">opacity: 0.5;</span><br>
      <span class="hl-red">cursor: not-allowed;</span> /* 💡 マウスカーソルが禁止マークになるだけ */<br>
    }<br><br>

    /* ⭕️ ラッパーと本体の「役割分担」で完璧な無効化を作る */<br>
    <span class="hl-blue">.btn-wrapper</span> {<br>
      <span class="hl-red">cursor: not-allowed;</span> /* 💡 ラッパーが禁止カーソルを表示する役割 */<br>
      <span class="hl-green">display: inline-block;</span><br>
    }<br>
    <span class="hl-blue">.btn-correct</span> {<br>
      <span class="hl-green">opacity: 0.5;</span><br>
      <span class="hl-red">pointer-events: none;</span> /* 💡 ボタン本体は一切のクリックを受け付けない */<br>
    }
  </div>

</div>
CSSコード表示
/* 共通ボタンスタイル */
.restrict-action-btn {
  padding: 12px 20px;
  background-color: #198754;
  color: white;
  border: none;
  font-weight: bold;
  border-radius: 4px;
}

/* ❌ 見た目だけ */
.is-wrong-cursor {
  opacity: 0.5;
  cursor: not-allowed;
  /* pointer-events が無いためクリック可能 */
}

/* ⭕️ 完全な無効化 */
.restrict-cursor-wrapper {
  cursor: not-allowed; /* 親がカーソルを変える */
  display: inline-block;
}

.is-correct-disabled {
  opacity: 0.5;
  pointer-events: none; /* 子は一切のイベントを無視する */
}

cursorプロパティの使い方を詳しく知りたい人は「【CSS】cursorの種類とpointerの使い方」を一読ください。

テキストを改行・折り返しさせない

表のヘッダーセルや横スクロールさせたいメニューなどにおいて、「テキストを途中で改行させない」という要件は多々あります。

これを実現するのが、テキストの折り返しを禁止するwhite-space: nowrap;プロパティです。

white-space: nowrap;を使用する際のルールは2つあります。

  1. はみ出した部分を「…」で省略したい場合はoverflow: hidden;text-overflow: ellipsis;をセットで指定する。
  2. 横スクロールメニューを作りたい場合は親要素にoverflow-x: auto;を指定し、スマホ等ではみ出した部分をスワイプ可能にする。

これらの処理を忘れて「改行禁止」だけを記述するのは、実務では厳禁です。

⭕️ nowrap で改行を禁止したら、必ず overflow で「はみ出した先」の面倒を見る

横スクロール対応(overflow-x: auto)

  • ホーム
  • お知らせ
  • サービス概要
  • 企業情報
  • よくある質問
  • お問い合わせ
(※枠内で横にスクロールできます)
/* ⭕️ 改行を禁止しつつ、親要素で横スクロール可能にする */
.scroll-wrapper {
  width: 100%;
  overflow-x: auto; /* 💡 はみ出した分はスクロールさせる */
  -webkit-overflow-scrolling: touch; /* 💡 スマホで滑らかにスクロール */
}

.nowrap-menu {
  display: flex; /* 💡 横並びにする */
  gap: 15px;
}

.nowrap-item {
  white-space: nowrap; /* 💡 テキストの折り返し(改行)を絶対に禁止する */
}
HTMLコード表示
<div class="restrict-tech-wrapper">
  
  <p class="restrict-caption">⭕️ nowrap で改行を禁止したら、必ず overflow で「はみ出した先」の面倒を見る</p>

  <div class="restrict-demo-area" style="flex-direction: column; gap: 30px; padding-left: 0; padding-right: 0;">
    
    <div class="restrict-box" style="width: 100%; padding: 0 20px;">
      <p class="restrict-label">横スクロール対応(overflow-x: auto)</p>
      
      <div class="nowrap-scroll-wrapper">
        <ul class="nowrap-menu">
          <li class="nowrap-item">ホーム</li>
          <li class="nowrap-item">お知らせ</li>
          <li class="nowrap-item">サービス概要</li>
          <li class="nowrap-item">企業情報</li>
          <li class="nowrap-item">よくある質問</li>
          <li class="nowrap-item">お問い合わせ</li>
        </ul>
      </div>
      <small style="display: block; margin-top: 5px; color: #6c757d;">(※枠内で横にスクロールできます)</small>
    </div>

  </div>

  <div class="restrict-code">
    /* ⭕️ 改行を禁止しつつ、親要素で横スクロール可能にする */<br>
    <span class="hl-blue">.scroll-wrapper</span> {<br>
      <span class="hl-green">width: 100%;</span><br>
      <span class="hl-red">overflow-x: auto;</span> /* 💡 はみ出した分はスクロールさせる */<br>
      <span class="hl-green">-webkit-overflow-scrolling: touch;</span> /* 💡 スマホで滑らかにスクロール */<br>
    }<br><br>

    <span class="hl-blue">.nowrap-menu</span> {<br>
      <span class="hl-green">display: flex;</span> /* 💡 横並びにする */<br>
      <span class="hl-green">gap: 15px;</span><br>
    }<br><br>

    <span class="hl-blue">.nowrap-item</span> {<br>
      <span class="hl-red">white-space: nowrap;</span> /* 💡 テキストの折り返し(改行)を絶対に禁止する */<br>
    }
  </div>

</div>
CSSコード表示
/* 💡 横スクロールラッパー */
.nowrap-scroll-wrapper {
  width: 100%;
  overflow-x: auto; /* はみ出した分をスクロール可能に */
  -webkit-overflow-scrolling: touch; /* iOSで滑らかにする */
  background-color: #fff;
  border: 1px solid #ced4da;
  border-radius: 4px;
  padding: 10px;
}

.nowrap-menu {
  display: flex;
  gap: 15px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.nowrap-item {
  white-space: nowrap; /* 💡 改行を禁止する(必須) */
  padding: 8px 15px;
  background-color: #e7f1ff;
  color: #0d6efd;
  font-weight: bold;
  border-radius: 20px;
  font-size: 13px;
}

white-spaceプロパティの使い方を詳しく知りたい人は「【html&css】white-spaceの使い方とnowrap・pre・pre-wrapの使い分け」を一読ください。

まとめ

分かりやすいようにまとめを記載します。

本記事のまとめ
  • :not()は、指定したセレクタに一致「しない」要素を対象とする否定疑似クラスである。
  • クラス、ID、属性、タグ、または:empty(空要素)などをカッコ内に指定して除外できる。
  • 「一度適用したスタイルを別のクラスで打ち消す」という冗長な記述を防ぎ、コードをクリーンに保つことができる。
  • li:not(:last-child)(最後の要素以外に線を引く)など、他の疑似クラスとの組み合わせが実務の基本である。
  • カンマで区切って:not(.a, .b)と記述すると、「AまたはBを持たない(OR条件)」の除外になる。
  • 連続して:not(.a):not(.b)と記述すると、「AかつBを持たない(AND条件)」の除外になる。
  • :not(:has(img))のように:has()と組み合わせることで、「特定の要素を内包していない親要素」のスタイリングが可能になる。
  • :not()自体の詳細度(優先度)は、カッコ内に指定されたセレクタの中で最も高い詳細度に依存するため、意図しないスタイルの上書きに注意が必要である。

よくある質問(FAQ)

:not()で複数のクラスや条件を同時に除外するにはどう書けばいいですか?

カンマで区切るか、続けて書くかで意味(AND/OR)が変わります。

「クラスA、またはクラスBを除外したい」場合は、カンマ区切りで:not(.A, .B)と書きます。

一方、「クラスAかつクラスBを持たない要素」を指定したい場合は、連結させて:not(.A):not(.B)と記述します。

:not()を使ったら、後から書いたCSSで上書きできなくなりました。

:not()の「詳細度(スタイルの優先度)」の仕様が原因です。

:not()自体の優先度はゼロですが、カッコの中に記述したセレクタの優先度が要素に加算されます。

例えばp:not(.active)と書いた場合、「タグ(1) + クラス(10)」の詳細度を持つため、後から単なるpタグ指定で上書きしようとしても優先度で負けてしまい、スタイルが効かなくなります。

:not(::before)のように、疑似要素を除外することはできますか?

いいえ、CSSの仕様上:not()のカッコの中に::before::afterなどの疑似要素を含めることはできません。

:not()の中に指定できるのは、タグ名、クラス、ID、属性、および疑似クラス(:hover:first-childなど)に限られます。

「特定の子要素を持たない親要素」を:not()で指定できますか?

:not()単体では不可能ですが、最新のCSSである:has()疑似クラスと組み合わせることで実現できます。

例えば、画像を持たないカード要素だけデザインを変えたい場合、.card:not(:has(img))と記述することで「<img>タグを内包していない.card要素」だけを正確に狙ってスタイリングすることが可能です。

リストの最初や最後の要素「以外」を指定する定番の書き方はありますか?

実務でよく使われるのは:not(:last-child):not(:first-child)です。

ナビゲーションメニューやリストで「要素と要素の間にだけ区切り線を引きたい」場合、li:not(:last-child) { border-bottom: 1px solid #ccc; }と記述します。

これで最後の要素には線を引かないという処理が1行で完結し、後からborder: none;で打ち消す無駄なコードを減らせます。

この記事を書いた人

sugiのアバター sugi Site operator

【経歴】玉川大学工学部卒業→新卒SIer企業入社→2年半後に独立→プログラミングスクール運営/受託案件→フリーランスエンジニア&SEOコンサル→Python特化のコンテンツサイトJob Code&UIコピペサイトCode Stock運営中

目次