How To Make a Hero Image in Next.js 13 and 14
Tags: nextjs, react, css, webdev
Published: 2023-11-12 15:48:29

I have noticed that one of my previously very popular article about [how to make a hero image in Next.js](https://www.perssondennis.com/articles/how-to-make-a-hero-image-in-nextjs) is still getting a lot of attention.

Unfortunately, that article was written when Next.js still used the Page Router. After that, with their new App Router in Next.js 13, the image component was replaced with a new one. With that in mind, I have now created a new article optimized for the new Image component in Next.js 13 and 14, for all of you who have, or want to, migrate to use the Image component.

## In This Article

1. [Next.js 13+ Image Component](#nextjs-13-image-component)
1. [Changes in Next.js 13+ Image Component](#changes-in-nextjs-13-image-component)
1. [How To Create a Hero Image With Next.js 13+](#how-to-create-a-hero-image-with-nextjs-13)
1. [Solution Explained](#solution-explained)
1. [Choosing a Hero Image](#choosing-a-hero-image)
1. [Summary](#summary)

{% cta https://2e015922.sibforms.com/serve/MUIFAGF3ypa0p6D6nTWI0MHVOIAC7q4TIJd0yXAhiBC9CswkNPnOlQBzeqSbR2XFM95gUn2G1IxWVkpkF0EQekcWpoNfmpxjm4RqEGjQvFrLOTkfFN9Y3X7tjUaaG9tz9UYhn_O_dWg1PPGS8kRM5ROREaJsslnGD8WEHszzZr0geJ9-g7lGsbn_hTT-wZSKWa1C8ay4Ok85ozro %}Subscribe to my articles{% endcta %}

## Next.js 13+ Image Component

The new image component which you can use in Next.js 13 and 14 has changed slightly from the legacy image component used in earlier versions. Both the legacy and the new one offer similar advantages, which makes it very beneficial to use instead of the regular image HTML element. Both of the components can help you with:

- Resizing images for you so [you don't need to use srcset manually](https://nextjs.org/docs/app/api-reference/components/image#sizes)
- Automatically lazy loads images when they are scrolled into view, which of course is [optional](https://nextjs.org/docs/app/api-reference/components/image#priority)
- Gives you various optimization option, such as [quality](https://nextjs.org/docs/app/api-reference/components/image#quality), [priority](https://nextjs.org/docs/app/api-reference/components/image#priority) and custom [image sizes](https://nextjs.org/docs/app/api-reference/components/image#sizes)
- Supports adding a placeholder to [blur images](https://nextjs.org/docs/app/api-reference/components/image#blurdataurl) when they are loading

For the blurring, you can check my [old article](https://www.perssondennis.com/articles/how-to-make-a-hero-image-in-nextjs) if you wonder more about how it works.

![Batman hero image](https://www.perssondennis.com/images/articles/what-if-movie-characters-had-linkedin-profiles/batman-linkedin-profile.webp)
_I bat [Batman](https://www.perssondennis.com/articles/what-if-movie-characters-had-linkedin-profiles) would make a great hero image_

## Changes in Next.js 13+ Image Component

Next.js offers a [migration codemod scripts](https://nextjs.org/docs/app/building-your-application/upgrading/app-router-migration#image-component) for migrating to the new image components. The codemods are not bullet-proof, so you should check [what has changed](https://nextjs.org/docs/pages/api-reference/components/image-legacy#comparison) in the new image component if you are planning to migrate.

Some of the changes have affected how a hero image can be implemented. Mainly, they have replaced _layout_ property, removed the objectFit prop and removed the absolute positioned _span_ element which was wrapping the _img_ element in the legacy image component.

## How To Create a Hero Image With Next.js 13+

The principe of how to implement a hero image is quite simple with the new Image component. I would recommend the following setup.

1. Start with a wrapper div with relative _position_, 100vw _width_ and your desired height
1. Insert the Next.js image component with _fill_ and _priority_ props set to true, and a class style with a _z-index_ of -1
1. Place whatever content you want after the image wrapper, but within the outer wrapper div

**Note**: You can optionally wrap the image in a wrapper div if you cannot set a style directly on your image component for some reason. In that case, the wrapper must set the CSS attribute _position_ to "absolute" value.

Following the steps above would give you a component looking something like below. The implementation is using css modules. You can also find the code at [CodeSandbox](https://codesandbox.io/p/sandbox/nextjs-13-hero-image-example-xl65cq?file=%2Fapp%2FHeroImage.tsx%3A10%2C34) and [GitHub](https://github.com/PerssonDennis/examples/blob/main/nextjs-13-and-14-hero-image/app/HeroImage.tsx).

```react
// HeroImage.jsx

import Image from "next/image";
import styles from "./heroImage.module.css";

const { heroContent, heroImage, heroWrapper } = styles;

const IMAGE_URL = "https://www.perssondennis.com/images/perfect-avocado.webp";

const HeroImage = () => {
  return (
    <div className={heroWrapper}>
      <Image
        className={heroImage}
        priority
        src={IMAGE_URL}
        fill
        alt="hero image example"
      />

      <div className={heroContent}>
        <h1>Hero Image</h1>
        <p>Next.js 13 hero image example.</p>
      </div>
    </div>
  );
};

export default HeroImage;

```

```css
// heroImage.module.css

.heroWrapper {
  position: relative;
  width: 100vw;
  height: 50vh;
}

.heroImage {
  object-fit: cover;
  object-position: center;
  z-index: -1;
}

.heroContent {
  display: flex;
  flex-direction: column;
  align-items: center;
}
```

Note that I did also set the _objectFit_ property to "cover". You decide how you want you image to scale by choosing a suitable value for _objectFit_ attribute.

- _contain_ value for objectFit will keep the aspect ratio, which may not be desired for a hero image
- the _cover_ value will fill up the available area in the parent element by cropping the image where it is necessary
- _fill_ option will stretch the image to fill up the parent element

When you crop the image by using "cover" as a value, you may want to set _objectPosition_ to make sure you keep the parts of the image you want from being cropped out.

![Next.js 13 and 14 hero image example](https://www.perssondennis.com/images/articles/how-to-make-a-hero-image-in-nextjs/nextjs-hero-image-example.webp)
_Above example could look something like this_

## Solution Explained

CSS is not always that intuitive, so I'll go through what we did there.

The wrapper div around everything had a relative _position_, what that does, is to tell that absolute positioned images within that element should be positioned relative to it. Absolute positioned elements are relative to the first parent which is explicitly positioned.

The image component Next.js provides does use an absolute position when we use the _fill_ prop for the image component, so the relative position of the wrapper ensures that the image will grow to fill the wrapper and not the whole viewport.

We also added a negative _z-index_ to the image. That is to ensure that the image will be placed under any other content rendered on the same area as the hero image, which means, all the other content we want to display on top of the hero image.

To the image component, we did pass a priority property. This is to disable lazy loading for hero image, since a hero image should always load as quick as possible.

Rest of code should be self explanatory. If it isn't, let me know about your questions.

{% embed https://dev.to/perssondennis/react-anti-patterns-and-best-practices-dos-and-donts-3c2g %}

## Choosing a Hero Image

If you don't have a hero image and don't want to buy one, there's a lot of free ways to get them. You can find links to some royalty free image sources in my [list of useful image tools](https://www.perssondennis.com/articles/list-of-free-image-tools-every-frontend-developer-needs#user-content-9-royalty-free-images-graphics-and-videos).

That article also lists a lot of useful resources to edit images, both an online Photoshop application and tools for editing, generating and converting images to other format.

Speaking of generating an image. You are probably aware of AIs which can generate images for you. While DALL-E may be the most known one, I prefer [Leonardo.Ai](https://app.leonardo.ai/) du to its high quality and realistic images which suits very well for hero images.

Whatever image you choose, make sure to reduce the size of it to a couple of 100 kB or preferably less, dependent on how high resolution and what detail level you need for your image. You can read about the impact of image size and how to optimize an image in my article about [how I improved Lighthouse Performance by adding a hero image](https://www.perssondennis.com/articles/how-i-improved-lighthouse-performance-by-adding-an-image).

{% embed https://dev.to/perssondennis/how-to-use-mvvm-in-react-using-hooks-and-typescript-3o4m %}

## Summary

- Next.js 13 comes with a new image component which is fairly similar to the old one
- Just as the old image component, it offers image optimizations, lazy loading and blurred placeholders
- The new image component can easily be used as a hero image, but remember to use relative position for the parent element
- Use z-index to control that the hero image stays below other content in the hero area

{% embed https://dev.to/perssondennis %}