mirror of
https://github.com/heygen-com/hyperframes.git
synced 2026-09-04 16:42:27 +00:00
docs(skills): teach transforms-over-layout-props up front
Reframe the gsap "prefer transforms" guidance from a GPU-perf nicety to the real HyperFrames render-correctness reason: the seek-by-frame capture engine integer-snaps layout props, so slow tweens stutter. Add the CSS-rest + x/y offset conversion recipe, the parent-relative %/px note, and the one exception (html-in-canvas <canvas layoutsubtree> elements). Frames the gsap_non_transform_motion lint rule as the backstop, not the teacher, so agents reach for transforms up front instead of relying on lint to reject. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
619a603eab
commit
58f7dc1c72
@@ -18,7 +18,7 @@
|
||||
"files": 1
|
||||
},
|
||||
"hyperframes-animation": {
|
||||
"hash": "57458f4308708e21",
|
||||
"hash": "9f0ccb60ff53e739",
|
||||
"files": 115
|
||||
},
|
||||
"hyperframes-cli": {
|
||||
|
||||
@@ -57,9 +57,25 @@ Animate any custom property. Works for color, length, number — anything CSS wi
|
||||
|
||||
## Performance Rules
|
||||
|
||||
### Prefer transforms and opacity
|
||||
### Animate transforms, not layout properties
|
||||
|
||||
Animating `x`, `y`, `scale`, `rotation`, `opacity` stays on the GPU compositor. Avoid `width`, `height`, `top`, `left`, `margin`, `padding` when transforms achieve the same effect.
|
||||
Animate `x`, `y`, `scale`, `rotation`, `opacity`. Never animate `left`, `right`, `top`, `bottom`, `width`, `height`, `margin*` — and never `roundProps`.
|
||||
|
||||
This is a **render-correctness** rule in HyperFrames, not just a GPU-performance nicety. The renderer seeks frame-by-frame and screenshots each frame, and the browser compositor snaps layout properties to whole device pixels. On a fast tween the per-frame step is several pixels, so the snap is invisible; on a slow tween or a long ease-out tail the value moves less than a pixel per frame — it holds the same pixel for several frames, then jumps a whole one. The result is motion that looks smooth when fast but visibly stutters when slow. Transforms interpolate sub-pixel and stay smooth at any speed. `roundProps` forces the same integer snap onto a transform — don't use it.
|
||||
|
||||
**Convert a position animation to a transform** by leaving the element at its resting `left`/`top` in CSS and animating the _offset_ with `x`/`y`:
|
||||
|
||||
```javascript
|
||||
// CSS: #card { left: 1340px; top: 540px } ← resting position stays in CSS
|
||||
tl.to("#card", { left: 1340, top: 540, duration: 1 }); // ✗ stutters
|
||||
tl.fromTo("#card", { x: 640, y: 0 }, { x: 0, y: 0, duration: 1 }); // ✓ x/y = delta from CSS rest (640 = startLeft − 1340)
|
||||
```
|
||||
|
||||
For a parent-relative `left: "100%"` sweep, use `xPercent: 100` only when the element is the full width of its container; otherwise convert to pixels (`x: containerWidth`).
|
||||
|
||||
**The one exception:** elements drawn through the html-in-canvas API — those under a `<canvas layoutsubtree>` ancestor, e.g. the `liquid-glass-*` blocks. The canvas rasterizes from sub-pixel `getComputedStyle`, so layout props don't snap there and those elements keep `left`/`top`. Everything the browser lays out (plain DOM) follows the rule.
|
||||
|
||||
The `gsap_non_transform_motion` lint rule is the backstop, not the teacher — reach for transforms from the start instead of animating layout props and waiting for lint to reject them.
|
||||
|
||||
### will-change (sparingly)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user