Modern & Next-Generation CSS Specifications

Explore CSS Subgrid, Cascade Layers (@layer), Donut Scoping (@scope), native CSS nesting, and relational selectors (:has).

1. CSS Subgrid: Perfect Track Alignment

Historically, nested grids were completely disconnected from parent grids. If a card had a header, body, and button, cards in adjacent columns could never align their buttons if text lengths varied.

Subgrid allows child grid items to adopt the exact tracks (rows or columns) of their parent:

CSS Example

/* Subgrid in action */
.parent-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  grid-template-rows: auto 1fr auto;
  gap: 16px;
  background: #f8fafc;
  padding: 16px;
  border-radius: 8px;
}

.subgrid-card {
  grid-row: span 3;
  display: grid;
  grid-template-rows: subgrid; /* Inherits 3 rows from parent! */
  background: #ffffff;
  padding: 12px;
  border: 1px solid #cbd5e1;
  border-radius: 6px;
}

.card-btn {
  background: #2563eb;
  color: white;
  border: none;
  padding: 8px 12px;
  border-radius: 4px;
}

2. Cascade Layers (@layer): Specificity Tamed

The CSS Cascade algorithm evaluates Cascade Layers before selector specificity. This gives developers complete architectural control over which stylesheet rules take precedence:

/* Declare explicit layer priority order upfront */
@layer reset, base, components, utilities;

@layer reset {
  button { padding: 0; border: none; }
}

@layer components {
  /* Even with high specificity, components lose to utilities */
  .btn.btn-primary { background: #2563eb; color: white; }
}

@layer utilities {
  /* Wins automatically because the utilities layer is declared last! */
  .bg-danger { background: #dc2626; }
}
Rule: Unlayered styles (styles outside any @layer block) always win over layered styles. Within layered styles, later declared layers defeat earlier declared layers.

3. Scoped Styles & Donut Scoping (@scope)

Native @scope scopes styles to a subtree without requiring CSS Modules or shadow DOM hashing. It also enables Donut Scoping (styling between an outer root and an inner limit):

/* Donut Scoping Example */
@scope (.card) to (.card__content) {
  /* Styles apply only to .card and its direct framing, 
     stopping immediately once .card__content is reached! */
  header { background: #f1f5f9; }
  img { border-radius: 8px 8px 0 0; }
}

4. Native CSS Nesting

Modern browsers support native CSS nesting directly, eliminating the requirement for preprocessors like Sass for standard nesting:

CSS Example

/* Native CSS nesting with & parent selector */
.nested-menu {
  background: #1e293b;
  border-radius: 8px;
  padding: 12px;

  & .menu-title {
    color: #38bdf8;
    margin: 0 0 8px 0;
  }

  & ul {
    list-style: none;
    padding: 0;
    margin: 0;

    & li {
      padding: 6px 0;
      color: #94a3b8;

      &:hover {
        color: #f8fafc;
        cursor: pointer;
      }
    }
  }
}

5. Frequently Asked Questions (FAQ)

Yes! You can assign entire external stylesheet files to a cascade layer directly in the HTML link tag: <link rel="stylesheet" href="bootstrap.css" layer="framework">, or via CSS import: @import "reset.css" layer(reset);.

The View Transitions API allows smooth animated morphs between DOM states or cross-document page navigations. In CSS, pseudo-elements like ::view-transition-old(root) and ::view-transition-new(root) allow styling transition timing, cross-fades, and geometry animations.

Modern browser engines (Blink, WebKit, Gecko) have heavily optimized the selector engine to cache relational queries. However, writing overly broad queries like body:has(*) will invalidate styles across the entire page during DOM mutations. Always scope :has() to specific components (e.g. .card:has(.badge)).

Explore Related Tools

Hand-picked utilities and calculators related to this tool.

Related Tools