CSS Nesting: How to Write Nested CSS Selectors

CSS Nesting lets you write selectors inside other style rules so related styles stay grouped together. It can make large stylesheets easier to read, especially when you are styling a component, a card, a menu, or a form with several related states and descendants.

Quick answer: CSS Nesting lets you place selectors inside another rule and reuse the parent selector with &. It is useful for organizing related styles, but you should still understand how it expands into normal CSS selectors.

Difficulty: Beginner

You'll understand this better if you know: basic CSS selectors, class names, and how descendant selectors work.

1. What Is CSS Nesting?

CSS Nesting is a way to write nested style rules inside a parent rule instead of repeating the parent selector over and over. The browser treats the nested rules as if they were written out as normal selectors.

In practice, nesting is a readability feature. It does not change what CSS can do; it changes how you organize the same styles.

2. Why CSS Nesting Matters

As stylesheets grow, related rules are often spread across many lines. Nesting helps keep a component’s styles together so you can understand them faster and update them with less searching.

It matters most when you are styling one UI section with several pieces, such as a product card with a title, image, button, hover state, and selected state. Instead of scanning a long file for related selectors, you can keep those rules in one place.

Nesting is especially useful when you work on design systems, reusable components, or pages with many repeated patterns. It is less helpful when your selectors are already short and flat or when grouping would hide important relationships.

3. Basic Syntax or Core Idea

At its simplest, nested CSS looks like a parent rule followed by child rules inside it. The browser expands the nested blocks into full selectors.

Minimal nested example

This example shows a parent class with a nested rule for its paragraph children.

.card {
  padding: 1rem;
  border: 1px solid #ccc;

  p {
    margin: 0;
  }
}

This is equivalent to writing .card p as a separate selector. The nested form keeps the paragraph rule visually attached to the card rule.

Using the parent selector with &

Use & when the nested selector needs to include the parent selector directly, such as for hover states or modifier classes.

.button {
  background: black;
  color: white;

  &:hover {
    background: dimgray;
  }
}

In this case, &:hover becomes .button:hover. Without &, the browser would treat the nested selector as a descendant selector instead.

4. Step-by-Step Examples

Example 1: Styling a card component

A card often has multiple related parts. Nesting keeps the title, text, and link styles under the same parent.

.card {
  padding: 1rem;
  background: white;

  h2 {
    margin: 0 0 0.5rem;
  }

  p {
    line-height: 1.5;
  }

  & a {
    color: royalblue;
  }
}

This structure makes it obvious that the heading, paragraph, and link belong to the card component. The last rule uses & so the selector becomes .card a.

Example 2: Hover and active states

Nesting is a natural fit for interactive states because the state belongs to the same element.

.tab {
  padding: 0.5rem 1rem;
  border: none;
  background: #eee;

  &:hover {
    background: #ddd;
  }

  &.is-active {
    background: black;
    color: white;
  }
}

Here, hover and active styles stay close to the base tab rule. This is easier to scan than three separate selectors scattered through the file.

Example 3: Descendant selectors inside a section

Nested selectors can target children inside a layout section without repeating the section name every time.

.article {
  max-width: 60ch;

  h1 {
    font-size: 2rem;
  }

  ul {
    padding-left: 1.25rem;
  }

  li {
    margin-bottom: 0.5rem;
  }
}

This works well when a section has a predictable internal structure. The nested rules are still normal CSS descendant selectors after expansion.

Example 4: Nested modifiers and subcomponents

You can nest further for variants, but keep the hierarchy readable. Use it when the relationship is real, not just to make selectors look shorter.

.alert {
  padding: 1rem;
  border-radius: 0.5rem;

  &.alert--success {
    background: #e7f7ea;
  }

  &.alert--error {
    background: #fdeaea;
  }
}

This pattern is useful for component variants. It keeps the base style and variant styles together so the component is easier to maintain.

5. Practical Use Cases

CSS Nesting is most useful when styling related rules that belong to the same visual component or section.

It is usually less helpful for one-off utility styles or very small stylesheets where plain selectors stay clearer.

6. Common Mistakes

Mistake 1: Forgetting that a nested selector is usually a descendant selector

Beginners often expect a nested selector to target the parent element again, but plain nested selectors target descendants. That difference changes which elements are styled.

Problem: This rule styles only span elements inside .button, not the button element itself.

.button {
  span {
    font-weight: bold;
  }
}

Fix: Use & if you mean the button itself or one of its states.

.button {
  & {
    font-weight: bold;
  }
}

The corrected version works because & refers to the parent selector instead of creating a descendant relationship.

