HTML Background Images

A “background image” is a picture that fills the area behind an element’s text and content, rather than appearing as its own inline image. Backgrounds are used for hero banners, textured page backers, decorative section dividers, and more. Here’s the key fact this lesson exists to teach: HTML itself has no attribute that sets a background image. That job belongs entirely to CSS. Understanding why, and understanding what HTML-level tools exist nearby (like the deprecated background attribute and the modern picture/img elements), will save you hours of confusion.

Overview: Why Background Images Are a CSS Job, Not an HTML Job

HTML’s purpose is to describe the structure and meaning of a document: this is a heading, this is a paragraph, this is a list, this is an image that conveys content. CSS’s purpose is to describe presentation: colors, spacing, fonts, and yes, background images. This separation of concerns is one of the foundational design principles of the web platform.

When the browser parses an HTML document, it builds the DOM tree (Document Object Model) purely from the tags and content it finds. No visual information lives in the DOM by itself. Separately, the browser builds a CSSOM (CSS Object Model) from any stylesheets, combines it with the DOM to form the render tree, and only then decides how each element should look — including whether it has a background image, what color it is, and how that image should repeat, position, or scale.

So when someone asks “how do I set a background image in HTML,” the honest answer is: you don’t, not in the modern web. You set it in CSS, using a property like background-image, typically inside a <style> block in the document’s <head>, an external .css file linked with <link>, or (less ideally) an inline style attribute on the element. This HTML course does not teach CSS syntax in depth — that’s covered in the CSS course — but you do need to know where the seam is so you don’t waste time hunting for an HTML background attribute that isn’t the right tool for the job.

A Brief History: the Old background Attribute

In very old HTML (HTML 4 and earlier), the <body> element supported a presentational attribute: <body background="tile.gif">. Some older table-based layouts also allowed a background attribute on <table>, <td>, and <th>. This attribute is obsolete in HTML5. Modern browsers still render it for backward compatibility with decades-old pages, but you should never write it in new markup, and validators will flag it as an error or warning. Anywhere you see background="..." on an HTML element in a tutorial, treat that tutorial as outdated.

Syntax: Where a Background Image Actually Gets Declared

Since the mechanism lives in CSS, the “syntax” a modern HTML author needs to know is really about how to attach CSS to an element so that CSS can declare the background. There are three attachment points:

Method Where it lives Typical use
External stylesheet <link rel="stylesheet" href="styles.css"> in <head> Best practice for real sites — keeps structure and presentation separate and cacheable
Internal stylesheet <style> block in <head> Fine for single-page demos or this-lesson-style examples
Inline style attribute style="..." on the element itself Quick prototyping only; hard to maintain, cannot be cached or reused

The general form, using an internal stylesheet, looks like this:

<head>
  <style>
    .hero {
      background-image: url("hero.jpg");
      background-size: cover;
      background-position: center;
      background-repeat: no-repeat;
    }
  </style>
</head>
<body>
  <section class="hero">
    <h1>Welcome</h1>
  </section>
</body>
  • class="hero" — the HTML part: a plain, meaning-neutral hook that CSS can target. HTML’s only job here is to give the element an identifiable name.
  • background-image: url(...) — the CSS property that actually points at the image file.
  • background-size, background-position, background-repeat — companion CSS properties that control how the image scales, where it’s anchored, and whether it tiles. These are CSS concerns, listed here only so you recognize them when you see them alongside background-image.

Examples

Example 1: A Section With a Background via Internal Stylesheet

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Background Basics</title>
  <style>
    .banner {
      background-image: url("mountains.jpg");
      background-repeat: no-repeat;
      background-size: cover;
      min-height: 300px;
    }
  </style>
</head>
<body>
  <section class="banner">
    <h1>Explore the Mountains</h1>
    <p>Adventure awaits.</p>
  </section>
</body>
</html>

Result: A full-width band at least 300 pixels tall appears, filled edge-to-edge with the mountains.jpg photo scaled to cover the whole area without tiling. The heading “Explore the Mountains” and the paragraph beneath it are rendered as normal text sitting on top of that image.

The HTML here contributes nothing about the image itself — it only supplies the <section class="banner"> element for the CSS rule to target. The DOM has no idea an image is involved; the render tree adds that visual detail after combining DOM and CSSOM.

Example 2: Multiple Elements, One Shared Background Style

<style>
  .card {
    background-image: url("paper-texture.png");
    background-repeat: repeat;
    padding: 16px;
  }
</style>

<article class="card">
  <h2>Recipe: Sourdough Bread</h2>
  <p>A simple three-ingredient loaf.</p>
</article>

<article class="card">
  <h2>Recipe: Pancakes</h2>
  <p>Fluffy weekend breakfast classic.</p>
</article>

Result: Two separate card-like blocks appear, each tiled with a repeating paper-texture pattern behind its heading and paragraph, with 16 pixels of padding keeping the text away from the edges.

This demonstrates reuse: because the background is defined once via the .card class rather than per element, both <article> elements automatically share the same background without repeating any CSS or HTML attributes.

Example 3: Content Image vs. Decorative Background — Choosing the Right Tool

