Our site hides every scrollbar, smooth-scrolls for exactly one link, and that link does not scroll
pub-trivia.app has one stylesheet of its own. app/globals.css is 117 lines: a Tailwind import, two blocks of design tokens, and then four rules that are not about tokens at all. @layer base { * { @apply border-b
pub-trivia.app has one stylesheet of its own. app/globals.css is 117 lines: a Tailwind import, two blocks of design tokens, and then four rules that are not about tokens at all.
@layer base {
* {
@apply border-border;
}
html {
scroll-behavior: smooth;
}
}
/* Hide all scrollbars */
* {
scrollbar-width: none;
}
*::-webkit-scrollbar {
display: none;
}
All four survive into the compiled 86,718-byte stylesheet the browser downloads, three of them unchanged and one with a redundancy removed:
*{border-color:hsl(var(--border))}
*{scrollbar-width:none}
::-webkit-scrollbar{display:none}
html{scroll-behavior:smooth}
I counted what * means here. Across the 72 public pages the site serves 20,962 elements, from 114 on the cookie page to 733 on the homepage, a mean of 291. Every one of them is matched by the first two rules.
The scrollbar one is doing something, and you cannot see it on a Mac
Read the computed value on the root element of our site and of this one, in the same browser, in the same session:
// on pub-trivia.app
getComputedStyle(document.documentElement).scrollbarWidth // "none"
// on dev.to
getComputedStyle(document.documentElement).scrollbarWidth // "auto"
The rule is live and it applies to the page's own scrollbar, not just to inner panels. What it does not do, on the machine I measured from, is change a single pixel:
window.innerWidth - document.documentElement.clientWidth // 0 on both sites
Zero on both, because macOS uses overlay scrollbars that take no layout space and fade out anyway. The people this rule is for are on Windows and Linux, where the page scrollbar is a persistent 15-pixel column with a thumb whose size tells you how long the document is and whose position tells you where you are in it.
The FAQ is 4,596 pixels tall in a 752-pixel window. Six screens of content, no scroll indicator, nothing to drag. I also checked whether the rule is earning its keep somewhere inside the page, by walking every element for an overflow that actually overflows:
[...document.querySelectorAll('*')].filter(e => {
const s = getComputedStyle(e);
return /auto|scroll/.test(s.overflowY + s.overflowX)
&& (e.scrollHeight > e.clientHeight + 2 || e.scrollWidth > e.clientWidth + 2);
}).length // 0
Zero. There is no inner scroller on that page for the rule to tidy up. And the one place on the site where something genuinely does not fit, the competitor column in our comparison tables, is overflow-hidden rather than scrollable, which is a separate bug I wrote about when the rounded corner turned out to be why you cannot reach it.
So a comment that says "Hide all scrollbars" hides exactly one scrollbar, the page's own, on the platforms where it was load-bearing.
One link on 72 pages
html { scroll-behavior: smooth } only matters when something navigates within the document. I grepped all 72 pages for in-page links and got one:
[...document.querySelectorAll('a[href^="#"]')]
// [{ href: '#how-it-works', text: 'See how it works' }]
One anchor, in the homepage hero. The homepage carries three section ids, how-it-works, features and pricing, and nothing anywhere links to the second two.
Then I clicked it, with the page fully settled, and sampled the scroll position fourteen times over 1.4 seconds:
scrollY: 0 0 0 0 0 0 0 0 0 0 0 0 0 0
hash: #how-it-works
The URL updates. The page does not move. The target is real and it is 2,696 pixels down:
document.getElementById('how-it-works') // <section id="how-it-works">
getBoundingClientRect().top + window.scrollY // 2696
Loading https://pub-trivia.app/#how-it-works directly lands at 2,696, and assigning location.hash from the console scrolls too. It is only the click that does nothing, and here is why:
window.addEventListener('click', (e) => console.log(e.defaultPrevented));
// clicking the Next <Link>: true
// clicking a plain <a href="#features"> I injected myself: true
Both. Something above us intercepts same-document anchor clicks, calls preventDefault, and does the navigation itself by pushing the hash into history. The browser's own fragment-scroll step never runs, and the router's replacement for it does not scroll to the element. It is not the <Link> component: a bare <a> added to the DOM by hand behaves identically, which means the interception is global, not per component.
The consequence for this post is small and quite funny. The smooth-scroll rule has never animated a click on this website. It is a rule written for one link, and that link has been broken the whole time, so the rule has never had an opportunity to be either nice or annoying.
Nothing here knows about Reduce Motion
The string prefers-reduced-motion appears zero times in the 86,718-byte stylesheet, and zero times anywhere in the repository. I confirmed what that means by emulating the preference over the DevTools protocol:
Emulation.setEmulatedMedia { features: [{ name: 'prefers-reduced-motion', value: 'reduce' }] }
matchMedia('(prefers-reduced-motion: reduce)').matches // true
getComputedStyle(document.documentElement).scrollBehavior // "smooth"
The browser is told motion is unwelcome and the document still declares itself smooth. For the one broken link that costs nobody anything. For the rest of the site, here is the inventory of motion-capable utility classes in the live HTML of all 72 pages:
| Class | Occurrences |
|---|---|
| transition-colors | 2,283 |
| transition-opacity | 288 |
| transition-all | 139 |
| duration-300 | 138 |
| ease-out | 138 |
| duration-200 | 9 |
| duration-500 | 1 |
| animate-pulse | 1 |
2,710 in total, none of them inside a media query. Nearly all of it is colour transitions on hover, which is the kind of motion reduced-motion users are not complaining about: no travel, no parallax, no scale.
The one that matters is the last row. A single animate-pulse ships on the public site, on a six-pixel dot inside the static product mock on the homepage, and it is an infinite loop. An element that never stops moving is close to the centre of what the preference was invented for, and it is the only animation the whole marketing site runs.
What I am changing
- Fix the link, not the rule. Three lines of click handler that find the section and scroll it into view, since the default has been prevented for us. If an anchor is the only in-page navigation on a site, it should work before anything decorates it.
-
Add the reduced-motion block.
html { scroll-behavior: auto }inside@media (prefers-reduced-motion: reduce), plus the standard animation and transition reset. It changes the experience of exactly one pulsing dot today, and it stops this being a thing somebody has to remember when the next animation lands. -
Give the page back its scrollbar.
scrollbar-width: noneon*was an aesthetic decision taken on a Mac, where it is invisible, and paid for on Windows by readers of a six-screen FAQ. If a specific panel wants no scrollbar it can ask for one with a class. - Delete the two unused ids, or link to them. A section id that nothing points at is a promise of navigation that does not exist.
Check it yourself
All four rules are in one file the browser will hand you:
CSS=$(curl -s https://pub-trivia.app/faq | grep -oE '/_next/static/chunks/[a-z0-9]+\.css' | head -1)
curl -s "https://pub-trivia.app$CSS" | grep -o 'scrollbar-width:[^;}]*'
curl -s "https://pub-trivia.app$CSS" | grep -o '::-webkit-scrollbar{[^}]*}'
curl -s "https://pub-trivia.app$CSS" | grep -o 'scroll-behavior:[^;}]*'
curl -s "https://pub-trivia.app$CSS" | grep -c 'prefers-reduced-motion' # 0
In a browser, open the homepage, click "See how it works", and watch the address bar gain a fragment while the page stays exactly where it is. Then paste pub-trivia.app/#how-it-works into the address bar and press enter, and you land on the section, because the anchor was never the problem.
On Windows or Linux, open the FAQ next to any other site and notice what is missing down the right-hand edge. On a Mac, run getComputedStyle(document.documentElement).scrollbarWidth in the console on both, which is the only way to see the difference.
The free tools are the pages with the most interaction on them and need no account, if you want somewhere to look for the hover transitions that the missing media query will eventually have to cover.
Originally published by Dev.to WebDev. Aggregated on AIWithGhost for educational purposes — full credit and traffic to the original publisher.