Essentials
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
backgroundshorthand 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
- Decoding the
backgroundShorthand - Placement: Position, Size, Repeat
- Boxes and Scrolling
- Blending and Compositing
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.
<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;
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-imagecan 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-colorsits 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 thebackgroundshorthand) is the top-most. background-coloris 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;
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:
- Remove layers until the result makes sense again.
- Add layers back one-by-one.
- Only then start tweaking sizes/positions.
This habit scales from “one gradient” to “twelve layered recipes”.
- Hide or show layers without deleting them.
- Drag layers to reorder the stack.
Key takeaways
- A background is a stack of images.
- Gradients are images.
- First listed layer is top-most.
background-colorsits 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-colorbackground-imagebackground-positionbackground-sizebackground-repeatbackground-attachmentbackground-originbackground-clip
The anatomy of a single background layer
Think of one layer as:
- an image token (a
url(...)or a gradient function) - optional position
- optional size (introduced by a
/) - 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.
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);
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-colorcan 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 / size → repeat → attachment → origin / clip.
If you’re unsure, rewrite that one layer as longhand temporarily. Correct > clever.
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 tobackground-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.
Key takeaways
- Split by commas first.
- Within a layer,
position / sizeis 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(includingcover/contain). - How tiling works with
background-repeat(includingspaceandround).
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 pair */
background-position: right top;
/* x then y */
background-position: 100px 50px;
/* percentage x then percentage y */
background-position: 25% 60%;
/* Keyword + offset */
background-position: right 16px bottom 16px;
“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.
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 like80px 80pxor100% 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)
spacekeeps tile size and adds spacing so tiles fit without clipping.roundadjusts 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%
);
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.
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 / sizeis 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-attachmentreally does (and when to avoid it).
The box matters: content / padding / border
Before touching origin/clip, build a box where the layers are obvious:
background-origin: Where positioning starts
background-origin controls the background positioning area: where background-position is measured from.
Values:
padding-box(default)border-boxcontent-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-boxcontent-box
Interactive demo (origin + clip)
Use the demo below and switch the origin to border-box and see what the difference is:
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;
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: isolatecan stop blending from affecting outside ancestors.
mix-blend-mode: multiply;
isolation: isolate;
Debugging blend issues
Reduce the problem
When a blend looks wrong:
- Temporarily reduce to two layers.
- Try the same colors with and without alpha.
- Make sure your
background-blend-modelist 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;
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-modeblends layers within an element.mix-blend-modeblends 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 / sizerule, and shorthand stops being scary. - Boxes matter:
originandclipdecide where things start and where they’re allowed to paint. - When blends look wrong, reduce to two layers and make lists explicit.
Next
- Continue with Gradients.
Footnotes
- Everything is a box. Understanding the fundamentals of CSS Layout ↩
- Bending Modes by Dan Hollick ↩