# Best Practices for Button Press Feedback Using Scale Transforms

> Enhance UX with button press feedback. Apply a subtle scale transform and ease out transition for tactile GPU accelerated feedback that mimics real world button compression.

- Repository: [Emil Kowalski/skills](https://github.com/emilkowalski/skills)
- Tags: best-practices
- Published: 2026-08-01

---

**Apply a subtle `scale(0.97)` transform to `:active` states with a 160ms ease-out transition to create tactile, GPU-accelerated feedback that mimics real-world button compression.**

Providing immediate visual feedback when users interact with buttons is essential for building responsive, polished interfaces. The `emilkowalski/skills` repository codifies proven techniques for button press feedback using scale transforms that balance physical realism with performance constraints. According to the animation standards documented in the source code, these guidelines ensure interactions feel instantaneous across devices while maintaining 60fps animations.

## Why Scale Transforms Matter for Button Feedback

Physical buttons compress visibly when pressed, and digital interfaces should replicate this tactile cue. The `scale()` transform is uniquely suited for this interaction because it runs entirely on the GPU, avoiding expensive layout and paint calculations. As noted in [`skills/review-animations/STANDARDS.md`](https://github.com/emilkowalski/skills/blob/main/skills/review-animations/STANDARDS.md), animating properties like `width`, `height`, or `margin` triggers browser layout recalculation, which can cause frame drops on lower-end devices during rapid interactions.

## Implementation Standards from the Source

### Subtle Down-Scaling on Active States

The standard implementation applies `transform: scale(0.97)` to the `:active` pseudo-class. According to [`skills/review-animations/STANDARDS.md`](https://github.com/emilkowalski/skills/blob/main/skills/review-animations/STANDARDS.md) at line 59, acceptable values range between **0.95 and 0.98**, with 0.97 serving as the baseline default. This range mimics the visual compression of a physical button under finger pressure while remaining subtle enough to avoid jarring visual disruption.

### Timing and Easing Functions

Pair the scale transform with a transition duration between **100ms and 160ms**, using an ease-out curve. The source code specifically recommends `transform 160ms ease-out` as documented in [`skills/review-animations/STANDARDS.md`](https://github.com/emilkowalski/skills/blob/main/skills/review-animations/STANDARDS.md) at line 41. The ease-out timing function starts quickly and decelerates, reinforcing the sensation that the interaction has already begun the moment the user presses.

### GPU Acceleration and Performance

Confine press feedback animations to GPU-friendly properties only. As implemented in `emilkowalski/skills`, the `transform` property is the only animated value, ensuring the browser compositor handles the animation without involving the main thread. This guarantees 60fps performance even during complex UI interactions or on constrained hardware.

## Extending the Pattern Across UI Elements

Consistency builds interaction literacy. According to [`skills/improve-animations/AUDIT.md`](https://github.com/emilkowalski/skills/blob/main/skills/improve-animations/AUDIT.md) at line 56, the same `:active` scale treatment should apply uniformly to **buttons**, **icon-only controls**, **list-items**, and any element receiving click or tap events. This uniformity creates a cohesive tactile language throughout the application, training users to expect consistent physical feedback regardless of the specific control type.

## Accessibility and Motion Preferences

Respect user system preferences for reduced motion. As documented in [`skills/review-animations/STANDARDS.md`](https://github.com/emilkowalski/skills/blob/main/skills/review-animations/STANDARDS.md) at line 62, when `prefers-reduced-motion: reduce` is detected, either disable the scale transition entirely or significantly shorten its duration. This preserves the visual feedback for users who need it while preventing motion discomfort for those sensitive to animation.

## Code Implementation

The following CSS implements the repository's standards for tactile button feedback:

```css
/* Base button with GPU-friendly transition */
.button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0.5rem 1rem;
  background: var(--brand);
  color: white;
  border: none;
  border-radius: 4px;
  cursor: pointer;

  /* Animate only transform for 60fps performance */
  transition: transform 160ms var(--ease-out);
}

/* Press feedback: subtle down-scale */
.button:active {
  transform: scale(0.97);
}

/* Respect reduced motion preferences */
@media (prefers-reduced-motion: reduce) {
  .button {
    transition: none;
  }
  .button:active {
    transform: none;
  }
}

```

For React implementations, apply the same CSS class to ensure consistency:

```jsx
// React component using standardized press feedback
export default function PrimaryButton({ children, ...rest }) {
  return (
    <button className="button" {...rest}>
      {children}
    </button>
  );
}

```

### Entrance Animation Considerations

While not strictly part of press feedback, the same physical principles extend to entry animations. According to [`skills/review-animations/STANDARDS.md`](https://github.com/emilkowalski/skills/blob/main/skills/review-animations/STANDARDS.md) at line 53, avoid starting entrance animations from `scale(0)`, which creates an unrealistic "pop-in" effect. Instead, use a starting scale of at least **0.9** combined with opacity transitions for natural-looking entrances.

## Summary

- **Apply `scale(0.97)`** (range 0.95–0.98) to `:active` states for realistic compression feedback
- **Animate with `transform 160ms ease-out`** to ensure immediate tactile response without layout thrashing
- **Keep animations GPU-only** by avoiding `width`, `height`, or `margin` changes during press states
- **Maintain consistency** across all pressable elements including buttons, icons, and list items as audited in [`skills/improve-animations/AUDIT.md`](https://github.com/emilkowalski/skills/blob/main/skills/improve-animations/AUDIT.md)
- **Respect `prefers-reduced-motion`** by disabling or shortening scale transitions for accessibility

## Frequently Asked Questions

### What is the optimal scale value for button press feedback?

The standard value is **`scale(0.97)`**, with an acceptable range between 0.95 and 0.98 according to [`skills/review-animations/STANDARDS.md`](https://github.com/emilkowalski/skills/blob/main/skills/review-animations/STANDARDS.md). Values below 0.95 tend to feel exaggerated and jarring, while values above 0.98 may be too subtle for users to perceive the interaction.

### Why should I avoid animating width or height for button feedback?

Animating dimensional properties like `width` or `height` triggers browser layout recalculation and paint cycles, which can drop frames on lower-end devices. The `scale()` transform operates entirely on the GPU compositor layer, ensuring 60fps performance even during rapid successive presses.

### How do I handle reduced motion preferences for button transforms?

Wrap scale transitions in a `@media (prefers-reduced-motion: reduce)` query to either disable the transition entirely or remove the transform change. This preserves the `:active` state for visual feedback while eliminating motion that could cause discomfort for users with vestibular disorders.

### Can I use scale transforms for entrance animations?

Yes, but never start from `scale(0)` as it creates an unrealistic pop-in effect. According to the physicality guidelines in the repository, use a starting scale of at least **0.9** combined with opacity transitions. This mimics objects entering the field of view rather than materializing from nothing.