• Homeright arrow
  • Blogright arrow
  • Creating Delightful Microinteractions with Motion in Next.js
Feature

Creating Delightful Microinteractions with Motion in Next.js

In modern web development, the difference between a good UI and a delightful one often comes down to the smallest details, like how a button responds to a hover, how a card reacts to a tap, or how feedback is subtly animated after a user action. These small design elements are called microinteractions.

In this post, you'll learn how to create microinteractions in a Next.js application using the motion library. We'll walk through:

  • What microinteractions are and why they matter
  • Installing and using the latest motion library
  • Creating reusable microinteraction components in Next.js
  • Practical examples: hover, tap, focus, loading, and feedback animations

What are Microinteractions?

Microinteractions are small, functional animations that give users subtle feedback or enhance usability. Think of:

  • A button that scales slightly when clicked
  • A loading indicator animating while data is fetched
  • A tooltip fading in on focus
  • An icon gently bouncing on hover

They may be small, but their impact on UX is massive—adding polish, delight, and clarity to your UI.

Benefits of Microinteractions

Microinteractions have practical UX uses and are not merely decorative elements. The following justifies their inclusion in your Next.js projects:

1. Enhanced User Feedback

Microinteractions let users know their input was received by providing instant visual confirmation for actions like clicks, taps, and hovers.

Example: To let the user know that their action has been recorded, a submit button briefly contracts when tapped.

2. Improved Usability

By emphasizing what is clickable, what is loading, and what has recently changed, they help users navigate workflows.

  • To show that it is ready for input, a focused input gently scales and changes color.

3. Reduced Cognitive Load

Small animations help users understand state changes without having to read text or guess what happened.

  • Success messages that fade in gently reinforce actions without overwhelming users.

4. Professional Feel

Motion adds polish and makes your interface feel modern and high-quality, setting your project apart.

  •  Even a simple hover scale effect can make your app feel premium.

5. Accessible Interactions

Thoughtful microinteractions—like animated focus indicators—enhance accessibility for keyboard and screen reader users.

  • They help ensure all users, regardless of input method, get clear visual cues.

6. Brand Personality

Custom motion behaviors give your app a unique personality and brand expression.

  •  A playful bounce or fade-in can make your UI feel more human and memorable.

Getting Started

We’ll use the latest motion library—install it with:

npm install motion

Then, import it like this:

import { motion } from 'motion/react'

Microinteractions with Code Examples

Here are some useful use cases of microinteractions:

Button Hover & Tap Feedback

This interaction gives your buttons a tactile feel. When users hover or press the button, it slightly grows or shrinks, making the interaction feel more physical.

<motion.button
whileHover={{ scale: 1.05 }}
whileTap={{ scale: 0.95 }}
className="bg-blue-600 text-white px-4 py-2 rounded"
>
Click Me
</motion.button>

 How it works:

  • whileHover enlarges the button slightly.
  • whileTap shrinks it on click.
  • These scale changes create tactile feedback.

Fade In on Load

Use this effect to gently reveal elements on initial render. It makes the UI feel polished and reduces abrupt layout shifts.

<motion.div
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
transition={{ duration: 0.5 }}
>
<h2 className="text-xl">Hello World</h2>
</motion.div>

How it works:

  • initial hides the element.
  • animate brings it in.
  • transition defines timing.

Slide in From the Left

Slide-in animations help guide the user's eye. Great for headings, sections, or list items.

<motion.div
initial={{ x: -50, opacity: 0 }}
animate={{ x: 0, opacity: 1 }}
transition={{ duration: 0.6 }}
>
<p>This content slides in from the left.</p>
</motion.div>

How it works:

  • x: -50 starts it off-screen.
  • opacity: 0 keeps it invisible.
  • Both animate to natural position and full visibility.

Add Focus Animation

Enhance form interactions with subtle animations when users focus on input fields. This microinteraction is useful for improving accessibility and drawing attention to active elements. It makes your form feel more modern and reactive without needing external validation libraries or complex logic.

'use client'
import { motion } from 'motion/react'
import { useState } from 'react'


export function FocusInput() {
const [focused, setFocused] = useState(false)


return (
<motion.div
animate={focused ? { scale: 1.02, borderColor: '#3b82f6' } : { scale: 1, borderColor: '#e5e7eb' }}
transition={{ type: 'spring', stiffness: 300 }}
className="border-2 p-2 rounded"
>
<input
onFocus={() => setFocused(true)}
onBlur={() => setFocused(false)}
className="outline-none w-full"
placeholder="Focus me"
/>
</motion.div>
)
}

