Skip to content

CSS Background Image Generator

Add your image, click the part that must stay in view, and see how it crops on desktop, tablet and phone. Add a darkening overlay for text, a placeholder colour and retina or AVIF/WebP versions, then copy the CSS.

Click the part that must stay in view

1600×900px image. This becomes background-position: 72% 30%.

How it crops

Desktop hero 1280×480
Shows 100% of the width, 67% of the height
Tablet 820×600
Shows 77% of the width, 100% of the height
Phone 390×640
Shows 34% of the width, 100% of the height
.hero {
  background-color: #64748B;
  background-image: linear-gradient(to top, rgb(2 6 23 / 60%), rgb(2 6 23 / 0%) 70%),
    url("/images/hero.jpg");
  background-size: 100% 100%, cover;
  background-position: 0 0, 72% 30%;
  background-repeat: no-repeat, no-repeat;
}

cover, contain and auto

background-size keywords
ValueWhat it doesUse it for
coverScales until both sides are filled; the overflow is croppedHero banners, full-bleed photos
containScales until the whole image fits; leaves empty bandsLogos, diagrams, product shots
autoThe image's own pixel sizeTiles and textures
400px autoFixed width, height in proportionPatterns at a set scale

With cover the browser picks the larger of the two scale factors. Take the 1600×900 sample in a 390×640 phone box: across it needs 390 ÷ 1600 = 0.244, down it needs 640 ÷ 900 = 0.711. It uses 0.711, so the image is drawn 1,138×640 and only 34% of its width fits on screen. The same image in the 1280×480 desktop hero uses 1280 ÷ 1600 = 0.8 and shows the full width but 67% of the height. One image, two very different crops, which is what the three previews above show.

Keeping the subject in frame

background-position percentages do not move the image by that amount. They line up a point on the image with the same point on the box: 72% 30% puts the spot 72% across and 30% down the image exactly 72% across and 30% down the box. The offset works out as:

offset = (box size − drawn image size) × percentage

In the phone example the image is 748px wider than the box, so 72% shifts it 748 × 0.72 = 539px left. The useful consequence: if the percentages are the subject's own position in the image, the subject stays inside the box at every screen size. That is why this tool asks you to click the subject rather than choose "left" or "center". Keywords are shortcuts for the same thing: left is 0%, center 50%, right 100%.

Overlays and layer order

background-image takes a comma-separated list and paints the first item on top. The overlay is listed first so it covers the photo; a linear-gradient() with the same colour at both ends is the usual way to write a flat tint, because CSS has no plain "colour layer" except background-color, which is always at the bottom.

Every other background property can take one value per layer, in the same order. That is why the export writes background-size: 100% 100%, cover: the overlay always fills the box while the photo is cropped, and with a pixel size or tiling the overlay still covers everything. A single value is simply reused for every layer.

The background: shorthand packs a layer into one line: image, position, then / and size, then repeat and attachment, with the colour allowed only in the last layer. One detail trips people up: a single box keyword there sets both background-origin and background-clip. To clip at the padding while keeping the default origin, the shorthand needs two boxes, padding-box padding-box, which is what the generator writes. Longhands avoid the question, and a later shorthand anywhere in your CSS resets every longhand, so pick one style per element.

For text, a bottom fade usually beats an even tint: it darkens only where a caption sits and leaves the rest of the photo bright. Check the text against the darkest and lightest parts of the photo under it, not against the overlay colour alone.

Sharp, small and fast images

image-set() is the CSS version of srcset: you list several files and the browser picks one by screen density (1x, 2x) and by format support (type("image/avif")). A phone with a 3× screen gets the @2x file instead of a blurry 1× one, and a browser that cannot decode AVIF skips to WebP or JPEG. Put the best format first; the browser takes the first one it supports.

Backgrounds have one drawback for the main image of a page: the browser only finds them after it has downloaded and parsed the stylesheet. An <img> in the HTML is spotted straight away by the preload scanner. For a hero image that is likely to be the Largest Contentful Paint, either use <img> with object-fit: cover and object-position (the same focal-point percentages work), or add <link rel="preload" as="image" href="…"> to the page head. The placeholder colour fills the gap while it loads, so text over it stays readable.

Browser support for background features used here
FeatureChrome / EdgeFirefoxSafari
background-size cover / contain33.65
repeat: space and round30498
image-set() with type()1138917
background-attachment: fixed1215.4 (not iOS)

Fixed backgrounds and parallax

background-attachment: fixed pins the image to the window, so content scrolls over it. It is the classic one-line parallax, with two catches. Safari on iPhone and iPad ignores it and scrolls the image normally, and with fixed the image is sized against the whole window rather than the element, so cover crops much more than the preview suggests on a short banner. local is the rarer option: it scrolls the background along with the element's own scrolling content.

When an image should not be a background

Screen readers do not announce background images, there is no alt text, and they disappear in Windows high-contrast mode and in most "print without backgrounds" settings. That is fine for decoration: textures, a mood photo behind a heading. If the picture carries information (a product, a person, a chart), use <img alt="…"> and style it with object-fit instead.

When the image does not show

Common background image problems
SymptomCauseFix
Nothing at allThe element has no height; backgrounds never create anyGive it a height, min-height or aspect-ratio
404 in the Network tabRelative paths resolve from the CSS file, not the pageUse a root path such as /images/hero.jpg
Image tilesrepeat is the defaultbackground-repeat: no-repeat
Subject cut off on phonescover crops the sides on tall boxesSet the position to the subject's percentages
Settings lostA later background: shorthand resets every longhandUse longhands, or put the shorthand first

Frequently asked questions

How do I make a background image cover the whole page?

Put it on body with background-size: cover and background-attachment: fixed (desktop), or on a full-height wrapper with min-height: 100vh. On phones, a wrapper element works more reliably than fixed.

Can I set the opacity of a background image only?

Not directly. Either lay a semi-transparent overlay of the page colour on top (as this tool does with Even tint), or put the image on a ::before pseudo-element and give that pseudo-element opacity.

Should I write url() with quotes?

Quotes are optional unless the path contains spaces, brackets or quotes. The generator always adds them, and escapes any quotes inside the path.

What is the difference between background-image and background?

background is a shorthand that sets image, size, position, repeat, attachment, origin, clip and colour together, and resets any you leave out. The generator writes longhands so each can be changed on its own later.

How big should a hero background image be?

Wide enough for the largest box it fills times the screen density: a 1280px hero needs 1280px for 1× screens and 2560px for 2×. Serve smaller files to phones with image-set() or media queries, and compress AVIF or WebP versions.

Why does my image look blurry?

cover or a large box is scaling it up past its own size. Check the drawn size in the previews above; if it is bigger than the image, use a larger source or a 2× version.

Sources