Advanced CSS selectors for common scenarios
Tags: css, webdev
Published: 2020-03-02 17:39:42

---
title: Advanced CSS selectors for common scenarios
published: true
date: 2020-02-27 19:00:00 UTC
tags: css,webdev
canonical_url: https://blog.logrocket.com/advanced-css-selectors-for-common-scenarios/
cover_image: https://dev-to-uploads.s3.amazonaws.com/i/763u5aciscriwbwj7ric.png
---
**Written by [Andrew Spencer](https://blog.logrocket.com/author/andrewspencer/)**✏️

CSS is weird. It’s unlike any other language that web developers use, yet it is critical to the visual representation of a website—the part that users interact with. In its most basic form, CSS is simple. For example, `background-color: red` means the background will be the color red. Yet, as anyone who has worked on a large CSS codebase will tell you, it can quickly become very complex and confusing.

[CSS Grid](https://seesparkbox.com/foundry/css_grid_layout_guide_with_flexbox_fallbacks), [BEM](https://seesparkbox.com/foundry/bem_by_example), [Dart Sass](https://seesparkbox.com/foundry/dart_sass_update_version_1.23.0), there’s always something new to learn about CSS. It’s overwhelming! Instead of looking at what’s new, let’s focus on a fundamental building block of CSS—the [selector](https://www.w3schools.com/css/css_selectors.asp). With a better understanding of the selector, and how to use it in more advanced ways, you can solve common scenarios with less code and cleaner CSS.

## What is a selector?

Let’s make sure we’re on the same page. A [CSS selector](https://developer.mozilla.org/en-US/docs/Learn/CSS/Building_blocks/Selectors) is how you can tell the browser what element to apply properties too. They can be general and apply to a large group of elements or be more specific and apply to only a single HTML element. There are five [types of selectors](https://www.w3schools.com/css/css_selectors.asp):

- [Simple selectors](https://www.w3schools.com/css/css_selectors.asp) for selecting HTML pieces such as `div`, `#id`, or `.class`
- [Combinator selectors](https://www.w3schools.com/css/css_combinators.asp) which are based off code relationships like a “child” `p > div` or “adjacent sibling” `div + div`
- [Pseudo-class selectors](https://www.w3schools.com/css/css_pseudo_classes.asp) to select a specific **state** of an element such as `:hover`, `:first-child`, or `:nth-of-type`
- [Pseudo-elements selectors](https://www.w3schools.com/css/css_pseudo_elements.asp) to select specific **parts** of an element such as `::after`, `::selection`, or `::first-letter`. Note how these always use double colon notation`::` versus pseudo-class selectors which use a single colon
- [Attribute selectors](https://www.w3schools.com/css/css_attribute_selectors.asp) to select elements with certain attributes such as (`[class|="class-name"]`, `[type="text"]`, or `[target]`

If two separate selectors are used to declare a style for the same element, the more specific selector will win—no matter what their order is in your CSS file. For example, a class selector like `.class-name` is more specific than a general HTML element selector such as `span`. If you need a refresher on how browsers decide which CSS styles to apply, also known as the [CSS cascade](https://blog.logrocket.com/how-css-works-understanding-the-cascade-d181cd89a4d8/), try this [quiz.](https://wattenberger.com/blog/css-cascade)

Now that we understand what selectors are, let’s dive into how to use them effectively. You can take advantage of lesser-known selectors and even combine them to reduce the amount of code you need! Here are some more advanced selectors that I use in my CSS.

[![LogRocket Free Trial Banner](https://i0.wp.com/blog.logrocket.com/wp-content/uploads/2017/03/f760c-1gpjapknnuyhu8esa3z0jga.png?resize=1200%2C280&ssl=1)](https://logrocket.com/signup/)

## :nth-last-child(-n + 2)

There are many CSS pseudo-class selectors that can be used to select an element from a group of related elements—or children of a parent.

```jsx
<parent>
    <child></child>
    <child></child>
</parent>
```

There’s [`:first-child`](https://developer.mozilla.org/en-US/docs/Web/CSS/:first-child), [`:nth-child`](https://developer.mozilla.org/en-US/docs/Web/CSS/:nth-child), [`:nth-of-type`](https://developer.mozilla.org/en-US/docs/Web/CSS/:nth-of-type), and the [list goes on](https://css-tricks.com/how-nth-child-works/). These selectors become even more powerful when turned into expressions using numbers, the `n` counter, `odd`, or `even`. You can do math to select essentially any number of elements in a group. For example, `n` is a way to create algebraic expressions. So `(2n+4)` is equated as `(2*n)+4` which will select every other element, starting with the fourth:

```jsx
(2*0)+4 = 4
(2*1)+4 = 6
(2*2)+4 = 8
(2*4)+4 = 10
```

This is useful in many scenarios. For example, have you ever needed to style just the last two items in a list? You could add a class to those two elements which will result in more HTML and CSS, or you could use a single CSS selector, like this:

```jsx
.item:nth-last-child(-n+2)
```

You can read this selector as “select the last two children of `.item`.” Looking at how this works, `-n+2` equates to `(-0+2)=2` or the second to last item, then `(-1+2)=1` or the last item, then `(-2+2)=0` which selects nothing, then `(-3+2=-1)` which, again, selects nothing, and so on for the total number of children elements. Only two elements are selected because of the negative sign in front of `n` which causes it to count down. If you want to select the last three items, `-n+3` does just that. This allows us to select these elements without adding anything to the HTML!

{% codepen https://codepen.io/iam_aspencer/pen/RwPoYXq %}

## :not(:last-child)

To take the last example even further, you can combine `:last-child` with the `:not` selector. This can help in scenarios where the last element in a group has a different style. Websites often call for a list of items with some space between them. A common problem with these scenarios is the need to remove spacing under the last item in the group.

![selector demo](https://i0.wp.com/blog.logrocket.com/wp-content/uploads/2020/02/selectordemo.png?resize=1644%2C1064&ssl=1)  

Oftentimes with CSS, it can feel natural to style the most common scenario first and _then_ account for any outlying scenarios with a more specific selector. Then, the styles of the more specific selector will override the styles of the more general selector. Which, in our example, might result in something like this:

```jsx
.image {
  margin-bottom: 2rem;

  &:last-child {
    margin-bottom: 0;
  }
}
```

Or you might have added an entirely new class to the HTML using a [BEM CSS structure](https://seesparkbox.com/foundry/bem_css_organization). Which would give you this:

```jsx
.image {
  margin-bottom: 2rem;
}

.image--last {
  margin-bottom: 0;
}
```

Both paths result in seven lines of code and an overriding property. Not terrible, but if you think of your CSS as a programing language and “program” the logic right into the selector, you can reduce the CSS to this:

```jsx
.image:not(:last-child) {
  margin-bottom: 2rem;
}
```

Reading the selector above, it says “select the image that is not the last child.” Three lines of code and no overriding styles—not bad!

{% codepen https://codepen.io/iam_aspencer/pen/qBdqMQP %}

## element:hover + adjacent sibling

Let’s look at a different scenario—hover states. Sometimes you need to adjust an element that is different than the element that is hovered. In JavasScript, this is fairly straightforward since JavaScript makes it easy to search for a specific element—also called [traversing the DOM](https://www.digitalocean.com/community/tutorials/how-to-traverse-the-dom). Oftentimes though, with the right HTML structure, you only need CSS.

With CSS, you can use [combinator selectors](https://www.w3schools.com/css/css_combinators.asp) such as `.parent > .child` or `.element + .general-sibling` to target different elements. The one thing CSS cannot do is target an element that is a parent of the element that is hovered. Here’s a diagram of what CSS can target:

```jsx
<div>
  <a>
    The element that is hovered
    <span>This is a child, CSS can style this</span>
  </a>
  <span>This is a sibling, CSS can style this</span>
  The "parent" <div> cannot be styled with CSS when the <a> is hovered
</div>
```

How might you use the powerful sibling selector? If you have two sibling elements and need to style the hover state of the second element, you can do so like this:

{% codepen https://codepen.io/iam_aspencer/pen/wvaoYoB %}

The sibling selector can also be used for form fields. With a `label:hover + input` selector, interacting with a `<label>` element can be used to highlight the `<input>` that is a sibling after the `<label>`.

{% codepen https://codepen.io/iam_aspencer/pen/zYGomdR %}

## Your turn

Next time you think CSS is an inferior language, think again. It’s just… different. And that can be frustrating or rewarding depending on your point of view. Before you give up on CSS and resort to adding more HTML or blowing everything up with some JavaScript, take a look at the CSS selectors and properties you can use. Chances are there is one you can use to fit your needs.

* * *
## Is your frontend hogging your users' CPU?

As web frontends get increasingly complex, resource-greedy features demand more and more from the browser. If you’re interested in monitoring and tracking client-side CPU usage, memory usage, and more for all of your users in production, [try LogRocket.](https://logrocket.com/signup/) 

![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/403rye2ptzx994uhktk1.png)

[LogRocket](https://logrocket.com/signup/) is like a DVR for web apps, recording everything that happens in your web app or site. Instead of guessing why problems happen, you can aggregate and report on key frontend performance metrics, replay user sessions along with application state, log network requests, and automatically surface all errors.

Modernize how you debug web apps — [Start monitoring for free.](https://logrocket.com/signup/)
* * *

The post [Advanced CSS selectors for common scenarios](https://blog.logrocket.com/advanced-css-selectors-for-common-scenarios/) appeared first on [LogRocket Blog](https://blog.logrocket.com).