Presentational images

Decorative images: CSS backgrounds, image-set, and empty alt

What is a presentational image?

A presentational (or decorative) image is one that adds visual interest or atmosphere but carries no meaning on its own. Removing it would not cause a user to lose any information. Examples include:

  • A textured background behind a heading
  • An abstract illustration used as a section divider
  • A repeated pattern in a page's side margin
  • A faint watermark behind a pull-quote

Content images, by contrast, are the information — a product photo, a data chart, a photograph accompanying a news article. The distinction matters for two reasons:

  1. Accessibility: decorative images should be invisible to screen readers. A screen reader user does not benefit from hearing "decorative swirl pattern" read aloud mid-paragraph.
  2. Performance: decorative images are typically lower-urgency than content images. They should not compete with hero or product images for early-load bandwidth.

The delivery mechanism you choose — CSS background versus inline <img> — should reflect that distinction.

CSS background-image

When an image is purely decorative, the right place for it is CSS, not HTML. background-image keeps the image out of the document's content model: it is not part of the accessibility tree, cannot receive alt text, and is not reported by screen readers. That matches exactly what a decorative image should be.

Key properties that work alongside background-image:

  • background-position — where to anchor the image within the element (center, top right, percentage values, etc.)
  • background-sizecover scales the image to fill the element (may crop); contain fits it inside without cropping
  • background-repeatno-repeat for a single instance; repeat to tile; repeat-x / repeat-y for one axis

You can also swap the background image at different breakpoints using a media query — for example, serving a narrower crop on mobile and the full-width version on desktop.

/* Basic decorative background */ .banner { background-image: url("../assets/illustration.png"); background-position: center; background-size: cover; background-repeat: no-repeat; min-height: 200px; } /* Swap to a different image at a narrower viewport */ @media (max-width: 600px) { .banner { background-image: url("../assets/illustration.png"); background-size: contain; } }
Decorative background via background-image — no HTML image element, no alt text needed

Preloading backgrounds

CSS background images have a significant performance disadvantage: the browser does not discover them until it has parsed the HTML, constructed the DOM, applied the CSS, and determined which elements are actually visible. That is late in the page load timeline — much later than an <img> tag in the HTML, which the browser can begin fetching as soon as it encounters it.

If a CSS background image is important enough to appear above the fold (for example, a full-page hero background set in CSS), you can offset this late discovery using <link rel="preload">. Placing it in <head> tells the browser to fetch the image early, before it would otherwise find it in the stylesheet.

<!-- In <head>: preload the desktop background image --> <link rel="preload" as="image" href="../assets/illustration.png" media="(min-width: 800px)" >

image-set()

One limitation of a plain background-image: url() is that CSS cannot perform format negotiation on its own — the browser will fetch whatever file path you provide, with no ability to automatically choose AVIF over WebP over JPEG the way <picture><source type> does in HTML.

The image-set() CSS function addresses this. It accepts a list of image candidates — each pairing a URL with either a resolution descriptor (1x, 2x) or a type() hint — and the browser selects the best match based on its own format support and the device pixel ratio.

/* Format selection with type() hints */ .banner { background-image: image-set( url("../assets/illustration.png") type("image/png") ); /* Preferred — browser picks the first format it supports */ background-image: image-set( url("../assets/landscape-800.avif") type("image/avif"), url("../assets/landscape-800.webp") type("image/webp"), url("../assets/landscape-800.jpg") type("image/jpeg") ); background-size: cover; background-position: center; background-repeat: no-repeat; } /* Density selection with resolution descriptors */ .logo-bg { background-image: image-set( url("../assets/logo.png") 1x, url("../assets/logo@2x.png") 2x ); }

image-set() is now broadly supported across Chrome, Edge, Firefox, and Safari — the type() syntax for format hints landed later than density descriptors, so check caniuse.com/css-image-set for the current detail. For maximum compatibility, provide a plain url() fallback before the image-set() declaration:

.banner { /* Fallback for browsers that do not support image-set() */ background-image: url("../assets/landscape-800.jpg"); /* Progressive enhancement: overrides the fallback in supporting browsers */ background-image: image-set( url("../assets/landscape-800.avif") type("image/avif"), url("../assets/landscape-800.webp") type("image/webp"), url("../assets/landscape-800.jpg") type("image/jpeg") ); }

Decorative images in HTML — alt=""

Sometimes a decorative image must appear as an HTML <img> — for example, when it is part of a CMS template that generates <img> tags, or when you need it to participate in document flow. In those cases, the correct approach is to include the alt attribute with an empty string as its value: alt="".

An empty alt is not the same as a missing alt:

  • alt="" — explicitly marks the image as decorative. Screen readers skip it entirely. This is correct for decorative images.
  • No alt attribute at all — the browser treats the image as a content image whose description happens to be missing. Screen readers may announce the file name (e.g. "illustration dot png") which is worse than useless. This is an accessibility error.
  • alt="decorative" or alt="background" — describes the image's role rather than its content. Screen readers will announce it, which is exactly what you are trying to avoid. Also wrong.
<!-- Correct: empty alt signals "skip this" to screen readers --> <img src="../assets/illustration.png" alt="" width="400" height="267" loading="lazy" decoding="async" > <!-- Wrong: missing alt — screen reader may announce the filename --> <img src="../assets/illustration.png" width="400" height="267"> <!-- Wrong: descriptive alt on a decorative image — screen reader reads it --> <img src="../assets/illustration.png" alt="decorative background" width="400" height="267">
alt="" — screen readers skip this image entirely