- CSS :not() with Multiple Classes
- Comments
- CSS-селектор :not. Полезные примеры
- Пример 1. Элемент без класса
- Пример 2. Изменение внешнего вида всех элементов, кроме наведенного
- Пример 3. Меню с разделителями между элементами
- Пример 4. Debug css
- Пример 5. Поля форм
- Поддержка
- Exclude Any Class Name in CSS With This Selector
- Recommended
- How To Create a Toggleable FAQ Component in React
- 2 Easy Ways to Export HTML Tables to Excel
- How to Create Prefilled Email Links in HTML
CSS :not() with Multiple Classes
Say you want to select an element when it doesn’t have a certain class. That’s what the :not() selector is for.
But what if there are multiple classes you want to avoid? There are no logical combinators with :not() , like and or or , but you can chain them, which is effectively like and .
body:not(.home):not(.away):not(.page-50)
The :not() selector doesn’t add any specificy by itself, but what is inside does, so :not(.foo) adds the same weight as .foo does.
Psst! Create a DigitalOcean account and get $200 in free credit for cloud-based hosting and services.
Comments
Since this will be the same behaviour as chaining them, we can probably expect build tools to automatically convert between them in the future. Thanks for the info!
I think it goes without saying but having chained (:not)s just seems logically confusing. If 2 are checked for :not, then every class would be allowed. But there is clearly an additional layer of logic put into this pseudo class to make sure that a :not chain is self aware of the previous classes on the declaration. Oh well, good to know anyway!
You should also mention that with Selectors 4 spec (link) we can pass a selectors list inside the :not() function. Like :not(h1, h2, h3)
On first read, I found the and/or part a bit confusing, but this is basically using logical “and” to represent “or”: not(A or B) <=>not(A) and not(B). This also means that you can replace all “or” (represented in CSS by “,”) with a similar construct using “:not”: foo, bar < color: orange; >is (apart from specificity) equivalent to: :not(:not(foo):not(bar)) < color: orange; >Not sure if that is helpful in any context (where selector lists may not be allowed?).=>
If the tag is “body” and the class list does not include “home” and the class list does not include “away” and the class list does not include “page-50”, then …
Of course using the not yet widely available level 4 selectors ( body:not(.home, .away, .page-50) would be simpler:
Good grief, I hate to be the na sayer but Can I Use :not() sure kills any bright hopes for this. I fully expected IE11 to not support it (and I’ve got a bunch of those users) but even Edge, Chrome, and Firefox are not on board yet. This seems to be a Safari only selector…
To be clear, you’re ONLY talking about the fancy comma-separated :not(a, b, c) style. Regular :not(a):not(b):not(c) style is supported everywhere.
The CSS3 selector :not() is widely supported (including IE9+).
What is only supported by Saffari is the list argument, like :not(a, b, c).
You gave me a damn heart attack! That’s only for the selector list argument of :not(), which is the :not(.a, .b, .c) thing. Just straight up :not(.a) is fine, as is :not(.a):not(.b):not(.c)
That’s only for a list of multiple selectors, the basic implementation of :not() works across most browsers.
Being able to chain selectors within :not() is not fully supported but :not() itself is https://caniuse.com/#feat=mdn-css_selectors_not
I think you might be looking at selector list argument of :not() , which only works in Safari, yeah. But :not itself is part of the CSS3 selectors listing, which seems to be green across the board. So you can use :not() wherever, but we might have to hold off on using it with a list of selectors for now, like so:
I could see how this could be powerful, but I’m a little hesitant to start using this. Doesn’t this have the same dangers as using !important because you’re overriding the cascade? On the front page of CSS-Tricks I see this done with some a tags successfully (the site looks dayung good.) But I’m not sure I want to override things like this where selectors (and properties) are being overridden with frequency: a:not(.button):not(.commentPreviewButton):not(.comment-reply-link):focus, a:not(.button):not(.commentPreviewButton):not(.comment-reply-link):hover <
background: -webkit-gradient(linear,left top,right top,from(#ff8a00),to(#da1b60));
background: linear-gradient(to right,#ff8a00,#da1b60);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
-webkit-box-decoration-break: clone;
box-decoration-break: clone;
text-shadow: none;
> I guess I’d have to see the code, maybe it’s much simpler in their codebase?
I wasn’t even thinking of that particular code when writing this, but it makes a fairly good point. I don’t control the classes commentPreviewButton and comment-reply-link . They come from WordPress core or plugins. I could probably write filters to control them, but that’s technical debt at a level I’d rather not deal with. I’ll take my technical debt in a CSS selector, because of my personal skillset. That selector helps me to what I want to do, targeting most links, but avoiding a few specifically based on class name.
Yeah, I think I should take back in part what I said about !important- because it’s not an uncontrolled override. At least :not has you specify. The way it’s used here makes sense especially in environments where you don’t have control over some of the environment like WordPress like you said. But this probably is the exception more than the rule.
I encountered someone’s code that did not understand this concept in the wild — worse, in the Production code of a well-known CMS’s admin. The code was like this:
#some-id *, #some-id *:not(div), #some-id *:not(svg *)
…which is just insane. The first rule is not needed if the second rule is present. And the third rule just makes you wonder what this world is coming to. Please please be careful with the power that CSS gives you. Make sure you understand the rules before you apply them.
CSS-селектор :not. Полезные примеры
В спецификации и блогах про селектор :not обычно приводят какие-то искусственные примеры, которые хоть и объясняют синтаксис и принцип действия, но не несут никакой идеи о том, как получить пользу от нового селектора.
Ну окей, думаю я, в моей практике не встречались такие ситуации. Обходились мы ведь как-то раньше без :not . Приходилось немного переписать структуру селекторов или обнулить пару значений.
Пример 1. Элемент без класса
Селектор :not может быть крайне полезен, когда нам нужно застилить контент сгенерированный пользователем (нет возможности расставить в нем классы), или когда у нас контента очень много и расставлять в нем классы слишком трудоёмко.
Например, мы хотим на сайте сделать красивые буллиты для ненумерованных списков ul li . Мы пишем код:
ul li < /* наши красивые стили */ >
В результате, наши красивые буллиты появляются не только в контенте, но и, например, в навигации, где тоже используются ul li .
Мы ограничиваем область действия селектора:
Навигацию мы спасли, но ненужные буллиты всё еще вылазят на слайдерах, списках новостей и других конструкциях внутри .content , где тоже используются ul li .
1) обнулить мешающие стили в слайдерах и других местах. Но это противоречит « DRY » и является одним из признаков «вонючего» кода. К тому же не решает проблему раз и навсегда: добавите, например, аккордеон и списки в нем снова придется обнулять.
2) пойти от обратного и ставить класс всем спискам, которые нужно стилизовать:
Это добавляет лишней работы по расстановке классов в контенте. Иногда имеет смысл, но лишнюю работу никто не любит.
3) стилизовать только те ul li , у которых нет никаких классов вообще:
Победа! Нам не нужно делать дополнительную работу по расстановке классов в контенте. А на слайдерах, аккордеонах и прочих конструкциях, которые не должны выглядеть как списки, но используют их в своей разметке, в 99% случаев уже будут свои классы, и наши стили их не затронут.
Этот прием — «выбирать только элементы без класса» — очень полезен для оформления пользовательского контента и его можно применять не только к спискам, но и для других случаев.
Пример 2. Изменение внешнего вида всех элементов, кроме наведенного
Такой эффект можно реализовать без :not путем перезаписи значений. И это будет работать в бо́льшем количестве браузеров.
/* с перезаписью свойств */ ul:hover li < opacity:0.5; > ul:hover li:hover < opacity:1; >
Но если придется обнулять слишком много свойств, то есть смысл использовать :not .
/* используя :not() */ ul:hover li:not(:hover) < opacity:0.5; >
Пример 3. Меню с разделителями между элементами
Как и в предыдущем примере, желаемого можно добиться несколькими способами.
Через перезапись свойств. Но тут два правила вместо одного, что не есть « DRY ».
.menu-item:after < content: ' | '; > .menu-item:last-child:after < content: none; >
Через :nth-last-child() . Одно правило, но тяжело читается.
.menu-item:nth-last-child(n+2):after < content: ' | '; >
Через :not() — самая короткая и понятная запись.
.menu-item:not(:last-child):after < content: ' | '; >
Пример 4. Debug css
Удобно для отладки и самоконтроля искать/подсвечивать картинки без alt, label без for и другие ошибки.
/* подсвечиваем теги без необходимых атрибутов */ img:not([alt]), label:not([for]), input[type=submit]:not([value]) < outline:2px solid red; > /* тревога, если первый child внутри списка не li и прочие похожие примеры */ ul > *:not(li), ol > *:not(li), dl > *:not(dt):not(dd) < outline:2px solid red; >
Пример 5. Поля форм
Раньше текстовых полей форм было не много. Достаточно было написать:
select, textarea, [type="text"], [type="password"] < /* стили для текстовых полей ввода */ >
С появлением новых типов полей в HTML5 этот список увеличился:
select, textarea, [type="text"], [type="password"], [type="color"], [type="date"], [type="datetime"], [type="datetime-local"], [type="email"], [type="number"], [type="search"], [type="tel"], [type="time"], [type="url"], [type="month"], [type="week"] < /* стили для текстовых полей ввода */ >
Вместо перечисления 14 типов инпутов можно исключить 8 из них:
select, textarea, [type]:not([type="checkbox"]):not([type="radio"]):not([type="button"]):not([type="submit"]):not([type="reset"]):not([type="range"]):not([type="file"]):not([type="image"]) < /* стили для текстовых полей ввода */ >
Ладно, этот пример не очень красив, и я рекомендую всё же первый вариант с перечислением, он работает с IE8+, а второй вариант с IE9+.
Поддержка
Следует заметить, что согласно спецификации в скобках селектора :not() может стоять только простой селектор и в скобках нельзя использовать сам селектор :not() . Если нужно исключить несколько элементов, :not() можно повторить несолько раз, как в примере 5.
Если очень нужны CSS3-селекторы в браузерах, которые их не поддерживают, можно использовать полифил selectivizr.
Exclude Any Class Name in CSS With This Selector
To exclude a class in CSS, we can use the :not pseudo-class selector, also known as the not selector.
This can be used to style any element that is not matched by the selector written in parentheses. It accepts any valid CSS selector, and can also be chained off from other elements. For example:
/* Select all p tags that doesn't have the class "highlighted" */ p:not(.highlighted) . > /* Select every p, but not the last */ p:not(:last-child) background: red; >
Last paragraph with a :not(:last-child) selector
As you can see, the selector can be used with other than class selectors. There are also a couple of rare cases you should keep in mind whenever you use the :not selector. These are the following:
/* Using the :not selector with a wildcard selector */ :not(*) /* Globally using the :not selector */ :not(.class) /* Using :not with an invalid selector */ :not(:unsupported-pseudo-class)
- In the first example, we used :not with the * wildcard selector. This is a useless selector that will not be applied to anything, since the selector reads: «select any element that is not an element».
- When you globally use the :not selector (not attached to any element), it will also include html and body . More importantly, it will also increase specificity, so #id:not(.class) will be stronger than #id .
- Lastly, if you use an unsupported or invalid selector with :not , the entire rule will be invalidated, meaning no styles will be applied to the element.
📚 More Webtips
Level up your skills and master the art of frontend development with bite-sized tutorials.
We don’t spam. Unsubscribe anytime.
- Unlimited access to hundreds of tutorials
- Access to exclusive interactive lessons
- Remove ads to learn without distractions
Recommended
How To Create a Toggleable FAQ Component in React
2 Easy Ways to Export HTML Tables to Excel
How to Create Prefilled Email Links in HTML
Get access to 300+ webtips 💌
Level up your skills and master the art of frontend development with bite-sized tutorials.
We don’t spam. Unsubscribe anytime.
Level up your skills and master the art of frontend development with bite-sized tutorials.
We don’t spam. Unsubscribe anytime.