Skip to content
CodeAndBuild LogoCodeAndBuild

Next.js

Size Blog Cover Images So They Stay Sharp on Every Screen

Use next/image for local 16:9 covers, set a real sizes value, and keep the hero sharp without shipping a huge file to a phone.

CodeAndBuild Team9 min read
  • Next.js
  • Images
  • Performance
  • Blog
On this page
  1. Give the picture a frame, then fill it
  2. Write sizes for the slot, not the file
  3. Mark one image as the first paint
  4. Check the request, not the preview

A cover that looks crisp on a desktop and light on a phone is a layout decision, not a Photoshop export. Next.js can resize a local file into several widths and let the browser pick one. That only works when the Image component knows how wide the picture will be on the page. A missing sizes value makes the browser assume the image is full viewport width, so a small card still downloads a hero-sized file.

Keep the master file in public/images and reference it with a path that starts at the site root, such as /images/cover.jpg. Files in public are served as static assets. next/image still optimizes them: it generates a srcset, picks a modern format when the browser accepts one, and caches the result. You do not add a remote pattern for a file that already lives in the repo.

Give the picture a frame, then fill it

A 16:9 cover needs a box with a known aspect ratio. The image uses fill and sits inside a relative parent. object-cover crops the edges instead of stretching the photo. The alt text describes the scene a reader would miss if the file failed, in one calm sentence.

components/Cover.tsxtsx
import Image from "next/image";

export function Cover({ src, alt, priority = false }: { src: string; alt: string; priority?: boolean }) {
  return (
    <div className="relative aspect-[16/9] overflow-hidden rounded-2xl">
      <Image
        src={src}
        alt={alt}
        fill
        priority={priority}
        sizes="(min-width: 1024px) 42rem, 100vw"
        className="object-cover"
      />
    </div>
  );
}

Write sizes for the slot, not the file

sizes is a CSS media list that ends in a width. It answers one question: how wide will this image be drawn? On an article page the column might be 42rem once the viewport is at least 1024px, and nearly the full viewport below that. A home-page card in a three-column grid is closer to 33vw on a large screen and full width on a phone. Use a different sizes string for each slot. Reusing the hero string on a card is how a grid of twelve covers becomes a multi-megabyte page.

Slotsizes valueWhy
Article hero(min-width: 1024px) 42rem, 100vwThe reading column is the widest the photo gets.
Three-up card(min-width: 1024px) 22rem, (min-width: 640px) 50vw, 100vwThe card is a third of the grid, then half, then full width.
Open Graph onlyDo not use next/imageSocial cards want a fixed 1200×630 file, not a srcset.

Mark one image as the first paint

priority on the article hero tells Next.js to preload that image. It belongs on the single picture that is visible when the article opens. Cards below the fold stay lazy, which is the default. Putting priority on every card in a list makes the browser fetch them all at once and cancels the benefit.

  • Export covers at 16:9, around 1600 pixels wide. Next.js will make smaller copies.
  • Use a real photograph or illustration. Leave words out of the file so a title change does not require a new export.
  • Write alt text that names the subject. Decorative duplicates of the title can use an empty alt only when the title is already next to the image.
  • Keep remote hosts in images.remotePatterns. A local public file does not need an entry.

Check the request, not the preview

Open the article, then the network panel, and filter for the image. On a narrow window you should see a width parameter well under the master file. Widen the window and the chosen width should step up. If every viewport requests the same large width, the sizes string does not match the CSS. Fix the string before you compress the master again. Compression cannot repair a browser that was told the picture is 100vw inside a 280-pixel card.

More guides