CSS: Advanced pseudo-classes with examples

Shorten the styles and quicken the design
Dec 7 2022 · 5 min read

Introduction 

Have you ever thought, HTML elements can adopt the CSS based on some conditions?

The answer is YES.

Some CSS pseudo-classes are behind the scene for the same. Let’s get familiar with them!

Especially since CSS pseudo-class functions relax us from nested CSS rules, the styles will remain much more precise and easy to understand as well.

It takes a selector list as an argument and selects any element that can be selected by one of the selectors in that list.

Consider a scenario, when you don’t want to integrate javascript or jquery into your webpage and still want the styles to be applied conditionally!

:where()

Syntax:

:where( <selector-list> )

It’s the conditional selector same as where query in MySQL or if condition in programming, checks for the existence of something and then proceeds accordingly(applies specified styles in our case).

It’s majorly used as the replacement for the selector list. When we want to apply styles on multiple selectors and if any of them is invalid, styles will be ignored for the rest!

It also similarly works with nested selectors. 

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>:where() selector demo</title>
</head>

<body>
  <section class="header">
    <h1>Home</h1>
    <h1>About</h1>
    <h1><a>FAQ</a></h1>
  </section>

  <section class="footer">
    <h1>Home</h1>
    <h1>About</h1>
    <h1>FAQ</h1>
  </section>
</body>

</html>

// CSS

.header {
  display: flex;
  column-gap: 2rem;
}

:where(section.header h1) {
  color: blue;
}

:where(section.header h1) a {
  color: green;
}

:where(section.footer h1) {
  color: red;
}

Here, header and footer class’ <h1> tags differ in color.

If we see the working of :where(), it will look in the order of section tag -> header class -> h1 tag for the header and also for the footer class accordingly.

Also, it can be used to filter the specific tag to work on, as an example below. It applies color only on the <a> tag and not on all the <h1> tags.

Visit the Codepen.

:where(section.header h1) a {
  color: green;
}

:has()

Syntax:

:has( <forgiving-relative-selector-list> )

This pseudo-class is used to select the preceding siblings of a given element.

For example, If there’s a use case where <h1> tag is followed by a <p>tag, then apply some background, and if followed by any other tag, don’t apply it.

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>:has() demo</title>
</head>

<body>
  <div class="div1">
    <h1>Introvert people </h1>
    <p>Talks more with themselves</p>
  </div>
  <div class="div2">
    <h1>Extrovert people</h1>
    <h2>Talks more with others</h2>
  </div>
</body>

</html>

// CSS

body {
  display: flex;
  column-gap: 100px;
}

div1,
div2 {
  display: flex;
  flex-direction: column;
}

h1:has(+ p) {
  background: red;
}

It has applied the background property on <h1> tag, for the first case(where <h1> is followed by <p>).

On the other hand, I didn’t apply the same for the second case(where <h1> is followed by <h2>).
Visit the Codepen.

:is()

Syntax:

:is( <forgiving-selector-list> )

This pseudo-class function can also be used as an alternative of :where() as both works similarly.

The difference between the two is,
— :where() looks for 0 specificity and,
— :is() takes the specificity of the most specific selector from the selector list.

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>:is() selector demo</title>
</head>

<body>
  <section class="header">
    <h1>Home</h1>
    <h1>About</h1>
    <h1><a>FAQ</a></h1>
  </section>
</body>

</html>

// CSS

.header {
  display: flex;
  column-gap: 2rem;
}

:is(section.header h1) {
  color: blue;
}

/* :is(section.header h1) a {
  color: black;
}
 */
.header a {
  color: green;
}

In the example above, :is() applies styles on <h1> and <a> tags of the header class.

If you have observed, the below style makes the <a> tag black.

:is(section.header h1) a {
  color: black;
}

What if you still want to override the color using a normal CSS selector? like below,

.header a {
  color: green;
}

You will see it’s not working, why does it happen?

It’s the magic of the :is() function, it matches the specificity of the most specific selector and ignores all the applied styles except its own.

It doesn’t allow the ordering of styles to make sense!
Visit the Codepen.

:not()

Syntax:

:not( <selector-list> )

It is also known as the negation pseudo-class. It does the exact opposite job of other selectors or pseudo-classes, as it prevents specific items from being selected.

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>:not() selector demo</title>
</head>

<body>
  <section>
    <h2>Types of chocolates</h2>
    <ul>
      <li>Milk chocolate</li>
      <li>White chocolate</li>
      <li>Dark chocolate</li>
    </ul>
    <p>Chocolates are good stress reliever</p>
  </section>
</body>

</html>

// CSS

section :not(p) {
  color: blue;
}

In the above-given example,

— We want to change the font color of all the items residing inside the <section> tag, but not of the <p> tag.

section :not(p) {
  color: blue;
}

The above CSS handles the same for us. Alternatively, you can define it on the CSS selector and add it to every tag where you want to apply the blue color.

But when one or two tags need to be eliminated and the rest of the elements remain matchy, :not() can be helpful.
Visit the Codepen.

:dir()

Syntax:

:dir( [ ltr | rtl ] )

You have surely come across the words RTL and LTR at least once!

HTML provides a dir attribute for the same, and thus it’s easy to manage RTL and LTR support for a webpage.

It simply arranges the content in a specific direction provided by us.

If we want to apply a few styles to the specific content on the basis of its direction, we’re good to go with the help of :dir().

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>:dir() demo</title>
</head>

<body>
  <h1 dir="rtl">
    As long as you keep going, you'll keep getting better.
  </h1>
  <h1>Keep going, until you're done.</h1>
</body>

</html>

// CSS

h1[dir=rtl] {
  background: green;
}

In the given example, we want the content arranged in the RTL direction should have a green background.

Visit the Codepen.

:lang()

Syntax:

:lang( <language-code> )

HTML has a lang attribute that specifies the language used by that page. It represents the language code using the first two letters i.e,
1. For the English language, lang=”en”
2. For French, lang=”fr”

A lang attribute can also be applied over all the tags like <p>, <span>, etc, and not only on the <HTML> tag. Fortunately, it’s supported by all browsers!

The :lang() function works with the page’s/tag’s lang attribute and applies styles accordingly.

Say we want to apply background color to some tags if the language of an HTML page is french .

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>:lang() selector demo</title>
</head>

<body>
  <h1 lang="fr">
    I'm french language statement!
  </h1>
  <h1>I'm normal statement.</h1>
</body>

</html>

// CSS

h1 {
  background: green;
}

h1:lang(fr) {
  background: red;
}

Here, the language of an HTML page is en, but the individual <h1> tag has language fr.

Here, h1{background: green} will make all the <h1> tags green, but h1:lang(fr){background: red} will override the styles and update the background of <h1> tag with fr language to red color.

Visit the Codepen.

Enclosing thoughts

It’s always possible to design pages without advanced selectors. But if you want to make styles pretty and precise, it might be proved a savior!

Note: The above-listed CSS pseudo-classes are supported by almost all modern browsers, still you can verify them here before using them.

Last but not least, Keep exploring the advancement!


Code, Build, Repeat.
Stay updated with the latest trends and tutorials in Android, iOS, and web development.
nidhi-d image
Nidhi Davra
Web developer@canopas | Gravitated towards Web | Eager to assist
nidhi-d image
Nidhi Davra
Web developer@canopas | Gravitated towards Web | Eager to assist
canopas-logo
We build products that customers can't help but love!
Get in touch
contact-footer
Say Hello!
footer
Follow us on
2024 Canopas Software LLP. All rights reserved.