Next.js: Build a Simple Interactive Image Gallery

Written by

in

In today’s fast-paced digital world, images are king. Websites and applications are visually driven, and the way we display images can significantly impact user engagement. Imagine a website where users can easily browse through a collection of photos, zoom in for details, and enjoy a seamless viewing experience. This is where an interactive image gallery comes into play. Building one might seem daunting, but with Next.js, a powerful React framework, we can create a dynamic and user-friendly image gallery with ease.

Why Build an Image Gallery with Next.js?

Next.js offers several advantages for building interactive image galleries:

  • Server-Side Rendering (SSR) & Static Site Generation (SSG): Next.js allows you to pre-render your image gallery on the server or at build time, leading to faster initial page loads and improved SEO.
  • Image Optimization: Next.js has built-in image optimization features, automatically resizing and compressing images for optimal performance.
  • Routing and Navigation: Next.js simplifies routing, making it easy to create different pages or sections for your image gallery.
  • React Ecosystem: Leverage the vast React ecosystem for components, libraries, and styling solutions.

This tutorial will guide you through the process of building a simple, yet functional, interactive image gallery using Next.js. We’ll cover everything from setting up your project to implementing features like image display, zoom, and navigation. By the end, you’ll have a solid understanding of how to create engaging image galleries that enhance user experience.

Prerequisites

Before we begin, make sure you have the following:

  • Node.js and npm (or yarn) installed on your system.
  • A basic understanding of HTML, CSS, and JavaScript.
  • Familiarity with React is helpful but not strictly required.

Project Setup

Let’s start by creating a new Next.js project. Open your terminal and run the following command:

npx create-next-app image-gallery-app
cd image-gallery-app

This command creates a new Next.js project named “image-gallery-app”. Navigate into the project directory using `cd image-gallery-app`.

Project Structure

Your project structure should look something like this:


image-gallery-app/
├── node_modules/
├── pages/
│   ├── _app.js
│   ├── index.js
│   └── ...
├── public/
│   ├── ...
├── styles/
│   ├── globals.css
│   └── ...
├── .gitignore
├── next.config.js
├── package-lock.json
├── package.json
└── README.md

The `pages` directory is where we’ll create our routes. The `index.js` file inside the `pages` directory will be the homepage of our image gallery.

Adding Images

For this tutorial, we’ll use a few sample images. You can either download images from a free stock photo website or use your own. Place your images in the `public` directory of your project. For example, you might create a folder called `images` inside the `public` directory and place your images there.

Here’s how your `public` directory might look:


public/
└── images/
    ├── image1.jpg
    ├── image2.jpg
    ├── image3.jpg
    └── ...

Creating the Image Gallery Component

Now, let’s create a reusable component for displaying our images. Create a new file called `ImageGallery.js` inside the `components` directory. If the `components` directory doesn’t exist, create it.

Here’s the code for `ImageGallery.js`:

// components/ImageGallery.js
import Image from 'next/image';
import { useState } from 'react';

const ImageGallery = ({ images }) => {
  const [selectedImage, setSelectedImage] = useState(null);

  const openModal = (image) => {
    setSelectedImage(image);
  };

  const closeModal = () => {
    setSelectedImage(null);
  };

  return (
    <div className="image-gallery">
      <div className="gallery-grid">
        {images.map((image, index) => (
          <div key={index} className="gallery-item" onClick={() => openModal(image)}>
            <Image
              src={image.src}
              alt={image.alt}
              width={image.width}
              height={image.height}
              layout="responsive"
              objectFit="cover"
            />
          </div>
        ))}
      </div>

      {selectedImage && (
        <div className="modal" onClick={closeModal}>
          <div className="modal-content" onClick={(e) => e.stopPropagation()}>
            <span className="close" onClick={closeModal}>&times;</span>
            <Image
              src={selectedImage.src}
              alt={selectedImage.alt}
              width={selectedImage.width}
              height={selectedImage.height}
              layout="responsive"
            />
          </div>
        </div>
      )}
    </div>
  );
};

export default ImageGallery;

Let’s break down this code:

  • Import Statements: We import `Image` from `next/image` for optimized image rendering and `useState` from `react` for managing state.
  • State Management: `selectedImage` is a state variable that holds the currently selected image, which will be displayed in a modal.
  • `openModal` function: This function sets the `selectedImage` state when an image is clicked, opening the modal.
  • `closeModal` function: This function sets `selectedImage` to `null`, closing the modal.
  • Image Mapping: We iterate over the `images` array using `.map()` and render an `Image` component for each image. The `onClick` event on the gallery item calls the `openModal` function, passing the image data.
  • Modal: The modal is conditionally rendered based on the `selectedImage` state. It displays the full-sized image when an image is selected. The `onClick={(e) => e.stopPropagation()}` prevents the modal’s click from triggering the close function.
  • `next/image` Component: We use the `Image` component from Next.js. It provides image optimization features. The `layout=”responsive”` and `objectFit=”cover”` are used for responsive image display and cover the container.

