ScreenshotNeo

BlogHow-to

How to Add a Background Image with HTML and CSS

Add CSS background images with working HTML, responsive sizing, overlays, accessibility guidance, troubleshooting, and screenshot verification.

By the ScreenshotNeo team1 October 20266 min read

Use CSS to put the image behind the element that owns the content. Give that element a visible height (or content and padding), set background-image, then choose how the image fits with background-size, background-position, and background-repeat.

<section class="hero">
  <h1>Welcome</h1>
</section>
.hero {
  min-height: 24rem;
  background-image: url("images/hero.jpg");
  background-color: #333;
  background-position: center;
  background-repeat: no-repeat;
  background-size: cover;
}

This keeps the source proportions, fills the section, and may crop the image edges. The color remains visible while the image loads or if it fails.

1. Add a background image to an HTML element

The HTML element defines the box; CSS paints the background inside that box. A background does not create layout height by itself, so use content, padding, height, or min-height.

<main>
  <section class="hero">
    <div class="hero__content">
      <p class="eyebrow">Product update</p>
      <h1>A readable hero over a photo</h1>
      <p>The text stays in normal document flow.</p>
    </div>
  </section>
</main>
.hero {
  min-height: 24rem;
  padding: 4rem 1.5rem;
  color: white;
  background-color: #263238;
  background-image: url("../images/hero.jpg"); /* relative to this CSS file */
  background-repeat: no-repeat;
  background-position: center;
  background-size: cover;
}

.hero__content {
  max-width: 42rem;
  margin-inline: auto;
}

Paths in url() are resolved from the CSS file, not from the HTML document. An absolute URL also works when the resource allows cross-origin requests.

2. Make the image cover a section or the whole page

Section background

cover scales the image until every part of the box is covered while preserving its aspect ratio. If the box and image have different proportions, the excess is cropped. Centering gives a balanced crop:

.hero {
  background-size: cover;
  background-position: center;
}

Keep a subject near the top with background-position: center top, or bias it precisely with percentages such as background-position: 65% 30%.

Full-page background

html, body {
  min-height: 100%;
}

body {
  margin: 0;
  color: #fff;
  background-color: #111;
  background-image: url("images/page.jpg");
  background-repeat: no-repeat;
  background-position: center;
  background-size: cover;
}

A body’s background can be propagated to the root under normal transparent-root conditions. If you need a controlled page layer, use a wrapper instead:

.page {
  min-height: 100vh;
  background: url("images/page.jpg") center / cover no-repeat #111;
}

3. Choose cover, contain, or an explicit size

Value What it does Use it when Trade-off
cover Fills the entire box without distortion A full bleed hero or card is required Edges can be cropped
contain Shows the complete image without distortion The whole source must remain visible Empty space may remain; disable tiling
auto Uses the image’s intrinsic dimensions You want its natural size It may not fill the box
Length or percentage Sets a deliberate rendered size You control the visual scale Independent dimensions can distort proportions
.poster {
  min-height: 20rem;
  background-color: #eee;
  background-image: url("images/poster.jpg");
  background-repeat: no-repeat;
  background-position: center;
  background-size: contain;
}

4. Stop repeating and control the crop

Backgrounds repeat by default. Photographs normally need no-repeat; repeating is useful for small textures.

.banner {
  background-repeat: no-repeat;
  background-position: 50% 20%;
  background-size: cover;
}

background-position accepts keywords (top, right, bottom, left, center), percentages, and lengths. Check both wide and narrow boxes because a responsive crop changes which pixels are visible.

5. Make text readable with layered backgrounds

CSS paints comma-separated layers from first (topmost) to last (bottommost). Put a translucent gradient above the photo:

.hero {
  color: #fff;
  background-color: #222;
  background-image:
    linear-gradient(rgb(0 0 0 / 45%), rgb(0 0 0 / 45%)),
    url("images/hero.jpg");
  background-position: center, center;
  background-repeat: no-repeat, no-repeat;
  background-size: cover, cover;
}

Each comma position maps to the corresponding layer. If a property has fewer values than layers, the shorter list repeats. In shorthand, put background-size after background-position with a slash:

.hero {
  background: linear-gradient(rgb(0 0 0 / 45%), rgb(0 0 0 / 45%)),
              url("images/hero.jpg") center / cover no-repeat;
  background-color: #222;
}

Keep the fallback color because it protects contrast before the image loads and around a contain image.

6. Responsive backgrounds

Use a stable focal point and let the box define the crop. Change the minimum height or position at a breakpoint when mobile composition needs a different subject area:

