---
title: "CSS Clamp(): How To Build Fluid Typography And Spacing In Elementor"
url: https://theplusaddons.com/blog/css-clamp/
date: 2026-09-25
modified: 2026-09-25
lang: en
author: "Sagar Patel"
description: "[nexter-builder id=\"118291\"] Open the responsive preview on almost any Elementor site and you will find the same pattern in the Typography panel: a heading set to 64px on desktop, 44px..."
image: https://theplusaddons.com/wp-content/uploads/2026/09/css-clamp-fluid-typography-elementor-featured-1024x538.jpg
word_count: 2661
---

# CSS Clamp(): How To Build Fluid Typography And Spacing In Elementor

## 

- CSS clamp() replaces three fixed values with one expression that scales smoothly between a minimum, a preferred value, and a maximum, and MDN resolves it as max(MIN, min(VAL, MAX)).
- Elementor accepts clamp() in the Custom unit field for Typography, Line Height, Container Width, Padding, and Global Fonts, and Elementor Pro is not required.
- The Plus Addons for Elementor free plugin version 6.5.2 uses Elementor's shared Typography group across 201 groups in 47 files, so headings, titles, and body text in those widgets can use the Custom unit.
- Widget-specific controls in The Plus Addons for Elementor are mostly fixed-unit only: a scan finds 1,137 size unit lists and only 2 offer the Custom unit, so fluid values go in CSS through a class and stylesheet.
- Fluid spacing uses clamp() for section padding and gaps, while readable line length uses min(100% - 2rem, 70ch), and the post warns that bare vw text sizes can break WCAG Success Criterion 1.4.4 at 200% zoom.

Table Of Contents

Open the responsive preview on almost any Elementor site and you will find the same pattern in the Typography panel: a heading set to 64px on desktop, 44px on tablet and 32px on mobile. Three values, three breakpoints, and a heading that jumps in size at 1025px and again at 768px instead of growing with the screen. Multiply that by every heading, paragraph and padding value on the site and you have hundreds of numbers to keep in sync.

The CSS `clamp()` function replaces those three numbers with one expression that scales smoothly between a floor and a ceiling. It has been safe to use for years: the caniuse dataset puts support for `min()`, `max()` and `clamp()` at 96.2% of global users. This guide covers how the function resolves, the formula for the middle value, a ready-to-use type scale, where to type it in the Elementor editor, and the zoom and accessibility checks worth running before you ship.

## What Clamp() Actually Does

The function takes three comma-separated values: a minimum, a preferred value, and a maximum. The browser uses the preferred value as long as it sits between the other two. If the preferred value drops below the minimum, the minimum wins. If it rises above the maximum, the maximum wins.

`/* clamp(MIN, PREFERRED, MAX) */
h1 {
font-size: clamp(2rem, 1.217rem + 3.478vw, 4rem);
}

/* The browser resolves it exactly like this */
h1 {
font-size: max(2rem, min(1.217rem + 3.478vw, 4rem));
}`

That second rule is how MDN documents the behaviour: `clamp(MIN, VAL, MAX)` is resolved as `max(MIN, min(VAL, MAX))`. It is worth remembering, because it explains an edge case people hit sooner or later. If you accidentally set a minimum larger than the maximum, the minimum wins every time, since the outer `max()` is evaluated last.

The preferred value is where the fluid behaviour lives. It is almost always a mix of a fixed length and a viewport-relative length, such as `1.217rem + 3.478vw`. The `vw` part makes it grow with the window, and the `rem` part anchors it to the user's font size. You do not need to wrap that sum in `calc()`, because math functions accept arithmetic directly inside their arguments.

## Clamp() Vs Breakpoints Vs Min() And Max()

The three math functions are closely related, and they are often mixed up with plain media query breakpoints. Here is how they divide the work.

| Approach | What it does | Best used for |
| -------- | ------------ | ------------- |
| Breakpoint values | Switches to a new fixed value at set widths | Layout changes, such as stacking columns on mobile |
| `min(a, b)` | Uses whichever value is smaller | Setting a maximum, such as `width: min(75ch, 100%)` |
| `max(a, b)` | Uses whichever value is larger | Setting a minimum, such as a padding that never drops under 1rem |
| `clamp(min, val, max)` | Keeps a fluid value inside a floor and a ceiling | Font sizes, section padding, gaps and container widths |