Styling the Image Gallery

To style the image gallery, open `styles/globals.css` and add the following CSS:


.image-gallery {
  padding: 20px;
}

.gallery-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
  gap: 20px;
}

.gallery-item {
  cursor: pointer;
  border-radius: 8px;
  overflow: hidden;
}

.gallery-item img {
  width: 100%;
  height: auto;
  transition: transform 0.3s ease;
}

.gallery-item:hover img {
  transform: scale(1.05);
}

.modal {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background-color: rgba(0, 0, 0, 0.8);
  display: flex;
  justify-content: center;
  align-items: center;
  z-index: 1000;
}

.modal-content {
  background-color: #fff;
  padding: 20px;
  border-radius: 8px;
  position: relative;
}

.modal-content img {
  max-width: 90vw;
  max-height: 90vh;
}

.close {
  position: absolute;
  top: 10px;
  right: 10px;
  font-size: 30px;
  color: #aaa;
  cursor: pointer;
}

This CSS provides basic styling for the gallery grid, image items, and the modal. Feel free to customize the styles to match your design preferences.

Using the Image Gallery Component in `index.js`

Now, let’s use the `ImageGallery` component in our `pages/index.js` file. Replace the contents of `index.js` with the following code:

// pages/index.js
import ImageGallery from '../components/ImageGallery';

const images = [
  {
    src: '/images/image1.jpg',
    alt: 'Image 1',
    width: 800,
    height: 600,
  },
  {
    src: '/images/image2.jpg',
    alt: 'Image 2',
    width: 800,
    height: 600,
  },
  {
    src: '/images/image3.jpg',
    alt: 'Image 3',
    width: 800,
    height: 600,
  },
  // Add more image objects as needed
];

const Home = () => {
  return (
    <div>
      <h1>My Image Gallery</h1>
      <ImageGallery images={images} />
    </div>
  );
};

export default Home;

Here’s what’s happening:

  • Import the component: We import the `ImageGallery` component we created earlier.
  • Define the images array: We create an array of `image` objects. Each object contains the `src`, `alt`, `width` and `height` properties. Make sure to update the `src` paths to match the location of your images in the `public` directory.
  • Render the component: We render the `ImageGallery` component and pass the `images` array as a prop.

Running the Application

To run your Next.js application, open your terminal and run the following command from the root directory of your project:

npm run dev

or

yarn dev

This will start the development server. Open your web browser and go to `http://localhost:3000`. You should see your image gallery with the images you added, and clicking on an image should open it in a modal.

Common Mistakes and Troubleshooting

Here are some common mistakes and how to fix them:

  • Image Paths: Double-check that the image paths in your `images` array are correct and match the location of your images in the `public` directory. A common error is a 404 error if your paths are incorrect.
  • Image Dimensions: Make sure to specify the `width` and `height` properties for each image. These are required for the `next/image` component to work correctly and optimize the images.
  • CSS Conflicts: If your gallery doesn’t look right, inspect your CSS and make sure there are no conflicting styles. Use your browser’s developer tools to identify and resolve any issues.
  • Modal Not Appearing: If the modal isn’t appearing, check your CSS for the `.modal` class. Ensure that `display: flex;` is set and that the `z-index` is high enough to be on top of other elements. Also, ensure that the modal is conditionally rendered based on the `selectedImage` state.

Enhancements and Further Development

This is a basic image gallery, and there are many ways to enhance it:

  • Image Zoom: Implement a zoom feature to allow users to zoom in on images within the modal. Libraries like `react-zoom-pan-pinch` can be helpful for this.
  • Image Navigation: Add navigation arrows to move between images in the modal.
  • Lazy Loading: Implement lazy loading to improve performance by loading images only when they are visible in the viewport. Next.js’s `Image` component handles this automatically.
  • Image Captions: Add captions or descriptions to your images.
  • Responsive Design: Ensure that your gallery is responsive and looks good on different screen sizes.
  • Server-Side Rendering (SSR) for Image Data: Fetch the image data from an external source (e.g., a database or API) and use server-side rendering to improve SEO and performance.

Key Takeaways

Building an interactive image gallery in Next.js is a rewarding project that combines front-end development with image optimization and user experience. By leveraging Next.js’s features, you can create a fast, responsive, and visually appealing gallery. Remember to pay attention to image paths, dimensions, and styling to ensure a smooth user experience. This tutorial provides a solid foundation for building more complex image galleries. Experiment with different features and libraries to further enhance your gallery.

This tutorial provides a functional starting point, but the true power of Next.js lies in its flexibility. You can adapt the code to fetch images from an API, incorporate animations, or integrate with other services. The key is to break down the problem into smaller, manageable components and to leverage the features that Next.js offers. Consider the user experience throughout the design process, and always test your application on different devices and browsers. With a little creativity and effort, you can create a stunning and engaging image gallery that showcases your photos in the best possible light. Keep in mind that continuous learning and experimentation are crucial in the ever-evolving world of web development. Embrace the challenges, and enjoy the process of building something amazing!