Creating a Responsive Image Component in Next.js with TypeScript
In this tutorial, we'll create a ResponsiveImg component that uses the Next.js Image component for optimized image rendering.
Introduction
The ResponsiveImg Component
The ResponsiveImg component accepts properties for both mobile and desktop versions of the image. It uses the useEffect and useState hooks to determine the screen size and adjust the image properties accordingly.
Here's the complete code for the ResponsiveImg component:
/**
* ResponsiveImg component that renders an image which adapts to screen size.
* It uses the Next.js Image component for optimized image rendering.
*
* @component
* @param {ResponsiveImgProps} props - The properties for the ResponsiveImg component.
* @param {Object} props.mobile - The properties for the mobile version of the image.
* @param {string | StaticImport} props.mobile.src - The source of the mobile image.
* @param {number} props.mobile.width - The width of the mobile image.
* @param {number} props.mobile.height - The height of the mobile image.
* @param {Object} props.desktop - The properties for the desktop version of the image.
* @param {string | StaticImport} props.desktop.src - The source of the desktop image.
* @param {number} props.desktop.width - The width of the desktop image.
* @param {number} props.desktop.height - The height of the desktop image.
* @param {string} props.title - The alt text for the image.
* @param {string} [props.className] - Additional class names for the image.
* @param {boolean} [props.isFill=false] - Whether the image should fill its container.
*
* @returns {JSX.Element} The rendered ResponsiveImg component.
*
* @example
* <ResponsiveImg
* mobile={{ src: '/images/mobile.jpg', width: 300, height: 200 }}
* desktop={{ src: '/images/desktop.jpg', width: 600, height: 400 }}
* title="Responsive Image"
* className="custom-class"
* isFill={false}
* />
*/
"use client";
import Image from "next/image";
import { useEffect, useState } from "react";
import { ResponsiveImgProps } from "@/interfaces/basic";
import { StaticImport } from "next/dist/shared/lib/get-img-props";
const ResponsiveImg: React.FC<ResponsiveImgProps> = (props) => {
const [isSmallScreen, setIsSmallScreen] = useState(false);
useEffect(() => {
if (typeof window !== 'undefined') {
setIsSmallScreen(window.innerWidth < 768);
const handleResize = () => {
setIsSmallScreen(window.innerWidth < 768);
};
window.addEventListener("resize", handleResize);
return () => {
window.removeEventListener("resize", handleResize);
};
}
}, []);
const imgProps: Omit<React.ComponentProps<typeof Image>, "src"> & {
src: string | StaticImport;
} = {
src: (isSmallScreen ? props.mobile.src : props.desktop.src) as string,
alt: props.title,
className: props.className + (props.isFill ? " important-relative" : ""),
width: props.isFill
? undefined
: isSmallScreen
? props.mobile.width
: props.desktop.width,
height: props.isFill
? undefined
: isSmallScreen
? props.mobile.height
: props.desktop.height,
layout: props.isFill ? "fill" : undefined,
style: props.isFill ? { objectFit: "contain" } : undefined,
};
return (
<>
<Image {...imgProps} />
</>
);
};
The typescript interface :
export interface ResponsiveImgProps {
title: string;
className?: string;
isFill?: boolean;
mobile: { width?: number; height?: number; src: string |
import("next/dist/shared/lib/get-img-props").StaticImport;};
desktop: { width?: number; height?: number; src: string |
import("next/dist/shared/lib/get-img-props").StaticImport;};
}
Example Usage
Let's see how we can use the ResponsiveImg component in different parts of our application.
Example 1: 100%
<ResponsiveImg
title="img 100%"
className="h-48 w-full object-cover md:h-full md:w-48 justify-center"
isFill={true}
mobile={{
src: "/images/mobile.png",
}}
desktop={{
src: "/images/desktop.png",
}}
/>
Example 2: sizes
<ResponsiveImg
title="change img size"
className="inline-block"
mobile={{
width: 110,
height: 20,
src: "/images/master/negevMobileFooter.png",
}}
desktop={{
width: 280,
height: 60,
src: "/images/master/footerNegevIcon.png",
}}
/>
Conclusion
In this post, we've created a ResponsiveImg component that adapts to different screen sizes by changing the image source and dimensions. This component leverages the power of Next.js and TypeScript to provide optimized and type-safe image rendering.
Feel free to use and modify this component in your projects to enhance the responsiveness of your web applications.
Happy coding!
Roi
Comments
Post a Comment