Briefly
A very useful pseudo-class that will help you save quite a few lines of code. The essence of this guy's work is to cut off all elements that do not meet the condition. It sounds more complicated than it looks.
Example
As you probably already know, it is common to set margins between elements so that the last or first one does not have extra margins, so they do not stick out uselessly and do not change the parent's size for no reason.
For example, there is a task to set a bottom margin for all list items except the last one:
Set bottom margins for all list items:
li { margin-bottom: 1em;}
li { margin-bottom: 1em; }
Reset the bottom margin for the last list item so it doesn’t hang:
li:last-child { margin-bottom: 0;}
li:last-child { margin-bottom: 0; }
For the simplest solution to this task, we needed 2 blocks of code. But, most likely, in your project, you will need to reset unnecessary margins not only for this element. There must be a simpler way.
Of course it can be done! Let’s reduce two blocks of code to one, using the pseudo-class :not
. We will select all list items except the last one and set them bottom margins:
li:not(:last-child) { margin-bottom: 1em;}
li:not(:last-child) { margin-bottom: 1em; }
Voilà! Beautifully, neatly, and most importantly, it works just as intended 😏
How to Write
Take any selector, put a colon and write the keyword not
. After it, put parentheses and inside them indicate the selector that should be excluded from the selection. The selector in parentheses can be anything, as long as it does not include pseudo-elements. You can also specify multiple selectors in parentheses, separated by commas. In that case, elements matching any of the listed selectors will be excluded.
You can also select any element within body
that is not, for example, a paragraph: body
. Similarly, you can choose any element within a certain parent that does not meet the condition.
How to Understand
You can say it abstractly that :not
is a function that takes selector X as an argument and finds in the markup elements that do not correspond to this very element X.
Or you can put it simply: we command the browser "Select all elements that match the selector up to :not
and exclude from the selection all elements that match the selector in parentheses."
Tips
💡 To the left of :not
there does not have to be a selector. You can write :not
, and the browser will select all elements on the page except those that have the class .hidden
.
💡 If you really want to — you can fly into space write a useless selector: :not
. This selector will select any element that is not any element 🤦♀️
💡 You cannot nest one :not
inside another.
💡 You can build chains of :not
. Then the selection will decrease in order, excluding elements that meet the conditions.
Let's color all list items red except for the last element and those that have the class .active
:
li:not(:last-child):not(.active) { color: red;}
li:not(:last-child):not(.active) { color: red; }
In practice
Advice 1
🛠 After support for this pseudo-class was implemented in all browsers, I started using it everywhere. It's much more convenient to write one selector than to write two blocks of code for such a trivial task as resetting the last margin or selecting an element, except for some class.
Recently: I needed to style all input fields except for those that were hidden (sometimes hidden fields are added to the form to send auxiliary data along with the user's data). Instead of writing a compound selector, selecting individual fields, or coming up with a separate class just for those fields that are visible or not, I wrote the selector input
, and the interpreter applied the styles I needed only to those fields that do not have the hidden
attribute.