Modern CSS 2026: Container Queries, CSS Grid, Layers, and New Features
Advertisement
Modern CSS 2026: The Platform Has Caught Up
CSS in 2026 is more powerful than any CSS-in-JS solution from 2020. Native container queries, cascade layers, :has(), nesting, and animations that were impossible before are now standard.
- Container Queries: Component-Based Responsiveness
- CSS Cascade Layers
- :has() — The Parent Selector
- Native CSS Nesting
- OKLCH Colors: Better Color Manipulation
- Scroll-Driven Animations
- CSS View Transitions
- Anchor Positioning
- CSS Grid Advanced Patterns
- Browser Support Summary (2026)
Container Queries: Component-Based Responsiveness
Media queries respond to the viewport. Container queries respond to the parent element:
/* Define a container */
.card-grid {
container-type: inline-size;
container-name: cards;
}
/* Style children based on container width */
@container cards (min-width: 600px) {
.card {
display: grid;
grid-template-columns: 200px 1fr;
gap: 1rem;
}
}
@container cards (min-width: 900px) {
.card {
grid-template-columns: 280px 1fr;
}
}
/* Named container queries */
.sidebar {
container: sidebar / inline-size;
}
@container sidebar (width < 250px) {
.nav-label { display: none; }
.nav-icon { font-size: 1.5rem; }
}
CSS Cascade Layers
/* Control specificity without !important hell */
@layer reset, base, components, utilities;
@layer reset {
*, *::before, *::after { box-sizing: border-box; }
body { margin: 0; }
}
@layer base {
h1 { font-size: 2rem; font-weight: 700; }
a { color: var(--color-primary); }
}
@layer components {
.btn {
padding: 0.5rem 1rem;
border-radius: 0.375rem;
font-weight: 500;
}
.btn-primary {
background: var(--color-primary);
color: white;
}
}
@layer utilities {
/* Utilities always win over components */
.text-center { text-align: center; }
.hidden { display: none; }
}
/* Styles outside layers trump all layers */
.critical { color: red; }
:has() — The Parent Selector
/* Style parent based on children */
/* Card with image gets different layout */
.card:has(img) {
display: grid;
grid-template-columns: auto 1fr;
}
/* Form field with error */
.field:has(input:invalid) label {
color: red;
}
/* Navigation with open dropdown */
nav:has(.dropdown:hover) .overlay {
display: block;
}
/* Article with no headings gets fallback */
article:not(:has(h2, h3)) .toc {
display: none;
}
/* Sibling relationships — style preceding elements */
.gallery:has(.item:hover) .item:not(:hover) {
opacity: 0.5;
}
Native CSS Nesting
/* No preprocessor needed */
.card {
border: 1px solid var(--border);
border-radius: 8px;
padding: 1rem;
& .title {
font-size: 1.25rem;
font-weight: 600;
}
& .description {
color: var(--text-muted);
}
&:hover {
border-color: var(--color-primary);
box-shadow: 0 4px 20px rgb(0 0 0 / 0.1);
}
/* BEM modifier */
&--featured {
border-color: var(--color-primary);
background: var(--color-primary-50);
}
@media (max-width: 640px) {
padding: 0.75rem;
}
}
OKLCH Colors: Better Color Manipulation
/* OKLCH: perceptually uniform — "lighter" actually looks lighter */
:root {
--primary: oklch(55% 0.2 250); /* Base blue */
--primary-light: oklch(75% 0.15 250); /* Actually lighter */
--primary-dark: oklch(35% 0.2 250); /* Actually darker */
--primary-muted: oklch(55% 0.1 250); /* Same lightness, less chroma */
}
/* Dynamic color scales */
.badge {
background: oklch(from var(--color) l c h); /* Same as base */
background: oklch(from var(--color) 90% 0.05 h); /* Light tint */
border-color: oklch(from var(--color) 40% c h); /* Dark border */
}
/* Color-mix */
.overlay {
background: color-mix(in oklch, var(--primary) 20%, transparent);
}
Scroll-Driven Animations
/* Animate based on scroll position — no JavaScript! */
@keyframes reveal {
from { opacity: 0; transform: translateY(20px); }
to { opacity: 1; transform: translateY(0); }
}
.section {
animation: reveal linear;
animation-timeline: view();
animation-range: entry 0% entry 25%; /* Animate as element enters viewport */
}
/* Progress bar */
@keyframes grow {
from { transform: scaleX(0); }
to { transform: scaleX(1); }
}
.reading-progress {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 3px;
background: var(--color-primary);
transform-origin: left;
animation: grow linear;
animation-timeline: scroll(); /* Based on page scroll */
}
CSS View Transitions
/* Animate between pages/states */
/* Enable view transitions */
@view-transition {
navigation: auto;
}
/* Customize transition for specific element */
.hero-image {
view-transition-name: hero; /* Must be unique */
}
@keyframes fade-in {
from { opacity: 0; }
}
@keyframes fade-out {
to { opacity: 0; }
}
::view-transition-old(root) {
animation: fade-out 0.2s ease;
}
::view-transition-new(root) {
animation: fade-in 0.2s ease;
}
/* Shared element transition (hero to detail) */
::view-transition-old(hero) {
animation: none;
}
::view-transition-new(hero) {
animation: none;
}
Anchor Positioning
/* Position tooltip relative to any element */
.trigger {
anchor-name: --trigger;
}
.tooltip {
position: absolute;
position-anchor: --trigger;
bottom: anchor(top); /* Align tooltip bottom to trigger top */
left: anchor(center);
translate: -50% -0.5rem;
}
/* Automatic overflow handling */
.dropdown {
position-try-fallbacks: flip-block, flip-inline, flip-block flip-inline;
}
CSS Grid Advanced Patterns
/* Subgrid — child grids align to parent columns */
.card-grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 1rem;
}
.card {
display: grid;
grid-row: span 3;
grid-template-rows: subgrid; /* Inherit parent row sizing */
}
/* All cards: title, description, and button align perfectly */
.card .title { grid-row: 1; }
.card .body { grid-row: 2; }
.card .footer { grid-row: 3; margin-top: auto; }
/* Masonry-style layout */
.masonry {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
grid-template-rows: masonry; /* Experimental but shipping 2026 */
}
Browser Support Summary (2026)
| Feature | Chrome | Firefox | Safari | Global |
|---|---|---|---|---|
| Container Queries | ✓ 105+ | ✓ 110+ | ✓ 16+ | 93% |
:has() | ✓ 105+ | ✓ 121+ | ✓ 15.4+ | 90% |
| CSS Nesting | ✓ 120+ | ✓ 117+ | ✓ 17.2+ | 88% |
| Scroll Animations | ✓ 115+ | ✓ 110+ | Partial | 75% |
| View Transitions | ✓ 111+ | Partial | ✓ 18+ | 82% |
| Anchor Positioning | ✓ 125+ | Partial | Partial | 70% |
Modern CSS reduces the need for JavaScript by 30-40% for UI interactions. Start with container queries and :has() today — they solve real layout problems.
Advertisement