Complete CSS Course Module 11: Intermediate: Floats and Visual Effects

CSS Multiple Backgrounds and background-attachment

  • Beginner
  • Lesson 11.3
  • 5 min read
  • 44 of 77 in the course

In short

CSS multiple backgrounds let you stack images and gradients on one element. Learn layering, background-attachment fixed, scroll and local, a parallax effect, background-clip and background-origin. How do multiple backgrounds work?

CSS multiple backgrounds let you stack images and gradients on one element. Learn layering, background-attachment fixed, scroll and local, a parallax effect, background-clip and background-origin.

How do multiple backgrounds work?

In the CSS Backgrounds lesson you added one image or gradient to an element. But one element can have many background layers, stacked like sheets of transparent plastic on a projector. You list them in background-image, separated by commas.

The most important rule: the first layer in the list is on top, and the last one is at the bottom. A background-color, if you set one, always sits below all the images.

Every other background property can also take a comma-separated list. The first value goes with the first image, the second with the second, and so on.

<header class="hero">
  <h1>Summer Sale</h1>
  <p>Up to 50% off everything</p>
</header>
.hero {
  min-height: 60vh;
  display: grid;
  place-content: center;
  text-align: center;
  color: white;
  background-color: #1e293b;
  background-image:
    linear-gradient(rgb(0 0 0 / 0.55), rgb(0 0 0 / 0.2)),
    url("https://picsum.photos/id/1011/1600/900");
  background-size: cover, cover;
  background-position: center, center;
}

You'll see a photo with a dark see-through layer on top, and white text that is easy to read. The gradient is listed first, so it covers the photo. This "dark overlay" is the most useful multiple-background trick: it makes any photo work behind white text.

Layering images and gradients with the shorthand

You can also write each layer in the background shorthand, separated by commas. Each layer can have its own image, position, size (after a /) and repeat. The color goes only in the last layer.

.card {
  padding: 32px;
  border-radius: 16px;
  background:
    radial-gradient(circle at 100% 0%, #fde68a 0 60px, transparent 61px) no-repeat,
    radial-gradient(circle at 0% 100%, #c7d2fe 0 80px, transparent 81px) no-repeat,
    linear-gradient(135deg, #fff7ed, #eef2ff);
}

This card has a soft two-color gradient, with a yellow quarter-circle in the top-right corner and a lilac quarter-circle in the bottom-left. No extra HTML elements or image files are needed: three gradient layers draw the whole decoration.

Common mistake: Putting the color in the first layer, like background: red, url(photo.jpg);. That is invalid, and the browser ignores the whole declaration. A color is only allowed in the final layer.

background-attachment: scroll, fixed and local

background-attachment controls what happens to a background when the page or the box scrolls.

ValueWhat the background does
scrollThe default. Moves with the element as the page scrolls, but stays still if the element's own content scrolls.
fixedStays fixed to the browser window. The element moves over it, like looking through a window at a still landscape.
localMoves with the element's own content when that content scrolls (for example in a box with overflow: auto).

A simple parallax effect with background-attachment: fixed

Parallax means things at different distances move at different speeds, like trees and mountains seen from a train window. With fixed, the background stays still while the section scrolls past it, which creates a cheap parallax look.

<section class="text">Scroll down to see the effect.</section>
<section class="parallax">
  <h2>Explore the mountains</h2>
</section>
<section class="text">More content below.</section>
.text {
  min-height: 80vh;
  padding: 40px;
}

.parallax {
  min-height: 60vh;
  display: grid;
  place-items: center;
  color: white;
  background-image: url("https://picsum.photos/id/1018/1600/1000");
  background-size: cover;
  background-position: center;
  background-attachment: fixed;
}

As you scroll, the text sections move normally, but the mountain photo seems to stay still behind the window made by the middle section.

Note: Many mobile browsers, including Safari on iPhone, ignore background-attachment: fixed for performance reasons and treat it like scroll. The page still works; the effect is just missing. Treat parallax as a bonus, and respect users who don't like motion with @media (prefers-reduced-motion: reduce) { .parallax { background-attachment: scroll; } }.

Scroll shadows with background-attachment: local

local enables a clever trick: shadows that appear only when a scrolling box has more content to show.

.scroll-box {
  max-height: 200px;
  overflow: auto;
  padding: 12px;
  background:
    linear-gradient(white 30%, transparent) center top,
    linear-gradient(transparent, white 70%) center bottom,
    radial-gradient(farthest-side at 50% 0, rgb(0 0 0 / 0.25), transparent) center top,
    radial-gradient(farthest-side at 50% 100%, rgb(0 0 0 / 0.25), transparent) center bottom;
  background-color: white;
  background-repeat: no-repeat;
  background-size: 100% 40px, 100% 40px, 100% 14px, 100% 14px;
  background-attachment: local, local, scroll, scroll;
}

Put a long list inside a <div class="scroll-box">. At the top, there's no top shadow; when you scroll down, a soft shadow appears at the top edge. When you reach the end, the bottom shadow disappears. The white "covers" (local) move with the content and hide the shadows (scroll) only when you're at an edge.

background-clip and background-origin

These two properties decide which part of the box the background uses.

  • background-origin sets where a background image starts (its position 0 0). Values: padding-box (the default), border-box, content-box.
  • background-clip sets where the background is visible; it cuts off everything outside. Values: border-box (the default), padding-box, content-box, and text.
<h1 class="gradient-text">Hello, CodeCraft!</h1>
<div class="framed">Padding stays white here.</div>
.gradient-text {
  font-size: 3rem;
  background: linear-gradient(90deg, #ec4899, #8b5cf6, #3b82f6);
  background-clip: text;
  color: transparent;
}

.framed {
  padding: 24px;
  border: 8px dashed #94a3b8;
  background: linear-gradient(#bae6fd, #bae6fd) content-box, white;
}

The heading's letters are filled with a pink-to-blue gradient, because the background is clipped to the shape of the text and the text color is transparent. In the second box, the blue layer (a "gradient" of one color, because a plain color isn't allowed in an upper layer) fills only the content area: the padding stays white, and the white also shows through the gaps in the dashed border. A single box value in a layer (here content-box) sets both the origin and the clip.

Tip: With background-clip: text, always keep a readable fallback: if the background fails, transparent text is invisible. Test your gradient colors for contrast against the page background.

Practice exercise

Build a landing page header with three background layers: a dark gradient overlay, a small repeating dot pattern made with radial-gradient, and a photo at the bottom. Below it, add a parallax section with background-attachment: fixed, and a "Terms and conditions" box with scroll shadows.

Hint: for the dot pattern use radial-gradient(rgb(255 255 255 / 0.2) 1px, transparent 1px) with background-size: 16px 16px for that layer only.

Key takeaways

  • Separate background layers with commas; the first layer is on top, and a color goes only in the last.
  • A dark gradient over a photo makes white text readable.
  • background-attachment: fixed pins the background to the window for a simple parallax effect (often ignored on mobile).
  • background-attachment: local scrolls with the box's content and enables scroll shadows.
  • background-origin sets where the image starts; background-clip sets where it's visible, and text creates gradient text.