Interaction Design and Prototyping Questions
Designing how a product behaves and expressing it as testable artifacts: ideation and sketching, low- to high-fidelity prototypes, interaction patterns, and interactive specifications. Covers rapid solution exploration, choosing prototype fidelity for the question at hand, and designing real-time and dynamic interactions. The craft of turning concepts into interactive form.
Engineering limits heavy JavaScript animations; you can only use CSS transitions and transforms. Propose interaction alternatives for a dropdown menu, tooltip, and modal that balance perceived polish with performance. Describe timing, easing choices, and how you'd prototype them under these constraints.
Sample Answer
Overview (role lens)
As a Product Designer I propose micro-interactions that feel polished while staying within CSS transitions/transforms so engineers avoid JS-heavy repaints. I pair design tokens (duration, easing) with accessible patterns and lightweight prototypes for handoff.
Dropdown menu
- Interaction: a subtle vertical slide plus fade using transform: translateY and opacity.
- Timing/easing: 170ms, cubic-bezier(0.22, 1, 0.36, 1) (snappy, slightly overshoot feel without JS).
- Implementation notes: animate from translateY(-6px) to 0 and opacity 0 to 1; set transform-origin: top; use will-change: transform, opacity (a hint that tells the browser to prepare a fast rendering path for these specific properties ahead of time, so the animation doesn't stutter on its first frame); avoid animating height/width.
- Accessibility: open on focus/keyboard, close on Esc.
Tooltip
- Interaction: scale plus fade from the pointer origin for perceived precision.
- Timing/easing: 120ms, ease-out (cubic-bezier(0.0, 0.0, 0.2, 1)).
- Implementation notes: scale(0.96) to 1 and opacity 0 to 1; use transform-origin aligned to placement; use a pointer-delay (50-150ms) to prevent flicker.
Modal
- Interaction: backdrop fade plus modal pop (scale plus translateZ for GPU, meaning the transform is nudged onto its own compositing layer, a piece of the screen the graphics chip can move around without redrawing everything else, which is what keeps the animation smooth even on weaker phones).
- Timing/easing: backdrop 200ms linear, modal 220ms cubic-bezier(0.2, 0, 0, 1) (a gentle entrance).
- Implementation notes: animate opacity and transform: translateY(8px) plus scale(0.995) to scale(1); add inert/aria-hidden while closed; avoid animating position/layout.
Performance and accessibility
- Strictly animate transform and opacity, since both can run on a compositing layer as described above, which minimizes repaint (the cost of the browser redrawing pixels) compared to animating properties like width or top.
- Use will-change sparingly and remove it after the transition, since leaving it on permanently wastes memory holding a compositing layer open for nothing.
- Respect prefers-reduced-motion: provide a no-motion fallback and an immediate state change.
- Limit simultaneous animations and stagger only when necessary.
Prototyping and handoff
- Start in Figma interactive components to validate timing/easing with stakeholders.
- Build lightweight HTML/CSS prototypes (CodePen) using only transitions/transforms to confirm the feel and performance on devices.
- Provide engineers CSS tokens (durations, easings) and snippets, acceptance criteria (reduced-motion, focus behavior), and a short test plan.
This approach balances perceived polish with real-world constraints and gives engineers clear, testable specs.
You're designing a card-flip or slide animation for a product where most users are on low-end Android phones over patchy networks. How would you make sure the animation actually feels smooth in that environment, what would you measure to prove it, and what would you prototype differently than you would for a flagship-device demo?
Sample Answer
Direct answer
"Feels smooth" is really a frame-budget problem: at a 60fps target you have 1000ms divided by 60 frames, 16.7ms, to do everything needed for one frame, and on a low-end device with a weak GPU, only compositor-friendly properties reliably fit inside that budget. I'd design the animation around those properties from the start rather than designing something rich and shrinking it later, measure it with dropped-frame percentage, the share of frames that render late during the animation, and jank, a perceptible skip or stutter caused by badly dropped frames, on the actual target device class, and prototype the low-end version differently from the flagship demo from day one: real low-end hardware, with the network throttled to simulate the patchy connection.
GPU acceleration and repaint reduction, explained
Some properties, transform translate, scale, rotate, and opacity, can be handled by the compositor, a separate step backed by the device's GPU that combines already-drawn layers on screen without asking the rest of the rendering pipeline to redraw anything. Animating these is comparatively cheap even on weak hardware. Other properties, width, height, top or left position, box-shadow, blur, force a repaint: the system redraws the actual pixels of the affected element, and often its layout neighbors, on every single frame, which is expensive, and on a low-end GPU with limited fill-rate this is usually where perceptible jank comes from. Concretely, for a card-flip or slide: build it from transform and opacity only, translate the card horizontally, rotate it around the vertical axis for a flip, fade in the new face, and avoid animating a drop shadow's blur radius directly, since that forces a repaint every frame. Fake the same depth cue with a pre-rendered, static shadow that only fades in and out through opacity.
What I'd prototype differently for a low-end and patchy-network demo versus a flagship demo
- Device: test and demo on an actual low- or mid-tier Android device, not a flagship or a desktop browser simulator, since a simulator typically runs on desktop-class hardware and won't reproduce the problem.
- Network: throttle the connection to a slow, high-latency profile, a few hundred kilobits per second with noticeable round-trip delay, rather than testing on office wifi, since a patchy network changes what "smooth" even means. If the content the animation reveals hasn't loaded yet, the animation needs a defined behavior, wait, show a placeholder, or fail gracefully, rather than assuming the data is always there the instant the transition starts.
- Assets: use production-weight images and content in the prototype, not lightweight placeholders, since a slide animation over a placeholder gray box will always look smoother than the same animation once a real, larger image has to decode and paint.
Metrics I'd bring to engineers, in terms they can act on directly
- Frame budget: state the 16.7ms-per-frame number explicitly and name which specific properties in the design exceed it, a repaint-triggering blur is a description of a device-independent problem, not an environment-dependent timing claim.
- Dropped-frame percentage during the animation, measured with the platform's own rendering profiler, Android's on-device GPU rendering tools, or a browser's built-in performance panel for a web-based build, since this is the standard way engineers already talk about jank internally, and handing them a percentage in their own units gets a faster, more precise fix than "it feels laggy."
- A named property list, which elements in the design currently animate width, height, or blur versus transform and opacity, since that list is directly actionable: an engineer can swap the implementation without needing to re-derive what's expensive from scratch.
Trade-offs and pitfalls
It's tempting to validate an animation only after it's already built, when the fix options have narrowed to keeping it or cutting it; involve engineering during the design of the motion itself, which properties, roughly how long, so the performance conversation happens before there's a finished thing anyone feels reluctant to change. The other common mistake is chasing a specific frame-rate number as if it's the whole story: a technically smooth animation that reveals content before the network has actually delivered it will still feel broken, so treat animation performance and content readiness as one combined problem, not two separate ones.
You must prototype a complex drag-and-drop dashboard (resizable widgets, nested drop targets). Compare prototyping in Figma (potential plugins/overlays) versus building a coded prototype (React/Framer). Discuss testability, fidelity, handoff to devs, maintenance, and state management. Which would you pick and why?
Sample Answer
Situation and goal
I need a prototype for a complex drag-and-drop dashboard with resizable widgets and nested drop targets, to validate interaction flows with users and hand off a spec to engineers.
Figma (with plugins/overlays)
- Fidelity: Medium. Animations and constraints simulate resizing and drop feedback but feel canned; overlays and Smart Animate (Figma's built-in tool for faking a smooth transition between two pre-built screens) can mimic transitions.
- Testability: Good for early usability tasks (mental models, discoverability), limited for fine-grained behavioral testing (drag physics, nested-target edge cases).
- Handoff: Excellent. Specs, measurements, CSS tokens, and assets are exportable; engineers get screens and interaction notes.
- Maintenance: Low overhead for visual updates, but complex interactions become brittle as workarounds multiply.
- State: what a component is currently holding onto, like which widget is selected or how wide it currently is. In Figma this is faked using multiple frames/pages, or FigJam (Figma's separate whiteboard-style canvas, useful for sketching the underlying logic) and Variants (pre-built alternate versions of the same component, like "card, default" and "card, resized," manually swapped between). There is no real number tracking exact size or position, so it only shows the states you thought to pre-build.
Coded prototype (React and Framer)
- Fidelity: High. Real drag, drop, resize, and collision logic for nested targets; can match production behavior.
- Testability: Strong. Supports moderated testing, quantitative event logging, edge-case scenarios, and performance checks.
- Handoff: Provides a working reference, a component API, and potentially reusable code; still needs documentation for styling and accessibility.
- Maintenance: Higher initial cost but scalable if structured as components and documented.
- State: true runtime state, meaning the card's actual width, height, and position live in a variable that updates the instant the user drags or resizes it. That value is kept in Redux (a library for centralizing state so many components can read and update it consistently) or React Context/hooks (React's own simpler, built-in way to share and update that same kind of state without a separate library). This makes it straightforward to model complex interactions and to persist a layout between sessions.
Worked example: one resizable card
Take a single card the user can drag to a new grid position and resize from its corner.
- In Figma: build 2-3 Variants of that card (default, resized, mid-drag) and wire a hotspot with Smart Animate to fake the jump between them. Drag it to a size you did not pre-build and nothing happens, because there is no real size value underneath.
- In the coded version: the card's width, height, and position is a real state value, so dragging or resizing to any size updates that value and the card re-renders to match, and every drag/resize event can be logged to see how people actually use it.
Decision (which I would pick)
Start with a high-fidelity Figma flow to validate concepts quickly with stakeholders, since it is cheap and fast to iterate on the overall layout, then invest in a focused coded prototype (React and Framer) for usability testing and engineering sign-off on the trickiest interactions (nested drop targets, resize collision). This hybrid minimizes risk: Figma speeds alignment, and the coded prototype validates the nuanced behaviors and hands engineering a practical, working reference instead of just pictures.
Animation tooling trade-offs: compare three approaches to prototyping complex animations and microinteractions: (A) built-in prototyping tool animations (e.g., Figma smart animate), (B) export to Lottie/Bodymovin, (C) code-based prototypes (Framer/HTML+CSS+JS). For each approach list strengths, weaknesses, and suitable use cases.
Sample Answer
Overview
As a UI Designer I choose tooling based on fidelity, handoff clarity, iteration speed, and developer constraints. Below I compare three approaches.
A) Built-in prototyping (Figma Smart Animate, Principle, XD)
- Strengths: fastest for exploring timing/flow; no code; easy to iterate and share; integrates with design files and design systems.
- Weaknesses: limited physics/complex motion; inconsistent across platforms; export/handoff to devs can be ambiguous.
- Use cases: early concept validation, stakeholder demos, simple microinteractions (transitions, simple morphs).
B) Export to Lottie / Bodymovin
- Strengths: performant vector animations, runs in production, reusable as JSON, good for scalable icons/illustrations. Clear handoff to engineers.
- Weaknesses: limited to After Effects feature subset; learning curve to rig/export; heavier tooling pipeline.
- Use cases: production-ready micro-animations (icons, loaders, onboarding illustrations).
C) Code-based prototypes (Framer / HTML+CSS+JS)
- Strengths: highest fidelity and realism; exact behavior across platforms; can test edge cases, responsiveness, accessibility. Engineers can reuse patterns.
- Weaknesses: slowest to iterate; requires dev skills; maintenance cost.
- Use cases: final validation, complex interactive components, motion that depends on runtime state.
Decision pattern: start in Figma for exploration, move to Lottie for reusable visual pieces, and build code prototypes when behavior needs exact validation or developer buy-in.
Worked example
Say a checkout flow needs a subtle success animation, a checkmark that draws itself in, then settles, when payment completes. Prototyping it first in Figma Smart Animate lets the team agree on the shape and rough timing in an afternoon and get a thumbs-up from the PM without touching a design tool most engineers do not use daily. Once the shape and timing are approved, exporting the actual checkmark artwork to Lottie gives engineering a small, reusable JSON file that plays the exact same animation in the app with no hand-coded keyframes to maintain, which is the right choice here because the animation itself never depends on runtime data. If the same checkmark instead needed to morph differently depending on the payment method or scale with a dynamically sized order total, that runtime dependency is exactly the case that pushes the decision to a code-based prototype instead, since neither Smart Animate nor a static Lottie file can react to a value that is not known until the app is running.
Trade-offs & pitfalls
The common mistake is picking Lottie by default because it feels like the "production-ready" option, then discovering the animation actually needs to branch on live data, at which point the exported file has to be thrown away and rebuilt in code anyway. The safer order is to confirm with engineering, before exporting anything, whether the interaction is purely decorative (a good fit for Lottie) or state-dependent (better proven directly in code), since finding that out after the export wastes the rigging work.
You need to validate how dynamic content updates are announced to assistive technologies (for example using ARIA live regions). Explain how you would prototype and test dynamic content updates for accessibility, what tool or code approach you'd use, and how you'd document expected behavior for engineers.
Sample Answer
Approach summary
I’d prototype minimal, testable interactions that surface dynamic updates to screen readers, verify with real AT, then document expected announcements and implementation notes for engineers.
Prototype & code
- Start in the design tool (Figma prototyping) to show when/how content changes.
- Build a small HTML/React sandbox to validate behavior with real screen readers.
Example (plain JS live region):
<!-- use role="status" for polite updates; aria-atomic preserves full message -->
<div id="live" role="status" aria-atomic="true" aria-live="polite" class="sr-only"></div>
<script>
function announce(text){
const live = document.getElementById('live');
live.textContent = ''; // reset to ensure announcement
setTimeout(()=> live.textContent = text, 50);
}
// announce('File uploaded successfully');
</script>
Testing
- Manual: VoiceOver (macOS/iOS), NVDA (Windows), ChromeVox. Test various scenarios: rapid updates, identical text, focus changes.
- Automated: axe-core to catch missing roles/labels; Accessibility Insights for fast checks.
- Edge cases: focus-driven modals vs live regions, duplicate messages, timing (debounce).
Documentation for engineers
- Expected announcement text examples per scenario (success, error, progress).
- Required attributes: role, aria-live value, aria-atomic, mutate pattern (replace vs append).
- Performance notes: debounce/throttle rules, DOM update strategy (reset then set).
- Acceptance criteria: list of ATs/platforms where behavior was validated and sample test steps.
Unlock Full Question Bank
Get access to all 30 Interaction Design and Prototyping interview questions and detailed answers.
Sign in to ContinueJoin thousands of developers preparing for their dream job.