Skip to content

Add fluid spacing support to theme.json (parity with fluid typography) #81864

Open

Description

@alexandrebuffet

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 / max per 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

  1. Manual clamp() in size but verbose and hard to maintain
  2. Theme polyfill via wp_theme_json_data_theme, works but shouldn't be necessary. Declaring settings.spacing.fluid and spacingSizes[].fluid also invalidates the official theme.json schema, since those properties are not part of it today.

Related: #39371 · #61986 · #72301 · #39529 · #41527

Activity

  1. vedant-ere commented on Aug 20, 2026

    @vedant-ere
    Contributor

    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() in typography.php and the value_func in PRESETS_METADATA in class-wp-theme-json-gutenberg.php). From what I understand, spacingSizes currently just uses the raw size value and doesn’t have a compute function like fontSizes.

    My plan is:

    • Add settings.spacing.fluid and spacingSizes[].fluid, with fluid: false as an opt-out, following the typography approach.
    • Add a value_func for spacing presets, similar to typography.
    • Update the theme.json schema to support these new keys.
    • Leave the spacingScale fluid generator for a later PR. It looks like spacingScale is 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 min and max to be explicitly defined for spacing presets for now?

    Thanks for any pointers!

    • Note: used ai to articulate this better
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

[Feature] LayoutLayout block support, its UI controls, and style output.[Status] In ProgressTracking issues with work in progress[Type] EnhancementA suggestion for improvement.

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions