Responsive Design in Block Themes: Fluid Typography and Spacing with theme.json

Fixed font sizes and static spacing values break the moment a visitor resizes their browser window. On a 1440px monitor, your carefully chosen 48px heading looks commanding. On a 375px phone screen, that same heading dominates the viewport, pushing content below the fold and forcing horizontal scrolling on long words.

Block themes solve this with fluid typography and fluid spacing, values that scale smoothly between a minimum and maximum based on the viewport width. Instead of writing dozens of media queries, you define your constraints in theme.json and let WordPress generate the CSS clamp() functions that handle every screen size in between.

This guide covers everything you need to build a fully responsive block theme using fluid values: how clamp() works under the hood, how to configure fluid typography and spacing in theme.json, responsive layout controls, container queries for block-level responsiveness, complete working examples, testing strategies, common pitfalls, and the improvements landing in WordPress 6.9.

How Fluid Typography Works: The clamp() Function

Before configuring anything in theme.json, you need to understand the CSS function that powers fluid values. The clamp() function takes three arguments and returns a value that stays within a defined range:

Here is what each argument does:

  • Minimum, The smallest the value can ever be. On the narrowest screens, this is the floor.
  • Preferred, A fluid calculation (usually viewport-based) that scales between the min and max. This is where the magic happens.
  • Maximum, The largest the value can ever be. On the widest screens, this is the ceiling.

For fluid typography, a practical clamp() value looks like this:

Breaking that down: the font size will never go below 1rem (16px at default root size), never exceed 2.25rem (36px), and will scale fluidly between those values using the calculation 0.5rem + 1.5vw. As the viewport grows, 1.5vw contributes more, pushing the size toward the maximum. As the viewport shrinks, it contributes less, pulling the size toward the minimum.

The preferred value formula follows this pattern:

WordPress generates this formula for you when you enable fluid typography in theme.json. You define the minimum and maximum font sizes, and WordPress calculates the preferred value targeting a viewport range of 768px to 1600px by default.

Why clamp() Beats Media Queries

The traditional approach to responsive typography looks like this:

The media query approach creates discrete jumps. At 599px the heading is 1.5rem, then it snaps to 2rem at 600px. Users see abrupt changes during resize, and you must manage every breakpoint manually. The clamp() approach produces a smooth, continuous scale with no jumps and no breakpoints to maintain.

Here is a comparison at different viewport widths showing the difference in behavior:

Viewport Width Media Query Approach Fluid clamp() Approach
375px (mobile) 1.5rem (24px) 1.5rem (24px), at minimum
599px 1.5rem (24px) 1.75rem (28px), scaling
600px 2rem (32px), jumps! 1.75rem (28px), smooth
768px 2rem (32px) 1.96rem (31.4px), scaling
1024px 2.5rem (40px) 2.28rem (36.5px), scaling
1200px 3rem (48px), jumps! 2.5rem (40px), scaling
1600px 3rem (48px) 3rem (48px), at maximum

The fluid approach also generates far less CSS. Instead of potentially dozens of media query rules across your entire type scale, you get a single clamp() declaration per font size preset. With a typical 7-step type scale, that is 7 lines instead of potentially 28 or more.


Configuring Fluid Typography in theme.json

WordPress introduced fluid typography support in version 6.1. The configuration lives in settings.typography within your theme.json file. There are two parts: enabling the fluid system globally and defining fluid parameters for each font size preset.

Enabling the Fluid Engine

First, enable fluid typography at the global level:

Setting "fluid": true tells WordPress to automatically generate clamp() values for any font size preset that qualifies. By default, WordPress uses a viewport range of 768px (minimum) to 1600px (maximum) for calculating the fluid scale.

You can customize that viewport range:

This tells WordPress to start the fluid scaling at 320px and reach the maximum value at 1440px. Below 320px the font stays at its minimum. Above 1440px it stays at its maximum. Adjusting these values changes the slope of the fluid scale, a narrower range produces more aggressive scaling, a wider range produces gentler scaling.

Defining Fluid Font Sizes

Each font size preset in your fontSizes array can include a fluid property with explicit minimum and maximum values:

The size property serves as the fallback for browsers that do not support clamp() (extremely rare today, but good practice). The fluid.min and fluid.max values define the actual range WordPress uses to generate the clamp() function.

WordPress generates CSS custom properties for each preset. If you want to understand how CSS custom properties fit into the broader block theme architecture, see our guide on using CSS custom properties in block themes for scalable styling. For the configuration above, the output looks like this:

Notice how the smaller sizes have gentler scaling (small range between min and max) while the larger sizes have more dramatic scaling. This is intentional, body text should remain relatively stable across viewports, while headings need to shrink significantly on mobile to avoid overflow.

Disabling Fluid for Specific Sizes

Sometimes you want certain sizes to remain fixed regardless of viewport. Set "fluid": false on individual presets to opt them out:

This is particularly useful for small UI text like captions, labels, or button text where fluid scaling would make the text illegibly small on mobile devices.


Fluid Spacing Presets in theme.json

Fluid spacing follows the same principle as fluid typography, values that scale smoothly between viewport sizes instead of jumping at breakpoints. WordPress added fluid spacing support in version 6.1 through the settings.spacing.spacingSizes property.

Defining Fluid Spacing Sizes

The spacing presets accept the same fluid property structure as font sizes. Here is a complete spacing scale with fluid values:

This generates CSS custom properties that scale fluidly:

The spacing presets are available in the block editor’s spacing controls. When users adjust padding, margin, or block gap using the spacing options, they pick from these fluid presets rather than entering fixed pixel values.

Using Spacing Presets in Styles

Reference spacing presets throughout your theme.json styles section using the var:preset|spacing|{slug} syntax:

Because these reference fluid presets, every spacing value in your theme scales proportionally. Wide sections get generous padding on desktop that tightens appropriately on mobile. Column gaps reduce to prevent cramped layouts on small screens. The entire spatial rhythm of your theme adapts without a single media query.

Spacing Scale vs. Custom Spacing Sizes

WordPress also offers settings.spacing.spacingScale, an automatic scale generator. However, spacingSizes with explicit fluid values gives you full control. The auto-generated scale does not support fluid min/max per step. If responsive spacing matters to your theme (it should), define spacingSizes manually with fluid parameters rather than relying on the auto scale.


Responsive Layout Controls

Layout configuration in theme.json controls how content containers behave across screen sizes. The key settings are contentSize and wideSize, which define the default and wide-alignment maximum widths for your content area.

contentSize sets the maximum width for default-aligned blocks, paragraphs, headings, lists, and any block without explicit width alignment. wideSize sets the maximum width for blocks using the “wide” alignment option, like full-width images or wide group blocks.

Both values act as max-width constraints, meaning they naturally respond to smaller viewports. A paragraph constrained to 720px will never exceed that width but will shrink freely on screens narrower than 720px. No additional responsive handling is needed for the content width itself.

Combining Layout with Fluid Padding

The real responsiveness comes from combining layout sizes with fluid root padding. The root padding controls the space between the content and the edge of the viewport:

The useRootPaddingAwareAlignments setting is critical. When enabled, WordPress applies the root padding to the content container and allows full-width aligned blocks to break out of it, spanning the full viewport. Without this setting, full-width blocks would be constrained by the root padding.

Because we referenced var:preset|spacing|50 for horizontal padding, a fluid preset, the root padding scales with the viewport. On desktop, the content sits within generous margins. On mobile, those margins tighten to maximize content space. The content itself flows naturally within the contentSize constraint.

Here is what the effective content area looks like at different widths:

Viewport Width Root Padding (each side) Available Content Width Effective Content Width
375px 20px (fluid min) 335px 335px (no max-width constraint)
768px 26px (scaling) 716px 716px (at contentSize limit)
1024px 30px (scaling) 964px 720px (contentSize max-width applies)
1440px 32px (fluid max) 1376px 720px (contentSize max-width applies)

Per-Block Layout Overrides

You can override layout behavior for specific blocks. For example, giving the post content area a different content size or adjusting spacing within columns:

Cover blocks get extra vertical padding using the large fluid spacing preset, spacious on desktop, compact on mobile. Group blocks and post content use medium spacing for their block gap, keeping vertical rhythm consistent and responsive.


Container Queries and Blocks

Viewport-based fluid values handle most responsive needs, but they have a limitation: they respond to the browser window width, not the width of the container a block sits in. A paragraph inside a narrow sidebar column gets the same fluid font size as a paragraph in the main content area, even though the available space is drastically different.

Container queries solve this by letting you style elements based on their parent container’s dimensions rather than the viewport. CSS container queries use the @container rule and require a containment context to be established on the parent element.

How Container Queries Work

The setup requires two parts: declaring a container on the parent, and writing query rules for the children.

