Skip to content

perf(nav): drop the backdrop-blur behind the sticky header (scroll jank) - #175

Merged
marinom2 merged 1 commit into
mainfrom
perf/nav-scroll-jank
Jul 29, 2026
Merged

perf(nav): drop the backdrop-blur behind the sticky header (scroll jank)#175
marinom2 merged 1 commit into
mainfrom
perf/nav-scroll-jank

Conversation

@marinom2

Copy link
Copy Markdown
Owner

Scrolling in the desktop app was painful while the app measured 0% CPU at idle — the entire cost was per-frame, and only while the view moved. That shape is what pointed here.

The header is sticky top-0 and carried backdrop-blur-xl over a 55%-opaque background. A backdrop-filter samples whatever sits behind the element and blurs it — and because the header is sticky, what's behind it changes on every scroll frame. So the browser re-sampled and re-blurred the full viewport width ~60×/second at Tailwind's largest radius (24px).

At 3840×2160 that's a lot of pixels, and WebKitGTK is substantially slower at backdrop-filter than Chromium — which matters because the AppImage is a shell over this site, so the desktop app renders with WebKit, not Chrome.

Replaced with an opaque background. On the dark theme the two are near-indistinguishable; the per-frame cost goes to zero.

Also dropped the blur on the nav dropdown — its background was already bg-card/95, so the filter bought almost nothing visually while still forcing a filtered layer. It sits over static content, so it was never part of the scroll problem.

Left alone: the other 23 backdrop-blur uses. They're on ordinary cards that don't sit over moving content. Blur isn't the problem — blur over a scrolling backdrop is.

Verified: tsc clean · 673 tests · eslint clean · next build succeeds.

Scrolling in the desktop app was painful while the app sat at 0% CPU when
idle - the cost was entirely per-frame, and only while the view moved.

The header is `sticky top-0` and carried `backdrop-blur-xl` over a 55%-opaque
background. A backdrop-filter has to sample whatever is behind the element and
blur it; because the header is sticky, "whatever is behind it" is different on
every scroll frame. So the browser re-sampled and re-blurred the full width of
the viewport ~60 times a second, at Tailwind's largest radius. On a 3840x2160
display that is a lot of pixels, and WebKitGTK - which is what the desktop app
renders with, since the AppImage is a shell over the site - is substantially
slower at backdrop-filter than Chromium.

Replaced with an opaque background. On a dark theme the two are nearly
indistinguishable, and the per-frame cost goes to zero.

Also dropped the blur on the nav dropdown: its background was already bg-card/95,
so the filter bought almost nothing visually while still forcing a filtered
layer. It sits over static content anyway, so it was never the scroll problem.

The other 23 backdrop-blur uses are on ordinary cards that do not sit over
moving content, and are left alone - blur is not the problem, blur over a
scrolling backdrop is.

Verified: tsc clean, 673 tests, eslint clean, next build succeeds.
@vercel

vercel Bot commented Jul 29, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
lightnode Ready Ready Preview, Comment Jul 29, 2026 9:27am

Request Review

@marinom2
marinom2 merged commit 104aef8 into main Jul 29, 2026
6 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.

1 participant