# How Should Buttons Be Animated for Responsiveness: Lessons from emilkowalski/skills

> Learn how to animate buttons for responsiveness using the emilkowalski/skills repo. Apply subtle scale transforms and custom easing for snappy, natural tactile feedback.

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

---

**Apply a subtle `transform: scale(0.97)` on the `:active` state with a 100–160ms transition using a strong custom ease-out curve (`cubic-bezier(0.23, 1, 0.32, 1)`) to deliver instant tactile feedback that feels snappy and natural.**

Responsive button animation is central to Emil Kowalski's UI polish philosophy documented in the `emilkowalski/skills` repository. The goal is to provide users with immediate, physical feedback that confirms interactions without introducing perceptible lag or jarring motion. According to the source code analysis, following specific timing, easing, and transform standards ensures buttons feel fast and responsive across all devices.

## Core Principles for Responsive Button Animations

### Apply Subtle Scaling on Press

The foundation of responsive button feedback lies in a subtle scale transform. In [`skills/emil-design-eng/SKILL.md`](https://github.com/emilkowalski/skills/blob/main/skills/emil-design-eng/SKILL.md) (lines 199–210), the recommended approach is to apply `transform: scale(0.97)` — or within the range of 0.95–0.98 — when the button receives the `:active` state. This creates a "press-in" effect that mimics physical buttons, giving users immediate confirmation that their touch or click registered.

### Optimize Timing and Easing

Duration and easing curves determine whether an animation feels snappy or sluggish. The [`skills/review-animations/STANDARDS.md`](https://github.com/emilkowalski/skills/blob/main/skills/review-animations/STANDARDS.md) file (lines 41–44) specifies a duration between **100–160ms** with a strong custom `ease-out` curve. This timing ensures the motion starts fast and ends gently, creating a responsive feel. The repository defines the specific curve as:

```css
--ease-out: cubic-bezier(0.23, 1, 0.32, 1);

```

Built-in CSS easings are considered too weak for UI feedback, making this custom curve essential for achieving a punchy, tactile response.

### Avoid Scaling From Zero

For entrance animations or state changes, never animate from `scale(0)`. As noted in [`skills/review-animations/STANDARDS.md`](https://github.com/emilkowalski/skills/blob/main/skills/review-animations/STANDARDS.md) (lines 53–55), starting from a value below 0.9 appears unnatural. Instead, begin at `scale(0.95)` or higher, combining it with an opacity fade if necessary. This maintains the physical plausibility of the interface element.

### Prefer CSS Transitions Over Keyframes

CSS transitions offer a critical advantage for responsive buttons: they are interruptible. According to [`skills/review-animations/STANDARDS.md`](https://github.com/emilkowalski/skills/blob/main/skills/review-animations/STANDARDS.md) (lines 69–78), if a user quickly clicks another button, the new animation can overwrite the previous one seamlessly. Keyframe animations, by contrast, can create jarring restarts or queue up awkwardly, degrading the responsive feel.

## Implementation Example

The following CSS implements the responsive button pattern found in [`skills/animate/RECIPES.md`](https://github.com/emilkowalski/skills/blob/main/skills/animate/RECIPES.md) and the standards documentation:

```css
/* Core button style using the strong custom ease-out */
.button {
  transition: transform 160ms var(--ease-out);
}

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

/* Optional overlay for richer feedback */
.button:active .overlay {
  transition: clip-path 200ms ease-out;
  clip-path: inset(0 0 0 0);
}

/* Entrance animation avoiding scale-from-zero */
.entering {
  transform: scale(0.95);
  opacity: 0;
  transition: transform 200ms var(--ease-out), opacity 200ms var(--ease-out);
}

```

## Source Files and Standards

| File | Purpose |
|------|---------|
| [`skills/review-animations/STANDARDS.md`](https://github.com/emilkowalski/skills/blob/main/skills/review-animations/STANDARDS.md) | Defines duration tables, custom easing curves, and performance rules governing button press feedback. |
| [`skills/emil-design-eng/SKILL.md`](https://github.com/emilkowalski/skills/blob/main/skills/emil-design-eng/SKILL.md) | Provides the concrete CSS implementation (`transform: scale(0.97)` on `:active`) and philosophical rationale for tactile feedback. |
| [`skills/animate/RECIPES.md`](https://github.com/emilkowalski/skills/blob/main/skills/animate/RECIPES.md) | Contains ready-to-use component recipes, including the specific button animation pattern referenced above. |

## Summary

- **Apply `transform: scale(0.97)`** (or 0.95–0.98) to the `:active` state to create a tactile "press-in" effect.
- **Use 100–160ms durations** with a strong custom `ease-out` curve (`cubic-bezier(0.23, 1, 0.32, 1)`) for snappy feedback.
- **Avoid `scale(0)`** entrance animations; start at 0.95 or higher with opacity fades.
- **Prefer CSS transitions** over keyframes to ensure animations remain interruptible and responsive to rapid user input.
- **Keep animations under 300ms** to stay within the recommended UI animation budget.

## Frequently Asked Questions

### What is the recommended scale value for button press animations?

According to [`skills/emil-design-eng/SKILL.md`](https://github.com/emilkowalski/skills/blob/main/skills/emil-design-eng/SKILL.md), you should apply `transform: scale(0.97)` when the button enters the `:active` state. The acceptable range falls between 0.95 and 0.98, creating a subtle "press-in" effect that confirms user interaction without distraction.

### Why use a custom easing curve instead of standard CSS easings?

Standard CSS easings like `ease-out` are too weak for tactile UI feedback. The [`skills/review-animations/STANDARDS.md`](https://github.com/emilkowalski/skills/blob/main/skills/review-animations/STANDARDS.md) file recommends `cubic-bezier(0.23, 1, 0.32, 1)` because it creates a motion that starts fast and decelerates gently, giving the button press a punchy, responsive feel that built-in curves cannot achieve.

### How long should a button press animation last?

The optimal duration falls between **100ms and 160ms** as specified in [`skills/review-animations/STANDARDS.md`](https://github.com/emilkowalski/skills/blob/main/skills/review-animations/STANDARDS.md). This range is short enough to feel instantaneous yet long enough to provide perceptible feedback, keeping the total interaction under the 300ms UI animation budget.

### Why are CSS transitions preferred over keyframes for button animations?

CSS transitions are interruptible, meaning if a user rapidly clicks different buttons, the new animation can immediately replace the previous one without jarring restarts or animation queuing. As documented in [`skills/review-animations/STANDARDS.md`](https://github.com/emilkowalski/skills/blob/main/skills/review-animations/STANDARDS.md) (lines 69–78), this property makes transitions superior for maintaining responsiveness during rapid user interactions.