<figure>
  <img src="chart-2025-sales.png" alt="Bar chart showing 2025 quarterly sales growth">
  <figcaption>Figure 1: Quarterly sales growth in 2025</figcaption>
</figure>

<style>
  .page-footer {
    background-image: url("subtle-lines.svg");
    background-repeat: repeat-x;
  }
</style>
<footer class="page-footer">
  <p>© 2026 Example Co.</p>
</footer>

Result: The sales chart appears as a genuine, meaningful <img> with a visible caption below it, while the footer displays a thin decorative line pattern tiled horizontally behind the copyright text.

This is the most important conceptual example in the lesson: the chart is content — it conveys information, so it belongs in an <img> element with meaningful alt text that screen readers announce. The footer pattern is purely decorative — it conveys no information, so it belongs in CSS as a background-image, which screen readers correctly skip entirely. Mixing these up either buries real content where assistive technology can’t find it, or forces decorative noise into every screen reader’s output.

Under the Hood: How the Browser Actually Paints a Background

Once the browser has both the DOM (from HTML) and the CSSOM (from CSS), it merges them into the render tree, keeping only elements that will actually be visible. For any element whose computed style includes a background-image, the rendering engine performs roughly these steps:

  1. It resolves the element’s box — its width, height, padding, and border — during the layout (reflow) phase.
  2. It fetches the image resource referenced by the url() value, decoding it asynchronously so it doesn’t block the rest of the page.
  3. During the paint phase, it draws the background image into the element’s padding box, applying whatever background-size, background-position, and background-repeat rules apply, before drawing the element’s own text and child content on top.
  4. If the image hasn’t finished downloading yet, the element simply renders without it (often showing its background color, if any) until the image arrives, then repaints.

Notice that none of this touches the DOM tree at all — a background image is never a DOM node, never has an alt attribute, and is invisible to the accessibility tree. That’s precisely why it’s the wrong tool for content that matters to your page’s meaning.

Common Mistakes

Mistake 1: Using the Obsolete background Attribute

<body background="wallpaper.gif">
  <p>Hello world</p>
</body>

Why it’s wrong: background is an obsolete presentational attribute removed from the HTML5 standard. It still “works” in most browsers for legacy compatibility, but it fails modern validators, cannot be overridden responsively the way CSS can, and mixes presentation into structure.

<style>
  body {
    background-image: url("wallpaper.gif");
  }
</style>
<body>
  <p>Hello world</p>
</body>

Corrected: the exact same visual effect, declared in CSS where it belongs.

Mistake 2: Using an <img> Purely for Decoration

<div>
  <img src="stripe-pattern.png" alt="">
  <h1>Welcome to Our Site</h1>
</div>

Why it’s questionable: stacking a purely decorative pattern image as a sibling <img> in the DOM adds an extra HTTP-relevant, layout-relevant node for something that conveys no content. It also requires extra CSS positioning tricks to layer it behind the heading, work that a background image handles natively.

<style>
  .welcome-wrap {
    background-image: url("stripe-pattern.png");
  }
</style>
<div class="welcome-wrap">
  <h1>Welcome to Our Site</h1>
</div>

Corrected: the pattern becomes a true background, automatically sitting behind the heading with no extra markup or positioning hacks.

Best Practices

  • Use CSS background-image for anything decorative — patterns, textures, hero banners, section dividers.
  • Use a real <img> element (with meaningful alt text) for anything that conveys information, like photos, charts, diagrams, or logos.
  • Never use the obsolete background attribute on <body> or table elements in new markup.
  • Prefer an external stylesheet linked via <link> over inline style attributes so background rules stay reusable and cacheable.
  • Always give the element carrying a background image enough height (via content or a min-height rule in CSS) so the image has room to be visible.
  • Remember that background images are invisible to screen readers and search engines — never hide meaningful text-in-an-image content behind a CSS background as a substitute for real text or a proper <img>.
  • If you need a background image to also have a fallback color for slow connections, pair it with a CSS background-color, not an HTML attribute.

Practice Exercises

  1. Create an HTML document with a <header> element containing an <h1>. Using an internal <style> block, give the header a decorative background image that covers the full area without repeating.
  2. Take a page that currently uses <body background="tile.png"> and rewrite it using modern CSS instead, producing the same visual tiling effect.
  3. Build a small page with two sections: one showing a photograph that conveys real information (use a properly described <img>), and one showing a decorative divider pattern (use CSS background-image). Explain in a comment-free sentence to yourself why each choice is correct.

Summary

  • HTML has no modern attribute for setting background images — that responsibility belongs to CSS’s background-image property.
  • The old background attribute on <body> and table elements is obsolete and should never be used in new code.
  • HTML’s role is to supply a targetable element (often via a class); CSS’s role is to declare the image, sizing, position, and repeat behavior.
  • The browser paints backgrounds during the paint phase, behind an element’s content, using information from the merged DOM + CSSOM render tree — backgrounds are never DOM nodes.
  • Use a real <img> with alt text for meaningful content; use a CSS background for purely decorative imagery, since backgrounds are invisible to screen readers and search engines.