What CSS “background” means

In CSS, background is a family of properties that paint “behind” an element’s content. You can paint a color, an image, or even a gradient. And you can control how that paint behaves: where it sits, how it scales, whether it repeats, and more.

A key idea that’ll save you from many “why is this weird?” moments: CSS backgrounds are like wallpaper for an element — they’re not actual DOM elements. That means you can’t select a background image with CSS selectors, and it doesn’t affect layout like an <img> tag does.

 .demo { background: #ffe08a; } 
 .demo { background: #c7f9cc; } 
 .demo { background: #a0c4ff; } 
 *, ::before, ::after { box-sizing: border-box; } body { font-family: ui-sans-serif, system-ui, sans-serif; } .demo { width: min(640px, 100%); padding: 24px; border: 3px solid #111; border-radius: 14px; } .demo h3 { margin: 0 0 10px; font-size: 20px; } .demo p { margin: 0; line-height: 1.4; } 
 

Backgrounds paint behind content

Try switching snippets. The content stays put, the “paint” changes.

CSS background color

The simplest background is background-color (or the shorthand background). It fills the element’s background painting area (by default, the area inside the border).

background-color and the background shorthand

These two are equivalent for plain colors:

  • background-color: #ffd6a5;
  • background: #ffd6a5;

People often use background because it’s shorter and also lets you set images, positions, sizes, and repeats. Just remember: the shorthand can reset other background sub-properties you previously set.

 .card { background-color: #ffd6a5; } 
 .card { background: #bdb2ff; } 
 .card { background: #111; color: #fff; } 
 *, ::before, ::after { box-sizing: border-box; } .card { width: min(640px, 100%); padding: 18px 18px; border: 3px solid #111; border-radius: 16px; font-family: ui-sans-serif, system-ui, sans-serif; } .card h3 { margin: 0 0 8px; font-size: 20px; } .card p { margin: 0; line-height: 1.4; } 
 

Background color

Pick a snippet. Same element, different paint.

CSS background image

A background image is set with background-image (or the background shorthand). By default, the image repeats (tiles) in both directions. That’s because backgrounds were originally designed for patterns.

Adding a background image

Let’s use a real image and see the default behavior (repeat).

 .hero { background-image: url("https://picsum.photos/300/140"); } 
 .hero { background-image: url("https://picsum.photos/300/140"); background-repeat: no-repeat; } 
 .hero { background-image: url("https://picsum.photos/300/140"); background-repeat: repeat-x; } 
 *, ::before, ::after { box-sizing: border-box; } .hero { width: min(720px, 100%); height: 260px; border: 3px solid #111; border-radius: 18px; overflow: hidden; font-family: ui-sans-serif, system-ui, sans-serif; padding: 16px; display: grid; align-content: start; gap: 8px; } .badge { display: inline-block; width: fit-content; padding: 6px 10px; border-radius: 999px; border: 2px solid #111; background: rgba(255, 255, 255, 0.85); font-size: 14px; } .hero h3 { margin: 0; font-size: 20px; background: rgba(255, 255, 255, 0.85); width: fit-content; padding: 6px 10px; border-radius: 10px; border: 2px solid #111; } 
 
Background image demo

Watch how it repeats by default

Where the paint goes: background-clip and background-origin

Two less-famous but very useful properties:

  • background-clip decides how far the background is allowed to paint (to the border edge, padding edge, or content box).
  • background-origin decides where the background positioning starts from (border box, padding box, content box).
 .panel { background: url("https://picsum.photos/900/700"); background-size: cover; background-repeat: no-repeat; background-clip: border-box; } 
 .panel { background: url("https://picsum.photos/900/700"); background-size: cover; background-repeat: no-repeat; background-clip: padding-box; } 
 .panel { background: url("https://picsum.photos/900/700"); background-size: cover; background-repeat: no-repeat; background-clip: content-box; } 
 *, ::before, ::after { box-sizing: border-box; } .panel { width: min(720px, 100%); height: 260px; border: 10px dashed #111; padding: 18px; border-radius: 20px; font-family: ui-sans-serif, system-ui, sans-serif; display: grid; place-items: center; } .panel .label { background: rgba(255, 255, 255, 0.88); border: 2px solid #111; border-radius: 12px; padding: 10px 12px; } 
 
Try the snippets: border-box vs padding-box vs content-box

CSS background size

background-size controls how big the background image is inside the element. The most common values are cover and contain.

  • cover fills the whole element (no empty space), but may crop the image.
  • contain keeps the whole image visible, but may leave empty space.

cover vs contain vs exact sizing

 .box { background-image: url("https://picsum.photos/900/600"); background-repeat: no-repeat; background-size: cover; } 
 .box { background-image: url("https://picsum.photos/900/600"); background-repeat: no-repeat; background-size: contain; } 
 .box { background-image: url("https://picsum.photos/900/600"); background-repeat: no-repeat; background-size: 220px 140px; } 
 *, ::before, ::after { box-sizing: border-box; } .box { width: min(720px, 100%); height: 260px; border: 3px solid #111; border-radius: 18px; font-family: ui-sans-serif, system-ui, sans-serif; padding: 16px; display: grid; align-content: start; gap: 8px; } .note { background: rgba(255, 255, 255, 0.88); border: 2px solid #111; border-radius: 12px; padding: 10px 12px; width: fit-content; } 
 
Try: cover, contain, fixed px size

Interactive background-size with a slider

When you set a single length value (like 120%), you’re effectively scaling the background image. Let’s make that interactive.

 .zoom { background-image: url("https://picsum.photos/900/650"); background-repeat: no-repeat; background-position: center; background-size: 110%; } 
 *, ::before, ::after { box-sizing: border-box; } .zoom { width: min(720px, 100%); height: 280px; border: 3px solid #111; border-radius: 18px; overflow: hidden; font-family: ui-sans-serif, system-ui, sans-serif; display: grid; place-items: end start; padding: 14px; } .zoom .label { background: rgba(255, 255, 255, 0.9); border: 2px solid #111; border-radius: 12px; padding: 8px 10px; } 
 
Slide to “zoom” the background

CSS background position

background-position decides where the background image sits inside the element. It can use keywords (left, center, right, top, bottom), percentages, or lengths like px.

Keywords, percentages, and lengths

 .stage { background-image: url("https://picsum.photos/950/650"); background-repeat: no-repeat; background-size: cover; background-position: center; } 
 .stage { background-image: url("https://picsum.photos/950/650"); background-repeat: no-repeat; background-size: cover; background-position: left top; } 
 .stage { background-image: url("https://picsum.photos/950/650"); background-repeat: no-repeat; background-size: cover; background-position: 80% 30%; } 
 *, ::before, ::after { box-sizing: border-box; } .stage { width: min(720px, 100%); height: 280px; border: 3px solid #111; border-radius: 18px; overflow: hidden; font-family: ui-sans-serif, system-ui, sans-serif; padding: 14px; display: grid; place-items: start; } .tag { background: rgba(255, 255, 255, 0.9); border: 2px solid #111; border-radius: 999px; padding: 6px 10px; font-size: 14px; } 
 
Move the “camera” with background-position

CSS Background position with center, top, bottom, left, right values

Click on the different named values that can have CSS Background position

background-position:
 .photo { background-image: url("https://picsum.photos/950/650"); background-repeat: no-repeat; background-size: cover; background-position: center; } 
 *, ::before, ::after { box-sizing: border-box; } .photo { width: min(720px, 100%); height: 280px; border: 3px solid #111; border-radius: 18px; overflow: hidden; } 
 

Left and Right look the same, because the background is set to background-size: cover; and here the width is the limiting factor.

CSS background image fit

People often say “fit” when they really mean how an image fills a box. For background images, that “fit” is controlled by background-size:

  • cover behaves like “fill the box, crop if needed”
  • contain behaves like “show the whole thing, letterbox if needed”

Background “fit” vs <img> object-fit

An <img> element uses object-fit. A background image uses background-size. They can look similar, but they apply to different things.

 .wrap { display: grid; gap: 14px; }

.bg {
height: 220px;
border-radius: 16px;
background-image: url("https://picsum.photos/900/650");
background-repeat: no-repeat;
background-size: cover;
background-position: center;
}

.img img {
width: 100%;
height: 220px;
display: block;
object-fit: cover;
border-radius: 16px;
}
 .wrap { display: grid; gap: 14px; } .bg { height: 220px; border-radius: 16px; background-image: url("https://picsum.photos/900/650"); background-repeat: no-repeat; background-size: contain; background-position: center; background-color: #f2f2f2; } .img img { width: 100%; height: 220px; display: block; object-fit: contain; border-radius: 16px; background: #f2f2f2; } 
 *, ::before, ::after { box-sizing: border-box; } .wrap { width: min(720px, 100%); font-family: ui-sans-serif, system-ui, sans-serif; } .card { border: 3px solid #111; border-radius: 18px; padding: 14px; } .title { margin: 0 0 10px; font-size: 16px; } .bg { border: 2px solid #111; } .img img { border: 2px solid #111; } 
 

Background image (uses background-size)

<img> (uses object-fit)

Random example

CSS background gradient

Gradients are “generated images” in CSS. That’s why they’re used with background-image (or the background shorthand).

Linear and radial gradients

 .tile { background-image: linear-gradient(90deg, #ffadad, #ffd6a5, #fdffb6); } 
 .tile { background-image: linear-gradient(135deg, #a0c4ff, #bdb2ff, #ffc6ff); } 
 .tile { background-image: radial-gradient(circle at 30% 30%, #caffbf, #9bf6ff, #a0c4ff); } 
 *, ::before, ::after { box-sizing: border-box; } .tile { width: min(720px, 100%); height: 260px; border: 3px solid #111; border-radius: 18px; font-family: ui-sans-serif, system-ui, sans-serif; display: grid; place-items: center; } .tile .text { background: rgba(255, 255, 255, 0.88); border: 2px solid #111; border-radius: 12px; padding: 10px 12px; } 
 
Gradients are backgrounds too

Learn more about gradients in the CSS Gradient Interactive Tutorial.

Layering multiple backgrounds

You can stack multiple backgrounds by separating them with commas. The first one is painted on top of the next one (like layers).

 .banner { background-image: linear-gradient(90deg, rgba(0, 0, 0, 0.55), rgba(0, 0, 0, 0)), url("https://picsum.photos/980/520"); background-size: cover; background-position: center; background-repeat: no-repeat; } 
 .banner { background-image: radial-gradient(circle at 30% 30%, rgba(255, 255, 255, 0.75), rgba(255, 255, 255, 0)), url("https://picsum.photos/980/520"); background-size: cover; background-position: center; background-repeat: no-repeat; } 
 *, ::before, ::after { box-sizing: border-box; } .banner { width: min(720px, 100%); height: 260px; border: 3px solid #111; border-radius: 18px; overflow: hidden; font-family: ui-sans-serif, system-ui, sans-serif; display: grid; place-items: end start; padding: 16px; } .banner .headline { margin: 0; color: #fff; font-size: 22px; letter-spacing: 0.2px; text-shadow: 0 1px 2px rgba(0, 0, 0, 0.35); } 
  

CSS background opacity and background image opacity

There’s no background-opacity property in CSS. If you do opacity: 0.5; on the element, you’ll fade everything (background and text and children). That’s usually not what you want.

Here are three correct patterns:

  1. Use an alpha color for background-color (like rgba()).
  2. Layer a semi-transparent gradient over the image.
  3. Use a pseudo-element (::before) for the background and fade that layer only.

Pattern 1: Alpha background-color (only affects the color)

 .card { background: rgba(255, 255, 255, 0.65); } 
 .card { background: rgba(0, 0, 0, 0.55); color: #fff; } 
 *, ::before, ::after { box-sizing: border-box; } .shell { width: min(720px, 100%); border-radius: 18px; border: 3px solid #111; overflow: hidden; background-image: url("https://picsum.photos/980/520"); background-size: cover; background-position: center; background-repeat: no-repeat; padding: 18px; font-family: ui-sans-serif, system-ui, sans-serif; } .card { border: 2px solid #111; border-radius: 16px; padding: 16px; } .card h3 { margin: 0 0 8px; font-size: 20px; } .card p { margin: 0; line-height: 1.4; } 
 

Only the background color is transparent

The text stays fully opaque.

Pattern 2: Overlay gradient on top of the image

This is a super common trick to “make text readable on a photo”.

 .hero { background-image: linear-gradient(90deg, rgba(0, 0, 0, 0.65), rgba(0, 0, 0, 0)), url("https://picsum.photos/980/520"); } 
 .hero { background-image: linear-gradient(180deg, rgba(255, 255, 255, 0.75), rgba(255, 255, 255, 0)), url("https://picsum.photos/980/520"); } 
 *, ::before, ::after { box-sizing: border-box; } .hero { width: min(720px, 100%); height: 260px; border: 3px solid #111; border-radius: 18px; overflow: hidden; background-size: cover; background-position: center; background-repeat: no-repeat; font-family: ui-sans-serif, system-ui, sans-serif; display: grid; align-content: end; padding: 16px; } .hero p { margin: 0; width: fit-content; padding: 8px 10px; border-radius: 12px; border: 2px solid #111; background: rgba(255, 255, 255, 0.88); } 
 

Gradient overlay + image

Pattern 3: Pseudo-element layer for opacity

This is the “I want the image faded but not the content” pattern. We place the background image on ::before, fade that layer, and keep content on top.

 .panel { position: relative; overflow: hidden; }

.panel::before {
content: "";
position: absolute;
inset: 0;
background-image: url("https://picsum.photos/980/520");
background-size: cover;
background-position: center;
opacity: 0.35;
}

.panel > * {
position: relative;
}
 .panel { position: relative; overflow: hidden; } .panel::before { content: ""; position: absolute; inset: 0; background-image: url("https://picsum.photos/980/520"); background-size: cover; background-position: center; opacity: 0.75; } .panel > * { position: relative; } 
 *, ::before, ::after { box-sizing: border-box; } .panel { width: min(720px, 100%); height: 260px; border: 3px solid #111; border-radius: 18px; font-family: ui-sans-serif, system-ui, sans-serif; padding: 18px; display: grid; align-content: end; gap: 10px; } .panel h3 { margin: 0; font-size: 20px; } .panel p { margin: 0; line-height: 1.4; background: rgba(255, 255, 255, 0.9); border: 2px solid #111; border-radius: 12px; padding: 10px 12px; width: fit-content; } 
 

Image opacity without fading the text

The image is on ::before.

CSS background blur

“Background blur” can mean two different things:

  • Blur the background behind the element (like frosted glass).
  • Blur the background image you’re using (blur the wallpaper).

They’re not the same technique, so let’s do both.

Blur the background behind: backdrop-filter

backdrop-filter blurs what’s behind the element. To see the blur, the element usually needs a semi-transparent background.

 .glass { background: rgba(255, 255, 255, 0.35); backdrop-filter: blur(10px); } 
 .glass { background: rgba(0, 0, 0, 0.25); color: #fff; backdrop-filter: blur(16px); } 
 *, ::before, ::after { box-sizing: border-box; } .scene { width: min(720px, 100%); height: 280px; border: 3px solid #111; border-radius: 18px; overflow: hidden; background-image: url("https://picsum.photos/980/560"); background-size: cover; background-position: center; background-repeat: no-repeat; position: relative; font-family: ui-sans-serif, system-ui, sans-serif; } .glass { position: absolute; left: 16px; right: 16px; bottom: 16px; border: 2px solid #111; border-radius: 16px; padding: 14px; } .glass h3 { margin: 0 0 6px; font-size: 18px; } .glass p { margin: 0; line-height: 1.4; } 
 

Frosted glass

Blur happens to what’s behind this panel.

Blur the background image itself

You can’t apply filter: blur() directly to background-image. But you can put the background image on a pseudo-element and blur that layer.

 .card { position: relative; overflow: hidden; }

.card::before {
content: "";
position: absolute;
inset: -20px;
background-image: url("https://picsum.photos/980/520");
background-size: cover;
background-position: center;
filter: blur(10px);
transform: scale(1.1);
}

.card > * {
position: relative;
}
 .card { position: relative; overflow: hidden; } .card::before { content: ""; position: absolute; inset: -20px; background-image: url("https://picsum.photos/980/520"); background-size: cover; background-position: center; filter: blur(18px); transform: scale(1.2); } .card > * { position: relative; } 
 *, ::before, ::after { box-sizing: border-box; } .card { width: min(720px, 100%); height: 260px; border: 3px solid #111; border-radius: 18px; font-family: ui-sans-serif, system-ui, sans-serif; display: grid; place-items: center; padding: 18px; } .card .content { background: rgba(255, 255, 255, 0.9); border: 2px solid #111; border-radius: 14px; padding: 12px 14px; text-align: center; max-width: 42ch; } .card .content h3 { margin: 0 0 6px; font-size: 18px; } .card .content p { margin: 0; line-height: 1.4; } 
 

Blurred background image layer

The blur is applied to ::before, not the text.

Common background shortcuts and best practices

In real projects, you’ll often use the shorthand:

  • background: color;
  • background: url(...) no-repeat center / cover;

That second one includes position and size in one line. The syntax is: position then / then size.

The background shorthand with position and size

 .box { background: url("https://picsum.photos/980/520") no-repeat center / cover; } 
 .box { background: url("https://picsum.photos/980/520") no-repeat left 20px top 10px / 140%; } 
 .box { background: linear-gradient(90deg, rgba(0, 0, 0, 0.55), rgba(0, 0, 0, 0)), url("https://picsum.photos/980/520") no-repeat center / cover; } 
 *, ::before, ::after { box-sizing: border-box; } .box { width: min(720px, 100%); height: 260px; border: 3px solid #111; border-radius: 18px; overflow: hidden; font-family: ui-sans-serif, system-ui, sans-serif; display: grid; place-items: end start; padding: 16px; } .box .pill { background: rgba(255, 255, 255, 0.9); border: 2px solid #111; border-radius: 999px; padding: 6px 10px; font-size: 14px; } 
 
Shorthand: position / size

Quick CSS Background recap and checklist

  • background-color paints a color behind the element’s content.
  • background-image can be a URL image or a gradient.
  • background-repeat defaults to repeat (tiling).
  • background-size controls the “fit” (cover vs contain).
  • background-position moves the background inside the element.
  • There’s no background-opacity; use alpha colors, overlays, or pseudo-elements.
  • For blur: use backdrop-filter to blur what’s behind, or blur a pseudo-element layer to blur the image itself.

If something looks off, the usual suspects are: repeat happening unexpectedly, size not set (so the image tiles), or position not doing what you expect because the image is being cropped by cover.