.hero {
  min-height: 28rem;
  padding: 5rem 1.5rem;
  background: url("images/hero.jpg") 60% center / cover no-repeat #333;
}

@media (max-width: 40rem) {
  .hero {
    min-height: 22rem;
    padding: 3rem 1rem;
    background-position: 70% center;
  }
}

For art direction that needs a different file, use a semantic <picture> or <img> instead of forcing one CSS background to serve every crop.

7. Accessibility and content decisions

Use a CSS background for decoration. If the image communicates information needed to understand the page, put it in HTML with an appropriate text alternative or describe the information in the document. MDN states: “Browsers do not provide any special information about background images to assistive technology.” MDN’s background-image reference also points to WCAG contrast thresholds of 4.5:1 for ordinary text and 3:1 for large text.

  • Do not put essential labels, prices, or diagrams only in the background.
  • Check foreground contrast at every likely crop, not just the desktop screenshot.
  • Use a gradient or solid color behind text; do not rely on the photograph alone.
  • Respect prefers-reduced-motion if you add animated background effects.

8. Performance and reliability

  • Use appropriately sized, compressed assets; a CSS background still downloads when the rule applies.
  • Set a fallback background-color so layout and text remain usable during a slow or failed image request.
  • Reserve space with min-height or padding to avoid a collapsing hero.
  • Verify cache headers and stable URLs on your image host.
  • Do not use a large decorative background where an optimized, responsive content image is more appropriate.

Background images are widely established, but check the MDN compatibility table for a specific browser or embedded webview version.

9. Troubleshooting checklist

Symptom Likely cause Fix
Nothing appears The element has no visible area Add content, padding, height, or min-height.
404 or broken request Path is relative to the wrong file Resolve it from the CSS file location; inspect the Network panel.
Image tiles repeat is the default Set background-repeat: no-repeat.
Subject is cut off cover crops to fill the box Change background-position, box ratio, or use contain.
Text is hard to read Photo has bright or busy areas Add a gradient layer, fallback color, and verify contrast.
Image looks stretched Independent width and height values changed its ratio Use cover, contain, or matching dimensions.
It works in one route but not another Relative URL changed with a different stylesheet location Use the correct CSS-relative path or an absolute asset URL.

10. Verify the result in a screenshot

When a background is part of a visual regression check, capture the rendered page at the viewport and device scale you care about. Confirm the crop, fallback color, overlay contrast, and mobile breakpoint—not just whether the URL loaded.

Or skip the browser setup

ScreenshotNeo captures a URL with one request and returns PNG, JPEG, WebP, or PDF. Its cleanup steps accept cookie/consent banners and remove more than 60 known consent platforms, newsletter popups, and chat widgets before the shot; each step can be turned off. Bot checks, CAPTCHAs, blank pages, timeouts, failed loads, and cache hits cost nothing, and the response identifies the result with X-Page-Verdict and X-Billed headers. An MCP server provides take_screenshot, get_page_info, and capture_pdf for Claude, Cursor, and other MCP clients.

See the ScreenshotNeo API docs for all options. This minimal call captures the page that contains your CSS background:

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
import requests

r = requests.get(
    "https://api.screenshotneo.com/v1/shot",
    params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"},
    timeout=90,
)
r.raise_for_status()
open("shot.webp", "wb").write(r.content)
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
if (!res.ok) throw new Error(`HTTP ${res.status}`);
const image = Buffer.from(await res.arrayBuffer());
await Bun.write('shot.webp', image);

Use options for full-page lazy-image capture, a device preset or custom viewport, retina scale, dark mode, a CSS selector, custom CSS or JavaScript, waits (selector, delay, or network idle), blocked ads/trackers/resources, headers/cookies/user agent, timezone/geolocation, transparent backgrounds, resizing, a chosen cache TTL, signed image links, asynchronous jobs with signed webhooks, bulk capture of up to 100 URLs per call, and PDF paper/margin/orientation/page-range settings. Parameter names used by other screenshot APIs also work. Every plan includes every feature: 1,000 shots/month are free with no card; paid plans start at $5 for 3,000 shots. Create a free ScreenshotNeo account.

FAQ

Can I use a background image without HTML?

Yes, apply the rule to an existing element such as body, but that element still needs a visible box.

Should a logo be a background?

Usually no when it conveys identity or text. Use an HTML image with an appropriate alternative instead.

Why does contain leave gaps?

It preserves the entire image inside the box, so mismatched aspect ratios create unused space. Set a background color and disable repeat.

Can I layer more than a gradient and photo?

Yes. Add more comma-separated image layers; the first is painted on top and each property value maps by layer.