Now the heading inside a column responds to the column’s width, not the viewport. A 3-column layout where each column is roughly 33% of the content area will trigger the narrow container query, even on a wide desktop screen. If the user switches to a single-column layout, the wider container queries take effect.

Container Query Units for Fluid Values

Container queries also introduce container query length units, cqw, cqh, cqi, cqb, cqmin, and cqmax. These work like viewport units but relative to the container. You can use them inside clamp() for truly container-responsive fluid values:

The cqi unit represents 1% of the container’s inline size (width in horizontal writing modes). This gives you smooth, container-aware fluid scaling that works regardless of how many columns the user adds or what width the parent container happens to be.

Applying Container Queries in Block Themes

Since theme.json does not yet have native container query support, you implement them in your theme’s style.css or a block-specific stylesheet. The most practical blocks to target for container queries are:

  • core/column, Individual columns within a columns block. Their width varies based on the number of columns and any custom width settings.
  • core/group, Groups used as layout containers, especially when nested inside columns or sidebars.
  • core/query, Query loop containers where post cards display in grid layouts that change density.
  • core/navigation, Navigation blocks that collapse or expand based on available space.

Here is a practical example for a block theme stylesheet that makes the query loop responsive at the container level:

This approach is far more robust than viewport-based media queries because the query loop adapts to its actual available space. Place it in a full-width template and it uses three columns. Put it in a sidebar-constrained area and it drops to one or two columns. The container, not the viewport, dictates the layout.


Complete theme.json for a Fully Responsive Block Theme

Here is a production-ready theme.json that combines all the responsive techniques covered above, fluid typography, fluid spacing, responsive layout, and properly referenced styles. For a walkthrough on controlling which block settings appear in the editor, check out how to define block settings in theme.json:

This configuration creates a complete responsive system. The typography scales from mobile to desktop using the 375px-1440px viewport range. Spacing presets scale proportionally. Layout uses contentSize and wideSize for content width constraints with fluid root padding. Heading margins use spacing presets to maintain vertical rhythm that adapts to the viewport. Code blocks use the small fluid font size and padded with responsive spacing. Every value in the system responds to the screen size without a single media query.


Testing Fluid Values Across Screen Sizes

Fluid typography and spacing need careful testing because the scaling behavior is continuous, problems can appear at viewport widths you might not think to check. Here is a systematic testing approach for block themes.

Browser DevTools Responsive Mode

Every modern browser’s developer tools include a responsive design mode. Instead of checking just a few preset device sizes, slowly drag the viewport width from your minimum (375px) to your maximum (1440px) and watch the text and spacing change in real time. Look for:

  • Text that becomes unreadably small at any point in the range
  • Headings that overflow their containers during the transition
  • Spacing that collapses too aggressively, causing elements to touch
  • Spacing that remains too large on mobile, wasting screen space
  • Line lengths that exceed 75 characters at any viewport width (hurts readability)

Computed Values Inspection

Inspect specific elements in DevTools and check the computed values tab. You should see clamp() functions in the specified styles and resolved pixel values in the computed output. Verify that the computed value at different viewport widths matches your expectations.

Use this CSS snippet in your browser console to display computed font sizes for all heading levels on the current page:

Critical Viewport Widths to Check

Focus your testing on these specific widths:

Width Why It Matters What to Check
320px Smallest common mobile All text readable, nothing overflows
375px iPhone SE / fluid min point Font sizes at their defined minimums
428px iPhone Pro Max Comfortable reading, good line lengths
768px iPad portrait / default WP fluid min Typography scaling smoothly, not too small
1024px iPad landscape / small laptops Content width constraints active, proper spacing
1280px Common laptop width Good balance, not too small, not too large
1440px Fluid max point Font sizes at their defined maximums
1920px Full HD desktop Values stay at max, content centered properly
2560px QHD / large monitors No excessive whitespace, content not tiny

The Site Editor Preview

WordPress includes device preview buttons in the Site Editor (desktop, tablet, mobile icons in the top bar). While these offer a quick check, they simulate viewport widths rather than truly resizing the browser. Always verify with real browser responsive mode for accurate results, especially for clamp() values that depend on the true viewport width.


Common Pitfalls and How to Avoid Them

Fluid typography and spacing are powerful, but several common mistakes can produce results that look worse than static values. Watch for these issues in your theme development.

1. Minimum Font Sizes That Are Too Small

