Using the CSS :not() pseudo-class
Tags: css, frontend
Published: 2023-04-03 23:45:16

The year is 2023, and CSS is continually improving. It is now possible to target not selected selectors like elements, classes, ids etc on a webpage using the CSS `:not()` [pseudo-class](https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-classes)

In this article, we are going to talk about how the CSS `:not()` pseudo-class (or `:not()` for short and read as **`not function`**) is used in production, how it can save you the stress of writing longer lines of CSS code and how we can tailor this to meet our specific needs.

## Prerequisites
This article assumes that you at least know the basics of **HTML**, **CSS** and **Javascript**. You do not have to be an expert to follow along.

With that said, let's Dive in 🐬

## Table of Content
1. [What is `:not()`?] (#what-is-raw-not-endraw-)
2. [Things to note about the `:not()`](#things-to-note-about-the-raw-not-endraw-)
3. [`:not()` use-cases] (#-raw-not-endraw-usecases)


## What is `:not()`?

According to the [MDN] (https://developer.mozilla.org/en-US/docs/Web/CSS/:not), the `:not()` represents elements that do not match a list of selectors eg (elements, classes, ids). Since it prevents specific items from being selected, it is known as the `negation pseudo-class`

In CSS, we exclude items with the `:not()`. The excluded items do not get the styling in the CSS rule

```HTML
<div class="container">
   <div class="box">This div has the box class</div>
   <div>This div does not have the box class</div>
   <div class="box">This div has the box class</div>
   <div>This div does not have the box class</div>
   <div class="box">This div has the box class</div>
   <div>This div does not have the box class</div>
 </div>    
```

```CSS
.container div:not(.box){
    border: 1px solid red;
}

/* The boxes that do not have the .box class will have a red border around it */
```


![Code Result](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ykftopsbz8tz646jw4yo.jpg)

### Anatomy of the :not()

``` css
:not(X){
    property: value;
}

/* X can be one or more CSS selectors eg elements, classes, ids  */
```

Looking at the Anatomy or Structure of the `:not()`, we can see the `()` after the `:not` which signifies that the `:not()` is **Functional**. It means that the `:not()` takes in arguments.

```CSS
/* using the HTML code we used above earlier */

.container > div:not(.box, :nth-child(4)){
    border: 1px solid red;
}

/* All div elements with the .box class and the 4th direct child in the .container will not get styled. */
```


![Code Result 2](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3x75k6kml18l47ets06k.jpg)


## Things to note about the `:not()`

1.The :not() Equivalence Theory.

Note that we can chain two `:not()` together

```CSS
:not(.foo):not(.bar){
    border: 2px solid red;
}
```

This piece of code works but it does not look readable and can get messy real quick if more `:not()` are added

The code above is equivalent to


```CSS
:not(.foo, .bar){
    border: 2px solid red;
}
```

This is more readable and easy to understand


2.The `:not()` does not accept [**Pseudo-elements**](https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-elements) as arguments. Simply put using pseudo-elements as arguments to the `:not()` makes the style invalid

```CSS
/* Example */
article:not(h2, ul, img::before) { }
```

The **img::before** is a pseudo-element. This makes the CSS rule Invalid.

3.The `:not()` is an **unforgiving selector**
If any selector passed to the `:not()` is invalid or not supported by the browser, the whole rule will be invalidated.

```CSS
/* Example */
article:not(h2, ul, ::devyoma) { }
```

The **devyoma** is totally invalid. A forgiving selector list disregards that false selector(`::devyoma`) and evaluates the remaining elements as though it were written as follows:

```CSS
/* Example */
article:not(h2, ul) { }
```

4.The `:not()` allows useless selectors to be written. Try to be careful when using the `:not()`.

```CSS
:not(*){
    color: red;
}

/* The (*) represents all elements and therefore no element on the page will be styled */
```



## `:not()` use-cases

1.Selecting element(s) by excluding some. This is by far the basic use-case of the `:not()`

```HTML
<div class="container">
	<p class="first">This is a normal paragraph </p>
	<p class="second">This is a normal paragraph </p>
	<p>This is a normal paragraph </p>
	<p>This is a normal paragraph </p>
</div>
```

```CSS
.container > p:not(.first, .second){
	border: 1px solid red;
}
```

The CSS code above gives a border line to the paragraph tags in the container div that do not have the `.first` and `.second` class.


![Code Result 2](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/50th6ovfn0a3ebwlia87.jpg)

2.Styling other elements in a div excluding the **first** and/or the **last** child element of that div

Now, this is by far my favourite use-case of the `:not()`

```CSS
/* using the same html we have in use-case 1 */

.container > p:not(:first-child, :last-child){
	border: 1px solid red;
}

```
NB: The `>` targets elements which are **direct children** of a particular element. You can read more about it [here](https://developer.mozilla.org/en-US/docs/Web/CSS/Child_combinator)

![Code Result 3](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/662j6fnx1ietsh6bdq3u.jpg)

3.Improving Accessibility and Search Engine Optimization (SEO)

**Alt tags** provide context to what an image is displaying, informing search engine crawlers and allowing them to index an image correctly.

Images should have an `alt` attribute, even if it is empty i.e `<img src="photo.jpg" alt=""/>`

Let us imagine we want to find images on our webpage that do not have the `alt` attribute, we can write the following CSS code to fish it out

```HTML
<div class="container">
    <img src="./images/gaara.jpg" alt="Gaara">
    <img src="./images/kakashi.jpg" >
    <img src="./images/jiraiya.jpg" alt="Jiraya">
    <img src="./images/minato.jpg" >
    <img src="./images/sai.jpg" alt="Sai">
</div>
```

```CSS
.container > img:not([alt]){
    border: 3px dashed black;
}
```


![Code Result 4](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/74fnbg5hoyafnxmonain.jpg)

## Wrap Up
The `:not()` is useful and has some important use-cases discussed above. We also sighted examples where we can write invalid styles using the `:not()`.

I am happy you read to this point and I would love it if you would not only read it but also put the `:not()` into practice. Happy Coding 


What are your thoughts on the `:not()`? Kindly share other instances where the `:not()` has been of help to you. Let us know in the comments section below. 

Thank you.