Why Images Need width and height Attributes

An image can load quickly and still make a page feel broken if it pushes the article down when it appears. The fix is wonderfully unglamorous: include width and height in the HTML.

Those attributes do not have to lock a responsive image to one display size. They give the browser its intrinsic dimensions, which are enough to work out the aspect ratio before the file arrives.

Without dimensions, the browser has to wait

Consider an article image with no size information:

<h1>My article</h1>

<img
  src="/photo.webp"
  alt="Street photograph"
>

<p>Article text...</p>

Before the download reveals the image dimensions, the browser may lay out the paragraph directly below the heading. The loaded image then takes its place and moves that paragraph down. This movement contributes to Cumulative Layout Shift.

Add the source dimensions:

<img
  src="/photo.webp"
  width="1200"
  height="800"
  alt="Street photograph"
>

The browser now knows the ratio is 1200 / 800, or 3 / 2, and can reserve a correctly shaped space straight away.

CSS still decides the displayed size

Responsive CSS can shrink the image without changing that ratio:

img {
  max-width: 100%;
  height: auto;
}

The HTML describes the source. CSS describes how it fits the layout. These jobs complement each other rather than compete.

A solid basic pattern is therefore:

<img
  src="/photo-1200.webp"
  width="1200"
  height="800"
  alt="Street photograph in Riga"
  loading="lazy"
>
img {
  max-width: 100%;
  height: auto;
}

Lazy loading makes sense here only if the image is not important near the top of the page.

Responsive sources need the same ratio information

srcset lets the browser choose a suitable file; dimensions let it reserve the layout:

<img
  src="/photo-800.webp"
  srcset="
    /photo-400.webp 400w,
    /photo-800.webp 800w,
    /photo-1200.webp 1200w
  "
  sizes="(max-width: 800px) 100vw, 800px"
  width="1200"
  height="800"
  alt="Street photograph"
>

This assumes the candidates share an aspect ratio. If mobile and desktop use different crops, <picture> and source-specific dimensions need more deliberate handling. The principle stays the same: provide enough information for the browser to know the shape it is about to display.

CSS aspect-ratio can also reserve a shape:

.image {
  aspect-ratio: 3 / 2;
}

I still prefer real image dimensions when they are available, because they come from the asset rather than duplicating its ratio in CSS.

Let Hugo output dimensions from the processed file

When Hugo processes an image:

{{ $image := $image.Resize "1200x webp" }}

the template can use the resulting metadata:

width="{{ $image.Width }}"
height="{{ $image.Height }}"

That removes both the manual work and the possibility of copying stale dimensions after an image changes.

My default image markup starts with src, useful alt, width, and height. Responsive sources, lazy loading, and fetch priority come next according to the image’s place on the page. The boring attributes do the important early job: they stop the rest of the page moving while the image arrives.