Move every looping animation onto the compositor

Performancekamo-marketing
Shipped
August 20, 2026 at 8:02 PM UTC
Author
Kamo
Commit
c945d88

All 26 elements Lighthouse listed under "avoid non-composited animations" were the same mistake in four places: animating a paint property. Measured with Chrome via getAnimations(), which reports exactly what the audit inspects. desktop 29 -> 2 (the 2 left are backgroundColor TRANSITIONS, mobile 1 -> 1 not animations, and are not in the audit's list) Worth noting the report was desktop: at =<767px the site already stops these, so mobile measured 1 before and after. hexagon-glow-rotate, x12. Animated `background-position` AND `transform: rotate` together. Dropping the background travel leaves a transform-only animation; a gradient sliding underneath a rotating, 8px-blurred glow is not something anyone can pick out. gradient-border-travel, x12. See below — this one fought back. shimmer, x1. Animated `left`, a layout property, so the banner relaid out every frame. Now `transform`. The percentages are NOT interchangeable: `left` resolves against the containing block, `translateX` against the element's own width, which here is 60% of it — so -100% became -166.667% and 200% became 333.333%. badge-pulse, x1. Animated the `background` shorthand. The fill moved to an ::after that fades opacity between the same two alphas. It sits at z-index -1, because a positioned pseudo-element at 0 paints OVER inline content and would have washed out the word it sits behind. hero-headline-pass, x1. Removed rather than reimplemented. A text-clipped sweep cannot be composited — it is moving paint inside glyph shapes, and no transform or opacity expresses it. The workaround was tried before and measured worse: duplicating the sentence in a masked overlay took the count UP from 34 to 41 and left a second full raster of the headline running forever. The vertical fill it travelled over remains, as does the one-shot entrance. THE GRADIENT BORDER, AND WHY ::before WAS THE WRONG ANSWER. The obvious rewrite is to put the gradient on `::before` and translate it. It rendered nothing, and the reason is worth keeping: these cards are `<GradientBorder className="... hexagon-border-glow">`, so ONE element carries both classes — and `.hexagon-border-glow::before` already exists as a hexagon-clipped, blurred hover glow at `opacity: 0`. An element has exactly one ::before, so the rule sets merged and the gradient inherited the invisibility, the clip-path and the blur. The `overflow: hidden` needed to clip a 200%-wide sweep would also have cropped that glow's `inset: -4px` and broken the hover. So the sweep gets its own elements, which cannot collide: a `__track` that clips, and a `__sweep` twice as wide that translates -50% against a gradient repeating at its midpoint, so the loop has no seam. Verified by screenshot at 2x against production, not by reading the CSS: the blue-violet hairline is present and matches. Console and Issues clean, all guards pass.

All changes

Like what you see shipping?

Every one of these updates lands in your workspace automatically. Start free and watch it grow week after week.

Start Free ForeverView Pricing