Essentials

Build a reliable mental model and learn the background properties you’ll use on every project.

This chapter turns CSS backgrounds from “mysterious” into predictable.

  • You’ll internalize the layer model (gradients are images).
  • You’ll learn to read/write the background shorthand without guessing.
  • You’ll control placement, tiling, and the boxes backgrounds paint into.
  • You’ll know when blending is the right tool (and how to debug it).

On this page

Mental Models

The mental model: “paint inside a box”

CSS layout decides where the element’s box is1. Backgrounds are then painted into that box. They don’t affect layout; they’re just pixels behind the element’s content. Backgrounds won’t show if the box has no size.

margin
border-box
padding-box
content-box
Backgrounds won’t show if the box has no visible size (e.g. an empty <div> with no height, it may “work” but you won’t see it).

Backgrounds are layers (and each layer is an image)

/* 2 layers, with repeating horizontal and vertical lines */
background-image:
  linear-gradient(#fff9 1px, transparent 1px),
  linear-gradient(90deg, #fff9 1px, transparent 1px);

background-size:
  18px 18px,
  18px 18px;

background-color: #97acff;
Open the editor in another tab and import snippets as you read.

Gradients are images

Treat linear-gradient(), radial-gradient(), and conic-gradient() as generated images.

That one idea explains why gradients behave like other background images:

  • They can be layered.
  • They can be positioned and sized.
  • They can repeat (or you can use repeating gradient functions).

Multiple backgrounds mean multiple layers

  • background-image can contain multiple comma-separated images.
  • Each image becomes a layer.
  • Related properties (position/size/repeat/attachment/origin/clip) can also be comma-separated so each layer can be controlled independently.
  • background-color sits under all image layers.

Painting order (the rule you must memorize)

The first listed layer is painted on top

This is the rule most people get backwards:

  • The first layer listed in background-image (or the background shorthand) is the top-most.
  • background-color is painted under all background image layers.

Try this tiny proof, the red gradient sits on top of the blue one where they overlap:

background-image:
  linear-gradient(135deg, rgb(255 0 0 / 0.9), rgb(255 0 0 / 0)),
  linear-gradient(135deg, rgb(0 128 255 / 0.9), rgb(0 128 255 / 0));

background-color: #111827;

Comma-separated lists must line up

When you specify multiple background layers, many related properties become lists too. Each comma-separated value maps to the layer with the same index:

background-image: url(a.png), url(b.png), url(c.png);
background-position: left top, center, right bottom;
If a property has fewer items than layers, the browser repeats values to match the number of layers (rules vary by property, but you should not rely on it in real code).

The element box matters (more than you think)

“My background is offset / clipped / scrolling weirdly” usually comes down to which box you’re painting into.

Positioning area vs painting area

  • Some properties decide where the background is positioned (the positioning area).
  • Other properties decide where it is allowed to paint (the painting area).

You’ll learn the exact controls in Boxes and Scrolling. For now, remember: “positioning” and “painting” are different concepts.

A simple debugging habit

When something looks wrong, don’t guess. Do this instead:

  1. Remove layers until the result makes sense again.
  2. Add layers back one-by-one.
  3. Only then start tweaking sizes/positions.

This habit scales from “one gradient” to “twelve layered recipes”.

If you’re using the editor, you can
  • Hide or show layers without deleting them.
  • Drag layers to reorder the stack.
The editor currently targets the background of a single box at a time.

Key takeaways

  • A background is a stack of images.
  • Gradients are images.
  • First listed layer is top-most.
  • background-color sits under all background images.

Decoding the background Shorthand

What background is actually shorthand for

The background shorthand can set many sub-properties at once, including:

  • background-color
  • background-image
  • background-position
  • background-size
  • background-repeat
  • background-attachment
  • background-origin
  • background-clip

The anatomy of a single background layer

Think of one layer as:

  1. an image token (a url(...) or a gradient function)
  2. optional position
  3. optional size (introduced by a /)
  4. optional repeat / attachment / origin / clip

The browser is flexible about token order, except for the position / size pair: the / always belongs to background-size, and it must come after the position.

Using the shorthand resets any omitted background sub-properties back to their defaults. This is the #1 reason shorthand causes “why did my background change?” bugs.
The editor includes a compact toggle that reveals background’s default values—an excellent debugging aid.

A minimal “one-layer” example

Expected output: a card with the favicon centered and not tiled.

background: url("/favicon.svg") center / 96px 96px no-repeat var(--ui-color-primary-100);
The background-color property can be included in the final layer of the shorthand notation, without needing a separate layer. This demo uses a color variable.

The / is not a layer separator

Commas separate layers. The / only separates position from size inside one layer:

/* position  / size */
background: center / cover;

Multiple layers: commas + one final color

When you have multiple layers:

  • Each layer is comma-separated.
  • Each layer can have its own position/size/repeat/etc.
  • background-color can appear once (commonly at the end). It’s painted under all image layers.
background:
  radial-gradient(circle at 30% 30%, rgb(255 255 255 / 0.35), transparent 55%),
  linear-gradient(rgb(255 255 255 / 0.06) 1px, transparent 1px) 0 0 / 18px 18px,
  linear-gradient(90deg, rgb(255 255 255 / 0.06) 1px, transparent 1px) 0 0 / 18px 18px,
  #0b1020;

What the shorthand cannot express

background-blend-mode is not part of the shorthand

Blending is a separate property. For multi-layer designs you often need at least two declarations (see Blending and Compositing):

background:
  url("/noise.png") 0 0 / 128px 128px repeat,
  linear-gradient(135deg, #7c3aed, #06b6d4);

background-blend-mode: overlay, normal;

Some “background-ish” effects are not background properties

Common examples:

  • filter / backdrop-filter (post-processing)
  • mix-blend-mode (element blending)
  • mask-* (masking)

How to parse shorthand (a reliable checklist)

Split layers by commas

Each comma introduces a new background layer.

Find the image token

Look for url(...) / image-set(...) / linear-gradient(...) / etc.

Parse the rest of the layer

Scan for: position → optional / sizerepeatattachmentorigin / clip.

If you’re unsure, rewrite that one layer as longhand temporarily. Correct > clever.

The editor always converts imported CSS into shorthand. Use it as a quick shorthand converter when you need one.

Shorthand ↔ longhand translation (example)

Here’s a multi-layer shorthand and its equivalent longhands.

background:
  url("/favicon.svg") 24px 24px / 72px 72px no-repeat,
  radial-gradient(circle at 30% 30%, rgb(255 255 255 / 0.35), transparent 55%),
  #0b1020;

Equivalent longhands:

background-image:
  url("/favicon.svg"),
  radial-gradient(circle at 30% 30%, rgb(255 255 255 / 0.35), transparent 55%);

background-position:
  24px 24px,
  30% 30%;

background-size:
  72px 72px,
  auto;

background-repeat:
  no-repeat,
  repeat;

background-color: #0b1020;

Common mistakes

Forgetting that commas must align across properties

If you have 3 images, you usually want 3 values for position/size/repeat too. Otherwise you’re relying on defaults or repeating behavior, which makes later edits error-prone.

Misreading center / cover

  • The / belongs to background-size (not a separator between layers).

Accidentally resetting sub-properties

This is common when you mix shorthand and longhand:

/* Later you add this… */
background: url("/a.png") center no-repeat;

/* …and you unknowingly reset background-size / clip / origin, etc. */

When in doubt, keep related background styles together, or use longhands. If something changes unexpectedly, compare the computed styles in your browser DevTools to spot what differs.

Paste your CSS code into the Background Converter to clean it up and convert it to either shorthand or longhand format, with a preview option available.

Key takeaways

  • Split by commas first.
  • Within a layer, position / size is the special pair.
  • Blending is separate.

Placement: Position, Size, Repeat

You’ll learn

  • How to place a background layer with background-position.
  • How to scale a layer with background-size (including cover/contain).
  • How tiling works with background-repeat (including space and round).
All examples on this section work with either image URLs or gradients (because gradients are images).

background-position

The simplest mental model

background-position answers: where should the image be anchored inside the box.

You can express positions using:

  • Keywords: left, center, right, top, bottom
  • Lengths: 20px 10px
  • Percentages: 25% 60%

Quick examples

/* center both axes */
background-position: center;

“Keyword + offset” is extremely practical

This is one of the most useful forms in real UI work:

background-position: right 16px bottom 16px;

What percentages really mean (the part people skip)

Percentages are relative to the background positioning area, but the image size matters too. In practice:

  • 0% 0% aligns the image to the top-left.
  • 50% 50% centers the image.
  • 100% 100% aligns it to the bottom-right.

If the image is larger than the box, percentages still work — you’re choosing which part is visible.

In many cases, negative values are also meaningful, allowing parts of the image to be displayed.

background-size

The sizing modes

background-size answers: how big is the image when painted.

Common values:

  • auto (default): use the image’s intrinsic size (or the gradient’s default sizing rules)
  • <length> / <percentage>: explicit sizes like 80px 80px or 100% 100%
  • contain: fit the whole image inside the box (may leave empty space)
  • cover: fill the box completely (may crop)

One value vs two values

/* one value: width is 120px, height becomes auto */
background-size: 120px;

/* two values: width and height */
background-size: 120px 80px;

contain vs cover (what to expect)

  • contain: always shows the whole image; might leave empty space.
  • cover: never leaves empty space; might crop parts of the image.

The position / size pairing (shorthand rule)

In shorthand, position / size is written like this:

background: url("/favicon.svg") center / 96px 96px no-repeat;

background-repeat

The repeat modes

background-repeat answers: should the image be tiled when it’s smaller than the box.

background-repeat: repeat; /* default */
background-repeat: no-repeat;
background-repeat: repeat-x;
background-repeat: repeat-y;

space and round (pattern designer modes)

  • space keeps tile size and adds spacing so tiles fit without clipping.
  • round adjusts tile size so an integer number of tiles fit (can subtly distort).
background-repeat: space;
background-repeat: round;

Patterns: background-size often matters more than repeat

For patterns (dots, grids, stripes), you often control the “tile size” with background-size. In the demonstration below, the first two layers are 50px, 50px, and combined with the default background-repeat: repeat, they form a repeating pattern:

background:
  linear-gradient(to left top,
    #fff 0% 20%, #ffffffe6 0 42%, #fff0 0 58%, #ffffffe6 0 80%, #fff 0 80%
  )
    0% 0% / 50px 50px,
  linear-gradient(to left bottom,
    #fff 0% 20%, #ffffffe6 0 42%, #fff0 0 58%, #ffffffe6 0 80%, #fff 0 80%
  )
    0% 0% / 50px 50px,
  radial-gradient(circle at 100% 100%,
    #ffe6a7 0%, #ffd899 20%, #ffacac 40%, #fd99ff 60%, #9edfff 80% 100%, #ebebebd1 100%
  );
A value of 0 (without units) represents repeating the previous position. This is commonly used to create sharp edges.

Multi-layer reminder: lists must align

If you have multiple layers, you can control them independently:

background-image: url(a.png), url(b.png);
background-position: left top, right bottom;
background-size: 80px 80px, cover;
background-repeat: no-repeat, no-repeat;

Interactive sandbox (position + size + repeat)

Use the controls to see how one layer moves and scales inside the box.

Try: 120px 80px, contain, cover.
/* initial value */
background-image: url("/favicon.svg");
background-position: center;
background-size: 96px 96px;
background-repeat: no-repeat;
background-color: var(--ui-color-primary-100);

Key takeaways

  • Position decides placement; size decides scaling; repeat decides tiling.
  • In shorthand, position / size is the only strict ordering you must remember.

Boxes and Scrolling

This section includes:

  • The difference between positioning (background-origin) and painting (background-clip).
  • How borders and padding affect backgrounds.
  • What background-attachment really does (and when to avoid it).

The box matters: content / padding / border

Before touching origin/clip, build a box where the layers are obvious:

border
padding
content

background-origin: Where positioning starts

background-origin controls the background positioning area: where background-position is measured from.

Values:

  • padding-box (default)
  • border-box
  • content-box

The same background-position can land in a different place depending on which box is used as the origin.

background-clip: Where painting stops

background-clip controls the background painting area: where the background is allowed to paint.

Values:

  • border-box (default)
  • padding-box
  • content-box

Interactive demo (origin + clip)

Use the demo below and switch the origin to border-box and see what the difference is:

Margin
Padding
Content
background-image:
  url("/favicon.svg"),
  linear-gradient(rgb(255 255 255 / 0.25) 1px, transparent 1px),
  linear-gradient(90deg, rgb(255 255 255 / 0.25) 1px, transparent 1px),
  repeating-linear-gradient(to left top,#292524 0 5%,#78716c 0 10%,#57534e 0 15%,#44403c 0 20%);

background-size: 64px 64px, 16px 16px, 16px 16px, auto;
background-repeat: no-repeat, repeat, repeat, repeat;
background-position: left top, 0 0, 0 0, 0 0;

background-origin: padding-box; /* try: border-box / content-box */
background-clip: border-box; /* try: padding-box / content-box */
background-color: #0b1020;
This demo uniformly sets the origin/clip for all layers. Setting each layer individually allows for more flexibility.

Origin/Clip can be set per-layer

Like other background properties, background-origin and background-clip can be a comma-separated list that matches layers.

border:16px solid transparent;
padding: 24px;

background:
  linear-gradient(var(--ui-color-primary-400), var(--ui-color-primary-400)) content-box,
  linear-gradient(var(--ui-color-primary-300), var(--ui-color-primary-300)) padding-box,
  linear-gradient(#7c3aed, #06b6d4) border-box;

background-attachment

How the background scrolls

background-attachment controls whether the background is attached to:

  • the element (scroll, default)
  • the element’s scrollable content (local)
  • the viewport (fixed)
fixed can be expensive and behaves differently on some mobile browsers. Use it deliberately.

A “hero section” style example

min-height: 60vh;
background-image:
  linear-gradient(rgb(0 0 0 / 0.35), rgb(0 0 0 / 0.35)),
  url("/photos/hero.jpg");
background-size: cover;
background-position: center;
background-attachment: fixed;

Key takeaways

  • Origin affects positioning.
  • Clip affects painting.
  • Attachment affects scrolling behavior.

Blending and Compositing

Prefer reading Dan Hollick’s article2 to learn about blend modes first.

background-blend-mode

Layer-to-layer blending (inside one element)

background-blend-mode blends each background layer with the layer(s) below it (and ultimately with background-color).

It’s great for:

  • Adding subtle texture overlays (noise, paper grain, crosshatch).
  • Tinting a photo/gradient without editing an image.
  • Making multi-layer backgrounds feel cohesive.

When you actually want mix-blend-mode

Element-to-element blending (across the page)

mix-blend-mode blends an element’s pixels with whatever is behind it in the page’s stacking context.

Use it when you want:

  • Text or UI to blend with a hero background.
  • One element to interact visually with another element behind it.

Important interactions:

  • Stacking contexts (e.g. position, transform, filter) can change what gets blended.
  • isolation: isolate can stop blending from affecting outside ancestors.
mix-blend-mode: multiply;
isolation: isolate;

Debugging blend issues

Reduce the problem

When a blend looks wrong:

  1. Temporarily reduce to two layers.
  2. Try the same colors with and without alpha.
  3. Make sure your background-blend-mode list aligns with your layers.
/* If you have 3 layers, you usually want 3 blend-mode values */
background-image: url(a.png), url(b.png), linear-gradient(...);
background-blend-mode: overlay, multiply, normal;
In the editor, click the blend-mode value in the layer list to preview different modes instantly. You can also choose whether to preview how the current layer blends with the layers below, or the final result of the whole stack.

Blend modes are sensitive to contrast

If both layers are low-contrast or nearly flat, many blend modes will look like “nothing happened”. Temporarily increase contrast while debugging.

Key takeaways

  • background-blend-mode blends layers within an element.
  • mix-blend-mode blends an element with the backdrop.

Recap

  • Backgrounds paint inside a box; if the box has no size, you’ll see nothing.
  • Gradients are images, and backgrounds are a stack of layers.
  • Learn the position / size rule, and shorthand stops being scary.
  • Boxes matter: origin and clip decide where things start and where they’re allowed to paint.
  • When blends look wrong, reduce to two layers and make lists explicit.

Next

Footnotes

  1. Everything is a box. Understanding the fundamentals of CSS Layout
  2. Bending Modes by Dan Hollick