DevToolBoxGRATIS
Blogg

Nativ CSS Nesting 2026

11 minby DevToolBox

Native CSS Nesting in 2026: No Preprocessor Needed

Native CSS nesting is now supported in all major browsers. You can nest selectors directly in your stylesheets without Sass, Less, or any build tool. The syntax is slightly different from preprocessor nesting but achieves the same goal: scoped, readable, maintainable styles. This guide covers the full specification, real-world patterns, migration tips, and edge cases.

Browser Support

BrowserVersionRelease
Chrome120+December 2023
Firefox117+August 2023
Safari17.2+December 2023
Edge120+December 2023

As of 2026, native CSS nesting has over 95% global browser support. You can safely use it in production without a preprocessor for any project that does not need to support very old browsers.

Basic Nesting Syntax

/* Native CSS nesting */
.card {
  padding: 1.5rem;
  border-radius: 0.75rem;
  background: white;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);

  /* Nested child selector — & is optional for element and class selectors */
  .card-header {
    font-size: 1.25rem;
    font-weight: 600;
    margin-bottom: 1rem;
    border-bottom: 1px solid #e5e7eb;
    padding-bottom: 0.75rem;
  }

  .card-body {
    line-height: 1.6;
    color: #374151;
  }

  .card-footer {
    margin-top: 1rem;
    padding-top: 0.75rem;
    border-top: 1px solid #e5e7eb;
    display: flex;
    justify-content: flex-end;
    gap: 0.5rem;
  }
}

/* Equivalent flat CSS */
/*
.card { ... }
.card .card-header { ... }
.card .card-body { ... }
.card .card-footer { ... }
*/

The & Nesting Selector

The & represents the parent selector. It is required when combining selectors (like pseudo-classes, attribute selectors, or chaining class names) and optional for descendant selectors.

/* & for pseudo-classes and pseudo-elements */
.button {
  padding: 0.5rem 1rem;
  background: #3b82f6;
  color: white;
  border: none;
  border-radius: 0.375rem;
  cursor: pointer;
  transition: all 0.15s ease;

  /* Pseudo-classes require & */
  &:hover {
    background: #2563eb;
    transform: translateY(-1px);
  }

  &:active {
    transform: translateY(0);
  }

  &:focus-visible {
    outline: 2px solid #3b82f6;
    outline-offset: 2px;
  }

  &:disabled {
    opacity: 0.5;
    cursor: not-allowed;
    pointer-events: none;
  }

  /* Pseudo-elements */
  &::before {
    content: "";
    display: inline-block;
    width: 1em;
    height: 1em;
  }

  /* Chaining classes (no space — same element) */
  &.primary {
    background: #3b82f6;
  }

  &.danger {
    background: #ef4444;
  }

  &.outline {
    background: transparent;
    border: 2px solid #3b82f6;
    color: #3b82f6;

    &:hover {
      background: #3b82f6;
      color: white;
    }
  }
}

Deep Nesting

/* You can nest multiple levels deep */
.nav {
  display: flex;
  align-items: center;

  .nav-list {
    display: flex;
    list-style: none;
    gap: 0.25rem;

    .nav-item {
      position: relative;

      .nav-link {
        display: block;
        padding: 0.5rem 1rem;
        color: #4b5563;
        text-decoration: none;
        border-radius: 0.375rem;

        &:hover {
          background: #f3f4f6;
          color: #111827;
        }

        &.active {
          background: #eff6ff;
          color: #2563eb;
          font-weight: 500;
        }
      }

      /* Dropdown submenu */
      .dropdown {
        display: none;
        position: absolute;
        top: 100%;
        left: 0;
        min-width: 200px;
        background: white;
        border-radius: 0.5rem;
        box-shadow: 0 10px 25px rgba(0, 0, 0, 0.15);
      }

      &:hover .dropdown {
        display: block;
      }
    }
  }
}

/*
  Best practice: Keep nesting to 3 levels max.
  Deeper nesting creates overly specific selectors.
*/

Nesting Media Queries and Container Queries

/* Media queries can be nested inside selectors */
.grid {
  display: grid;
  gap: 1rem;
  grid-template-columns: 1fr;

  @media (min-width: 640px) {
    grid-template-columns: repeat(2, 1fr);
  }

  @media (min-width: 1024px) {
    grid-template-columns: repeat(3, 1fr);
    gap: 1.5rem;
  }

  @media (min-width: 1280px) {
    grid-template-columns: repeat(4, 1fr);
  }
}

/* Container queries nested */
.card-container {
  container-type: inline-size;
  container-name: card;
}

.card {
  padding: 1rem;

  @container card (min-width: 400px) {
    display: flex;
    gap: 1rem;

    .card-image {
      width: 150px;
      flex-shrink: 0;
    }
  }

  @container card (min-width: 600px) {
    padding: 2rem;

    .card-image {
      width: 250px;
    }
  }
}

/* Supports query nested */
.backdrop {
  background: rgba(0, 0, 0, 0.5);

  @supports (backdrop-filter: blur(10px)) {
    background: rgba(0, 0, 0, 0.2);
    backdrop-filter: blur(10px);
  }
}

Nesting with Combinators

/* Direct child combinator */
.list {
  > li {
    padding: 0.75rem 0;
    border-bottom: 1px solid #e5e7eb;

    &:last-child {
      border-bottom: none;
    }

    > a {
      color: #2563eb;
      text-decoration: none;

      &:hover {
        text-decoration: underline;
      }
    }
  }
}

/* Adjacent sibling */
.heading {
  margin-bottom: 0.5rem;

  + p {
    margin-top: 0;
    color: #6b7280;
  }

  + .heading {
    margin-top: 2rem;
  }
}

