learn.colinkim.dev

CSS nesting and scoped styling

Learn native CSS nesting, the & selector, nested at-rules, specificity, @scope, and safe scoped organization patterns.

Native CSS nesting lets you write related selectors together:

.card {
  padding: 1rem;
  border: 1px solid rgb(210 215 225);

  h2 {
    margin-block: 0;
  }

  a {
    color: royalblue;
  }
}

The nested selectors are relative to .card.

The & selector

& means the parent selector:

.button {
  background: royalblue;
  color: white;

  &:hover {
    background: rgb(35 80 190);
  }

  &[aria-pressed="true"] {
    box-shadow: inset 0 0 0 2px currentColor;
  }
}

Use & when the nested selector needs to combine with the parent.

Nesting at-rules

At-rules can be nested:

.card {
  padding: 1rem;

  @media (width >= 48rem) {
    padding: 1.5rem;
  }

  @container (width >= 32rem) {
    display: grid;
    grid-template-columns: 10rem 1fr;
  }
}

This keeps responsive adjustments close to the component they affect.

Keep nesting shallow

Nesting can become hard to read:

.page {
  .main {
    .card {
      .title {
        a {
          span {
            color: red;
          }
        }
      }
    }
  }
}

That creates deeply coupled selectors. Prefer one or two levels.

CSS nesting is not Sass

Native CSS nesting does not concatenate class names:

.card {
  &__title {
    /* Not a native CSS way to create .card__title */
  }
}

Write the full class:

.card {
  padding: 1rem;
}

.card__title {
  margin-block: 0;
}

Scoped styling with @scope

@scope limits selectors to a subtree:

@scope (.profile-card) {
  h2 {
    font-size: 1.25rem;
  }

  a {
    color: royalblue;
  }
}

This styles h2 and a only inside .profile-card.

You can also define a lower boundary:

@scope (.article) to (.comments) {
  a {
    text-decoration-thickness: 0.08em;
  }
}

The comments subtree is excluded.

Component CSS without a framework

You can organize plain CSS by component:

@layer components {
  .profile-card {
    container: profile-card / inline-size;
    padding: 1rem;

    & h2 {
      font-size: 1.25rem;
    }

    @container profile-card (width >= 30rem) {
      & {
        display: grid;
        grid-template-columns: 8rem 1fr;
      }
    }
  }
}

This combines layers, nesting, and container queries while keeping the selector boundary clear.

What to carry forward

  • native nesting groups related CSS
  • & refers to the parent selector
  • nested at-rules keep responsive adjustments near the component
  • keep nesting shallow
  • native CSS nesting does not concatenate class names like Sass
  • @scope limits selectors to a subtree, but it is newer and needs support awareness

The next lesson uses modern color spaces and color mixing for more reliable palettes.

Progress

Quick checks

No quick checks in this lesson.

Mark lesson manually or answer quick checks to track progress.