Mistake 2: Mixing nesting depth until the selector becomes hard to read

Deeply nested CSS can become harder to maintain than flat CSS. Even though nesting looks organized at first, too many levels can hide the actual selector path.

Problem: This nesting is technically valid, but it creates a selector chain that is difficult to understand and may encourage overly specific styles.

.page {
  .sidebar {
    .menu {
      li {
        a {
          color: red;
        }
      }
    }
  }
}

Fix: Keep nesting shallow and flatten selectors when the relationship is not directly component-based.

.sidebar {
  background: #f7f7f7;
}

.sidebar .menu a {
  color: red;
}

The corrected version is easier to scan and reduces the chance of creating selectors that are too specific.

Mistake 3: Expecting nesting to behave the same in every browser version

CSS Nesting is a relatively new feature, so older browsers or older project environments may not support it fully. If the styles do not apply, the issue may be compatibility rather than syntax.

Problem: A stylesheet that uses nesting may appear to do nothing in browsers or tools that do not understand nested syntax.

.card {
  h2 {
    color: navy;
  }
}

Fix: Check browser support for your target audience and provide a flat fallback if needed.

.card h2 {
  color: navy;
}

@supports (selector(.card { h2 { color: navy; } })) {
  .card {
    h2 {
      color: navy;
    }
  }
}

The fixed approach preserves support for older environments while still allowing nesting where it is available.

7. Best Practices

Practice 1: Nest only when the styles truly belong together

Use nesting for styles that are part of the same component or section. This keeps related rules grouped without turning the file into a maze of nested blocks.

.profile-card {
  .avatar {
    border-radius: 50%;
  }
}

This is better than nesting unrelated selectors just because they can be nested.

Practice 2: Use & for states, variants, and self-references

When the selector must refer to the parent element itself, & avoids ambiguity and makes intent clear.

.toggle {
  &.is-open {
    max-height: 20rem;
  }
}

This makes it obvious that the open state applies to the same element as the base rule.

Practice 3: Keep nesting shallow

Shallow nesting is easier to maintain and less likely to create selectors that are difficult to override later. A useful rule is to avoid nesting just because the feature is available.

.menu {
  a {
    text-decoration: none;
  }
}

A short selector path is usually enough for a small component like a menu.

8. Limitations and Edge Cases

One common surprise is that nesting can look like a preprocessor feature, but modern CSS nesting is part of CSS itself. That means you still need to think about how the browser interprets the selector, especially when using &.

9. Practical Mini Project

Let’s build a small newsletter signup card with nested styles. This keeps the card, heading, form, and button styles together in one component block.

.signup-card {
  max-width: 28rem;
  padding: 1.5rem;
  border: 1px solid #ddd;
  border-radius: 0.75rem;
  background: #fff;

  h2 {
    margin-top: 0;
  }

  form {
    display: grid;
    gap: 0.75rem;
  }

  input {
    padding: 0.75rem;
    border: 1px solid #bbb;
    border-radius: 0.5rem;
  }

  button {
    padding: 0.75rem 1rem;
    border: none;
    border-radius: 0.5rem;
    background: black;
    color: white;

    &:hover {
      background: #333;
    }
  }
}

This example is small enough to stay readable, but it still shows the main value of nesting: related styles are grouped in one place. The output is normal CSS selectors, just organized more clearly in the source.

10. Key Points

11. Practice Exercise

Try rewriting a flat stylesheet into nested CSS for a simple product card.

Expected output: A component stylesheet where all product-card-related rules are grouped together and the hover state is written with &.

Hint: Start with the parent class, then add one nested block for each child element or state.

Solution:

.product-card {
  padding: 1rem;
  border: 1px solid #ddd;
  background: white;

  h3 {
    margin-top: 0;
  }

  p {
    color: #555;
  }

  button {
    padding: 0.5rem 0.75rem;
    border: none;
    background: black;
    color: white;

    &:hover {
      background: #333;
    }
  }
}

This solution keeps the component organized while still producing standard CSS behavior.

12. Final Summary

CSS Nesting is a readability feature that helps you group related selectors under a parent rule. It is especially useful for components, sections, and state styles where the relationship between selectors is clear.

The most important idea is that nested selectors still follow normal CSS logic. A plain nested selector usually means a descendant selector, while & lets you reference the parent selector directly. If you understand that distinction, you can use nesting without getting surprised by the output.

For best results, keep nesting shallow, use it for real component relationships, and check browser support for the users you care about. If you want to go further, the next step is to practice translating nested rules back into flat selectors so you can always predict what the browser will apply.