Fluid Design

Fluid Responsive Design - Typography

Create fluid typography systems that scale smoothly across viewports using mathematical modular scales and CSS clamp functions.
Pro Feature

Unlock advanced capabilities with styleframe Pro. This feature requires a Pro license to access.

Upgrade to Pro

Overview

The useFluidFontSize() composable creates complete fluid typography systems that scale smoothly across all viewport sizes. It combines base font size ranges with modular scale multipliers to generate type hierarchies that maintain perfect proportions from mobile to desktop.

Unlike traditional responsive typography that jumps between fixed sizes at breakpoints, fluid typography creates smooth, continuous transitions that look perfect at every viewport width.

Why use fluid typography?

Fluid typography helps you:

  • Eliminate breakpoint jumps: Text scales smoothly instead of jumping between fixed sizes at media queries.
  • Maintain perfect proportions: Use modular scales to ensure harmonious relationships at every viewport width.
  • Reduce code complexity: Define your entire type system once instead of managing multiple breakpoints.
  • Improve readability: Automatically optimize text size for the available space.
  • Create responsive hierarchies: Scale relationships between different text sizes remain consistent.

useFluidFontSize()

The useFluidFontSize() composable generates a complete set of fluid font size variables based on base size ranges and modular scale multipliers.

styleframe.config.ts
import { styleframe } from 'styleframe';
import { useScale, useScalePowers, defaultScaleValues } from '@styleframe/theme';
import { useFluidViewport, useFluidFontSize } from '@styleframe/pro';

const s = styleframe();

// Set up fluid viewport range (320px - 1440px)
useFluidViewport(s);

// Define scales for mobile and desktop
const { scaleMin, scaleMax } = useScale(s, { 
    ...defaultScaleValues,
    min: '@minor-third',   // Minor Third scale for mobile
    max: '@major-third'    // Major Third scale for desktop
});

// Calculate scale powers
const scaleMinPowers = useScalePowers(s, scaleMin);
const scaleMaxPowers = useScalePowers(s, scaleMax);

// Generate fluid font sizes
const {
    fontSize,
    fontSizeXs,
    fontSizeSm,
    fontSizeMd,
    fontSizeLg,
    fontSizeXl,
} = useFluidFontSize(s, 
    { min: 16, max: 18 },  // Base font size range
    {
        xs: { min: scaleMinPowers[-2], max: scaleMaxPowers[-2] },
        sm: { min: scaleMinPowers[-1], max: scaleMaxPowers[-1] },
        md: { min: scaleMinPowers[0], max: scaleMaxPowers[0] },
        lg: { min: scaleMinPowers[1], max: scaleMaxPowers[1] },
        xl: { min: scaleMinPowers[2], max: scaleMaxPowers[2] },
        default: '@md'
    }
);

export default s;
Pro tip: Always call useFluidViewport() before using useFluidFontSize(). The fluid font size composable relies on the fluid breakpoint variables created which are picked up automatically.

Understanding the Parameters

The useFluidFontSize() composable accepts three main parameters:

1. Base size range - Define minimum and maximum font sizes:

{ min: 16, max: 18 }  // Base text scales from 16px to 18px

2. Size definitions - Define which scale power each size should use. The base size range will be multiplied by these powers to create each font size:

{
    xs: { min: scaleMinPowers[-2], max: scaleMaxPowers[-2] },
    sm: { min: scaleMinPowers[-1], max: scaleMaxPowers[-1] },
    md: { min: scaleMinPowers[0], max: scaleMaxPowers[0] },
    lg: { min: scaleMinPowers[1], max: scaleMaxPowers[1] },
    xl: { min: scaleMinPowers[2], max: scaleMaxPowers[2] },
}

3. Custom breakpoint (optional) - By default, references the fluidBreakpoint variable from useFluidViewport(). You can override the default fluid breakpoint:

const { fluidBreakpoint } = useFluidViewport();

useFluidFontSize(s, { min: 16, max: 18 }, sizes, customBreakpoint);

Understanding Modular Scales

Modular scales create harmonious proportions by multiplying a base value by consistent ratios. The scale ratio determines how dramatically your font sizes grow.

Common Scale Ratios