Setting aggressive minimums to maximize the fluid range is tempting, but body text below 14px becomes difficult to read on mobile devices, and headings below 18px lose their visual hierarchy.

A safe rule: body text minimums should never drop below 0.875rem (14px). For headings, maintain at least a 1.2x ratio between adjacent levels at their minimum sizes to preserve the visual hierarchy.

2. Broken Type Scale Ratios

Your type scale should maintain a consistent ratio between sizes at both the minimum and maximum ends. If your max sizes follow a 1.25 ratio (Major Third) but your min sizes follow random increments, the hierarchy will feel inconsistent on different screens.

Use a type scale calculator to define both your min and max scales, then map them to your theme.json presets. Tools like Utopia (utopia.fyi) generate fluid type scales with consistent ratios at both ends of the viewport range.

3. Overly Aggressive Spacing Scaling

Large spacing presets with extreme min-to-max ratios can make layouts feel empty on desktop or cramped on mobile:

Keep the ratio between minimum and maximum spacing values below 2.5x for most presets. The largest preset in your scale might stretch to a 2x ratio, but smaller presets should stay under 1.5x to maintain visual stability.

4. Forgetting the Fallback Size

The size property in your font size and spacing presets serves as the fallback when fluid is not supported. Always set it to match your max value or the value you want at your design’s target viewport width:

5. Not Accounting for User Font Size Preferences

Using rem units in your fluid values respects the user’s browser font size setting. If a user sets their default to 20px instead of 16px, all your rem-based values scale up proportionally. This is correct behavior for accessibility.

However, mixing px and rem in your clamp() values can create unexpected results when users change their font size. Stick to rem for min and max values consistently. WordPress handles the viewport portion of the calculation using a mix of rem and vw, which works correctly.

6. Ignoring Line Length at Scale

Fluid font sizes change the number of characters per line at every viewport width. A line length that is perfect at 1024px might become too long at 1440px if the font size does not scale enough relative to the content width. Test your contentSize setting against your body font size across the full viewport range. The ideal line length is 45-75 characters. If any viewport width produces lines longer than 80 characters, either reduce your contentSize or increase your body font size minimum.


WordPress 6.9 Responsive Improvements

WordPress 6.9 brings several improvements to the fluid and responsive system in block themes. Here are the key changes relevant to theme developers.

Refined Fluid Typography Algorithm

The fluid typography engine in 6.9 uses an improved algorithm for calculating the preferred (middle) value of the clamp() function. The previous implementation could produce scaling curves that felt uneven, sizes would change rapidly in one viewport range and barely change in another. The updated algorithm produces a more linear, perceptually even scaling curve between the minimum and maximum viewport widths.

For most themes, this is a behind-the-scenes improvement. Your theme.json configuration stays the same, and WordPress generates better clamp() values from the same inputs. If you had previously hand-tuned your min/max values to compensate for uneven scaling, you may want to revisit them after updating to 6.9.

Improved Minimum Font Size Handling

WordPress 6.9 introduces smarter handling of the minimum font size threshold. When a font size preset does not define explicit fluid min/max values but fluid is enabled globally, WordPress auto-generates fluid values. In previous versions, this auto-generation could produce minimums that were too small for readability. The 6.9 algorithm applies a configurable floor to prevent auto-generated minimums from dropping below a readable threshold.

Better Support for Nested Fluid Contexts

Blocks inside constrained layouts (like columns or group blocks with max-width) now interact more predictably with fluid values. The style engine is more aware of layout context, ensuring that fluid values assigned at the block level account for the block’s constrained width rather than always referencing the viewport. This is a step toward native container query awareness in the block editor, though full container query support in theme.json remains a future goal.

Spacing Presets in the Editor UI

The spacing controls in the block editor have been refined for themes using custom spacingSizes. The range control now displays preset names and shows a visual preview of the spacing value. This makes it easier for content editors to understand the impact of their spacing choices and select the appropriate preset from your fluid scale.


Design Tokens: Building a Fluid System That Scales

The theme.json fluid system is essentially a design token system, named values with defined ranges that propagate through your entire theme via CSS custom properties. You can extend this further by creating style variations in theme.json that offer multiple design options while keeping the fluid system intact. To build a maintainable responsive theme, think in terms of these token relationships.

Establishing Your Base Scale

Start with your body font size and build outward. Every other value should derive from a ratio applied to the base:

Having systematic relationships between your values means changes propagate logically. If you adjust your base size, the entire system shifts proportionally. If you change your type scale ratio, every heading level recalculates consistently.

