Skip to content

feat(preset-wind4): add scrollbar width and color utilities - #5343

Merged
zyyv merged 5 commits into
unocss:mainfrom
anandghegde:feat/preset-wind4-scrollbar-utilities
Oct 20, 2026
Merged

zyyv merged 5 commits into
unocss:mainfrom
anandghegde:feat/preset-wind4-scrollbar-utilities

Conversation

@anandghegde

Copy link
Copy Markdown
Contributor

Description

Tailwind CSS v4.3 added scrollbar-{auto,thin,none} and scrollbar-thumb-* / scrollbar-track-* (tailwindlabs/tailwindcss#19981, #20019). preset-wind4 already has the scrollbar-gutter-* utilities from the same release (#5224), but not these. This PR adds them to rules/scrolls.ts.

  • scrollbar-auto / scrollbar-thin / scrollbar-none set scrollbar-width.
  • scrollbar-thumb-<color> / scrollbar-track-<color> set --un-scrollbar-thumb / --un-scrollbar-track and scrollbar-color: var(--un-scrollbar-thumb) var(--un-scrollbar-track). This matches Tailwind's output. Both variables are registered with @property (<color>, initial value #0000) and get the usual properties-layer fallback, the same as Tailwind's --tw-scrollbar-*. That way, setting only one of the two still gives a valid scrollbar-color.
  • The colors go through colorResolver, so theme colors, /50 alpha, arbitrary values, $var and current/transparent/inherit all work. There are also scrollbar-(thumb|track)-op-<n> rules, like the other wind4 color utilities (accent-op-*, caret-op-*, ring-op-*).
<div class="overflow-auto scrollbar-thin scrollbar-thumb-gray-400 scrollbar-track-transparent"></div>
.scrollbar-thin{scrollbar-width:thin;}
.scrollbar-thumb-gray-400{--un-scrollbar-thumb:color-mix(in srgb, var(--colors-gray-400) var(--un-scrollbar-thumb-opacity), transparent);scrollbar-color:var(--un-scrollbar-thumb) var(--un-scrollbar-track);}
.scrollbar-track-transparent{--un-scrollbar-track:transparent;scrollbar-color:var(--un-scrollbar-thumb) var(--un-scrollbar-track);}

Notes:

  • Name clashes: no other built-in rule starts with scrollbar- apart from scrollbar-gutter-*, and those still work. The community unocss-preset-scrollbar uses scrollbar-(thumb|track)-color-* and -radius-*. Neither of those parses as a color, so these new rules don't match them. Its scrollbar-thin/scrollbar-none emit the same scrollbar-width declaration.
  • Autocomplete suggests scrollbar-(thumb|track)-$colors and the opacity variants.

Tests

  • Added the new utilities to test/assets/preset-wind4-targets.ts. The regenerated snapshot only changes for the new entries.
  • Added an inline test to test/preset-wind4.test.ts that covers the @property output and the preflight fallback.
  • pnpm build, then pnpm vitest run: 100 files, 731 passed / 3 skipped.
  • tsgo --noEmit passes, and eslint on the changed files passes.

This PR was written with help from Claude Code, and I reviewed it.

🤖 Generated with Claude Code

https://claude.ai/code/session_01QBWFWqjbUQGS1c9LsM2bxX

@netlify

netlify Bot commented Sep 14, 2026 •

Copy link
Copy Markdown

✅ Deploy Preview for unocss ready!

Built without sensitive environment variables

Name Link
🔨 Latest commit fb80f7f
🔍 Latest deploy log https://app.netlify.com/projects/unocss/deploys/6ad7728206864fd51da8bf74
😎 Deploy Preview https://deploy-preview-5343--unocss.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
🤖 Make changes Run an agent on this branch

To edit notification comments on pull requests, go to your Netlify project configuration.

['scrollbar-thin', { 'scrollbar-width': 'thin' }],
['scrollbar-none', { 'scrollbar-width': 'none' }],

[/^scrollbar-(thumb|track)-(.+)$/, function* ([, part, body], ctx) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Happy to add it, but I want to check which "size" you mean, since the two readings pull the PR in quite different directions.

1. Sizes for the WebKit scrollbar parts, like unocss-preset-scrollbar's scrollbar-w-*, scrollbar-h-* and scrollbar-radius-* / scrollbar-(thumb|track)-radius-*. Those write --scrollbar-width / --scrollbar-height and apply them through ::-webkit-scrollbar selectors.

One thing to weigh if that's the intent: ::-webkit-scrollbar styling is ignored once the element has a standard scrollbar-width or scrollbar-color, which is what scrollbar-thin and scrollbar-thumb-* in this PR set. That's the reason the community preset gates the two behind its compatible option. So combining them in one preset means scrollbar-w-2 scrollbar-thin silently drops the width. In current UnoCSS the WebKit parts are also already reachable without new rules, e.g. [&::-webkit-scrollbar]:w-2.

2. A parsed value for scrollbar-width itself, replacing the three static rules with something like:

[/^scrollbar-(?:width-)?(.+)$/, ([, w], { theme }) => ({ 'scrollbar-width': h.bracket.cssvar.global(w) })]

so scrollbar-[thin] and scrollbar-$my-width work alongside scrollbar-auto|thin|none. The property only accepts auto | thin | none per spec, so a length there is invalid CSS, and the pattern needs care not to shadow scrollbar-gutter-* or scrollbar-thumb-*.

My own preference is to keep this PR at Tailwind v4.3 parity (scrollbar-width keywords plus thumb/track colors) and do the WebKit part sizes as a follow-up, where the interaction above can be handled properly. But it's your call. Tell me which one you want and I'll push it.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added the size parsing in 67b718f: scrollbar-(w|h)-<length> and scrollbar-(track-|thumb-)?radius-*, following unocss-preset-scrollbar, applied to the ::-webkit-scrollbar* pseudo elements.

  • Length parsing follows preset-wind4's value semantics: scrollbar-w-4 → calc(var(--spacing) * 4), while explicit units (scrollbar-w-2px), brackets (scrollbar-h-[3rem]) and cssvars (scrollbar-w-$var) pass through as-is.
  • scrollbar-radius-* accepts the radius theme (scrollbar-radius-sm → var(--radius-sm)) plus full, and sets both thumb and track; scrollbar-(track|thumb)-radius-* targets a single part.
  • Since a rule can't retarget its own selector, the pseudo-element selectors come from a new scrollbar variant (variants/scrollbar.ts, same $ -prefixed internal-rule pattern as placeholder), so the utilities also compose with variants (md:scrollbar-w-4 works).

That picks reading 1 from my earlier question. The standard-vs-WebKit interaction I mentioned still applies — WebKit part styling is ignored once standard scrollbar-width/scrollbar-color is set on the element — which is the same trade-off the community preset makes.

@anandghegde
anandghegde force-pushed the feat/preset-wind4-scrollbar-utilities branch from 6b65708 to 0b5ed63 Compare September 15, 2026 16:40
Add `scrollbar-(w|h)-*` and `scrollbar-(track-|thumb-)?radius-*` parsing
following unocss-community/unocss-preset-scrollbar, applied to the
`::-webkit-scrollbar*` pseudo elements. Length values follow preset-wind4
semantics (spacing scale, units, brackets, cssvars), radius values follow
the `radius` theme. The pseudo-element selectors are applied by a new
`scrollbar` variant using the same `$ `-prefixed internal-rule pattern as
`placeholder`.

Co-Authored-By: Claude Code <[email protected]>
@anandghegde

Copy link
Copy Markdown
Contributor Author

The size parsing requested in the inline review is now present in the current head. The existing test/preset-wind4.test.ts size case covers scrollbar-w-2px, scrollbar-w-4, scrollbar-h-[3rem], and radius variants, with generated CSS asserting the expected width/height values. I built the required workspace packages and ran pnpm vitest run test/preset-wind4.test.ts: 24 tests passed. Could you please re-check the current head?

@anandghegde

Copy link
Copy Markdown
Contributor Author

@zyyv the size parsing is in 67b718f. scrollbar-(w|h)-* and scrollbar-(track-|thumb-)?radius-* apply to ::-webkit-scrollbar* via a scrollbar variant, so they compose with other variants. This is the WebKit-parts reading of "size", following unocss-preset-scrollbar. If you meant parsing the scrollbar-width value itself, tell me and I'll change it. The caveat about standard scrollbar-width and scrollbar-color overriding the WebKit parts still applies. Could you take another look?

@zyyv

zyyv commented Oct 14, 2026

Copy link
Copy Markdown
Member

@zyyv the size parsing is in 67b718f. scrollbar-(w|h)-* and scrollbar-(track-|thumb-)?radius-* apply to ::-webkit-scrollbar* via a scrollbar variant, so they compose with other variants. This is the WebKit-parts reading of "size", following unocss-preset-scrollbar. If you meant parsing the scrollbar-width value itself, tell me and I'll change it. The caveat about standard scrollbar-width and scrollbar-color overriding the WebKit parts still applies. Could you take another look?

Thanks for submitting the update; I'll review it carefully later.

@pkg-pr-new

pkg-pr-new Bot commented Oct 20, 2026 •

Copy link
Copy Markdown

Open in StackBlitz

commit: fb80f7f

@zyyv
zyyv added this pull request to the merge queue Oct 20, 2026
Merged via the queue into unocss:main with commit 5537531 Oct 20, 2026
11 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants