Overlap images using CSS Grid and NextJS/Image

This tutorial works regardless if you use NextJS’s Image component or just a regular img tag.

But the genesis of this solution came from NextJS’s Image component not working well with the traditional position:relative/absolute method.

smoke screen layer demonstration

I needed to overlay a smoke layer on the skier so that he “blends” into the white page. While I could have created an image in Photoshop, I wanted to do it more efficiently by layering the smoke over every skier.

I have found this method to be MUCH better than the traditional way too, since it’s significantly less CSS to write.

I think there’s a change in NextJS 12’s Image component, so you will need to target the child span instead of the child div (which I used in Next 11).

You can review all files below in the Github repo. I have also included my smoke.png file, but the image of the guy is not in there because I cannot share it.

HTML and CSS structure to overlay images

If you want the full details, make sure to watch the YouTube video. The following is meant for quick reference so that if you know what you’re doing, you can save some time.

athletes with smoke layer blending into page css grid
Use case in a real project

This method of overlapping two images was used in a real project, and I am using a default deployment of Next.JS (via npx create-next-app) to share this example.

Below is the code used in index.js.

Fundamentally, you need a div with a class that will contain your grid layout that has two of Next.JS’s Image components. Make sure to declare the width and height in pixels since it’s necessary if you are using a responsive layout.

import Head from "next/head";
import Image from "next/image";
import styles from "../styles/Home.module.css";

export default function Home() {
  return (
    <div className={styles.container}>
      <div className={styles.overlapGrid}>

The styles of all styles are contained in the CSS module called Home.module.css, so here’s the accompanying code that goes there.

.overlapGrid {
  display: grid;
  grid-template-areas: "overlay";

.overlapGrid > span {
  grid-area: overlay;
.overlapGrid > div {
  grid-area: overlay;

To explain what’s happening here:

  1. overlapGrid is the div that contains two images; it declares the grid layout using display:grid and a grid-template-areas named “overlay”.
  2. overlapGrid > span (or div) selects spans and divs created by Next/Image and places that on the grid-area: overlay which means both are placed on the same area.

Why target >div and >span

The code above is “failsafe”.

I wrote an app in NextJS 11 and the code worked when I only targeted overlapGrid > div .

But when I re-created it with Next 12, I seem to have to target the span for it to work.

Also, be wary that your overlain images might be 1px offset. Just put both images on a contrasty background (such as black on a white smoke layer), and you will be able to judge better. To fix this bug, use this:

.overlapGrid > div:nth-child(2) {
  /* offset to kill bug where smoke is 1px too high */
  top: 1px;


Github repo:

Have a project in mind?

Websites. Graphics. SEO-oriented content.

I can get your next project off the ground.

See how I have helped my clients.