How to Implement Button Press Feedback with scale(0.97) on :active State
Apply transform: scale(0.97) to a button's :active state with a 100–160 ms transition to create immediate tactile feedback that signals the UI is responding to user input.
The emilkowalski/skills repository establishes a definitive pattern for button press feedback using a subtle scale transform. This approach, documented across multiple skill files including the Design Engineering and Apple Design guidelines, ensures buttons feel responsive and "listening" without requiring JavaScript or complex keyframe animations.
The Design Philosophy Behind Scale(0.97) Feedback
According to the source code in skills/emil-design-eng/SKILL.md, buttons must provide instant visual confirmation when pressed to communicate that the interface is actively processing the user's action. The guidelines at lines 199–211 define this as a fundamental interaction principle: a button should never feel static or unresponsive during pointer-down events.
The pattern relies on CSS transforms rather than layout-affecting properties like width or height changes. This ensures the feedback remains performant and does not trigger expensive reflow calculations during the animation.
Implementing the :active Scale Transform
Basic CSS Structure
The implementation requires only two CSS rules: a transition property on the base state and a transform on the :active pseudo-class.
<button class="btn-primary">Press me</button>
.btn-primary {
background: #0066ff;
color: white;
border: none;
padding: 0.6rem 1.2rem;
font-size: 1rem;
border-radius: 4px;
/* Smooth restoration when releasing */
transition: transform 120ms ease-out;
}
.btn-primary:active {
transform: scale(0.97);
}
The :active selector triggers specifically while the user holds the mouse button down (or maintains touch contact), ensuring the visual feedback coincides exactly with the press action.
Transition Timing and Easing
The repository recommends a transition duration between 100–160 ms (with 120 ms as the default) to balance responsiveness against jarring motion. As implemented in skills/emil-design-eng/SKILL.md, the easing function should typically be ease-out or cubic-bezier variants that decelerate toward the resting state, creating a natural physical sensation of compression.
Why 0.97? Selecting the Optimal Scale Value
The specific value of 0.97 represents the default within an acceptable range of 0.95–0.98, as noted in skills/emil-design-eng/SKILL.md at lines 13–15. This range provides several technical advantages:
- Visual noticeability: Large enough to be perceived as deliberate motion
- Layout stability: Small enough to avoid shifting surrounding elements or causing "jumpy" interface behavior
- Tactile illusion: Mimics the physical compression of real-world buttons without distortion
Values below 0.95 risk appearing broken or accidental, while values above 0.98 often fail to register as intentional feedback on high-density displays.
Apple Design Guidelines and Pointer-Down Response
The pattern receives additional validation in skills/apple-design/SKILL.md (lines 28–33), which reinforces the principle that buttons must respond on pointer-down rather than waiting for the click event to complete. This file echoes the same CSS implementation, emphasizing that delayed feedback creates perceived latency and reduces user confidence.
The guidelines explicitly reject approaches that delay visual feedback until the mouse-up event or the completion of an asynchronous action. The transform: scale(0.97) technique satisfies this requirement by leveraging browser-native :active state management, which fires immediately upon press initiation.
Summary
- Apply
transform: scale(0.97)to the:activestate of buttons for consistent press feedback across your design system - Use transition durations of 100–160 ms (120 ms recommended) with
ease-outtiming for natural motion - Acceptable scale range is 0.95–0.98, with 0.97 serving as the default sweet spot for visibility without layout disruption
- Reference
skills/emil-design-eng/SKILL.mdfor the core implementation guidelines andskills/apple-design/SKILL.mdfor interaction philosophy - No JavaScript required: The technique relies entirely on CSS
:activepseudo-classes and hardware-accelerated transforms
Frequently Asked Questions
What is the optimal transition duration for button press feedback?
The optimal duration ranges between 100–160 ms, with 120 ms serving as the standard default according to skills/emil-design-eng/SKILL.md. Durations shorter than 100 ms may appear instantaneous or flicker, while durations exceeding 160 ms create a sluggish, unresponsive sensation that contradicts the goal of immediate feedback.
Why use scale(0.97) instead of scale(0.9)?
The value 0.97 provides sufficient visual noticeability without triggering layout shifts or appearing as a bug. As documented in the source guidelines, the 0.95–0.98 range ensures the button remains visually anchored in its original position while clearly communicating the pressed state. A 0.9 scale (10% reduction) typically distorts text and icons excessively and may cause surrounding elements to reflow.
Does this technique work on mobile touch devices?
Yes, the :active state and transform properties work consistently across modern mobile browsers including Safari on iOS and Chrome on Android. The hardware-accelerated scale() transform ensures 60fps performance even on lower-end devices. However, some mobile browsers require the -webkit-tap-highlight-color property to be set to transparent to prevent default blue overlays from competing with your custom feedback.
Where are these button press guidelines documented in the repository?
The primary documentation resides in skills/emil-design-eng/SKILL.md at lines 199–211, which provides the core CSS snippet and design rationale. Complementary guidance appears in skills/apple-design/SKILL.md (lines 28–33) regarding the pointer-down philosophy, while skills/review-animations/STANDARDS.md (line 107) offers additional context for animation reviews.
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 →