Chapter 1 of ?
css 8 min read

CSS3 Mastery — Chapter 21: CSS At-Rules & Modern CSS Features

Chapter 21: CSS At-Rules & Modern CSS Features

CSS At-Rules (prefixed with @) instruct the browser rendering engine how to parse, import, encapsulate, scope, and structure stylesheets. Mastering conditional media queries, keyframes, font loading (@font-face), feature queries (@supports), container queries (@container), Houdini properties (@property), Cascade Layers (@layer), native DOM scoping (@scope), and entry transitions (@starting-style) creates enterprise-grade CSS architecture.

21.1 Comprehensive At-Rules Reference Guide

At-Rule Syntax Pattern Primary Purpose & Key Advantage
@import @import url("styles.css") layer(base); Imports an external CSS stylesheet (can optionally assign to a cascade layer).
@font-face @font-face { font-family: 'Custom'; src: url(...); } Defines custom web font files and loading behaviors (font-display: swap).
@media @media (width >= 768px) { ... } Applies CSS rules conditionally based on device viewport or screen capabilities.
@keyframes @keyframes pulse { 0% { opacity: 0; } 100% { opacity: 1; } } Defines keyframe milestones for smooth CSS animations.
@supports @supports (backdrop-filter: blur(5px)) { ... } Feature query testing browser property/selector support before applying styles.
@container @container card (min-width: 400px) { ... } Component-level responsive queries checking direct parent container size.
@layer @layer reset, base, components, utilities; Declares explicit Cascade Layer priority order to eliminate specificity wars.
@scope @scope (.card) to (.card-slot) { ... } Scopes CSS selectors to a specific DOM subtree without leaking styles.
@starting-style @starting-style { opacity: 0; transform: scale(0.9); } Defines initial entry state when elements transition from display: none.
@property @property --angle { syntax: "<angle>"; ... } Registers typed custom CSS variables for smooth Houdini gradient animations.

21.2 Cascade Layers (@layer) & Specificity Architecture

Cascade Layers allow developers to establish explicit priority order for CSS blocks regardless of selector specificity. Rules inside later-declared layers always override earlier-declared layers:

Cascade Layer Rule Syntax Pattern Behavioral Impact
Layer Declaration Order @layer reset, base, components, utilities; Establishes priority order from lowest (reset) to highest (utilities).
Nested Layers @layer components.buttons { .btn { ... } } Sub-divides layer architecture using dot notation.
Unlayered Styles Rule Unlayered rules declared outside any @layer CRITICAL: Unlayered CSS rules ALWAYS defeat layered CSS rules.
<!DOCTYPE html>
<html>
<head>
  <style>
    *, *::before, *::after { box-sizing: border-box; }
    body { font-family: system-ui, sans-serif; background: #0f172a; color: #f8fafc; padding: 24px; margin: 0; }
    h4 { color: #818cf8; margin: 0 0 10px; }

    /* Establish Layer Precedence: reset -> components -> utilities */
    @layer reset, components, utilities;

    @layer reset {
      /* High specificity ID selector in lower reset layer */
      #main-btn { background: #ef4444; color: #fff; padding: 12px 24px; border: none; border-radius: 8px; font-weight: bold; }
    }

    @layer utilities {
      /* Utility layer wins over reset layer despite lower selector specificity! */
      .bg-indigo { background: #6366f1; cursor: pointer; }
    }
  </style>
</head>
<body>
  <h4>@layer Specificity Precedence Demo</h4>
  <p style="font-size:12px;color:#64748b;">Button has id="main-btn" (in reset layer) and class="bg-indigo" (in utilities layer):</p>

  <button id="main-btn" class="bg-indigo">Styled by @layer utilities ✅</button>
</body>
</html>

21.3 CSS Native Scoping (@scope) & Donut Boundaries

The @scope at-rule limits selector matching strictly to a specific DOM subtree. By defining a "donut scope" with to (boundary), styles are prevented from bleeding into inner slotted child elements:

@scope (.media-card) to (.card-slot) {
  img { border-radius: 8px; } /* Styles ONLY images inside .media-card, ignoring images inside .card-slot! */
}
<!DOCTYPE html>
<html>
<head>
  <style>
    *, *::before, *::after { box-sizing: border-box; }
    body { font-family: system-ui, sans-serif; background: #0f172a; color: #f8fafc; padding: 24px; margin: 0; }
    h4 { color: #38bdf8; margin: 0 0 10px; }

    /* @scope targets .scope-card but stops at .slot-boundary */
    @scope (.scope-card) to (.slot-boundary) {
      p { color: #38bdf8; font-weight: bold; }
    }
  </style>
</head>
<body>
  <h4>@scope Donut Boundary Demo</h4>

  <div class="scope-card" style="background:#1e293b;border:2px solid #334155;border-radius:12px;padding:16px;max-width:380px;">
    <p style="margin:0 0 10px;">Scoped paragraph text (Styled blue by @scope)</p>

    <div class="slot-boundary" style="background:#0f172a;padding:12px;border-radius:8px;">
      <p style="margin:0;color:#94a3b8;font-weight:normal;">Inner slot text (Protected from @scope leakage!)</p>
    </div>
  </div>
</body>
</html>

21.4 CSS Entry Animations (@starting-style) Without JavaScript

Historically, animating elements when inserted into the DOM or transitioning from display: none to display: block required JavaScript timeouts. @starting-style defines the element's initial pre-render state for smooth CSS entrance transitions:

.dialog { transition: opacity 0.4s ease, display 0.4s allow-discrete; }
@starting-style { .dialog { opacity: 0; transform: scale(0.9); } }
<!DOCTYPE html>
<html>
<head>
  <style>
    *, *::before, *::after { box-sizing: border-box; }
    body { font-family: system-ui, sans-serif; background: #0f172a; color: #f8fafc; padding: 24px; margin: 0; }
    h4 { color: #10b981; margin: 0 0 10px; }

    .entry-card {
      background: #1e293b; border: 2px solid #10b981; border-radius: 12px;
      padding: 16px; max-width: 320px;
      opacity: 1; transform: scale(1);
      transition: opacity 0.6s ease, transform 0.6s ease;
    }

    /* Defines initial state when element first enters DOM */
    @starting-style {
      .entry-card {
        opacity: 0;
        transform: scale(0.85) translateY(15px);
      }
    }
  </style>
</head>
<body>
  <h4>@starting-style DOM Entry Transition Demo</h4>
  <div class="entry-card">
    <strong style="color:#34d399;">DOM Entry Animation</strong>
    <p style="font-size:12px;color:#94a3b8;margin:4px 0 0;">Smoothly scales &amp; fades in on page load without JavaScript!</p>
  </div>
</body>
</html>

21.5 Interactive Sandbox — At-Rules, @layer, @scope & @starting-style

Test @layer priority ordering, @scope boundary limits, and @container queries live in the playground below:

Live Playground — Chapter 21 Sandbox
Done with this chapter?
Mark it complete to track your progress and unlock your certificate.
Next Up

Learner Reviews

Write a Review
Share your experience to help other learners.
Your Rating *