fix: isolate content layer from animated background to eliminate flickering

Root cause: backdrop-filter on header/nav resamples the animated
background 60fps, causing GPU compositing flicker (Chromium bug).

- Add isolation: isolate wrapper in AppShell to prevent backdrop-filter
  from seeing through to the animated background layer
- Add will-change: transform + translateZ(0) to BackgroundRenderer
  for stable GPU layer
- Replace contain: layout style with contain: content on main
- Replace transition-all with specific properties in Card component
This commit is contained in:
Fringg
2026-02-27 07:52:45 +03:00
parent d8cf4301ca
commit 04eacf6421
4 changed files with 142 additions and 136 deletions

View File

@@ -90,6 +90,8 @@ export function BackgroundRenderer() {
opacity: effectiveConfig.opacity,
filter: effectiveConfig.blur > 0 ? `blur(${effectiveConfig.blur}px)` : undefined,
contain: 'strict',
willChange: 'transform',
transform: 'translateZ(0)',
}}
>
<Suspense fallback={null}>

View File

@@ -11,7 +11,7 @@ const cardVariants = cva(
'relative overflow-hidden',
'border border-dark-700/40 bg-dark-900/70',
'rounded-[var(--bento-radius)]',
'transition-all duration-200',
'transition-[border-color,background-color,box-shadow,transform,opacity] duration-200',
// GPU acceleration
'transform-gpu',
// Glass border inset

View File

@@ -280,9 +280,12 @@ export function AppShell({ children }: AppShellProps) {
return (
<div className="min-h-screen">
{/* Animated background */}
{/* Animated background — on its own GPU layer, below everything */}
<BackgroundRenderer />
{/* Content layer — isolated from background to prevent backdrop-filter
from resampling the animated background every frame (Chromium bug) */}
<div className="relative z-10" style={{ isolation: 'isolate' }}>
{/* Global components */}
<WebSocketNotifications />
<CampaignBonusNotifier />
@@ -433,5 +436,6 @@ export function AppShell({ children }: AppShellProps) {
wheelEnabled={wheelEnabled}
/>
</div>
</div>
);
}

View File

@@ -268,10 +268,10 @@
}
}
/* Optimize main scrollable content */
/* Main content — containment removed to avoid GPU layer conflicts
with isolation: isolate on content wrapper */
main {
/* Prevent layout shifts during scroll */
contain: layout style;
contain: content;
}
/* Light theme - Champagne */