CSS techniques every frontend developer should know in 2024
Tags: webdev, frontend, css, tips
Published: 2024-04-17 07:06:36

CSS has evolved significantly over the years, with recent updates offering frontend developers powerful tools to create more efficient, clean, and complex layouts **across all major browsers**. 

Among these, there are some techniques which I've been using the most lately, and in my opinion they should be part of any frontend developer's arsenal in 2024.

## CSS Nesting

Traditional CSS often led to lengthy and repetitive code. Until 2023 we needed tools like SCSS to write our styles in a structured way but now we can [safely do so](https://caniuse.com/css-nesting) with plain CSS too. 

#### CSS without CSS nesting

```css
.container {
  display: flex;
}
.container .header {
  background-color: blue;
}
.container .header h1 {
  color: white;
}
```

#### CSS with CSS nesting

```css
.container {
  display: flex;
  .header {
    background-color: blue;
    h1 {
      color: white;
    }
  }
}
```

CSS nesting allows us to write cleaner, more organised styles by nesting selectors within one another, mimicking a more natural hierarchy in the stylesheet. 

## The :has() Selector

The `:has()` selector offers us a new level of styling flexibility, allowing for parent selectors based on child conditions and [can safely be used](https://caniuse.com/css-has) across all major browsers. 

This was a challenge with older CSS, where selecting parent elements based on child or sibling conditions required convoluted selectors or JavaScript. The `:has()` selector streamlines this process, opening up new possibilities for responsive and dynamic designs.

#### CSS without :has() selector

Before the `:has()` selector, CSS couldn't directly target parent elements based on the presence of specific child elements. Instead, developers would typically use JS to dynamically add a class to the parent `div`.

```js
// JavaScript to add a class to divs containing a specific child
document.querySelectorAll('div > a.special-class').forEach(link => {
  link.parentElement.classList.add('has-special-link');
});
```

```css
/* CSS targeting the dynamically added class */
div.has-special-link {
  border: 1px solid green;
}
```

#### CSS with :has() selector

```css
div:has(> a.special-class) {
  border: 1px solid green;
}
```

The `:has` selector enables us to directly target a `div` element that has an `a` child with a `.special-class`, changing the `div`'s border. It simplifies our CSS by removing the need for additional JS code or complex sibling selectors.

## The :is() Selector

Another convenient selector that can help us write more readable CSS and [can safely be used](https://caniuse.com/css-matches-pseudo) across all major browsers is the `:is()` selector.

Before the `:is()` selector, selecting multiple elements that share styles often led to long, repetitive CSS selectors. 

#### CSS without :is() selector

```css
.article > h1, .article > h2, .article > h3 {
  font-family: sans-serif;
  color: blue;
}
```

#### CSS with :is() selector

```css
.article > :is(h1,h2,h3) {
  font-family: sans-serif;
  color: blue;
}
```

Traditionally, styling multiple elements required listing each selector individually, as shown in the first block, where `h1`, `h2`, and `h3` elements within `.article` are styled identically. With `:is()`, as demonstrated in the second block, the same effect is achieved more concisely by grouping the selectors within `:is()`, reducing repetition and enhancing code readability.

As CSS continues to evolve, techniques like nesting and pseudo-classes like `:has` and `:is` enable us to improve our styles and our UI code overall.