Question

How to Stretch and Scale a CSS Background Image to Fit the Viewport

cssbackground

Question

I want a background image to stretch and scale based on the browser viewport size.

I have seen older solutions that use an <img> element and apply styles like:

width: 100%;
height: 100%;

That approach works, but I want to use background-image in CSS instead of placing an image in the HTML.

I also read that CSS3 allows background images to resize properly, and I tried examples based on that idea, but they did not work for me.

What is the best CSS-only way to make a background image scale with the viewport when using background-image?

Short Answer

By the end of this page, you will understand how to resize a background image with CSS using background-size, especially cover and contain. You will also learn how to make a background fill the viewport, how positioning affects the result, and which common mistakes prevent the image from scaling correctly.

Concept

When you use background-image in CSS, the image is painted inside an element's background area rather than inserted as page content like an <img> tag.

To make that background image scale, the key property is:

background-size

This property controls how large the background image should be rendered inside the element.

The most common values are:

  • cover: scales the image so the entire element is covered
  • contain: scales the image so the whole image remains visible
  • specific sizes like 100% 100%, auto, 300px 200px

Why this matters:

  • Full-screen landing pages often need a background image that fills the browser window.
  • Hero sections commonly use large responsive backgrounds.
  • Background images are useful when the image is decorative rather than meaningful content.

For viewport-based backgrounds, cover is usually the best choice because it preserves the image's aspect ratio while filling the entire area.

A typical solution looks like this:

body {
  background-image: url("background.jpg");
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
}

If you want the background to fill the whole browser window, the element itself must also fill the viewport. That is why you often see html, body { height: 100%; } or min-height: 100vh; used together with the background styles.

Mental Model

Think of the element as a picture frame and the background image as a photo placed behind the glass.

  • background-size: cover means: make the photo big enough to cover the whole frame, even if some edges get cropped.
  • background-size: contain means: make the whole photo fit inside the frame, even if empty space appears around it.
  • 100% 100% means: stretch the photo exactly to the frame's width and height, even if it becomes distorted.

So the main question is not just "How do I resize the image?" but also "Do I want to preserve the image proportions, crop it, or stretch it?"

Take Quiz

Syntax and Examples

The core syntax is:

selector {
  background-image: url("image.jpg");
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
}

Example: full-page background

html, body {
  height: 100%;
  margin: 0;
}

body {
  background-image: url("background.jpg");
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
}

What this does

  • height: 100% lets the page fill the viewport height.
  • margin: 0 removes the browser's default body margin.
  • background-size: cover makes the image fill the available area.
  • background-position: center keeps the image centered when cropping happens.
  • background-repeat: no-repeat prevents tiling.

Example: fit the whole image inside a section

.hero {
  height: 400px;
  background-image: url("banner.jpg");
  background-size: contain;
  background-position: center;
  background-repeat: no-repeat;
}

This keeps the full image visible, but may leave empty space around it.

Example: force stretch

.box {
  width: 500px;
  height: 300px;
  background-image: url("photo.jpg");
  background-size: 100% 100%;
  background-repeat: no-repeat;
}

This stretches the image to exactly match the box size. It works, but it may look squashed or distorted.

Step by Step Execution

Consider this example:

html, body {
  height: 100%;
  margin: 0;
}

body {
  background-image: url("background.jpg");
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
}

Here is what happens step by step:

  1. The browser loads the html and body elements.
  2. height: 100% on both elements allows the body to grow to the full height of the viewport.
  3. The browser applies background-image: url("background.jpg") to the body.
  4. background-repeat: no-repeat tells the browser not to tile the image.
  5. background-size: cover scales the image up or down until the entire body area is covered.
  6. If the image aspect ratio does not match the viewport aspect ratio, some part of the image is cropped.
  7. background-position: center makes sure the cropping happens evenly around the center instead of cutting only from one side.

Small example with dimensions

Imagine:

  • viewport: 1200 x 800
  • image: 1000 x 1000

Because the image is square and the viewport is wide, cover enlarges the image enough to fill the full width and height. That means some top and bottom or side areas may be cropped depending on the ratio.

If you switched to contain, the whole square image would stay visible, but empty space would appear because the viewport and image shapes do not match.

Real World Use Cases

Common places where this is used

  • Landing pages: a full-screen hero background that scales on desktop and mobile.
  • Login pages: decorative full-window backgrounds behind a form.
  • Marketing banners: section backgrounds that adapt to different screen sizes.
  • Dashboard headers: visually rich panels with centered background images.
  • Portfolio sites: fullscreen background sections for featured work.

Why use background-image instead of <img>

Use a CSS background when the image is mainly decorative and not part of the document's content.

Examples:

  • A textured page background
  • A hero banner behind text
  • A card background image with overlay content

