How to Implement Button Press Feedback with Scale Transform: A Complete Guide

The emilkowalski/skills repository specifies that button press feedback should use transform: scale(0.97) applied on the :active pseudo-class with a 160ms ease-out transition to create subtle, GPU-accelerated tactile feedback.

The emilkowalski/skills repository serves as a curated collection of design and animation guidelines for high-quality UI components. Mastering button press feedback with scale transform ensures users receive immediate physical confirmation of interactions while maintaining optimal rendering performance across devices.

Animation Standards in STANDARDS.md

According to skills/review-animations/STANDARDS.md, the canonical standard for pressable elements requires any pressable element to implement a subtle scale-down effect. The specification mandates transform: scale(0.97) triggered on the :active state, accompanied by a 160ms ease-out transition.

This standard deliberately restricts the scale factor to the range of 0.95–0.98, with 0.97 serving as the repository's default value. The constraint prevents feel-breaking regressions where excessive scaling might disorient users or compromise visual hierarchy.

Implementation Approaches

Plain CSS Implementation

Apply the transform to any button or pressable element using standard CSS selectors. In skills/emil-design-eng/SKILL.md, the repository provides this baseline implementation:

/* Default state */
button,
[data-pressable] {
  transition: transform 160ms ease-out;
}

/* Pressed state – subtle shrink */
button:active,
[data-pressable]:active {
  transform: scale(0.97);
}

This approach leverages the GPU-accelerated transform property to avoid layout thrashing while affecting the button's content proportionally.

Tailwind CSS Utility Classes

For utility-first workflows, the equivalent Tailwind implementation uses the active: variant:

<button class="transition-transform duration-150 ease-out active:scale-95">
  Click me
</button>

While the Tailwind example above uses active:scale-95 for brevity, the repository standard in skills/review-animations/STANDARDS.md prefers scale(0.97) for consistency across design systems.

React with CSS-in-JS

When using styled-components or similar CSS-in-JS solutions, implement the pattern exactly as specified in the design engineering documentation:

import styled from 'styled-components';

const Pressable = styled.button`
  transition: transform 160ms ease-out;

  &:active {
    transform: scale(0.97);
  }
`;

export const Example = () => <Pressable>Press me</Pressable>;

Framer Motion Considerations

The repository contains specific warnings regarding Framer Motion implementations in skills/review-animations/STANDARDS.md. While Framer Motion provides shorthand properties, the documentation explicitly states that Framer Motion's shorthand scale prop is NOT hardware-accelerated under load.

Instead, use the full transform string to ensure GPU acceleration:

import { motion } from 'framer-motion';

export const MotionButton = () => (
  <motion.button
    whileTap={{ transform: 'scale(0.97)' }}
    transition={{ duration: 0.16, ease: 'easeOut' }}
  >
    Press
  </motion.button>
);

Audit and Quality Assurance

The skills/improve-animations/AUDIT.md file reinforces the scale transform requirement as a high-severity check. During code reviews, developers should search for missing :active states and verify that press feedback exists on all interactive elements.

The audit checklist categorizes missing press feedback as a feel-breaking issue that significantly degrades perceived application quality. Consistent application of the 0.97 scale factor across the codebase ensures unified tactile feedback.

Edge Cases and Exceptions

As documented in skills/emil-design-eng/SKILL.md, modal dialogs represent the primary exception to standard implementation. While standard buttons scale from their center origin, modal implementations may require adjusted transform origins to maintain visual stability during the scale animation.

Summary

  • The emilkowalski/skills repository mandates transform: scale(0.97) with a 160ms ease-out transition for all pressable elements
  • Apply the transform on the :active pseudo-class or equivalent JavaScript event handlers
  • Use the full transform string in Framer Motion rather than the scale shorthand to maintain GPU acceleration
  • Reference skills/improve-animations/AUDIT.md during code reviews to catch missing feedback implementations
  • Keep scale values between 0.95 and 0.98 to avoid visual disruption while maintaining perceptible physical feedback

Frequently Asked Questions

Why does the repository specify scale(0.97) instead of a more dramatic scale?

The 0.97 value strikes a deliberate balance between perceptibility and subtlety. As implemented in skills/emil-design-eng/SKILL.md, this scale factor provides sufficient physical feedback to confirm the press action without creating a feel-breaking regression that might disorient users or compromise the visual stability of the interface.

What makes transform scale more performant than width or height animations?

The transform property, including scale, is GPU-accelerated and operates on the compositor thread without triggering layout recalculations. According to the animation standards, this avoids layout thrashing that occurs when animating layout properties like width or height, ensuring the button press feedback maintains 60fps performance even on resource-constrained devices.

Should disabled buttons also implement this scale transform?

The repository standards in skills/review-animations/STANDARDS.md scope the requirement to "any pressable element." Disabled buttons that do not respond to user input should not display the :active state or the associated scale transform, as this would create confusing feedback suggesting an interaction occurred when the element is actually inert.

How do I audit existing code for missing button press feedback?

Reference skills/improve-animations/AUDIT.md and search for interactive elements lacking :active states or transform: scale declarations. The audit process involves checking that all buttons, links, and pressable cards implement the 160ms ease-out scale transition, flagging any omissions as high-severity feel-breaking issues requiring immediate correction.

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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →