Course outline · 0% complete

0/29 lessons0%

Course overview →

Images and fonts

lesson 8-2 · ~9 min · 26/29

next/image: img with the footguns removed

A plain <img> can silently wreck a page: huge files sent to phones, and content jumping as images pop in (layout shift). Next.js ships a component that fixes both:

import Image from "next/image";

<Image src="/team.jpg" alt="Our team" width={800} height={500} />

What it does for you:

  • Resizes and re-encodes to modern formats per device, so a phone never downloads a desktop-size JPEG.
  • Lazy-loads images below the fold by default.
  • Reserves space from width and height before loading, so the layout never jumps.

That is also why width, height, and alt are required: the first two prevent layout shift, and alt you know from accessibility basics.

plain <img>next/imageimage pops in late…text jumps downspace reservedtext never moves
Layout shift: a plain img inserts itself late and shoves content down. next/image reserves the exact space up front from width and height.

Why width and height are required

next/image insists on width and height for a local image so it can reserve the right space before the image loads, which is what prevents layout shift.

Knowing the aspect ratio up front lets Next.js render a correctly-sized placeholder box. Surrounding content is laid out around that box immediately, so nothing jumps when the real pixels arrive a moment later.

These props are a layout-stability contract, not a crop or a hard display size. The image can still be sized responsively with CSS. What Next.js needs is the ratio, so it can hold the right amount of room.

next/font: fonts without the flash

Loading Google Fonts with a <link> tag costs an extra round trip to Google and often a flash of fallback text. next/font downloads the font at build time and self-hosts it:

// app/layout.js
import { Inter } from "next/font/google";

const inter = Inter({ subsets: ["latin"] });

export default function RootLayout({ children }) {
  return (
    <html lang="en" className={inter.className}>
      <body>{children}</body>
    </html>
  );
}

No request ever goes to Google from your users' browsers (better privacy and speed), and the generated CSS includes fallback metrics that minimize text reflow. Set it once in the root layout and forget it.

Fixing a jumpy 4 MB hero photo

Here is a two-symptom bug: a teammate's hero photo makes the headline jump down half a second after page load, and mobile users download a 4 MB file. One component fixes both, the Image component from next/image.

Why it works out that way

  • The required width and height let it reserve space up front, so the headline never gets shoved down once the image arrives. That is the layout-shift half.
  • Its automatic resizing and format conversion serve mobile users an appropriately small file instead of the original 4 MB photo. That is the bandwidth half.
  • Both problems are exactly what the built-in image component exists to solve, which is why reaching for a plain img tag in Next.js is usually a mistake worth flagging in review.
SymptomPlain imgnext/image
File size on mobileOriginal, 4 MBResized and re-encoded
Space reserved before loadNoYes, from width/height
Below-the-fold loadingEager by defaultLazy by default
alt textOptional, often forgottenRequired