Перейти к содержанию
Инструкция

Фильтрация элементов с помощью псевдокласса :not() в CSS

Как исключить элементы из выборки на чистом CSS с помощью псевдокласса :not(). Разбираем синтаксис, списки селекторов 2026 года, специфичность, связку с :has() и типичные ошибки.

Обновлено 22 июля 5 минут чтения

Псевдокласс :not() – один из самых удобных инструментов CSS для «вычитания» элементов из выборки: вместо того чтобы перечислять, к чему применить стиль, вы описываете, к чему его применять не нужно. Раньше это была скромная возможность, но к 2026 году :not() умеет принимать целые списки селекторов, отлично работает в связке с :has() и поддерживается всеми актуальными браузерами.

Как работает :not()

Псевдокласс :not(X) принимает селектор-аргумент и исключает из выборки всё, что этому селектору соответствует. Селектор p:not(.intro) выбирает каждый абзац, у которого нет класса intro: сначала указывается основной элемент (p), затем следует псевдокласс отрицания :not(), а внутри скобок – тот селектор, который нужно исключить.

/* Все абзацы, кроме вводного */
p:not(.intro) {
  color: #555;
}

Списки селекторов внутри :not() (2026)

Главное изменение последних лет – :not() принимает список селекторов через запятую. Это часть спецификации Selectors Level 4, и такой синтаксис поддерживается во всех современных браузерах.

/* Пункты меню без модификаторов is-active и is-disabled */
.menu__item:not(.is-active, .is-disabled) {
  cursor: pointer;
}

Раньше приходилось писать цепочку из нескольких псевдоклассов – .menu__item:not(.is-active):not(.is-disabled). Обе записи по-прежнему рабочие, но список короче и читаемее. Для поддержки очень старых браузеров используйте именно цепочку.

Специфичность :not()

Сам псевдокласс :not() не добавляет специфичности, но его аргумент – добавляет. Вес правила равен специфичности самого «тяжёлого» селектора внутри скобок. Это частый источник неожиданно «сильных» правил: :not(#id) получает специфичность идентификатора. Держите аргументы простыми, если хотите предсказуемый каскад.

Связка с :has() и :nth-child of S

В 2026 году :not() редко используют в одиночку. Он хорошо комбинируется с другими псевдоклассами Selectors Level 4:

/* Карточки товара, у которых НЕТ вложенного бейджа «нет в наличии» */
.card:not(:has(.badge--out)) {
  border-color: #0a0;
}

/* Первые три видимых пункта: :nth-child принимает фильтр of S */
li:nth-child(-n+3 of :not(.hidden)) {
  font-weight: 700;
}

Про выбор первых элементов подробнее – в гайде «Выбрать первые три элемента из списка с помощью CSS».

Частые ошибки

  • Пустой аргумент. :not() без селектора внутри недопустим и обрушит всё правило.
  • Список – это логика «хотя бы одно». В записи :not(.a, .b) элемент исключается, если совпал хотя бы с одним селектором. Цепочка :not(.a):not(.b) отсекает по очереди: для простых классов итог тот же, но для сложных селекторов поведение отличается.
  • Забытая специфичность. Правило с :not() может неожиданно перебить другие стили – см. раздел выше.

Поддержка браузеров и производительность

Простой :not(.class) поддерживается всеми браузерами уже более десяти лет. Возможность передавать список селекторов и сложные селекторы – часть Selectors Level 4 и доступна во всех актуальных версиях Chrome, Edge, Firefox и Safari; для устаревших браузеров применяйте цепочку из нескольких :not(). Точную таблицу совместимости всегда стоит сверять на caniuse.com.

По производительности :not() – быстрый селектор, но избегайте чрезмерно широких выборок вроде *:not(...) на больших деревьях: браузер проверит каждый узел документа. Держите слева от псевдокласса конкретный элемент или класс.

Эти же приёмы фильтрации пригодятся при вёрстке навигации – например, в новом шаблоне постраничной навигации или при оформлении вкладок (tabs).

Частые вопросы

Можно ли передать несколько селекторов в :not()?

Да. По Selectors Level 4 :not() принимает список: .item:not(.is-active, .is-disabled). Элемент исключается, если совпал хотя бы с одним селектором из списка. Синтаксис поддерживается всеми современными браузерами.

Влияет ли :not() на специфичность правила?

Сам псевдокласс – нет, но его аргумент влияет. Вес правила равен специфичности самого «тяжёлого» селектора внутри скобок, поэтому :not(#id) получает специфичность идентификатора.

Чем :not(.a, .b) отличается от :not(.a):not(.b)?

Для простых классов результат совпадает. Но список – это логика «совпал хотя бы с одним», а цепочка отсекает по очереди «не A и не B». Для сложных селекторов поведение может отличаться.

Быстрый ли селектор :not()?

Да, сам по себе он быстрый. Проблемы возникают только при широких выборках вроде *:not(...) – браузеру приходится проверять каждый узел. Ставьте слева конкретный элемент или класс.

Валентина Меланина

Хотите обсудить свой проект?

Помогу с разработкой, аналитикой и AI-видимостью вашего сайта

Если у вас есть задача — от внедрения разметки и аналитики до полной переработки сайта — напишите, обсудим объём и подход.