Fluid Scaling
Continuous viewport-responsive type and spacing with clamp() — no breakpoints, no jumps. Activate with a single attribute.
Why Fluid
Traditional responsive design uses breakpoints — fixed thresholds where layouts snap between states. This creates three problems:
- Jarring jumps. A heading that's 2rem at 767px and 3rem at 768px creates a visible pop.
- False taxonomy. "Mobile", "tablet", "desktop" are marketing categories, not engineering primitives. A 1024px laptop in portrait mode isn't a tablet.
- Combinatorial explosion. Every breakpoint doubles the test matrix. Three breakpoints means eight states to verify.
Fluid scaling replaces this with continuous interpolation. Values ease smoothly from a minimum (at 320px) to a maximum (at 1440px). One rule, infinite states, zero jumps.
Activation
Add the data-fluid attribute to <html>. Remove it to revert to fixed values instantly.
<!-- Default preset --><html data-fluid> <!-- Named presets --><html data-fluid="compact"><html data-fluid="spacious"> <!-- Combine with themes and dark mode --><html data-theme="modern" data-fluid data-mode="dark">
Fluid scaling is opt-in so existing sites aren't affected. Once activated, it overrides the static --font-size-* and --size-unit tokens with clamp() values.
What Changes
Typography
Each of the nine --font-size-* tokens gets a clamp() value. Small sizes barely change (xs stays near 0.75rem); large sizes scale dramatically (5xl grows from ~2rem to ~4rem). This creates a tighter ratio at narrow viewports (more uniform hierarchy, easier to scan) and a wider ratio at wide viewports (more dramatic headings, clearer visual weight).
Spacing
All nine --size-* tokens (3xs through 3xl) are derived from --size-unit via calc(). Making --size-unit a clamp() value makes every spacing token fluid automatically — a single override cascades to the entire system.
Content Widths
--content-normal and --measure-normal also scale, expanding reading areas on wider screens while keeping comfortable line lengths on narrow ones.
Presets
| Attribute | Type Ratio | Space Swing | Character |
|---|---|---|---|
data-fluid="compact" |
1.067 → 1.2 | ±11% | Tight, uniform hierarchy. Good for dense UIs and dashboards. |
data-fluid |
1.125 → 1.25 | ±10% | Balanced, general-purpose. Works for most content sites. |
data-fluid="spacious" |
1.2 → 1.333 | ±11% | Generous, dramatic headings. Marketing pages and editorial layouts. |
Pointer Detection
Pointer detection is always on — no opt-in attribute needed. It uses CSS media queries to adapt interaction style to the device's input capabilities.
/* These rules are always active — no opt-in needed */ /* Touch devices: enforce 44px minimum targets (WCAG 2.5.8) */@media (pointer: coarse) { button, select, input:not([type="hidden"]) { min-block-size: var(--size-touch-min); /* 2.75rem = 44px */ }} /* No hover capability: disable hover-only motion affordances */@media (hover: none) { :root { --motion-hover-lift: none; --motion-hover-scale: none; }}
What It Does
@media (pointer: coarse)- Touch and stylus devices get 44px minimum target sizes on buttons, inputs, and selects — enforcing WCAG 2.5.8 target size requirements.
@media (hover: none)- On devices without hover (phones, tablets), hover-only motion effects like lift and scale are disabled. Content remains accessible without hover interactions.
With Themes
data-fluid composes with data-theme. Most themes only customize colors and fonts, so fluid scaling works without any theme-side changes.
The a11y-large-text accessibility theme includes dedicated fluid compound rules — its larger base sizes (1.25rem body, 0.3125rem unit) also scale fluidly when data-fluid is present.
<html data-theme="modern" data-fluid><!-- Modern personality + fluid type/spacing --> <html data-theme="a11y-large-text" data-fluid><!-- Large text base + fluid scaling = maximum readability -->
Custom Parameters
For full control over ratios and viewport ranges, use the interactive tools:
- Fluid Sizing tool — visualize and export fluid type/space scales. Use the "VB-native" export mode for
[data-fluid="custom"]output. - Theme Composer — when fluid sizing is enabled, the exported CSS includes a
[data-fluid]compound block scoped to your theme.
Both tools produce production-ready clamp() CSS. Paste it into your project stylesheet:
/* Custom fluid preset — paste from the Fluid Sizing tool */[data-fluid="custom"] { /* Fluid Type Scale */ --font-size-xs: clamp(0.68rem, -0.16vi + 0.82rem, 0.79rem); --font-size-sm: clamp(0.85rem, -0.06vi + 0.90rem, 0.89rem); --font-size-md: clamp(1rem, 0.09vi + 0.98rem, 1.06rem); --font-size-lg: clamp(1.13rem, 0.29vi + 1.07rem, 1.33rem); --font-size-xl: clamp(1.27rem, 0.56vi + 1.15rem, 1.66rem); --font-size-2xl: clamp(1.42rem, 0.93vi + 1.24rem, 2.08rem); --font-size-3xl: clamp(1.60rem, 1.42vi + 1.32rem, 2.59rem); --font-size-4xl: clamp(1.80rem, 2.06vi + 1.39rem, 3.24rem); --font-size-5xl: clamp(2.03rem, 2.89vi + 1.45rem, 4.05rem); /* Fluid Space (via --size-unit — cascades to all --size-* tokens) */ --size-unit: clamp(0.225rem, 0.07vi + 0.21rem, 0.275rem);}
When Not To Use Fluid Scaling
- Pixel-precise dashboards — data-dense UIs where every pixel matters may prefer fixed tokens.
- Print stylesheets — print media has a fixed page size; fluid scaling adds no value.
- Embedded widgets — components that render at a known fixed size don't benefit from viewport-relative scaling. Use container queries instead.
- Existing breakpoint systems — if your project already has a mature breakpoint-based approach, mixing in fluid tokens can create unpredictable interactions.