fix(a11y): use pixels for spacing to allow for better text zoom#980
fix(a11y): use pixels for spacing to allow for better text zoom#980knowler wants to merge 1 commit intonpmx-dev:mainfrom
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
2 Skipped Deployments
|
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
📝 WalkthroughWalkthroughThe change modifies the UnoCSS configuration file to extend the theme object with a new spacing configuration. A default spacing value of 4px is introduced to the theme's spacing scale. This addition integrates with the existing typography and colour configuration within the theme object. No modifications are made to other theme tokens, behaviour, or public interfaces. The change consists of a single line addition with no lines removed. 🚥 Pre-merge checks | ✅ 1✅ Passed checks (1 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
🧪 Generate unit tests (beta)
Comment |
| ].filter(Boolean), | ||
| transformers: [transformerDirectives(), transformerVariantGroup()], | ||
| theme: { | ||
| spacing: { DEFAULT: '4px' }, |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
find . -name "uno.config.ts" -o -name "uno.config.js" | head -5Repository: npmx-dev/npmx.dev
Length of output: 76
🏁 Script executed:
cat uno.config.tsRepository: npmx-dev/npmx.dev
Length of output: 8459
🌐 Web query:
UnoCSS preset-wind4 spacing configuration theme override
💡 Result:
In preset-wind4, all the “size scale” utilities (including p-*, m-*, and also w-*, h-*, min/max-w/h, etc.) are unified to use theme.spacing. [1]
Override spacing via theme
// uno.config.ts
import { defineConfig, presetWind4 } from 'unocss'
export default defineConfig({
presets: [presetWind4()],
theme: {
spacing: {
0: '0px',
1: '0.25rem',
2: '0.5rem',
4: '1rem',
6: '1.5rem',
8: '2rem',
18: '4.5rem', // custom step (enables p-18, w-18, h-18, etc.)
},
},
})This is the standard UnoCSS way to change what e.g. p-4 (and w-4, h-4, …) resolve to. [2]
Override the generated CSS variable (optional)
preset-wind4 puts theme variables (including --spacing) in a dedicated theme layer specifically to make overriding easy. [1] You can override it in your own CSS loaded after UnoCSS:
:root { --spacing: 0.2rem; }Sources: UnoCSS preset-wind4 docs [1], UnoCSS theme spacing tutorial [2].
Note that numeric spacing utilities will still use rem values with this change.
Setting spacing: { DEFAULT: '4px' } affects only non-numeric utilities (e.g. bare p, m). Numeric utilities like p-1, m-2, px-4 will still resolve to the preset-wind4 default scale (where 1 = 0.25rem, 2 = 0.5rem, etc.) since you're not defining those numeric keys.
To convert all spacing utilities to px, the numeric scale must be explicitly defined:
spacing: {
DEFAULT: '4px',
0: '0px',
1: '0.25rem', // or '4px' if switching to px
2: '0.5rem', // or '8px'
// ... rest of scale
}This is a valid concern only if the goal is complete conversion; if this is intentionally a first step as noted in the PR, this can be disregarded.
There was a problem hiding this comment.
Nah, you’re wrong. The default value is used to set a custom property called --spacing. The relevant utilities use this custom property as a cascading variable which is multiplied by the step in the scale. For example, a partial sample of the output might look like this:
.pl-2 {
padding-left: calc(var(--spacing) * 2);
}
.pr-4 {
padding-right: calc(var(--spacing) * 4);
}There was a problem hiding this comment.
@knowler, you're absolutely right—thank you for the correction! I misunderstood how preset-wind4 handles the DEFAULT spacing value. Setting spacing: { DEFAULT: '4px' } creates the --spacing custom property that's then multiplied in the utility classes (e.g., pl-2 becomes calc(4px * 2)), so this change does indeed convert the numeric spacing utilities to pixels as intended. I appreciate the clarification!
✏️ Learnings added
Learnt from: knowler
Repo: npmx-dev/npmx.dev PR: 980
File: uno.config.ts:38-38
Timestamp: 2026-02-05T01:30:40.024Z
Learning: In UnoCSS preset-wind4, setting `spacing: { DEFAULT: '4px' }` in the theme configuration creates a CSS custom property `--spacing: 4px`. Numeric spacing utilities like `pl-2` or `pr-4` generate CSS using `calc(var(--spacing) * N)` where N is the numeric value, so `pl-2` becomes `padding-left: calc(var(--spacing) * 2)`. This means changing the DEFAULT value from rem to px affects all numeric spacing utilities.
Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.
|
I expected a massive diff but that seems reasonable. I m just a bit worried about two things (but we can still roll back later if they turn out to be true):
Mainly I would just like to avoid adding complexity to solve a problem I still haven't fully understood. |
|
Also just to be sure: which browser would support this as of now? Regular |
Browsers have two kinds of zoom:
While
remunits have long been held as a best practice unit overpx, that’s really only true of text. If we useremfor spacing, we lose the distinction between the two aforementioned kinds of zoom. This problem has been noted by Ashlee Boyer and Josh Comeau in recent years. In my experience, this newer best practice has proliferated throughout the design systems space (at least for those who care about accessibility).The goal of this PR is to restore the distinction and, in turn, act as a first step for improving the experience of zooming text for the app. Simply changing from
0.25remas the spacing unit to4pxshould have no consequences for anyone not using text zoom, as16pxis the default font size and4pxwould’ve been the computed size of the unit. For those using text zoom, this change will mean that anything using spacing units will no longer increase with the text size. This gives more room for the text in place which in turn helps with readability.Like I said, this is a first step. I do think we will find places where
remmakes sense to be used for spacing, but I think we can handle them in future PRs. There’s other places whereremuse could be problematic, such asborder-radiusand some sizing. This first step sets the stage for us to better design the text zoom experience.Testing
In Safari, you can change the text zoom by either:
In Chromium-based browsers, you can set the text size in chrome://settings/appearance. There are two options: using relative named sizes and changing the specific pixel size.
In Firefox, in about:preferences you can change the default font size or you can enable ”Zoom text only” for the default zoom level.
If you are testing for “regressions” I’d recommend sticking to the default text zoom. Like I said, this change should have no effect on that experience. The zoomed text experience might feel visually off. That’s normal. This is an accessibility preference taking precedence over design. We can improve the design of this experience, but we will need to specifically cater to that preference.