Use <img> when the image itself is meaningful content, such as:

  • Product photos
  • User-uploaded images
  • Blog post illustrations that need alt text
Take Quiz

Real Codebase Usage

In real projects, developers usually combine background-image scaling with a few supporting patterns.

1. Full-screen sections

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

This shorthand is common in production code.

2. Overlay on top of backgrounds

.hero {
  min-height: 100vh;
  background:
    linear-gradient(rgba(0, 0, 0, 0.4), rgba(0, 0, 0, 0.4)),
    url("hero.jpg") center / cover no-repeat;
}

This improves text readability.

3. Component-level backgrounds

.card {
  height: 220px;
  background: url("cover.jpg") center / cover no-repeat;
  border-radius: 12px;
}

This is common for cards, banners, and tiles.

4. Responsive fallback thinking

Developers often ask:

  • Should the image be cropped? Use cover.
  • Should the whole image stay visible? Use contain.
  • Should distortion be allowed? Use exact width and height values.

5. Guarding layout with explicit height

A background cannot show properly if the element has no height. In real codebases, developers make sure the element has one of these:

  • height
  • min-height
  • content that creates height
  • viewport height like 100vh

Common Mistakes

1. Forgetting to give the element a height

Broken example:

body {
  background-image: url("bg.jpg");
  background-size: cover;
}

Why it fails:

  • If the element does not actually occupy the expected area, the background may not appear as intended.

Fix:

html, body {
  height: 100%;
  margin: 0;
}

Or use:

.hero {
  min-height: 100vh;
}

2. Using 100% 100% when you really want proportional scaling

Broken idea:

background-size: 100% 100%;

Why it fails:

  • It stretches the image in both directions and can distort it.

Better:

background-size: cover;

3. Forgetting background-repeat: no-repeat

Broken example:

.box {
  background-image: url("small-pattern.jpg");
  background-size: cover;
}

Sometimes the browser still behaves in ways that are confusing if the setup is incomplete. To be explicit, add:

background-repeat: no-repeat;

4. Not centering the image

Without this:

background-position: center;

cropping may happen from the top-left by default, which can hide the important part of the image.

5. Using a background for meaningful content

If the image needs:

  • alt text
  • SEO value
  • accessibility meaning

then use an <img> element instead of background-image.

Comparisons

ApproachKeeps aspect ratioFills entire areaMay crop imageMay leave empty spaceMay distort
background-size: coverYesYesYesNoNo
background-size: containYesNoNoYesNo
background-size: 100% 100%NoYesNoNoYes
<img width:100%; height:100%;>No, unless handled carefullyYesNoNoOften yes

cover vs contain

  • Choose cover when the element must be fully filled.
  • Choose contain when the full image must stay visible.

background-image vs <img>

Use caseBetter choice
Decorative visual behind contentbackground-image
Content image that needs alt text<img>
Hero section backgroundbackground-image
Product photo or article image<img>
Take Quiz

Cheat Sheet

/* Full viewport background */
html, body {
  height: 100%;
  margin: 0;
}

body {
  background-image: url("background.jpg");
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
}

Quick rules

  • Use background-size: cover to fill the area.
  • Use background-size: contain to keep the whole image visible.
  • Use background-position: center to keep cropping balanced.
  • Use background-repeat: no-repeat to avoid tiling.
  • Make sure the element has height.

Shorthand

background: url("image.jpg") center / cover no-repeat;

Common height options

height: 100%;
min-height: 100vh;
height: 400px;

Important edge case

background-size: 100% 100% stretches the image and can distort it.

FAQ

How do I make a CSS background image fill the whole screen?

Use a full-height element and set:

background-size: cover;
background-position: center;
background-repeat: no-repeat;

Why is my background image not scaling?

Usually the element does not have a defined height, or the image is applied to the wrong element.

What is the difference between cover and contain?

cover fills the entire area and may crop the image. contain keeps the whole image visible and may leave empty space.

Can I stretch a background image without distortion?

Yes, use cover or contain. If you use 100% 100%, distortion can happen.

Should I use background-image or <img>?

Use background-image for decorative visuals. Use <img> for content images that need accessibility and semantic meaning.

Why does my background image repeat?

Because the default value is often repeating behavior. Add:

background-repeat: no-repeat;
Take Quiz

Mini Project

Description

Create a simple full-screen hero section with a responsive background image and centered text. This demonstrates how to make a decorative background scale with the viewport while keeping content readable.

Goal

Build a page section whose background image always fills the browser window using CSS only.

Requirements

  • Create a page section that fills at least the full viewport height.
  • Apply a background image using CSS, not an <img> element.
  • Make the image scale responsively without repeating.
  • Keep the important part of the image centered.
  • Display readable text on top of the background.
Take Quiz

Keep learning

Related questions

View more