Fix scroll jank, which got worse the bigger the window - #32
Merged
MyNamesEMurray merged 1 commit intoSep 7, 2026
Merged
Conversation
Two CSS effects were repainting the whole viewport on every scroll frame, on a CPU: the app disables hardware acceleration on purpose, since it shares a machine and a GPU with OBS and a game. Cost scales with area, so the bigger the window the worse it got -- exactly the complaint. Measured on the settings page at 2560x1440 with software rasterisation, scrolling 135 frames: as shipped p95 54ms max 221ms 80/135 frames dropped without the backdrop blur p95 31ms max 45ms without the fixed bg p95 52ms max 96ms without both p95 17ms max 17ms Neither alone was enough, which is why this reads as "just slow" rather than as one bad effect. `backdrop-filter: blur(14px)` on every .card meant re-reading and re-blurring the backdrop every frame the card moved, for an effect that is nearly invisible over a dark, low-contrast gradient. The card fill carries the panel instead (--glass-card). The deck header's blur goes too: the feed scrolls in its own container below it, so there was never anything moving behind it to blur. `background-attachment: fixed` cannot be scrolled as a layer, so the gradient was recomputed across the viewport every frame. It moves to its own fixed layer, which looks identical and paints once. That layer is opt-in (`<body class="studio">`) rather than automatic, and the direction matters: the overlay is a transparent guest on someone else's live stream, and its `background: transparent !important` would not have saved it -- a pseudo-element is not the body's background. A page that forgets the class looks flat; one that inherited it by default could paint over a broadcast. Verified the overlay has no such layer and still composites transparent. Deck feed and settings now hold a 17ms frame at 2560x1440. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LWa54BF5RjHWC5GFaENZMM
MyNamesEMurray
deleted the
claude/live-mic-transcription-accuracy-x5ptio
branch
September 7, 2026 03:09
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Scrolling was janky, and worse at fullscreen. Two CSS effects were repainting the whole viewport on every scroll frame, on the CPU: the app calls
app.disableHardwareAcceleration()on purpose, since it shares a machine and a GPU with OBS and a game. Software rasterisation cost scales with area, so the bigger the window the worse it got — which is exactly the reported symptom.The measurement
Settings page, 2560×1440, software rasterisation, 135 scroll frames:
Neither alone was enough, which is why this presented as "just slow" rather than as one obviously bad effect.
Changes
backdrop-filter: blur(14px)on every.cardis gone. Blurring a backdrop means re-reading and re-blurring it every frame the card moves — for an effect that is nearly invisible over a dark, low-contrast gradient. A new--glass-cardfill carries the panel instead. The deck header's blur goes too: the feed scrolls in its own container below it, so there was never anything moving behind it to blur.background-attachment: fixedis gone. A fixed attachment cannot be scrolled as a layer, so the gradient was recomputed across the viewport every frame. It moves to its own fixed layer (.studio::before), which looks identical and paints once.<body class="studio">), not automatic. The direction is deliberate and is the one thing I'd ask you to sanity-check: the overlay is a transparent guest on someone else's live stream, and itsbackground: transparent !importantwould not have protected it, because a pseudo-element is not the body's background. A page that forgets the class looks flat; one that inherited an automatic layer could paint over a broadcast.backdrop-filterand nobackground-attachment: fixedon anything that scrolls or sits over something that scrolls. Blur stays allowed on a transient overlay above a still page, like the command palette, which is the one place it does visible work.Verification
node --checkover every JS file,config.example.jsonparse,npm test(161 pass, 0 fail, 1 pre-existing Windows-only SAPI skip),npm run smoke→ SMOKE OK..studioclass, its::beforecomputes tocontent: none, and its body still composites fully transparent (rgba(0,0,0,0), no background image)./favicon.ico404.Caveat on the numbers: these are headless Chromium with
--disable-gpu, as the closest available stand-in for Electron'sdisableHardwareAccelerationon Windows. The relative before/after is solid and the effects removed are well-understood repaint traps, but the absolute milliseconds on your machine will differ.Risk & rollout
<body>tags. No server, config, or behaviour change.Checklist
npm run smokepasses locally (or CI is green)main🤖 Generated with Claude Code
https://claude.ai/code/session_01LWa54BF5RjHWC5GFaENZMM
Generated by Claude Code