Part 57: Enhancing the Product Page with Responsive Design and Image Optimization in Next.js

[Pages] Responsive Design and Image Optimisation

[Pages] Responsive Design and Image Optimisation

In today's post, we'll delve into enhancing the user experience on our product page by leveraging the Next.js Image component and responsive design principles. The goal is to display a larger, optimized product image alongside a detailed description and price. Additionally, we'll make sure the layout adjusts gracefully to different screen sizes.

Step 1: Adding the Product Image

To start, let's incorporate the Next.js Image component into our dynamic product page route. This component not only optimizes image loading but also adapts to different screen sizes seamlessly.

// pages/products/[id].js

import Head from 'next/head';
import Image from 'next/image';
import Title from '../../components/Title';
import { ApiError } from '../../lib/api';
import { getProduct, getProducts } from '../../lib/products';

function ProductPage({ product }) {
  return (
    <>
      <Head>
        <title>{product.title}</title>
      </Head>
      <main className="px-6 py-4">
        <Title>{product.title}</Title>
        <div className="flex flex-col lg:flex-row">
          <div>
            <Image src={product.pictureUrl} alt="" width={640} height={480} priority />
          </div>
          <div className="flex-1 lg:ml-4">
            <p className="text-sm">
              {product.description}
            </p>
            <p className="text-lg font-bold mt-2">
              {product.price}
            </p>
          </div>
        </div>
      </main>
    </>
  );
}

export async function getStaticPaths() {
  const products = await getProducts();
  const paths = products.map(product => ({
    params: { id: product.id.toString() },
  }));

  return { paths, fallback: false };
}

export async function getStaticProps({ params }) {
  try {
    const product = await getProduct(params.id);
    return { props: { product } };
  } catch (err) {
    if (err instanceof ApiError && err.status === 404) {
      return { notFound: true };
    }
    throw err;
  }
}

export default ProductPage;

Explanation:

  • Image Component: We've added the Image component with a width of 640 and height of 480 pixels. The priority attribute ensures that this image is a high-priority resource, loading it as soon as possible.

  • Responsive Flexbox Layout: To make the page responsive, we've wrapped the image and description in a div with Flexbox styling. This allows the layout to adapt based on screen size.

Step 2: Implementing Responsive Design

Using Flexbox, we can easily rearrange our layout for different screen sizes. On larger screens, we'll display the image and description side by side. On smaller screens, the description will appear below the image.

Flexbox Implementation:

  • Default Flexbox Direction: By default, the elements inside our Flexbox container are displayed in a column (flex-col). On large screens (lg:flex-row), they switch to a row layout.

  • Responsive Styling: We add a left margin (lg:ml-4) to the description only on large screens to ensure there's space between the image and text.

CSS Classes:

  • Text Styling: The description is styled with smaller text (text-sm), while the price is emphasized with larger, bold text (text-lg font-bold).

  • Layout Adjustments: Margins and spacing are adjusted to ensure the layout looks clean and readable on all devices.

Conclusion

By using the Next.js Image component and Flexbox, we've crafted a responsive product page that enhances the user experience. The image is optimized for performance, and the layout adapts seamlessly to different screen sizes. In future developments, we can expand this page by adding interactive elements like a purchase button, which will necessitate implementing user authentication.

Stay tuned for our next post, where we'll dive into adding authentication to our application, paving the way for personalized user experiences.

Last updated