Frontend Engineer Hub

CSS and Design-System Implementation for Frontend Engineers (2026)

In short

Modern CSS in 2026 is a different language than 2015. Cascade layers (<code>@layer</code>) let you order specificity by intent rather than by selector arms-race. Container queries make components self-aware of their layout context. CSS variables at the design-token tier enable theming, dark mode, and design-system extension without preprocessors. The senior bar in 2026: you can hand-write modern CSS without reaching for utility frameworks; you understand the design-token pipeline (Figma tokens → Style Dictionary → CSS variables); you know when CSS Modules / vanilla-extract / Tailwind / unstyled-with-css-variables fits which problem.

Key takeaways

  • Cascade layers (@layer) are the modern way to manage CSS specificity. They let you order specificity by intent — design-system base layer, component layer, utility layer, override layer — rather than by selector specificity arms-race.
  • Container queries (@container) make components self-aware of their parent's size, not the viewport's size. This is the modern primitive for true component-driven responsive design. MDN's container-query reference (developer.mozilla.org/en-US/docs/Web/CSS/CSS_containment/Container_queries) is the canonical reference.
  • CSS variables (custom properties) at the design-token tier enable theming, dark mode, and design-system extension without preprocessors. The pipeline: Figma design tokens → Style Dictionary (or similar tool) → CSS variables → component styles consume them.
  • Modern layout in 2026 is grid + flexbox + container queries. Flexbox for one-dimensional layout (rows or columns); CSS grid for two-dimensional layout (full-page layouts, card grids); container queries for component-level responsive behavior. Josh W. Comeau's CSS for JavaScript Developers (joshwcomeau.com/courses/css-for-js) is canonical.
  • Design-system implementation choices: CSS Modules (scoped-by-default, simple), vanilla-extract (typed CSS-in-TS at build time), Tailwind (utility-first, fast for prototyping), styled-components / emotion (runtime CSS-in-JS, increasingly out of favor). The 2026 lean is build-time over runtime.
  • The senior bar includes prefers-reduced-motion respect (a real accessibility requirement, not a nice-to-have), prefers-color-scheme handling for system dark mode, and forced-colors mode handling for high-contrast users. MDN covers each.
  • Logical properties (margin-inline, padding-block, inset) enable RTL support without separate stylesheets. Senior frontend engineers default to logical properties on global / shared CSS.

Cascade layers: ordering specificity by intent

Cascade layers (the @layer at-rule, broadly supported in 2024+) are the modern way to manage CSS specificity. Instead of fighting specificity with !important or selector-specificity-arms-race, you declare layers and order them by intent.

/* main.css — top-level style sheet */

/* Order layers from least-specific to most-specific intent.
 * Later layers always win over earlier layers regardless of selector
 * specificity. */
@layer reset, base, design-system, component, utility, override;

/* Reset layer — lightest possible specificity */
@layer reset {
  *,
  *::before,
  *::after {
    box-sizing: border-box;
    margin: 0;
    padding: 0;
  }
}

/* Base layer — typography, root colors, page-wide defaults */
@layer base {
  :root {
    --color-text: oklch(0.2 0 0);
    --color-bg: oklch(1 0 0);
    --font-sans: system-ui, sans-serif;
  }

  body {
    color: var(--color-text);
    background-color: var(--color-bg);
    font-family: var(--font-sans);
    line-height: 1.5;
  }
}

/* Design-system layer — primitive components */
@layer design-system {
  .button {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    padding-block: 0.5rem;
    padding-inline: 1rem;
    border-radius: 0.5rem;
    font-weight: 600;
  }

  .button[data-variant="primary"] {
    background-color: var(--color-accent);
    color: var(--color-on-accent);
  }
}

/* Component layer — feature-specific styles */
@layer component {
  .checkout-form .button {
    /* Even though .checkout-form .button is more specific by selector,
     * cascade-layer order is what wins. component layer beats
     * design-system layer regardless of selector specificity. */
    width: 100%;
  }
}

/* Utility layer — single-purpose utilities */
@layer utility {
  .visually-hidden {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
  }
}

The senior+ pattern: declare layers at the project root, place imported styles into named layers (@import "./design-system.css" layer(design-system)), and trust the layer-order to resolve specificity conflicts. The result is CSS that scales across hundreds of contributors without specificity wars.

MDN's cascade-layers reference (developer.mozilla.org/en-US/docs/Web/CSS/@layer) is the canonical reference; Josh W. Comeau's writing on cascade layers covers the practical patterns.

Container queries: component-driven responsive design

Container queries (the @container at-rule, broadly supported since 2023) let components respond to their parent's size rather than the viewport's size. The pattern enables true component-driven responsive design.

/* The component declares itself a container by setting container-type.
 * "inline-size" makes container queries query the inline (horizontal)
 * dimension. */
.product-card {
  container-type: inline-size;
  container-name: product-card;
}

