CSS Transform Properties in the Emil Kowalski Skills Repository: A Complete Guide
Use transform, transform-origin, scale(), translateX/Y(), rotateX/Y(), transform-style: preserve-3d, and will-change: transform for GPU-accelerated, 60 fps animations.
The Skills repository by Emil Kowalski (emilkowalski/skills) documents battle-tested conventions for performant UI animations. This guide covers every CSS transform property discussed across the codebase, with source file references and production-ready code examples.
Core Transform Properties
transform
The foundational property that enables all GPU-accelerated motion. According to skills/review-animations/STANDARDS.md, only transform and opacity should be animated because they run exclusively on the compositor thread, bypassing layout and paint calculations.
/* GPU-only animation — no layout thrashing */
.card {
transform: translateX(100px);
}
Source: skills/review-animations/STANDARDS.md at line 112
transform-origin
Controls the anchor point for scaling and rotation operations. The repository distinguishes between popover/tooltip origins (trigger-anchored) and modal origins (centered).
Popover pattern with custom property:
.popover {
transform-origin: var(--transform-origin);
transform: scale(0.95);
}
This aligns the popover's animation with the element that triggered it, creating natural visual continuity.
Source: skills/review-animations/STANDARDS.md at line 56
Transform Functions
scale()
Used for press feedback and entrance animations. The repository recommends scale(0.97) for button presses and scale(0.95) combined with opacity for element entrances.
Press feedback implementation:
.button:active {
transform: scale(0.97);
transition: transform 160ms ease-out;
}
Important: Scaling from 0 is discouraged as unrealistic. Use scale(0.95) with opacity instead.
Source: skills/review-animations/STANDARDS.md at line 59
translateX() and translateY()
The primary translation functions for horizontal and vertical movement. Used extensively in keyframe definitions.
Vertical slide-in animation:
@keyframes slideIn {
from { transform: translateY(100%); }
to { transform: translateY(0); }
}
Source: skills/review-animations/STANDARDS.md at line 86
rotateX() and rotateY()
Enable true 3D depth effects when combined with transform-style: preserve-3d. These create coin-flip, orbit, and depth animations without JavaScript overhead.
3D card flip:
.card {
transform-style: preserve-3d;
transition: transform 500ms ease;
}
.card:hover {
transform: rotateY(180deg);
}
Source: skills/emil-design-eng/SKILL.md at lines 370–376
transform-style: preserve-3d
Required for 3D transformations to propagate to child elements. Without this property, children flatten into their parent's plane.
.scene {
transform-style: preserve-3d;
/* Now children can use rotateX/Y with depth preserved */
}
Source: skills/emil-design-eng/SKILL.md at line 376
Performance Optimizations
Full Transform Strings Over Shorthand
The repository explicitly rejects Framer Motion shorthand (x, y, scale) in favor of full transform strings. Shorthand properties execute on the main thread, risking frame drops.
Recommended (compositor thread):
<motion.div animate={{ transform: "translateX(100px)" }} />
Avoid (main thread execution):
<motion.div animate={{ x: 100 }} />
Source: skills/improve-animations/AUDIT.md at line 75
will-change: transform
Hints to browsers that an element will animate, allowing early layer promotion. Use sparingly—only on elements that will actually animate.
.picker-highlight {
will-change: transform;
}
Source: skills/prototype/PICKER.md at line 60
Source File Reference
| File | Purpose | Key Content |
|---|---|---|
skills/review-animations/STANDARDS.md |
Core animation standards | GPU-only rule, transform-origin, scale() feedback, translateY() keyframes |
skills/review-animations/SKILL.md |
UI pattern guidelines | Popover vs. modal origin handling |
skills/improve-animations/AUDIT.md |
Performance auditing | Full transform strings, hardware acceleration |
skills/emil-design-eng/SKILL.md |
Advanced techniques | 3D transforms, preserve-3d, reduced-motion |
skills/prototype/PICKER.md |
Component examples | will-change implementation |
Summary
- Restrict animations to
transformandopacityfor guaranteed compositor-thread execution - Use
transform-origin: var(--transform-origin)for popovers aligned to triggers - Prefer
scale(0.97)for press feedback, avoid scaling from 0 - Combine
rotateX/Ywithpreserve-3dfor hardware-accelerated 3D without JavaScript - Write full transform strings in animation libraries to stay off the main thread
- Apply
will-change: transformonly to elements that will actually animate
Frequently Asked Questions
Why does the repository recommend against Framer Motion's x, y, and scale props?
These shorthand properties execute animations on the main thread rather than the compositor thread. According to skills/improve-animations/AUDIT.md, using transform: "translateX(100px)" ensures hardware acceleration and prevents frame drops during complex animations.
What's the difference between popover and modal transform origins in this system?
Popovers use transform-origin: var(--transform-origin) to align their scaling animation with the trigger element, creating visual continuity. Modals, which have no triggering element, remain centered with the default origin. This distinction is documented in skills/review-animations/STANDARDS.md.
When should will-change: transform be applied?
Use it on elements that will imminently animate, such as a picker highlight moving between options. The repository warns against overuse—will-change consumes GPU memory, so apply it only as needed and consider removing it after animations complete. See skills/prototype/PICKER.md for the implementation pattern.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →