My Code Chronicles #2: Creating a Dynamic Product Card Component in Next.js using Framer Motion

Hover effects are more than just eye candy—they are essential for creating an engaging user experience on modern websites. When implemented thoughtfully, hover effects can provide subtle visual feedback, improve usability, and guide user interaction intuitively. For e-commerce websites, like the one I was building for Glamour & Gourmandise, the product card is a critical component. It needs to be visually appealing, informative, and highly interactive. To achieve this, I implemented a sophisticated hover effect that reveals additional product details in a sleek and seamless way. Code "use client"; import { motion } from "framer-motion" // Imports... export default function ProductCard(){ // State const [isHovered, setIsHovered] = useState(false); return ( setIsHovered(true)} onMouseLeave={() => setIsHovered(false)} > {/* Product Image */} {/* Product Details */} {product.title} {product.tags.map( ({ tag }, i) => i < 2 && ( {tag} ), )} {product.description} {product.link && ( e.stopPropagation()} replace href={product.link} className="block w-fit text-xs font-semibold text-primary transition hover:text-secondary group-[.is-hovered]:block sm:hidden" > More info )} {product.formattedPrice.priceWithCurrency} {product.formattedPrice.priceUnit} {/* Add To Cart Button */} ); } Implementation The Wrapper The article element is the foundation of this hover effect. It is responsible for: Maintaining the aspect ratio (responsively adjusted based on screen size). Housing all child components, including the image and product details. Triggering hover state changes. Aspect Ratio: Ensures consistent sizing of the card across different devices. Hover State: Sets isHovered to true or false to control the animation. Product Details Section The product details are housed in an absolutely positioned div at the bottom of the wrapper. This positioning ensures that the expanding animation occurs within the wrapper, avoiding disruptions to the page layout. Framer Motion’s layout={true} is the key to this hover effect. It: Animates Height Changes: When the product details expand, layout={true} calculates the difference in height and interpolates the transition smoothly. Direction Control: Because the details div is positioned absolutely at the bottom, the expansion happens upward into the card instead of downward. User-Friendly Transitions: Without layout={true}, the height change would feel abrupt and jarring. Conclusion This hover effect showcases how to elevate user experience with smooth animations and thoughtful design. While the actual website for Glamour & Gourmandise opted for a simpler zoom-in effect on images (as per the owner’s preference), this implementation demonstrates the versatility and creative possibilities with Framer Motion and Next.js. If you’re interested in learning more about layout animations or have tips to optimize this implementation further, let me know!

Jan 19, 2025 - 02:10
My Code Chronicles #2: Creating a Dynamic Product Card Component in Next.js using Framer Motion

Hover effects are more than just eye candy—they are essential for creating an engaging user experience on modern websites. When implemented thoughtfully, hover effects can provide subtle visual feedback, improve usability, and guide user interaction intuitively.

For e-commerce websites, like the one I was building for Glamour & Gourmandise, the product card is a critical component. It needs to be visually appealing, informative, and highly interactive. To achieve this, I implemented a sophisticated hover effect that reveals additional product details in a sleek and seamless way.

Code

"use client";

import { motion } from "framer-motion" 
// Imports...


export default function ProductCard(){

  // State
  const [isHovered, setIsHovered] = useState(false);

  return (
    
setIsHovered(true)} onMouseLeave={() => setIsHovered(false)} > {/* Product Image */} {alt} {/* Product Details */}

{product.title}

{product.tags.map( ({ tag }, i) => i < 2 && ( {tag} ), )}

{product.description} {product.link && ( e.stopPropagation()} replace href={product.link} className="block w-fit text-xs font-semibold text-primary transition hover:text-secondary group-[.is-hovered]:block sm:hidden" > More info )}

{product.formattedPrice.priceWithCurrency} {product.formattedPrice.priceUnit}

{/* Add To Cart Button */}
); }

Implementation

The Wrapper

The article element is the foundation of this hover effect. It is responsible for:

  • Maintaining the aspect ratio (responsively adjusted based on screen size).
  • Housing all child components, including the image and product details.
  • Triggering hover state changes.
  • Aspect Ratio: Ensures consistent sizing of the card across different devices.
  • Hover State: Sets isHovered to true or false to control the animation.

Product Details Section

The product details are housed in an absolutely positioned div at the bottom of the wrapper. This positioning ensures that the expanding animation occurs within the wrapper, avoiding disruptions to the page layout.
Framer Motion’s layout={true} is the key to this hover effect. It:

  • Animates Height Changes: When the product details expand, layout={true} calculates the difference in height and interpolates the transition smoothly.
  • Direction Control: Because the details div is positioned absolutely at the bottom, the expansion happens upward into the card instead of downward.
  • User-Friendly Transitions: Without layout={true}, the height change would feel abrupt and jarring.

Conclusion

This hover effect showcases how to elevate user experience with smooth animations and thoughtful design. While the actual website for Glamour & Gourmandise opted for a simpler zoom-in effect on images (as per the owner’s preference), this implementation demonstrates the versatility and creative possibilities with Framer Motion and Next.js.
If you’re interested in learning more about layout animations or have tips to optimize this implementation further, let me know!