Breakpoints are still the right tool when the layout itself has to change shape. A three-column grid that becomes a single column on a phone is a structural decision, and no amount of fluid sizing replaces it. Clamp handles the in-between: the sizes and spacing that should scale gradually rather than snap. For component-level changes that depend on the width of a parent rather than the window, pair clamp with [CSS container queries](https://theplusaddons.com/blog/css-container-queries/) and their `cqi` unit.

## The Formula For The Middle Value

Picking the minimum and maximum is easy, because they are just your mobile and desktop sizes. The middle value is the part people guess at, and guessing is how you end up with a heading that hits its maximum at 900px and sits there for the rest of the range. There is an exact way to calculate it.

Start with four numbers: the smallest font size, the largest font size, the viewport width where scaling should begin, and the viewport width where it should stop. Then work out the slope and the starting offset.

`/* Inputs (px) */
min size = 24 at viewport 360
max size = 48 at viewport 1280

/* Step 1: slope, how much the size grows per px of viewport */
slope = (48 - 24) / (1280 - 360) = 0.026087

/* Step 2: the vw part of the preferred value */
vw value = slope x 100 = 2.609vw

/* Step 3: the fixed part, converted to rem (16px base) */
intercept = 24 - (0.026087 x 360) = 14.609px = 0.913rem

/* Result */
font-size: clamp(1.5rem, 0.913rem + 2.609vw, 3rem);`

Check the result at both ends before you trust it. At a 360px viewport, 2.609vw is 9.39px, and 14.609px plus 9.39px is 24px, which is exactly the minimum. At 1280px, 2.609vw is 33.39px, and adding 14.609px gives 48px, exactly the maximum. Between the two, the size grows in a straight line, and outside that range the floor and ceiling hold it still.

If you would rather not do the arithmetic by hand, a spreadsheet with those three steps is enough. Online clamp calculators do the same thing, but it is worth understanding the formula once so you can sanity check any value a tool hands you.

## A Fluid Type Scale You Can Copy

Here is a complete scale calculated with that formula, scaling between a 360px phone and a 1280px desktop. Every value below was checked so that it lands exactly on its minimum at 360px and its maximum at 1280px.

| Element | At 360px | At 1280px | Clamp value |
| ------- | -------- | --------- | ----------- |
| Body text | 16px | 18px | `clamp(1rem, 0.951rem + 0.217vw, 1.125rem)` |
| H3 | 20px | 28px | `clamp(1.25rem, 1.054rem + 0.87vw, 1.75rem)` |
| H2 | 24px | 40px | `clamp(1.5rem, 1.109rem + 1.739vw, 2.5rem)` |
| H1 | 32px | 64px | `clamp(2rem, 1.217rem + 3.478vw, 4rem)` |
| Section padding | 24px | 96px | `clamp(1.5rem, -0.261rem + 7.826vw, 6rem)` |

Notice the section padding row. Its fixed part is negative, and that is fine. It simply means the size would reach zero somewhere below 360px, which never happens because the minimum takes over first. Large ranges like padding often produce a negative intercept, so do not treat it as an error.

The cleanest way to use a scale like this is to store each value once as a variable and reference it everywhere, which is exactly the job [CSS custom properties](https://theplusaddons.com/blog/css-custom-properties/) were built for.

`:root {
--fs-body: clamp(1rem, 0.951rem + 0.217vw, 1.125rem);
--fs-h3: clamp(1.25rem, 1.054rem + 0.87vw, 1.75rem);
--fs-h2: clamp(1.5rem, 1.109rem + 1.739vw, 2.5rem);
--fs-h1: clamp(2rem, 1.217rem + 3.478vw, 4rem);
--space-section: clamp(1.5rem, -0.261rem + 7.826vw, 6rem);
}

body { font-size: var(--fs-body); }
h1 { font-size: var(--fs-h1); }
.section { padding-block: var(--space-section); }`

## Where To Type Clamp() In Elementor

You do not need custom CSS to use clamp in Elementor. The size controls include a Custom unit that accepts any valid CSS value as free text. In the editor it appears as a small pencil icon in the unit switcher next to px, em and rem, and its label for screen readers is "Custom unit". Pick it and the number slider turns into a text field.

This is part of the free Elementor plugin, so Elementor Pro is not required. We checked the control definitions in Elementor's own source code on GitHub (the current 4.x branch) to confirm exactly where the option is offered:

| Control | Where you find it | Units offered |
| ------- | ----------------- | ------------- |
| Font Size | Style tab, Typography group, on any widget that uses it | px, em, rem, vw, Custom |
| Line Height | Style tab, Typography group | px, em, rem, lh, rlh, Custom |
| Container Width | Container, Layout tab | px, %, em, rem, vw, Custom |
| Padding | Container, Advanced tab | px, %, em, rem, vw, Custom |
| Global Fonts | Site Settings, Global Fonts | Uses the same Typography group, so Custom is available |

The steps for a heading are short:

- Select the Heading widget and open the Style tab.

- Click the pencil icon next to Typography to open the group.

- Next to Size, open the unit switcher and choose the pencil icon for the Custom unit.

- Type the full value, for example `clamp(2rem, 1.217rem + 3.478vw, 4rem)`.

- Set it on the desktop view only and leave the tablet and mobile fields empty.

That last step is the one that matters. Responsive controls in Elementor inherit from the larger device when the smaller one is left blank, so a single clamp value on desktop covers every device. If you fill in the tablet and mobile fields as well, those fixed values override the fluid one and you are back to three separate sizes.

For a whole site, put the scale into Site Settings under Global Fonts instead of widget by widget. Every heading linked to a global font then picks up the fluid size, and changing the scale later means editing one place. The same idea works for section spacing, since the padding field on a container accepts the Custom unit too.

## Using Clamp() With The Plus Addons For Elementor Widgets

If you build with The Plus Addons for Elementor, the typography side works the same way. The widgets use Elementor's shared Typography group for their text styling, and a scan of the current free plugin (version 6.5.2) found 201 of those Typography groups across 47 files, so headings, titles and body text inside those widgets get the Custom unit automatically.

Widget-specific sliders are a different story. The same scan found 1,137 size unit lists in the plugin's controls, and only 2 of them offer the Custom unit. Settings such as icon size or the spacing between items usually accept fixed units like px, em or rem. For those, give the widget a CSS class in the Advanced tab and set the fluid value in a stylesheet, either through the site's custom CSS or with the [Custom CSS extension](https://theplusaddons.com/elementor-extras/custom-css/) that adds a CSS field to any container, section or column.

`/* Widget has the class .fluid-icons in the Advanced tab */
.fluid-icons {
--icon-size: clamp(1.5rem, 1.109rem + 1.739vw, 2.5rem);
}

.fluid-icons svg,
.fluid-icons i {
width: var(--icon-size);
height: var(--icon-size);
font-size: var(--icon-size);
}`

Inspect the widget on the front end first to confirm which element actually carries the size, because the markup differs from widget to widget. Our guide to [adding custom CSS in Elementor](https://theplusaddons.com/blog/add-custom-css-in-elementor/) covers the options for where that stylesheet can live.

## Fluid Spacing, Gaps And Widths

Typography gets most of the attention, but spacing is where clamp saves the most editing time. Section padding that is 96px on desktop and 24px on a phone is usually entered as three responsive values per container. One clamp value in the padding field replaces all of them.

`/* Section padding: 24px on phones, 96px on desktop */
.section {
padding-block: clamp(1.5rem, -0.261rem + 7.826vw, 6rem);
padding-inline: clamp(1rem, 0.5rem + 2.5vw, 3rem);
}

/* Grid gap that tightens on small screens */
.card-grid {
gap: clamp(1rem, 0.5rem + 2vw, 2.5rem);
}

/* Readable line length: fluid width with a hard ceiling */
.article-body {
width: min(100% - 2rem, 70ch);
margin-inline: auto;
}`

The last rule uses `min()` rather than clamp, because there is no minimum to enforce. A column of text should fill a narrow screen and stop growing at a comfortable line length, and a two-value `min()` expresses that directly. Gaps behave the same way in Flexbox and Grid, so the gap rule works whichever layout mode you choose. The practical differences between those two are covered in [Elementor Flexbox vs Grid containers](https://theplusaddons.com/blog/elementor-flexbox-vs-grid-container-differences/).

## Accessibility And Zoom Checks

Fluid type has one real accessibility risk. When a size depends only on the viewport, zooming the page does not make the text bigger in the way users expect, because `vw` is tied to the window rather than the user's font preference. That can break WCAG Success Criterion 1.4.4, which asks that text can be resized up to 200%.

Two habits keep you safe. First, never use a bare `vw` value as the preferred size. Always add a `rem` term, as every value in the scale above does, so the size keeps responding to the user's settings. Second, follow MDN's guidance on the bounds: when clamp controls text size, the maximum should be a relative unit that is no less than twice the minimum, so that text can still reach 200% when the page is zoomed.

The H1 and section padding rows in the scale meet that ratio. Body text, H3 and H2 do not, because smaller text rarely needs to double in size across the range. For those, do the manual test: open the page, zoom the browser to 200%, and confirm the text is clearly larger than it was at 100%. If it barely moves, lower the `vw` share of the preferred value and raise the `rem` share.

## Browser Support

Support is no longer a real concern. According to the caniuse dataset, the math functions sit at 96.2% global support, and every major engine has shipped them for years.

| Browser | First version with clamp() support |
| ------- | ---------------------------------- |
| Chrome | 79 |
| Edge | 79 |
| Firefox | 75 |
| Safari | 13.1 |
| Safari on iOS | 13.4 |
| Samsung Internet | 12 |
| Opera | 66 |

One detail from the same data: Safari 11.1 and 12 supported `min()` and `max()` but not `clamp()`. Those versions are long out of circulation, but if you need a fallback for a very old device, declare a fixed size first and the clamp value second. Browsers that do not understand the second declaration ignore it and keep the first.

`h2 {
font-size: 2rem; /* fallback */
font-size: clamp(1.5rem, 1.109rem + 1.739vw, 2.5rem);
}`

## Common Clamp() Mistakes

**Setting tablet and mobile values as well.** In Elementor, a fixed value on a smaller device overrides the fluid value inherited from desktop. If a clamp heading suddenly stops scaling on phones, check the mobile field first.

**Guessing the middle value.** A preferred value like `5vw` on its own reaches the maximum early or never reaches it at all, depending on the numbers. Calculate it from your two viewport widths so the scaling covers the range you intended.

**Mixing units in the wrong places.** The minimum and maximum should be `rem` so they respect the user's base font size. Using px for the bounds makes zoom behaviour less predictable.

**Forgetting spaces around the plus sign.** Inside a math function, `1rem+2vw` is invalid. The operators need a space on each side: `1rem + 2vw`. The browser silently drops the whole declaration otherwise, which makes it look as if clamp does not work.

**Testing only in the editor.** The Elementor editor preview is an iframe, and its width is not always the same as a real device. Check the published page at a few real window widths, and on a real phone, before you sign off. The same habit pays off for other visual techniques such as [gradient text](https://theplusaddons.com/blog/gradient-text-css/), where rendering differences between browsers are easy to miss inside a builder.

## Frequently Asked Questions

### Does Elementor support clamp()?

Yes. Font size, line height, container width and padding all offer a Custom unit that accepts a clamp expression as text. It is part of the free Elementor plugin, and it also works in Global Fonts under Site Settings.

### Do I still need breakpoints if I use clamp()?

For layout changes, yes. Stacking columns, hiding elements or switching a menu to a mobile toggle are structural changes that breakpoints handle. Clamp replaces the breakpoint values you were using purely to resize text and spacing.

### Should the bounds be px or rem?

Use rem. It follows the base font size a user sets in their browser, which px ignores. The px numbers in this guide are only the design targets used to calculate the rem values.

### Is clamp() bad for performance?

No. It is plain CSS evaluated by the browser's layout engine, with no JavaScript involved.

### Why is my clamp() value being ignored?

Check three things in order: the operators have spaces around them, there are exactly three comma-separated values, and no tablet or mobile value is overriding it. An invalid expression is dropped without any error message.

### Can I use clamp() with container query units?

Yes. Swap vw for cqi, as in `clamp(1rem, 0.75rem + 2.5cqi, 1.75rem)`, and the size scales with the component's container instead of the window. The container must declare `container-type` for the unit to resolve against it.

## Suggested Reading

- [How CSS Container Queries Actually Work (And Where Elementor Still Needs Them)](https://theplusaddons.com/blog/css-container-queries/)

- [CSS Custom Properties Explained: How CSS Variables Actually Work](https://theplusaddons.com/blog/css-custom-properties/)

- [Elementor Flexbox vs Grid Container: Which Should You Use?](https://theplusaddons.com/blog/elementor-flexbox-vs-grid-container-differences/)

- [CSS Scroll Snap: Full-Page Sections And Card Carousels Without A Plugin](https://theplusaddons.com/blog/css-scroll-snap/)

- [Bento Grid Layouts in 2026: CSS Grid vs Elementor (What Actually Works)](https://theplusaddons.com/blog/bento-grid-layout/)