Stop 04 · JavaScriptProjects · 8/8

Image Gallery

Part of the Frontend Developer Roadmap

In short

A gallery with thumbnails, a full-screen view and arrow-key controls looks great in a portfolio. It also makes you think about loading images smartly and about keyboard users.

A responsive image grid with a lightbox/modal viewer — practice for CSS Grid, modal UI patterns, and keyboard navigation (arrows, Esc to close). The project combines responsive layout, stateful modal behavior, image loading, keyboard accessibility, focus management, and efficient media handling.

The jaadu mascot holds a big phone with a grid of thumbnails as one picture pops out.

Think of it like this

Your phone's gallery app

A grid of small thumbnails. Tap one and it opens full screen, swipe for the next, tap outside to close. You're building that same thing for the web, with clicks and arrow keys in place of swipes.

Watch it happen

Next and previous with wrap-around

goa
0
current
manali
1
hampi
2

1/5Click the first thumbnail. show(0) opens the dialog with goa.

The big ideas

What you need to know

Responsive grid

CSS Grid with repeat(auto-fill, minmax(150px, 1fr)) gives a grid that fits any screen.

Lazy-load the images

Add loading="lazy" so images below the fold load only when the user scrolls near them.

Use <dialog> for the lightbox

dialog.showModal() opens a proper modal. Escape closes it for free and focus stays inside.

Keyboard and alt text

Arrow keys for next and previous, and a meaningful alt on every image for screen readers.

How it works

Build plan

  1. 1

    Image data

    An array of objects with thumbnail URL, full-size URL and alt text.

  2. 2

    Render the grid

    Make thumbnails from the array with lazy loading.

  3. 3

    Open the lightbox

    Clicking a thumbnail opens a <dialog> with the full-size image.

  4. 4

    Next and previous

    Buttons and arrow keys that wrap around at both ends.

  5. 5

    Polish

    Captions, an image counter like 3 / 12, and a loading state for big images.

See it in code

Walk through the code

js
1const images = ["goa.jpg", "manali.jpg", "hampi.jpg"];2let current = 0;3const dialog = document.querySelector("dialog");4const big = dialog.querySelector("img");5 6function show(index) {7  current = (index + images.length) % images.length;  // wraps at both ends8  big.src = images[current];9  if (!dialog.open) dialog.showModal();10}11 12document.addEventListener("keydown", (e) => {13  if (!dialog.open) return;14  if (e.key === "ArrowRight") show(current + 1);15  if (e.key === "ArrowLeft") show(current - 1);16});

1/4The image list, the current index and the dialog parts.

Adding images.length before % keeps the index positive, so pressing Left on the first image jumps to the last one instead of breaking.

Save yourself the pain

Common mistakes

Oops

Using full-size 4 MB photos as thumbnails.

Do this instead

Make small thumbnail versions and load the big one only in the lightbox.

Oops

Leaving alt empty on every photo.

Do this instead

Write a short description like alt="Sunset at Baga beach". Use alt="" only for purely decorative images.

Oops

Building the modal from a div and forgetting Escape and focus.

Do this instead

Use the built-in <dialog> element. It handles Escape and keeps focus inside the modal.

Your mission

Milestone 1: grid to full screen

~40 min

Quick check

You have 3 images and you're on index 0. You press Left. What is (current - 1 + images.length) % images.length?

Go deeper

  1. 1Build a responsive grid using CSS Grid's `auto-fill`/`auto-fit`. Keep the first version small, then add one improvement after the core behavior works.
  2. 2Add a modal lightbox that opens on click with next/prev navigation. Test the result on both a successful path and an invalid or unexpected input.
  3. 3Support closing the modal with the Escape key and clicking the backdrop.

More projects at this stop

Stuck on this topic? Ask an Insider

Get 1:1 guidance from people who've walked this exact path — on the InsideEdge app.

Download
InsideEdge