/* Default styles — narrow layout */
.product-card-content {
  display: grid;
  grid-template-columns: 1fr;
  gap: 1rem;
}

.product-card-image {
  width: 100%;
  aspect-ratio: 4 / 3;
}

/* When the container is wider than 480px, switch to two-column layout */
@container product-card (inline-size > 480px) {
  .product-card-content {
    grid-template-columns: 200px 1fr;
  }

  .product-card-image {
    aspect-ratio: 1 / 1;
  }
}

/* When the container is wider than 720px, switch to three-column layout */
@container product-card (inline-size > 720px) {
  .product-card-content {
    grid-template-columns: 280px 1fr 200px;
  }
}

The benefit: a product card on a sidebar (300px wide) renders in single-column mode; the same product card on a full-width grid (800px wide) renders in two-column mode automatically — without any JavaScript or media queries. The component is self-aware.

The contrast with viewport media queries: a viewport media query (@media) targets the browser viewport. A container query targets the component's parent container. The two coexist but solve different problems. Senior+ frontend engineers reach for container queries for component-level responsiveness and viewport queries for page-level layout.

MDN's container-query reference (developer.mozilla.org/en-US/docs/Web/CSS/CSS_containment/Container_queries) is the canonical reference.

Design tokens: the Figma to CSS variables pipeline

Design tokens are the named, structured values that define a design system's visual language — colors, typography scale, spacing scale, border radii, shadows. The modern pipeline: design tokens defined in Figma (or a design-token-tool) → Style Dictionary (or similar) transforms them to CSS variables → component styles consume them.

/* tokens.css — generated from Figma via Style Dictionary */

:root {
  /* Color palette (raw tokens) */
  --color-blue-500: oklch(0.65 0.18 245);
  --color-blue-600: oklch(0.58 0.18 245);
  --color-blue-700: oklch(0.52 0.18 245);

  --color-gray-50: oklch(0.98 0 0);
  --color-gray-100: oklch(0.96 0 0);
  --color-gray-900: oklch(0.18 0 0);
  --color-gray-950: oklch(0.10 0 0);

  /* Semantic tokens — alias raw tokens by intent */
  --color-bg-base: var(--color-gray-50);
  --color-bg-surface: var(--color-gray-100);
  --color-text-primary: var(--color-gray-900);
  --color-accent: var(--color-blue-600);
  --color-accent-hover: var(--color-blue-700);
  --color-on-accent: var(--color-gray-50);

  /* Spacing scale */
  --space-1: 0.25rem;
  --space-2: 0.5rem;
  --space-3: 0.75rem;
  --space-4: 1rem;
  --space-6: 1.5rem;
  --space-8: 2rem;

  /* Typography scale */
  --text-xs: 0.75rem;
  --text-sm: 0.875rem;
  --text-base: 1rem;
  --text-lg: 1.125rem;
  --text-xl: 1.25rem;
  --text-2xl: 1.5rem;
}

/* Dark mode overrides — flip the semantic layer, raw tokens stay */
@media (prefers-color-scheme: dark) {
  :root {
    --color-bg-base: var(--color-gray-950);
    --color-bg-surface: var(--color-gray-900);
    --color-text-primary: var(--color-gray-50);
    --color-on-accent: var(--color-gray-50);
  }
}

/* Components consume the semantic tokens — never the raw palette */
.card {
  background-color: var(--color-bg-surface);
  color: var(--color-text-primary);
  padding: var(--space-6);
  border-radius: 0.75rem;
}

The two-tier pattern: raw tokens (the actual color value) and semantic tokens (the named intent — bg-base, accent, on-accent). Components consume only semantic tokens; theming and dark mode swap the semantic layer while leaving raw tokens stable. Adding a new theme is changing semantic-token assignments, not rewriting components.

Style Dictionary (styledictionary.com) is the dominant tool for transforming design tokens from a source format (Figma JSON, Tokens Studio JSON) to CSS variables, JavaScript constants, iOS / Android assets. Modern Figma plugins like Tokens Studio sync directly to a GitHub repo where Style Dictionary runs in CI.

Modern layout: grid + flexbox + container queries

Modern CSS layout in 2026 is three primary primitives:

  • Flexbox for one-dimensional layout (a row of items, a column of items). Use when you want items to line up along a single axis.
  • CSS Grid for two-dimensional layout (full-page layouts, card grids, design-system templating). Use when you want explicit row + column control.
  • Container queries for component-driven responsive behavior layered on top of grid / flexbox.

A canonical layout — a dashboard with a sidebar, a header, a main content area, and a footer:

.dashboard {
  display: grid;
  grid-template-columns: 240px 1fr;
  grid-template-rows: 64px 1fr 48px;
  grid-template-areas:
    "sidebar header"
    "sidebar main"
    "sidebar footer";
  min-height: 100vh;
}

