CSS in 2026 has reached a maturity level that's making many JavaScript libraries obsolete. Let's explore the native CSS features now supported across all browsers.
Anchor Positioning
No more Popper.js or Floating UI for tooltips and dropdowns:
.trigger {
anchor-name: --my-anchor;
}
.tooltip {
position: absolute;
position-anchor: --my-anchor;
/* Position relative to anchor */
bottom: anchor(top);
left: anchor(center);
/* Automatic fallback positioning */
position-try-fallbacks: flip-block, flip-inline;
position-try-order: most-height;
}
Container Queries
Responsive components based on container size, not viewport:
.card-container {
container-type: inline-size;
container-name: card;
}
@container card (min-width: 400px) {
.card {
display: grid;
grid-template-columns: 1fr 2fr;
}
}
@container card (min-width: 600px) {
.card {
grid-template-columns: 1fr 1fr 1fr;
}
}
Scroll-Driven Animations
CSS-only scroll animations without Intersection Observer:
@keyframes fade-in {
from {
opacity: 0;
transform: translateY(50px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
.animate-on-scroll {
animation: fade-in linear both;
animation-timeline: view();
animation-range: entry 0% entry 100%;
}
/* Parallax effect */
.parallax {
animation: parallax linear;
animation-timeline: scroll();
}
@keyframes parallax {
to {
transform: translateY(-100px);
}
}
View Transitions
Native page transitions:
@view-transition {
navigation: auto;
}
/* Name elements to animate between pages */
.hero-image {
view-transition-name: hero;
}
/* Customize the transition */
::view-transition-old(hero) {
animation: fade-out 0.3s ease;
}
::view-transition-new(hero) {
animation: fade-in 0.3s ease;
}
Subgrid
True nested grid alignment:
.parent {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 1rem;
}
.child {
display: grid;
grid-template-columns: subgrid;
grid-column: span 3;
}
Color Functions
Modern color manipulation in CSS:
:root {
/* OKLCH for perceptually uniform colors */
--brand: oklch(65% 0.25 250);
/* Relative color syntax */
--brand-light: oklch(from var(--brand) calc(l + 20%) c h);
--brand-dark: oklch(from var(--brand) calc(l - 20%) c h);
/* Color mixing */
--brand-muted: color-mix(in oklch, var(--brand), gray 30%);
}
:has() Selector
Parent selectors are finally here:
/* Style parent based on child state */
.form-group:has(input:invalid) {
border-color: red;
}
/* Previous sibling styling */
h2:has(+ p) {
margin-bottom: 0.5rem;
}
/* Card with image vs without */
.card:has(img) {
grid-template-rows: auto 1fr;
}
Nesting
Native CSS nesting without preprocessors:
.card {
padding: 1rem;
& .title {
font-size: 1.5rem;
&:hover {
color: var(--brand);
}
}
@media (width >= 768px) {
padding: 2rem;
}
}
What This Means
JavaScript libraries becoming obsolete:
| Use Case | Old Solution | Native CSS |
|---|---|---|
| Tooltips | Floating UI | Anchor Positioning |
| Scroll Effects | GSAP ScrollTrigger | scroll-timeline |
| Page Transitions | Framer Motion | View Transitions |
| Responsive Components | ResizeObserver | Container Queries |
| Color Manipulation | Chroma.js | oklch, color-mix() |
CSS in 2026 is incredibly powerful. Time to reduce those JavaScript dependencies!
Posted oncsswith tags: