CSS Backgrounds Table
| Property | What it does | Field note |
|---|---|---|
background-color | The paint under everything | Extends under transparent borders by default (border-box reach) |
background-image | url() or a gradient | Comma-separated LAYERS - first listed paints on top |
background-repeat | repeat / space / round | space keeps gutters between tiles; round stretches so no tile is cut |
background-position | x y, keywords, % | Percent math: the 40% point of the image meets the 40% point of the box |
background-size | cover / contain / lengths | cover fills and CROPS; contain fits and letterboxes - pick per art direction |
background-attachment | fixed / scroll / local | fixed gives parallax-flavor - broken on iOS Safari, ship a fallback |
background-clip | border/padding/content/text | clip:text + transparent color = gradient-filled typography |
background-origin | Where position measures from | Pairs with clip - the border-box vs padding-box mismatch is the classic offset bug |
shorthand background | Sets everything at once | Resets EVERY sub-property you omit - a later shorthand silently deletes earlier images |
Background is not one property but a LAYER STACK: every comma group in background-image is a layer, the first listed paints on top, and each layer carries its own position, size and repeat. A gradient over a photo over a color is one declaration, not three elements.
Bottom line: cover fills the box and CROPS the overflow; contain fits the whole image and LETTERBOXES the leftover space - pick per art direction, not by feel. The classic bug to internalize: a later background shorthand resets every sub-property you omitted, which is how background: red silently deletes an earlier background-image.
The honest part: background-attachment: fixed - the parallax-flavor scroll effect - is broken on iOS Safari and janky on low-power devices. The modern replacement is a transformed pseudo-element or just not shipping the effect; the property remains fine for admin dashboards where nobody scrolls on a phone.
How to use
- Stack layers for free overlays: background-image: linear-gradient(rgba(0,0,0,.5), rgba(0,0,0,.5)), url(hero.jpg) - readable text on any photo, zero Photoshop.
- Fill text with an image: background-image on the heading, color: transparent, and -webkit-background-clip: text - gradient typography with no SVG.
- Set longhands in components, reserve the shorthand for one-shot resets - that ordering discipline prevents the silent-wipe bug across a codebase.
Frequently asked questions
Why did my background image disappear when I set a background color?
The shorthand reset. background: red is not just color - it resets background-image, position, size, repeat, clip and origin to their defaults in the same declaration. Any image set by an EARLIER rule (another selector, a theme file) is wiped if the shorthand wins the cascade. The fix is using the longhand background-color: red, which touches only the color. This is the most common backgrounds bug in team codebases, and the discipline is simply: longhands inside components, shorthand only where you truly mean 'reset everything'.
What is the difference between cover and contain?
cover scales the image until it covers EVERY pixel of the box, cropping whatever overflows - no empty space, but the edges of the photo may be cut. contain scales until the whole image FITS inside, letterboxing the leftover space with transparent background or the background-color. Hero banners use cover (a cropped edge beats a gap); logos and diagrams use contain (cropping a logo is a bug). The decision is really about which failure mode is acceptable: lost edges or empty margins.
How does background-position percentage math actually work?
Percentage positioning aligns the corresponding point of the image with the corresponding point of the box: background-position: 25% puts the image's 25%-across point at the box's 25%-across point. This is why 50% centers perfectly and why 0% and 100% pin the edges - but also why percentages behave 'backwards' when the image is larger than the box. Pixel positioning is literal (the image's top-left lands there); keywords (left, center, right) are the safe human-readable forms.
When do multiple background layers beat a pseudo-element?
Layers win when the overlay is purely decorative and must never capture events or require stacking-context management: a scrim gradient over a hero photo, a noise texture over a card, edge fades on a scroller. Pseudo-elements win when the decoration needs its own geometry (a positioned badge, a border drawn with transform) or must sit ABOVE child content, since background layers always paint behind the element's children. Decorative-behind goes to layers; structural-above goes to ::before/::after.