Scale NameRatioCharacterBest For
Minor Second1.067Very subtleMinimal designs, tight hierarchies
Major Second1.125SubtleClean, understated designs
Minor Third1.2BalancedMost websites, readable hierarchies
Major Third1.25DistinctMarketing sites, clear hierarchy
Perfect Fourth1.333BoldEditorial content, strong contrast
Perfect Fifth1.5DramaticLanding pages, hero sections
Golden Ratio1.618StrikingArt, design-forward sites

Choosing Scale Ratios

Choose different scales for mobile and desktop to optimize readability at different viewport sizes:

styleframe.config.ts
// Subtle on mobile, balanced on desktop
import { useScale, defaultScaleValues } from '@styleframe/theme';

const s = styleframe();

// Define scales for mobile and desktop
const { scaleMin, scaleMax } = useScale(s, { 
    ...defaultScaleValues,
    min: '@minor-third',   // Minor Third scale for mobile
    max: '@major-third'    // Major Third scale for desktop
});
Pro tip: Use tighter scales (1.125 - 1.25) on mobile to prevent text from becoming too large, and more dramatic scales (1.25 - 1.5) on desktop to enhance visual hierarchy.

Using Fluid Typography Variables

Once created, fluid typography variables can be applied to elements just like regular CSS variables:

styleframe.config.ts
import { styleframe } from 'styleframe';
import { useScale, useScalePowers, defaultScaleValues } from '@styleframe/theme';
import { useFluidViewport, useFluidFontSize } from '@styleframe/pro';

const s = styleframe();

// Set up fluid viewport range (320px - 1440px)
useFluidViewport(s);

// Define scales for mobile and desktop
const { scaleMin, scaleMax } = useScale(s, { 
    ...defaultScaleValues,
    min: '@minor-third',   // Minor Third scale for mobile
    max: '@major-third'    // Major Third scale for desktop
});

// Calculate scale powers
const scaleMinPowers = useScalePowers(s, scaleMin);
const scaleMaxPowers = useScalePowers(s, scaleMax);

// Generate fluid font sizes
const {
    fontSize,
    fontSizeXs,
    fontSizeSm,
    fontSizeMd,
    fontSizeLg,
    fontSizeXl,
    fontSize2xl,
} = useFluidFontSize(s, 
    { min: 16, max: 18 },  // Base font size range
    {
        xs: { min: scaleMinPowers[-2], max: scaleMaxPowers[-2] },
        sm: { min: scaleMinPowers[-1], max: scaleMaxPowers[-1] },
        md: { min: scaleMinPowers[0], max: scaleMaxPowers[0] },
        lg: { min: scaleMinPowers[1], max: scaleMaxPowers[1] },
        xl: { min: scaleMinPowers[2], max: scaleMaxPowers[2] },
        '2xl': { min: scaleMinPowers[3], max: scaleMaxPowers[3] },
        default: '@md'
    }
);

// Apply to semantic elements
selector('body', {
    fontSize: ref(fontSize),
});

selector('small', {
    fontSize: ref(fontSizeSm),
});

selector('h3', {
    fontSize: ref(fontSizeLg),
});

selector('h2', {
    fontSize: ref(fontSizeXl),
});

selector('h1', {
    fontSize: ref(fontSize2xl),
});

export default s;

Best Practices

  • Choose appropriate base size range: Keep body text scaling subtle for better readability. 16px to 18px (12.5% increase) is ideal. Avoid extreme ranges like 12px to 20px (67% increase) which harm readability.
  • Use consistent scale ratios: Stick to proven modular scales. Common combinations include Minor Third to Major Third (1.2 to 1.25), or Minor Third to Perfect Fourth (1.2 to 1.333).
  • Ensure mobile scale is smaller than or equal to desktop scale.
  • Always call useFluidViewport() first: The other fluid composables depend on fluid breakpoint variables.
  • Limit the number of font sizes: Aim for a smaller number distinct sizes to maintain clear hierarchy without creating confusion. Too many sizes (12+) lead to inconsistency.
  • Test at multiple viewports: Verify typography at mobile, tablet, and desktop sizes. Ensure body text remains readable with 45-75 characters per line.

FAQ

Next Steps