# CSS backgrounds: colours, gradients and images layered

[Canonical HTML page](https://gradiently.design/guide/css-background-image)

One property can hold a photo, a tint over it, a soft light in the corner and a fallback colour underneath. Once layer order clicks, most background effects take a single line.

## The short version

- The CSS background property can hold several comma separated layers, and the first layer listed is painted on top.
- A background colour can only be set once, in the last layer, and it shows beneath every image and gradient.
- In the background shorthand, background-size must follow background-position with a slash, as in center / cover.
- Placing a gradient layer above an image layer in one declaration is the simplest way to tint a photo for legible text.
- Images set in CSS are discovered later than img elements, so an important hero image may need a preload hint.

A **CSS background** is a stack of layers on one element. The `background` property accepts a comma separated list of images and gradients, painted with the first one on top, plus a single colour at the very bottom. That is all you need for a tinted hero photo, a soft light over a gradient or a texture over a brand colour, without extra elements or wrappers. The rest is knowing how the shorthand reads its values.

## The background shorthand, value by value

The shorthand sets up to eight longhand properties at once. Any you leave out are reset to their defaults, which is the most common source of "why did my background size disappear" bugs.

| Longhand | What it controls | Common values |
| --- | --- | --- |
| `background-color` | The colour under every layer | `#0f0b1e`, `oklch(20% 0.05 290)` |
| `background-image` | Images and gradients, comma separated | `url(photo.webp)`, `linear-gradient(…)` |
| `background-position` | Where each layer sits | `center`, `top right`, `50% 30%` |
| `background-size` | How big each layer is | `cover`, `contain`, `200px auto` |
| `background-repeat` | Whether it tiles | `no-repeat`, `repeat`, `repeat-x` |
| `background-attachment` | Scrolls with the element or the viewport | `scroll`, `fixed`, `local` |
| `background-origin` and `background-clip` | Which box it starts from and is cut to | `padding-box`, `border-box`, `text` |

Full reference on [MDN's background page](https://developer.mozilla.org/en-US/docs/Web/CSS/background).

```css
.hero {
  /* image | position / size | repeat | colour */
  background: url("harbour.webp") center 30% / cover no-repeat #0f172a;
}
```

The slash is required: size can only appear straight after position. The colour comes last and shows while the image loads.

## How background layers stack

List layers from top to bottom, separated by commas. Each layer can have its own position, size and repeat, given in the same order in each longhand. Only the final layer may include a colour. Think of it as reading down through a pile of tracing paper.

- Layer 1: pink light: `radial-gradient(circle at 80% 20%, #f472b6 0%, transparent 45%)`
- Layer 2: blue light: `radial-gradient(circle at 15% 85%, #38bdf8 0%, transparent 50%)`
- Layer 3: indigo ground: `linear-gradient(160deg, #1e1b4b 0%, #0f0b1e 100%)`

Three layers shown on their own. The first two fade to transparent, so the ground shows through wherever they don't paint.

```css
.section {
  background:
    radial-gradient(circle at 80% 20%, #f472b6 0%, transparent 45%),
    radial-gradient(circle at 15% 85%, #38bdf8 0%, transparent 50%),
    linear-gradient(160deg, #1e1b4b 0%, #0f0b1e 100%)
    #0f0b1e;
}
```

The same three layers stacked in one declaration, top first, with a solid fallback colour at the bottom.

Use `transparent` in the outer stops so lights blend into whatever is below. For the shapes themselves, see [CSS radial gradient](https://gradiently.design/guide/css-radial-gradient) and [CSS mesh gradient](https://gradiently.design/guide/css-mesh-gradient).

## A gradient over a background image

The most useful layered background tints a photo so words on top can be read. Put a gradient layer first and the image second. A gradient that is dark where the text sits and clear elsewhere keeps far more of the photo than a flat dark overlay.

```css
.hero {
  background:
    linear-gradient(90deg, rgb(10 12 24 / 0.85) 0%, rgb(10 12 24 / 0.4) 45%, transparent 70%),
    url("terrace.webp") center / cover no-repeat
    #0a0c18;
  color: #f8fafc;
}
```

Dark on the left where the headline sits, clear on the right where the photo should be seen.

A wide website hero with a headline over a uniformly darkened background

A flat overlay makes text readable by dimming everything equally.

The same hero where only the side behind the headline is calmer and darker

A directional layer darkens only where the words are and leaves the rest of the scene bright.

[Gradient overlay](https://gradiently.design/guide/gradient-overlay) has more overlay recipes, and [text over image](https://gradiently.design/guide/text-over-image) covers when to move the words instead of darkening the picture.

## background-size, position and repeat

- `cover` fills the box and crops whatever overflows. Right for photos and full bleed heroes.
- `contain` fits the whole image inside and leaves gaps. Right for logos and illustrations that must not be cropped.
- Pair `cover` with a deliberate `background-position` such as `50% 30%` so the crop keeps the subject's face or the product in view.
- Texture tiles want `repeat` and a fixed size, for example `200px 200px`, so the grain stays the same at every screen width.
- `background-attachment: fixed` creates a parallax look on desktop, but many mobile browsers ignore it, so never depend on it.

```css
.card {
  background:
    url("grain.png") 0 0 / 200px 200px repeat,
    linear-gradient(135deg, #7c2d12 0%, #ea580c 55%, #fdba74 100%);
}
```

A small repeating grain tile over a warm gradient. Per layer settings follow each image, so the gradient is untouched by the tile size.

One more longhand earns its place: `background-clip: text` cuts the background to the shape of the letters, which is how gradient lettering is made in CSS. Keep it for large display words, set a solid `color` fallback, and see [CSS gradient text](https://gradiently.design/guide/css-gradient-text) for the full pattern.

## Mistakes to avoid

### Avoid

- Setting `background-size` and then the shorthand after it, which resets it
- A colour in any layer except the last
- No fallback colour, so text is unreadable while the image loads
- A huge photo for a box that is 400 pixels wide
- Important content only in a background image, invisible to screen readers

### Do

- Write the shorthand first, then any longhand overrides
- One colour, at the end of the list
- A fallback colour close to the image's average tone
- Images sized to the box, served as WebP or AVIF
- Meaningful images as `img` with alt text; decoration as backgrounds

## Responsive and fast background images

`image-set()` lets the browser choose between formats or resolutions, much like `srcset` on an `img`. And because background images are only discovered once the CSS is parsed, a hero background can arrive late; a preload hint in the `head` fixes that.

```html
<link rel="preload" as="image" href="/hero-1920.avif" type="image/avif" fetchpriority="high">

<style>
  .hero {
    background: image-set(
      url("/hero-1920.avif") type("image/avif"),
      url("/hero-1920.webp") type("image/webp"),
      url("/hero-1920.jpg") type("image/jpeg")
    ) center / cover no-repeat #0f172a;
  }
</style>
```

The browser takes the first format it supports. The preload makes sure the main image starts downloading early.

Often the fastest background is no image at all. Layered gradients cost no download, and a tiny grain tile adds texture for a few kilobytes. [CSS gradient performance](https://gradiently.design/guide/css-gradient-performance) and [WebP vs PNG and JPG](https://gradiently.design/guide/webp-images) cover the trade offs. If you would rather not hand tune light and grain, a Gradiently Mark gives you a finished, distinctive background at the 1920×1080 website hero size, with the same look as your social posts.

## FAQ

### How do I add a background image in CSS?

Use `background: url("image.webp") center / cover no-repeat;` on the element, with a fallback colour at the end in case the image is slow to load.

### How do I put a gradient over a background image?

List the gradient first and the image second in one `background` declaration, separated by a comma. The first layer is painted on top.

### Can I use multiple backgrounds in CSS?

Yes. Separate layers with commas; each can have its own position, size and repeat, and only the last layer may include a colour.

### What is the difference between background-size cover and contain?

`cover` fills the whole element and crops the overflow; `contain` shows the whole image and can leave empty space around it.

### Why does my background-size stop working?

The `background` shorthand resets every longhand it doesn't mention. Set `background-size` after the shorthand, or include it in the shorthand after the position with a slash.