How it works:

  • The parent motion.div animates based on whether the input is focused.
  • On focus, it slightly scales up (scale: 1.02) and changes border color to blue (#3b82f6).
  • On blur, it reverts back to the default gray border.
  • transition uses a spring animation for a smooth bounce-in effect.
  • useStatetracks focus state, and onFocus/onBlur handlers toggle it.

This interaction gives immediate, visual feedback that the user is typing — simple, elegant, and effective.

Scroll Reveal (on View)

This component reveals only when scrolled into view. Great for portfolio sections, images, or stats.

'use client'
import { useRef } from 'react'
import { useInView, motion } from 'motion/react'


const RevealOnScroll = () => {
const ref = useRef(null)
const isInView = useInView(ref, { once: true, margin: '-100px' })


return (
<motion.div
ref={ref}
initial={{ opacity: 0, y: 40 }}
animate={isInView ? { opacity: 1, y: 0 } : {}}
transition={{ duration: 0.6 }}
>
<p>This fades in when you scroll to it.</p>
</motion.div>
)
}

How it works:

  • useInView tracks visibility.
  • Animation triggers only once when visible.

Modal Open/Close Animation

This smooth modal animation adds elegance to your overlays.

'use client'
import { useState } from 'react'
import { motion, AnimatePresence } from 'motion/react'


const Modal = () => {
const [open, setOpen] = useState(false)
return (
<>
<button onClick={() => setOpen(true)}>Open Modal</button>
<AnimatePresence>
{open && (
<motion.div
initial={{ opacity: 0, scale: 0.9 }}
animate={{ opacity: 1, scale: 1 }}
exit={{ opacity: 0, scale: 0.9 }}
transition={{ duration: 0.3 }}
className="fixed inset-0 flex items-center justify-center bg-black/50"
onClick={() => setOpen(false)}
>
<div className="bg-white p-6 rounded" onClick={e => e.stopPropagation()}>
<p>This is a modal!</p>
</div>
</motion.div>
)}
</AnimatePresence>
</>
)
}

How it works:

  • AnimatePresence handles exit animations.
  • Scaling and fading make the modal feel natural.
  • Clicking outside closes it.

Smooth Scroll to Section

Guide users to sections with smooth transitions. Ideal for nav menus or CTA buttons. You need to add the following CSS to your global styles (e.g., globals.css or inside app/layout.css):

html {
scroll-behavior: smooth;
}

Then use a standard anchor link using the Next.js <Link> component.

'use client'
import Link from 'next/link'


export default function NavLink() {
return (
<Link href="#contact" className="text-blue-600 underline">
Contact Us
</Link>
)
}

How it works:

  • scroll-behavior: smooth makes the browser scroll between anchor targets smoothly.

Staggered Animations for List

Want a list of items to appear one by one? Use staggered motion for a cascading effect.

<motion.ul
initial="hidden"
animate="show"
variants={{
hidden: {},
show: {
transition: {
staggerChildren: 0.2,
},
},
}}
>
{['One', 'Two', 'Three'].map((item, i) => (
<motion.li
key={i}
variants={{
hidden: { opacity: 0, y: 20 },
show: { opacity: 1, y: 0 },
}}
className="mb-2"
>
{item}
</motion.li>
))}
</motion.ul>

How it works:

  • The parent defines staggerChildren.
  • Each list item animates one after the other.

Icon Hover Spin

Spinning icons can show interactivity (like refresh or sync).

<motion.div whileHover={{ rotate: 360 }} transition={{ duration: 0.6 }}>
🔄
</motion.div>

How it works:

  • whileHover rotates the icon.
  • Spins once on each hover.

Toast Message Animation

Spinning icons can show interactivity (like refresh or sync).

<AnimatePresence>
{showToast && (
<motion.div
initial={{ y: -50, opacity: 0 }}
animate={{ y: 0, opacity: 1 }}
exit={{ y: -50, opacity: 0 }}
transition={{ duration: 0.4 }}
className="fixed top-4 right-4 bg-green-600 text-white px-4 py-2 rounded shadow"
>
Form Submitted!
</motion.div>
)}
</AnimatePresence>

How it works:

  • Toast slides and fades in.
  • Disappears on exit via AnimatePresence.

Reusable Microinteractions

The best part? There are motion variants. Instead of repeating animation logic, you can create motion variants. Then you can drop them into any page or layout in your Next.js app.

export const fadeVariant = {
hidden: { opacity: 0 },
show: { opacity: 1, transition: { duration: 0.5 } },
}

Then reuse across components:

<motion.div variants={fadeVariant} initial="hidden" animate="show">
<YourContent />
</motion.div>

Conclusion


Subtle animations used in microinteractions improve usability, direct users, and produce a more engaging and intuitive experience. You can create quick, user-friendly apps with responsive UI behavior by utilizing Next.js, Motion, and Tailwind CSS. With the help of Motion for handling rich animations, Tailwind for flexible styling, and Next.js for performance and scalability, you can easily update your website with meaningful, beautiful interactions that improve user experience.

Looking to elevate your website? Add microinteractions for a refined, interactive experience using motion — we’re here to help.


footer-particlefooter-particlefooter-particlefooter-particlefooter-particle
back-to-top