/* General sibling */
.toggle-input {
  display: none;

  &:checked ~ .toggle-panel {
    display: block;
    animation: slideDown 0.2s ease;
  }
}

/* Attribute selectors */
.input {
  border: 1px solid #d1d5db;
  border-radius: 0.375rem;

  &[type="email"],
  &[type="password"] {
    padding-left: 2.5rem;
  }

  &[aria-invalid="true"] {
    border-color: #ef4444;
    background: #fef2f2;
  }

  &[disabled] {
    opacity: 0.5;
    background: #f9fafb;
  }
}

CSS Nesting vs Sass Nesting

FeatureNative CSSSass/SCSS
Basic nesting.parent { .child {} }Same
Parent selector&&
String concatenationNot supported&__element
@media nestingSupportedSupported
Variablesvar(--custom)$variable
MixinsNot available@mixin / @include
FunctionsLimited (calc, min, max)Full function system
Build step requiredNoYes

Migration from Sass

/* Sass (won't work in native CSS) */
.block {
  &__element {    /* BEM concatenation — NOT supported natively */
    color: red;
  }
  &--modifier {   /* BEM concatenation — NOT supported natively */
    color: blue;
  }
}

/* Native CSS equivalent */
.block {
  .block__element {
    color: red;
  }
  .block--modifier {
    color: blue;
  }
}

/* Or better — drop BEM and use native nesting */
.block {
  .element {
    color: red;
  }
  &.modifier {
    color: blue;
  }
}

Real-World Component Example

/* A complete dialog component with native nesting */
.dialog-overlay {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.5);
  display: grid;
  place-items: center;
  z-index: 50;
  opacity: 0;
  transition: opacity 0.2s ease;

  &[data-open="true"] {
    opacity: 1;
  }

  .dialog {
    background: white;
    border-radius: 1rem;
    width: min(90vw, 500px);
    max-height: 85vh;
    display: flex;
    flex-direction: column;
    box-shadow: 0 25px 50px rgba(0, 0, 0, 0.25);
    transform: scale(0.95);
    transition: transform 0.2s ease;

    [data-open="true"] & {
      transform: scale(1);
    }

    .dialog-header {
      padding: 1.5rem;
      display: flex;
      align-items: center;
      justify-content: space-between;
      border-bottom: 1px solid #e5e7eb;

      h2 {
        font-size: 1.25rem;
        font-weight: 600;
        margin: 0;
      }

      .close-btn {
        width: 2rem;
        height: 2rem;
        border: none;
        background: none;
        border-radius: 0.375rem;
        cursor: pointer;
        display: grid;
        place-items: center;

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

    .dialog-body {
      padding: 1.5rem;
      overflow-y: auto;
      flex: 1;

      p {
        line-height: 1.6;
        color: #4b5563;

        &:first-child {
          margin-top: 0;
        }
      }
    }

    .dialog-footer {
      padding: 1rem 1.5rem;
      border-top: 1px solid #e5e7eb;
      display: flex;
      justify-content: flex-end;
      gap: 0.75rem;
    }

    @media (max-width: 640px) {
      width: 100vw;
      max-height: 100vh;
      border-radius: 0;
      margin: 0;
    }
  }
}

Dark Mode with Nesting

/* Combine nesting with CSS custom properties for dark mode */
:root {
  --bg-primary: #ffffff;
  --bg-secondary: #f9fafb;
  --text-primary: #111827;
  --text-secondary: #6b7280;
  --border: #e5e7eb;

  @media (prefers-color-scheme: dark) {
    --bg-primary: #111827;
    --bg-secondary: #1f2937;
    --text-primary: #f9fafb;
    --text-secondary: #9ca3af;
    --border: #374151;
  }
}

.card {
  background: var(--bg-primary);
  color: var(--text-primary);
  border: 1px solid var(--border);
  border-radius: 0.75rem;
  padding: 1.5rem;

  .subtitle {
    color: var(--text-secondary);
  }

  /* Explicit dark mode class override */
  .dark & {
    --bg-primary: #111827;
    --text-primary: #f9fafb;
    --border: #374151;
  }
}

Best Practices

  • Limit nesting depth to 3 levels — deeper nesting creates specificity problems and fragile selectors
  • Use & for pseudo-classes and chained selectors — it makes the relationship explicit
  • Nest media queries inside selectors — keeps responsive styles co-located with the component
  • Avoid nesting element selectors deeply — prefer class-based selectors for maintainability
  • Use CSS custom properties instead of Sass variables — they cascade and respond to context
  • PostCSS nesting plugin — if you need to support older browsers, use postcss-nesting as a fallback

Experiment with CSS nesting patterns using our CSS Formatter tool. For migrating from Tailwind utility classes to custom CSS nesting, read our CSS to Tailwind Migration guide. If you are building responsive layouts with nesting, check out our CSS Grid Layout Cheat Sheet.

𝕏 Twitterin LinkedIn
Var dette nyttig?

Hold deg oppdatert

Få ukentlige dev-tips og nye verktøy.

Ingen spam. Avslutt når som helst.

Try These Related Tools

{ }CSS Minifier / Beautifier🎨CSS FormatterTWCSS to Tailwind

Related Articles

CSS Container Queries: Komplett Guide 2026

Mestre CSS container queries: @container-syntaks, størrelsesbegrensning og container-enheter.

CSS :has() Selector: The Parent Selector You Always Wanted (2026)

Master the CSS :has() pseudo-class. Parent selection, form validation without JS, and advanced patterns.

Tailwind CSS Tips 2026: Avanserte Teknikker

Mestre avanserte Tailwind CSS-teknikker.