415 words, 3 min read

One of those tiny UI details that quietly annoys users more than you'd expect: scrollbars that flash in and out of existence, causing the page layout to jump around. This week I finally cleaned it up in my Phoenix app and the fix was surprisingly elegant.

The problem

The original root.html.heex had this on the <html> element:

<html lang="en" class="[scrollbar-gutter:stable]">

scrollbar-gutter: stable is a CSS property that reserves space for the scrollbar even when it isn't needed — the idea being to prevent layout shifts when content height changes. It's a reasonable approach, but it has a side effect: on macOS with "Show scroll bars: Always", you end up with a permanent empty gutter on pages that don't scroll. On Windows, where scrollbars are visible by default, the gutter is always there. Depending on your layout, that reserved space can look odd.

The solution

I removed the Tailwind utility class from the <html> tag and instead reached for a small CSS snippet:

/* Only show scrollbars when content actually overflows */
* {
scrollbar-width: thin;
scrollbar-color: transparent transparent;
}
*:hover {
scrollbar-color: rgba(0, 0, 0, 0.2) transparent;
}

What this does:

  • scrollbar-width: thin — uses the browser's thin scrollbar variant, which is less visually heavy than the default.
  • scrollbar-color: transparent transparent — hides the scrollbar thumb and track by making them fully transparent. The scrollbar doesn't disappear from the DOM; it just becomes invisible when you're not interacting with the element.
  • *:hover { scrollbar-color: rgba(0,0,0,0.2) transparent } — fades the scrollbar thumb in (as a subtle translucent grey) only when the user hovers over the element. This gives a clean overlay-style scrollbar feel, similar to what macOS does natively.

Why this feels better

The end result is a UI that looks clean and uncluttered at rest, but still gives users a clear scrollbar affordance the moment they move their cursor over a scrollable area. No layout jump, no reserved gutter space, and no permanently visible chrome competing for attention.

It's a two-file change — one CSS block and the removal of a single Tailwind class — but the visual impact is noticeable, especially on pages with sidebars or nested scrollable containers.

Browser support

scrollbar-width and scrollbar-color are part of the CSS Scrollbars Specification and have solid support in Firefox and Chromium-based browsers. Safari added support in version 18.2. For older Safari versions the scrollbar will just render with its default appearance — a perfectly acceptable fallback.

Small change, cleaner app. Sometimes that's all it takes.