5 Modern CSS Breakthroughs That Transform How You Build Block Themes
Block theme development has changed dramatically. If you’re still weighing whether to migrate from classic to block themes, the CSS story alone should convince you. Native nesting, container queries, :has(), cascade layers, and subgrid are no longer experimental — they’re baseline browser features with full support across Chrome, Firefox, Safari, and Edge.
For WordPress block theme developers specifically, these features solve real problems: responsive components that adapt to their container instead of the viewport, parent-aware styling without JavaScript, and cascade control that tames specificity conflicts between theme.json styles and custom CSS.
This guide covers five modern CSS techniques with practical examples you can use in block themes today.
1. CSS Nesting: Cleaner Block Theme Stylesheets
Native CSS nesting eliminates the need for preprocessors like Sass in most block theme projects. You can nest selectors directly in your stylesheets, making your code more readable and easier to maintain.
How It Works
Instead of repeating parent selectors, nest them using the & selector:
/* Traditional CSS */
.wp-block-group { padding: 2rem; }
.wp-block-group .wp-block-heading { margin-bottom: 1rem; }
.wp-block-group .wp-block-paragraph { line-height: 1.8; }
/* Native CSS Nesting */
.wp-block-group {
padding: 2rem;
.wp-block-heading {
margin-bottom: 1rem;
}
.wp-block-paragraph {
line-height: 1.8;
}
}
Block Theme Application
Nesting is particularly useful for block style variations. When you register custom styles for core blocks, nesting keeps the CSS organized:
/* Block style variation: "card" for the Group block */
.wp-block-group.is-style-card {
background: var(--wp--preset--color--base);
border-radius: 12px;
box-shadow: 0 2px 8px rgb(0 0 0 / 0.08);
padding: var(--wp--preset--spacing--40);
.wp-block-heading {
font-size: var(--wp--preset--font-size--large);
margin-bottom: var(--wp--preset--spacing--20);
}
.wp-block-button .wp-block-button__link {
border-radius: 8px;
}
&:hover {
box-shadow: 0 4px 16px rgb(0 0 0 / 0.12);
}
}
WordPress 6.2+ also supports the & selector in theme.json custom CSS, so you can use nesting directly in the Global Styles interface.
2. Container Queries: Component-Level Responsiveness
Container queries are arguably the biggest CSS advancement for block theme development. Instead of styling based on the viewport width (which you can’t control in the block editor), you style based on the container’s size.
This matters for block themes because blocks can appear in different layout contexts — a full-width content area, a narrow sidebar, a column layout, or a query loop grid. The same block needs to look good in all of them.
Setting Up Container Queries
/* Define a containment context */
.wp-block-column,
.wp-block-group {
container-type: inline-size;
}
/* Style a post card based on its container width */
.wp-block-post-template .wp-block-post {
display: grid;
gap: 1rem;
@container (min-width: 500px) {
grid-template-columns: 200px 1fr;
align-items: start;
}
@container (min-width: 700px) {
grid-template-columns: 300px 1fr;
}
}
Why This Beats Media Queries for Block Themes
Consider a post card component used in a Query Loop block. With media queries, you’d write responsive styles based on the viewport. But if that same Query Loop appears inside a Columns block (say, in a 2/3 + 1/3 layout), the viewport-based breakpoints are wrong — the column is narrower than the viewport.
Container queries fix this by making the component respond to its actual available space. The post card automatically switches between stacked and horizontal layouts based on the column width, not the screen width. As noted by Builder.io’s CSS guide, this enables truly modular, reusable components.
3. The :has() Selector: Parent-Aware Block Styling
The :has() selector lets you style a parent element based on its children. This was impossible in CSS before — you needed JavaScript for any parent-aware styling. For block themes, this unlocks conditional layouts without a single line of PHP or JS.
Practical Block Theme Examples
/* Style a Group block differently when it contains an image */
.wp-block-group:has(.wp-block-image) {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 2rem;
align-items: center;
}
/* Adjust spacing when a heading is followed by a separator */
.wp-block-heading:has(+ .wp-block-separator) {
margin-bottom: 0.5rem;
}
/* Add visual indicator to columns that contain a CTA button */
.wp-block-column:has(.wp-block-button) {
border-left: 3px solid var(--wp--preset--color--primary);
padding-left: var(--wp--preset--spacing--30);
}
/* Hide the featured image placeholder when no image exists */
.wp-block-post-featured-image:has(img) {
display: block;
}
.wp-block-post-featured-image:not(:has(img)) {
display: none;
}
Combining :has() with theme.json
You can use :has() in theme.json’s custom CSS section to create conditional block styles that work in the editor and on the frontend. For example, automatically applying a two-column layout when a Group block contains both text and an image — something that previously required a custom block variation or JavaScript.
4. Cascade Layers: Taming Specificity in Block Themes
If you’ve ever fought with WordPress’s default block styles overriding your theme CSS, or your theme CSS being overridden by a plugin, cascade layers (@layer) are the solution.
Cascade layers let you explicitly define the order of CSS precedence, regardless of selector specificity or source order. This is transformative for WordPress where styles come from multiple sources: core blocks, theme.json, custom stylesheets, and plugins.
Structuring Block Theme Layers
/* Define layer order: later layers win */
@layer wordpress-defaults, theme-base, theme-blocks, theme-utilities, customizations;
/* WordPress core block styles */
@layer wordpress-defaults {
/* Core block margins, fonts, colors */
.wp-block-paragraph { margin-bottom: 1.5em; }
}
/* Your theme's base design tokens */
@layer theme-base {
:root {
--card-radius: 12px;
--card-shadow: 0 2px 8px rgb(0 0 0 / 0.08);
}
}
/* Block-specific theme styles */
@layer theme-blocks {
.wp-block-group.is-style-card {
border-radius: var(--card-radius);
box-shadow: var(--card-shadow);
}
}
/* Utility overrides */
@layer theme-utilities {
.has-text-align-center { text-align: center; }
.is-visually-hidden { clip: rect(0, 0, 0, 0); }
}
/* User customizations always win */
@layer customizations {
/* Custom CSS from Site Editor goes here */
}
With this structure, your theme-block styles always override WordPress defaults without needing !important or artificially high specificity selectors. User customizations from the Site Editor always override your theme. No more specificity wars.
5. CSS Subgrid: Aligned Block Layouts
Subgrid solves a problem every block theme developer knows: aligning child elements across sibling blocks. Think of a row of cards where each card has a title, description, and button — you want all the titles to align, all the descriptions to align, and all the buttons to sit at the bottom, regardless of content length.
Without subgrid, you’d use fixed heights (fragile), flexbox with grow (doesn’t truly align), or JavaScript (overkill). Subgrid makes it pure CSS, and it’s now supported across all major browsers.
Subgrid for Post Card Grids
/* Parent grid: the Query Loop layout */
.wp-block-post-template {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 2rem;
}
/* Each post card inherits the parent grid's row tracks */
.wp-block-post-template .wp-block-post {
display: grid;
grid-template-rows: subgrid;
grid-row: span 4; /* title, image, excerpt, button */
gap: 1rem;
}
/* Now all titles align, all excerpts align, all buttons align */
.wp-block-post-template .wp-block-post .wp-block-post-title {
align-self: end;
}
.wp-block-post-template .wp-block-post .wp-block-button {
align-self: end;
}
This creates perfectly aligned card grids without any JavaScript or fixed heights. The browser handles alignment automatically, even when one card has a three-line title and another has a single line.
Integrating Modern CSS with theme.json
The power of these techniques multiplies when you combine them with WordPress’s theme.json styling system. If you haven’t yet, read our complete theme.json configuration guide first. Here’s how to structure your approach:
Design Tokens in theme.json, Layout Logic in CSS
Use theme.json for design tokens (colors, spacing, typography, shadows) and CSS for layout logic that theme.json can’t express:
// theme.json - design tokens
{
"version": 3,
"settings": {
"custom": {
"card": {
"radius": "12px",
"shadow": "0 2px 8px rgb(0 0 0 / 0.08)",
"padding": "var(--wp--preset--spacing--40)"
}
}
}
}
/* style.css - layout logic using theme.json tokens */
.wp-block-group.is-style-card {
border-radius: var(--wp--custom--card--radius);
box-shadow: var(--wp--custom--card--shadow);
padding: var(--wp--custom--card--padding);
container-type: inline-size;
@container (max-width: 400px) {
padding: var(--wp--preset--spacing--20);
}
}
This way, users can customize the visual tokens in the Site Editor while the layout logic remains consistent.
Per-Block CSS in theme.json
WordPress lets you add custom CSS directly to specific blocks through theme.json. This is the right place for block-specific overrides that use modern CSS:
// theme.json - per-block custom CSS
{
"styles": {
"blocks": {
"core/post-template": {
"css": ".wp-block-post { container-type: inline-size; }"
},
"core/columns": {
"css": "&:has(.wp-block-column:only-child) { max-width: 720px; margin-inline: auto; }"
}
}
}
}
Browser Support and Fallback Strategy
As of February 2026, all five techniques covered in this article have baseline support across modern browsers:
- CSS Nesting — Chrome 120+, Firefox 117+, Safari 17.2+
- Container Queries — Chrome 105+, Firefox 110+, Safari 16+
- :has() Selector — Chrome 105+, Firefox 121+, Safari 15.4+
- Cascade Layers — Chrome 99+, Firefox 97+, Safari 15.4+
- Subgrid — Chrome 117+, Firefox 71+, Safari 16+
For block themes, the fallback strategy is straightforward. WordPress’s minimum browser requirements already cover these features. If you’re building a new block theme in 2026, you can use all five techniques without polyfills.
For themes that need to support older browsers, use @supports to progressively enhance:
/* Base layout works everywhere */
.card-grid { display: flex; flex-wrap: wrap; gap: 2rem; }
/* Enhanced layout for modern browsers */
@supports (container-type: inline-size) {
.card-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
}
.card-grid > * { container-type: inline-size; }
}
Start Using These Today
Modern CSS isn’t experimental anymore. These five techniques are production-ready and solve real problems in block theme development:
- CSS Nesting replaces Sass for cleaner, maintainable stylesheets
- Container Queries make blocks truly responsive regardless of layout context
- :has() enables conditional styling without JavaScript
- Cascade Layers end specificity wars between core, theme, and plugin styles
- Subgrid creates perfectly aligned card grids without hacks
The block themes we build at Brndle use all five techniques. The result is cleaner code, fewer workarounds, better performance, and themes that adapt naturally to any layout context the Site Editor throws at them.