The State of CSS in 2025
The CSS landscape has transformed dramatically. Features that were once experimental or required preprocessors like Sass are now native to CSS itself, with browser support exceeding 90% across modern browsers. Modern CSS offers unprecedented power for building responsive, maintainable layouts without relying on complex build configurations or JavaScript workarounds.
This guide covers the essential features and best practices every modern web developer should master for clean, performant stylesheets.
Modern CSS Features You Should Be Using
Powerful features now available without preprocessors
Native CSS Nesting
Group related styles without Sass. Use the & parent selector for clean, readable selectors.
Subgrid
Align nested elements with parent grid tracks. Perfect for card layouts and form alignment.
Container Queries
Style components based on their container size, not the viewport. Enable truly reusable components.
:has() Selector
The breakthrough 'parent selector' - style elements conditionally based on their children.
Native CSS Nesting
Native CSS nesting eliminates the need for preprocessor nesting while offering the same organizational benefits. The & parent selector makes your intentions explicit and your stylesheets more maintainable.
Key patterns:
- Use & for pseudo-classes and pseudo-elements
- Nest child selectors naturally
- Avoid deep nesting chains for readability
1.card {2 padding: 1rem;3 4 &:hover {5 background: #f0f0f0;6 }7 8 &:focus-within {9 outline: 2px solid blue;10 }11 12 .title {13 font-weight: bold;14 font-size: 1.25rem;15 }16 17 .content {18 color: #333;19 }20}1.card {2 container-type: inline-size;3}4 5@container (min-width: 400px) {6 .card-content {7 display: flex;8 gap: 1rem;9 }10 11 .card-image {12 flex: 0 0 120px;13 }14}15 16@container (min-width: 600px) {17 .card-content {18 flex-direction: row;19 }20}Container Queries
Container queries revolutionize component-based design by allowing components to respond to their parent container's size rather than the viewport. This enables truly reusable, responsive components that work in any context.
Implementation:
- Set container-type on the parent
- Use @container for responsive rules
- Combine with CSS Grid and Flexbox
Use cases:
- Card components in different sized grid cells
- Navigation menus in sidebars vs headers
- Product cards in featured vs listing views
1/* Style card if it contains an image */2.card:has(img) {3 border: 1px solid purple;4}5 6/* Highlight form group when focused */7.form-group:focus-within {8 outline: 2px solid #7f5af0;9 box-shadow: 0 0 8px rgba(127, 90, 240, 0.3);10}11 12/* Style section with visible warnings */13.section:has(.warning) {14 background: #fff3cd;15}16 17/* Hide parent when child is hidden */18.item:has(.hidden) {19 display: none;20}The :has() Parent Selector
The :has() pseudo-class is a game-changer, enabling conditional styling based on child elements--something that was previously impossible without JavaScript. This breakthrough feature, now supported in all modern browsers, opens new possibilities for responsive and conditional styling patterns.
Practical applications:
- Highlight forms with invalid inputs
- Style cards containing images differently
- Show/hide elements based on content
- Create responsive layouts that adapt to their children
CSS Layers with @layer
CSS Layers give you explicit control over specificity without fighting with selector wars. Declare layer order upfront and let CSS handle the cascade intelligently. This is particularly valuable when integrating third-party CSS or managing large design systems.
Layer benefits:
- Predictable cascade behavior
- Easy third-party CSS integration
- Clean override patterns
Layer strategy:
- Reset/normalize (base layer)
- Design system tokens (tokens layer)
- Component styles (components layer)
- Utilities (utilities layer)
@layer base, components, utilities;
@layer base {
body { margin: 0; font-family: system-ui; }
}
@layer components {
.btn { padding: 0.5rem 1rem; border-radius: 4px; }
}
@layer utilities {
.text-center { text-align: center; }
}
CSS Performance Optimization
Optimization Techniques
Minification & Compression Remove all formatting whitespace and comments. Combined with gzip/Brotli compression, this can reduce CSS file size by 60% or more. Modern build tools like Tailwind CSS and Next.js handle this automatically in production builds.
Critical CSS Extract styles needed for above-the-fold content and inline them in the HTML head. Defer the remaining styles asynchronously. This technique can improve First Contentful Paint (FCP) significantly.
Remove Unused CSS Over time, stylesheets accumulate dead code. Use tools like PurgeCSS or the built-in optimization in Tailwind to analyze HTML/JS and remove unreferenced selectors automatically.
Preload Critical CSS Add preload links in your HTML head to prioritize critical stylesheets:
<link rel="preload" href="/styles/main.css" as="style">
Efficient Selectors
Browsers evaluate selectors from right to left. Complex, deeply nested selectors force the browser to do extra work before finding a match. According to MDN's CSS Performance guide, keeping selectors simple and avoiding over-qualification is crucial for rendering performance.
Inefficient:
body #sidebar ul li .nav-link { color: blue; }
Efficient:
.sidebar-nav-link { color: blue; }
Best practices:
- Prefer classes over element selectors
- Avoid the universal selector (*) in production
- Keep specificity low and flat
- Use semantic HTML to reduce selector depth
- Consider using [data-*] attributes sparingly
1.card {2 contain: layout;3 contain-intrinsic-size: 300px 200px;4}5 6.widget {7 contain: layout style;8 contain-intrinsic-size: 400px auto;9}10 11.feed-item {12 contain: layout paint;13 contain-intrinsic-size: auto 100px;14}CSS Containment
The contain property and contain-intrinsic-size tell the browser that an element's layout, style, or size won't affect its ancestors. As documented in the MDN CSS Performance guide, this prevents unnecessary recalculations and stabilizes layout for dynamic content.
Contain values:
- layout: Element doesn't affect ancestors' layout
- style: Element doesn't affect ancestors' style calculations
- paint: Element is invisible outside its bounds
contain-intrinsic-size reserves space for elements with dynamic content, preventing Cumulative Layout Shift (CLS) and improving Core Web Vitals scores. This is especially valuable for components that load data asynchronously.
Animation Performance
GPU-Friendly Animations
Animating properties like width, height, margin, or top forces the browser to recalculate the layout of the entire page (reflow), which is expensive. Instead, animate properties that can be handled by the GPU for smoother 60fps performance. This is a key technique for building performant web applications that feel responsive.
For smooth, natural-feeling animations, understanding easing functions is essential--they control the timing curve of your transitions.
GPU-accelerated properties:
- transform (translate, scale, rotate)
- opacity
Layout-triggering properties (avoid):
- width, height, margin, padding
- top, left, right, bottom
- font-size, line-height
- border-width
1/* ❌ Costly: Triggers reflow */2.box {3 transition: width 0.3s ease;4}5 6/* ✅ Efficient: GPU compositing */7.box {8 transition: transform 0.3s ease;9}10 11.box:hover {12 transform: scale(1.05);13}14 15/* ✅ Use transform for all animations */16.btn {17 transition: transform 0.2s,18 opacity 0.2s;19}20 21.btn:hover {22 transform: translateY(-2px);23 opacity: 0.9;24}25 26/* ✅ Respect user preferences */27@media (prefers-reduced-motion: reduce) {28 * {29 animation-duration: 0.01ms !important;30 transition-duration: 0.01ms !important;31 }32}Best Practices Checklist
Use this checklist when building modern CSS for your web projects:
Architecture
- Use native CSS nesting instead of preprocessor nesting
- Organize with @layer for large codebases
- Keep selectors simple and specific
- Use CSS Modules or similar for component isolation
Performance
- Minify and compress production CSS
- Extract critical CSS for above-the-fold content
- Remove unused styles with automated tools
- Preload critical CSS assets
Animations
- Animate only transform and opacity
- Use will-change sparingly and strategically
- Respect prefers-reduced-motion for accessibility
- Test on lower-end devices
Responsive Design
- Use container queries for components
- Implement mobile-first approach
- Use clamp() for fluid typography
- Test at real device breakpoints
Maintenance
- Document design tokens and global styles
- Use consistent naming conventions (BEM or similar)
- Keep stylesheets modular and organized
- Review and refactor periodically
For fluid typography and spacing, explore how min(), max(), and clamp() can simplify your responsive design workflow.
Frequently Asked Questions
Do I still need Sass or other CSS preprocessors?
Native CSS nesting, CSS custom properties (variables), and modern layout capabilities have replaced many preprocessor features. You may still want Sass for advanced mixins or module systems, but many projects now work fine with vanilla CSS. The key is evaluating your team's specific needs.
How do container queries differ from media queries?
Media queries respond to the viewport size, while container queries respond to the parent container's size. Container queries enable truly reusable components that adapt to their container context rather than the page layout. This is essential for component-based architectures.
What's the best way to handle CSS in Next.js?
Next.js supports CSS Modules for component-scoped styles and global CSS for application-wide styles. Use CSS Modules by default for component isolation, and be mindful of the order global styles are loaded to avoid specificity issues. Tailwind CSS is also well-integrated with Next.js for utility-first styling.
How do I measure CSS performance impact?
Use browser DevTools: the Coverage panel shows unused CSS, the Performance Monitor tracks layout recalculations, and the Network waterfall shows render-blocking CSS. Focus on Critical CSS extraction and unused code removal for the biggest performance improvements.