Recently, it has become common to adjust spacing using clamp() to make values fluid between a minimum and maximum.
While this is very handy for responsive design, there is a small pitfall to watch out for when considering accessibility zoom (magnification).
A Common clamp() Example
For example, when adjusting spacing with clamp(), you will often see something like the following.
:root {
--clamp-base: 16;
--clamp-viewport-min: 375;
--clamp-viewport-max: 1440;
--spacing-lg-min: 24;
--spacing-lg-max: 48;
--spacing-lg-slope: calc(
(var(--spacing-lg-max) - var(--spacing-lg-min)) / (var(--clamp-viewport-max) - var(--clamp-viewport-min))
);
--spacing-lg-intersection: calc(
(var(--spacing-lg-max) - var(--clamp-viewport-max) * var(--spacing-lg-slope)) / var(--clamp-base)
);
--spacing-lg: clamp(
calc(var(--spacing-lg-min) / var(--clamp-base) * 1rem),
calc(var(--spacing-lg-intersection) * 1rem + 100 * var(--spacing-lg-slope) * 1vw),
calc(var(--spacing-lg-max) / var(--clamp-base) * 1rem)
);
}
I will skip the detailed explanation here, but
- On smartphones, the size is
--spacing-lg-min - On PCs, the size is
--spacing-lg-max - Variable and smooth scaling in between
This makes it a very practical pattern, don't you think?
What are the pitfalls in accessibility?
The problem arises when you try to comply with WCAG 2.0 Success Criterion 1.4.4 "Resize Text".
This criterion was originally written before smartphones became widespread, with the intent of ensuring that "content can be viewed when enlarged up to 200% on a PC." However, the same conditions now apply to smartphone browsers as well.
When you actually zoom a smartphone to 200%, the following issues often occur.
- When text is zoomed,
spacing based on rem unitsalso gets scaled up along with the text. - As a result, the margins surrounding the actual content become excessively wide.
- Consequently, the content display area becomes extremely narrow, leading to layout breakage and content that is difficult to read.
Note: In reality, even overseas government websites where WCAG compliance is mandatory often do not seem to address this well. This is likely because the cost-benefit ratio is questionable, and because the need to zoom smartphones to 200% is seen as almost nonexistent, so on the ground it may be considered "not a major problem even if left unaddressed."
How do you resolve this issue?
Rather than using rem, which is affected by text scaling, it is important to use viewport-based units such as vw and avoid making margins excessively large even when zoomed.
However, specifying only vw means you cannot take advantage of the benefit of clamp(), which lets you control the minimum and maximum values.
This is where the min() function comes in!
min() uses the smallest value among the values passed to it. Taking advantage of this behavior, we switch the value applied between normal and zoomed states.
Here is how to write it.
--spacing-lg: min(
calc(var(--spacing-lg-min) / var(--clamp-viewport-min) * 100vw),
clamp(
calc(var(--spacing-lg-min) / var(--clamp-base) * 1rem),
calc(var(--spacing-lg-intersection) * 1rem + 100 * var(--spacing-lg-slope) * 1vw),
calc(var(--spacing-lg-max) / var(--clamp-base) * 1rem)
)
);
When displayed at 375 CSS px, the first value of min is 6.4vw, which is 24px converted to vw, the value of --spacing-lg-min.
The minimum value of clamp() is 1.5rem = 24px, but at 200% zoom it becomes 48px, so the 6.4vw on the left is smaller and is the value that gets applied.
In other words,
- Normal state (100% display):
- The
clamp()value ends up smaller than the value based onvw. - Because
min()uses the smaller of the two values,clamp()takes effect and the display scales fluidly with the screen width.
- The
- When zoomed in (200%):
- When zoomed in, the
reminsideclamp()grows larger, so thevw-based value becomes the smaller one. - The
vw-based value applies, and because the margins are fixed as a ratio of the screen width, excessive enlargement is prevented.
- When zoomed in, the
This way, you can achieve both responsive convenience and accessibility considerations!
Note: On desktop displays, it is generally better for the design balance if margins also scale up, so --clamp-viewport-min is used as the baseline and applied to smartphones only.
Compare the actual behavior
Top: clamp only. Bottom: min + clamp.
When you zoom to 200% on a smartphone, the difference becomes clearly visible.
Note: On iOS Safari, you can zoom in using the icon to the left of the address bar. On Android Chrome, use the icon at the top right.
Summary
- clamp() is handy for responsive spacing adjustments.
- However, when zoomed in, the spacing scales up as well, which may cause layout breakage.
- Combining it with min() allows for a well-balanced approach: variable sizing under normal conditions, with controlled sizing when zoomed in.
If you're mindful of WCAG compliance, it's reassuring to incorporate implementations like this. Supporting zoom up to 200% on mobile devices is still uncommon, but it helps reduce accessibility risks without compromising everyday readability.
Additionally, if you want to make finer adjustments beyond spacing, you can also use media queries targeting narrower breakpoints.
@media (max-width: 239px) {
/* 拡大時に適用したいCSS */
}
For example, when a 375px-wide screen is zoomed to 200%, the browser calculates the viewport width as half that size (about 188px). This means you can target this narrow condition with a media query.
Note: The 239px value is just an example. It's best to choose a value that leaves room for future larger screens while ensuring no impact on normal display.
By combining "clamp() + min()" with "narrow breakpoint media queries," you can achieve more flexible and reliable accessibility support!
Starting out in DTP and moving into the web, he now handles markup, frontend, direction, and accessibility alike. A "master of all trades" who has been versatile since Liberogic's early days and is now a walking encyclopedia of the company. Lately he has been hooked on exploring efficiency through prompts, asking, "Can't we rely more on AI for accessibility work?" Both his skills and his thinking are still evolving.
Ayumu Futamata
IAAP Certified Web Accessibility Specialist (WAS) / Markup Engineer / Frontend Engineer / Web Director