.dashboard-header { grid-area: header; }
.dashboard-sidebar { grid-area: sidebar; }
.dashboard-main { grid-area: main; padding: var(--space-6); overflow: auto; }
.dashboard-footer { grid-area: footer; }

/* Mobile — collapse to single column with sidebar as drawer */
@media (max-width: 768px) {
  .dashboard {
    grid-template-columns: 1fr;
    grid-template-rows: 64px 1fr 48px;
    grid-template-areas:
      "header"
      "main"
      "footer";
  }

  .dashboard-sidebar {
    /* Becomes a drawer; show / hide via JS or a checkbox hack */
    position: fixed;
    inset: 0 auto 0 0;
    width: 240px;
    transform: translateX(-100%);
    transition: transform 0.2s;
  }

  .dashboard-sidebar[data-open="true"] {
    transform: translateX(0);
  }
}

/* Card grid inside main — auto-fit to as many columns as fit */
.card-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: var(--space-6);
}

/* Flexbox for the card itself — image on left, content on right */
.card {
  display: flex;
  gap: var(--space-4);
  align-items: flex-start;
}

What this layout gets right: grid-template-areas for the page-level layout (more readable than column / row indices); auto-fit grid for responsive card grids; logical properties (inset) for RTL support; flexbox for the one-dimensional card layout.

Josh W. Comeau's CSS for JavaScript Developers (joshwcomeau.com/courses/css-for-js) is the canonical course; the MDN CSS reference (developer.mozilla.org/en-US/docs/Web/CSS) is the canonical specification reference.

Frequently asked questions

Should I use Tailwind or vanilla CSS?
Both work; the codebase consistency and team preference matters more. Tailwind (utility-first) is fast for prototyping and consistent at scale; vanilla CSS with cascade layers is more flexible and produces smaller HTML. The 2026 SaaS-tier reality: Vercel uses Tailwind heavily on marketing surfaces; Linear uses custom CSS Modules; Stripe uses internal-design-system CSS; Figma uses internal CSS-in-JS. The senior frontend bar: be conversant in both, articulate the trade-offs.
Is CSS-in-JS still recommended in 2026?
Runtime CSS-in-JS (styled-components, emotion) has fallen out of favor at SaaS-tier — the runtime cost on Server Components rendering is real, and the bundling story is awkward in App Router. Build-time CSS-in-JS (vanilla-extract, panda-css) is the modern alternative for teams that want typed CSS without the runtime cost. Most new SaaS-tier projects in 2026 use either Tailwind, CSS Modules, or vanilla-extract.
Should I learn Sass / Less in 2026?
Rarely necessary. Modern CSS has CSS variables, calc(), nesting (broadly supported in 2024+), and most of what Sass / Less provided historically. Sass is still used in legacy codebases; new projects rarely add it. The Microsoft-and-Bootstrap world is one exception where Sass is still common.
How do I handle dark mode?
Three approaches. (1) Pure CSS via @media (prefers-color-scheme: dark) and CSS variable overrides — simplest, no JS needed, respects user OS preference automatically. (2) JS-toggleable via a [data-theme='dark'] attribute on the html / body element — supports user override of OS preference. (3) Both, layered — default to OS preference, allow user override via cookie. Most production sites use approach (3).
Should I use logical properties?
Yes for any global / shared CSS. Logical properties (margin-inline, padding-block, inset, border-inline-start) automatically adapt to RTL languages. The cost is zero (CSS variables are unaffected); the benefit is real for any product that supports international users. Modern CSS lints (stylelint with logical-properties plugin) flag physical-property usage.
What's the role of CSS Houdini in 2026?
Limited but growing. Houdini APIs (Paint Worklet, Layout Worklet, Properties and Values API) ship in modern Chromium browsers. The Properties and Values API (@property at-rule) is the most-used part of Houdini in production — it lets you type-check CSS variables. Paint and Layout worklets have not seen wide adoption.
How important is print-stylesheet support in 2026?
Niche. Most consumer products skip print-specific CSS entirely. B2B / enterprise / fintech products with print-receipt or print-document use cases need print stylesheets (@media print). The 2026 senior bar: know that @media print exists and how to test it, not necessarily ship it on every project.

Sources

  1. MDN — Web/CSS reference. Canonical CSS specification reference.
  2. Josh W. Comeau — CSS for JavaScript Developers. Canonical practical CSS course.
  3. MDN — Cascade layers (@layer). Canonical for the modern specificity-management pattern.
  4. MDN — Container queries. Canonical for component-driven responsive design.
  5. Style Dictionary — the canonical design-token transformation tool.
  6. Smashing Magazine — CSS deep-dives. Practical articles at senior+ depth.
  7. Josh W. Comeau — joshwcomeau.com. CSS deep-dives and modern-layout writing.

About the author. Blake Crosley founded ResumeGeni and writes about frontend engineering, hiring technology, and ATS optimization. More writing at blakecrosley.com.