Tip of the week #019: Think of CSS selectors as queries

Ever struggle with CSS selectors and specificity? Here's a weird analogy for how to deal with selectors.

Imagine we have this code:

Language: html
<!DOCTYPE html>
<html>
  <head>
    <title>My website</title>
  </head>
  <body>
    <h1>Hello world</h1>
    <p>Lorem ipsum dolor sit amet.</p>
    <h2>Websites are cool!</h2>
    <p>Consectetur adipiscing elit.</p>
    <h2>CSS is even cooler!</h2>
    <p>Nunc quis posuere ipsum.</p>
  </body>
</html>

It's just a simple HTML document. Now imagine that this was a paper document and your friend was holding it up for you to read.

You don't like the look and feel of the document in his hands, so you'd wanna ask him to change some things, for instance:

"Can you change the color of all the subheadings to red?"

You see where I'm going with this?

A CSS selector and its properties is a kind of query. The paper document in your friend's hands are the DOM - and your friend is the browser.

So if you're having difficulties with selectors and specificity: think that you're just querying the browser for something.

"Can you give me all the <h2> elements in the document..." translates to

Language: css
h2

and "...and change the text color of them to red?" translates to

Language: css
color: red;

The query gives us:

Language: css
h2 {
  color: red;
}

The power of "rubberducking"

The example above is stupidly simple, but it is quite powerful. It's a kind of "rubberducking". Thinking of selectors as queries has helped me a lot, especially when in it comes to avoiding unnecessary nesting in SCSS or figuring out complex selectors like :has or subsequent-sibling selectors.

An example of a complex query which prompts the use of the :has selector:

Can you find all elements with the class .header__menu-toggle, while also having the class .is-open, and see if it has more than one <svg>-element inside. If so, can you find the last <svg>-element inside and remove it with display: none?

The code for it looks like this:

Language: css
.header__menu-toggle.is-open:has(svg:nth-of-type(2)) svg:last-of-type {
  display: none;
}

Yikes. Believe it or not, but this snippet is actually possible to find on my website.

Still, the template holds up - and it's easy for me to see if the selector doesn't do what I want it to.