Repository navigation
Add fluid spacing support to theme.json (parity with fluid typography) #81864
Description
What problem does this address?
Since 6.1 (#39529), fluid typography in theme.json is first-class: settings.typography.fluid, per-preset fontSizes[].fluid: { min, max }, and auto-generated clamp() for --wp--preset--font-size--*.
Spacing has no equivalent. spacingSizes[].size only accepts a raw CSS string so fluid spacing means hand-written clamp() in every preset (handbook).
Spacing also differs from typography in that it already has settings.spacing.spacingScale to auto-generate a scale from a few parameters. That scale only produces static values, though. Fluid spacing forces authors to abandon spacingScale and hand-author every entry in spacingSizes.
Missing compared to typography:
- Declarative
min/maxper preset - Global viewport settings (
minViewportWidth/maxViewportWidth) - Per-preset opt-out via
fluid: false - A consistent model for the upcoming spacing presets UI (#61986, #72301)
This was discussed early on (#39371) but never implemented in the theme.json engine.
What is your proposed solution?
Mirror fluid typography for spacing presets:
{
"settings": {
"spacing": {
"fluid": {
"minViewportWidth": "768px",
"maxViewportWidth": "1280px"
},
"spacingSizes": [
{
"name": "Medium",
"slug": "md",
"size": "1.75rem",
"fluid": { "min": "1.5rem", "max": "1.75rem" }
},
{
"name": "Small",
"slug": "sm",
"size": "1rem",
"fluid": false
}
]
}
}
}Expected output:
--wp--preset--spacing--md: clamp(1.5rem, …, 1.75rem);
--wp--preset--spacing--sm: 1rem;As a follow-up, fluid support could also extend to spacingScale. Today it generates a static scale from operator, increment, steps, mediumStep, and unit (with mediumStep always mapped to slug 50). When spacing.fluid is enabled, the same generator could emit fluid steps from a min/max medium value, for example:
{
"settings": {
"spacing": {
"fluid": {
"minViewportWidth": "768px",
"maxViewportWidth": "1280px"
},
"spacingScale": {
"operator": "*",
"increment": 1.5,
"steps": 7,
"unit": "rem",
"fluid": {
"min": { "mediumStep": 1.5 },
"max": { "mediumStep": 1.75 }
}
}
}
}
}That would generate both ends of the scale from the same rules, then clamp each step (e.g. --wp--preset--spacing--50: clamp(1.5rem, …, 1.75rem)), instead of requiring a fully manual spacingSizes list.
Implementation: reuse Core math (wp_get_typography_font_size_value(), wp_get_computed_fluid_typography_value()) during WP_Theme_JSON preset resolution. Longer term, extract a generic wp_get_fluid_size_value() shared by typography and spacing.
Workarounds today
- Manual
clamp()insizebut verbose and hard to maintain - Theme polyfill via
wp_theme_json_data_theme, works but shouldn't be necessary. Declaringsettings.spacing.fluidandspacingSizes[].fluidalso invalidates the officialtheme.jsonschema, since those properties are not part of it today.
Activity
vedant-ere commentedon Aug 20, 2026
Hi! I’d like to pick this up. This is my first time contributing to this part of the codebase, so please bear with me if I’m missing some context.
I looked through how fluid typography works (
gutenberg_get_typography_font_size_value()intypography.phpand thevalue_funcinPRESETS_METADATAinclass-wp-theme-json-gutenberg.php). From what I understand,spacingSizescurrently just uses the rawsizevalue and doesn’t have a compute function likefontSizes.My plan is:
settings.spacing.fluidandspacingSizes[].fluid, withfluid: falseas an opt-out, following the typography approach.value_funcfor spacing presets, similar to typography.spacingScalefluid generator for a later PR. It looks likespacingScaleis calculated eagerly in the constructor, while fluid typography is calculated when the value is needed. Since this is my first contribution here, I’d prefer to keep that timing change separate.One thing I’m not sure about is the default behavior for the fluid calculation. Typography has some font-size-specific defaults, like skipping fluid sizing below 14px and calculating a minimum value when one isn’t provided. I don’t think those defaults make sense for spacing.
Would it be better to have a default for spacing, or should we require
minandmaxto be explicitly defined for spacing presets for now?Thanks for any pointers!