Mapping Tokens to Block Styles

Once your tokens are defined, map them to blocks using the theme.json styles section. This creates a layer of indirection, blocks reference tokens, tokens define the fluid range, and the system handles the responsive behavior:

Every block that references a fluid preset inherits responsive behavior automatically. You never specify how a quote block should behave at 768px or 1200px, the fluid token handles every viewport width in one declaration.


Fluid Values in Template Parts and Patterns

Your theme.json fluid system extends into template parts and block patterns. Any block within a template part or pattern that uses a preset font size or spacing value automatically gets the fluid behavior defined in your configuration.

Header Template Part Example

A typical header template part might use the site title block with a fluid font size and padded with fluid spacing:

The site title uses the x-large fluid font size, so it scales from 1.313rem on mobile to 1.75rem on desktop. The navigation uses the small fluid size. The group padding uses fluid spacing presets. Every value in this template part is responsive through the token system, no per-template-part media queries needed.

Hero Pattern Example

Block patterns benefit even more from fluid values because they are reusable components that appear in different contexts. A hero pattern with fluid values adapts whether it is placed on a landing page template or a narrow inner page template:

The hero’s xxx-large heading scales from 2.25rem on mobile to 3.75rem on desktop. The vertical padding uses the 80 spacing preset, scaling from 3.75rem to 7rem. On a phone, the hero is compact and readable. On a desktop, it is expansive and visually striking. Same markup, fully responsive.


Advanced Techniques: Custom Fluid Properties

Sometimes you need fluid values that go beyond what theme.json presets offer. For these cases, define custom CSS properties in your theme’s style.css that use the same clamp() approach.

Fluid Border Radius

Fluid Gap for Grid Layouts

Fluid Decorative Elements

These custom fluid properties complement your theme.json presets. The preset system handles typography, spacing, and layout. Custom properties handle everything else, borders, shadows, icon sizes, decorative elements. Together they create a theme where every visual dimension responds to the viewport.


Putting It All Together: The Responsive Block Theme Checklist

Before shipping a block theme with fluid values, verify each layer of your responsive system:

  1. Fluid typography enabled, settings.typography.fluid is set with appropriate viewport range
  2. Font size presets have fluid min/max, Every preset except those that should be fixed has explicit fluid.min and fluid.max values
  3. Type scale ratios are consistent, Both the min and max ends of your scale follow the same ratio (or a deliberate pair of ratios)
  4. Spacing presets are fluid, settings.spacing.spacingSizes includes fluid parameters for every step
  5. Root padding is fluid, styles.spacing.padding references a fluid spacing preset
  6. Root padding aware alignments enabled, useRootPaddingAwareAlignments is true
  7. Layout sizes defined, contentSize and wideSize produce good line lengths at all viewports
  8. Heading margins use spacing presets, Vertical rhythm adapts with the spacing system
  9. Block-level spacing uses presets, blockGap, padding, and margins reference fluid tokens
  10. Container queries where needed, Blocks in variable-width contexts (columns, sidebars, grids) use container queries for layout changes
  11. Tested at all critical viewports, 320px through 2560px with continuous drag testing
  12. Accessible minimum sizes, No body text below 14px, heading hierarchy maintained at minimums

This checklist represents the minimum standard for a production-quality responsive block theme. Each item addresses a specific failure mode that results in a poor experience at some viewport width.


Build Responsive Block Themes the Right Way

Fluid typography and spacing in theme.json represent a fundamental shift in how WordPress themes handle responsiveness. Instead of layering media queries on top of static values, you define constraints and let the browser calculate every intermediate state. The result is smoother, more maintainable, and produces better experiences across the infinite range of screen sizes your visitors use.

The key principles to carry forward: use clamp() through theme.json’s fluid system rather than writing the functions manually. Maintain consistent type scale ratios at both the min and max ends. Keep spacing scale ratios under 2.5x. Test by slowly dragging the viewport, not just checking preset device widths. Use container queries for blocks that live in variable-width contexts. And always ensure your minimum sizes remain readable and accessible.

At brndle.com, we specialize in block theme development, from theme.json configuration and fluid design systems to custom block patterns, template parts, and Full Site Editing architecture. Whether you are building your first block theme or refining a production theme’s responsive behavior, our team can help you implement the techniques covered in this guide and take your theme to the next level. Get in touch to discuss your block theme project.

Scroll to Top