CSS Background Color

Build a solid fill or a two-stop gradient, watch sample text sit on top of it, and read the WCAG contrast ratio before the color reaches your stylesheet. Output comes in HEX, RGB or HSL with a solid fallback line already in place.

Background color workspace

Section heading

Text sitting on your background

Body copy at 15px. If this line starts to swim, the ratio below has already dropped under 4.5:1.

Call to action
White text1.00:1Fail
Near-black text1.00:1Fail

Ratios use the worst point of the fill, composited over white.

Starting points

The checkerboard shows through wherever alpha sits below 1, so a translucent fill reads as translucent rather than as a lighter tint.

background-color: #2f6fed;

Readable text is the constraint, not the color

A background color rarely fails on its own. It fails once text lands on it. WCAG 2.1 asks for a 4.5:1 ratio between body copy and its background, dropping to 3:1 for text at 24px or 18.66px bold. The strip under the preview runs your fill against white and against near-black on every change, so a soft blue-grey gets flagged while you are still picking rather than after a designer signs off on the mockup.

The trap sits in the middle of the lightness range. Pale tints clear the bar with dark text but fail with white, deep tones do the reverse, and a narrow band of greys fails both. Run the numbers on the neutral ramp against white and against #111827 and exactly ten values, #777777 through #808080, miss 4.5:1 in either direction. Those mid-greys look confident in a swatch grid, then leave you with no text color that passes.

Measured ratios against pure white and #111827, rounded to two places.
BackgroundWhite textDark textWorks with
#f8fafc1.05:116.96:1Dark text only
#2f6fed4.55:13.90:1White text, any size
#0f766e5.47:13.24:1White text, any size
#7c7c7c4.17:14.25:1Large text either way
#7f8ea33.33:15.32:1Dark text at any size
#0f172a17.85:11.01:1White text only

One caveat on the numbers here. A translucent fill has no fixed ratio, because what shows through changes with the layer underneath. This page composites your color over white before measuring, which matches the default page background. Drop the same rgba over a photo or a dark section, and the true ratio moves.

Alpha in the color beats the opacity property

Two lines look interchangeable until you put text inside the box:

Fades the fill
.overlay {background-color: rgba(15, 23, 42, 0.6);}

The panel softens. The caption inside stays at full strength.

Fades everything
.overlay {background-color: #0f172a;opacity: 0.6;}

The panel softens along with its heading, its body copy, its icons, its focus ring.

Move the alpha slider on this page and the value shifts to rgba() notation on its own, or to an 8-digit hex if you left the notation on HEX. Both forms have shipped in every current browser for years, though 8-digit hex still trips up older build tooling that predates CSS Color 4, which is the one reason to prefer the rgba form in a shared codebase.

Alpha earns its place in three spots: scrims over hero images, hover and pressed states built from the same brand color, and disabled surfaces where a separate grey token would drift out of sync. Outside those, a flat opaque value renders faster and reads the same.

Gradient backgrounds that survive a real page

Switch to gradient mode and the output grows a second line. That is deliberate:

background-color: #2f6fed;background-image: linear-gradient(135deg, #2f6fed, #0f766e);

A gradient is an image, not a color. Anything stripping background-image, from a print stylesheet to forced-colors mode to an email client, leaves the box with no fill at all unless a solid line sits behind it. Setting both costs nothing at render time.

Three things worth checking before shipping one

  • Contrast drifts across the sweep. White copy passing at the start stop often fails by the end. The ratios on this page report the worse of the two ends, not an average, since the failing corner is the one users read.
  • Banding shows on long, low-contrast sweeps. Two stops fading over 1200px on an 8-bit panel step visibly. Adding a midpoint stop breaks the ramp into shorter runs and hides most of it.
  • Angles are not compass bearings. In CSS, 0deg points up and rotation runs clockwise, so 90deg flows left to right. The keyword to right equals 90deg, and to bottom equals 180deg.

The fade checkbox rewrites the end stop as the same color at zero alpha, which is the standard recipe for a scrim over a hero image. Do not fade to the keyword transparent by hand. WebKit has a long history of interpolating that ramp through transparent black, which greys out the middle of the sweep. Naming the same color at zero alpha sidesteps the question in every engine.

What this page leaves to other tools

The scope stops where a background stops being a background color.

  • Two stops, no positions. There is no way to add a third stop or pin one at 40%. Multi-stop ramps belong in the CSS gradient generator.
  • No images, patterns or layers. Repeating SVG textures, stacked background layers, and background-blend-mode live in the background image generator.
  • HEX, RGB, HSL only. No oklch(), lab() or color-mix() output. Those notations pick better perceptual midpoints for gradients, but they still lack a fallback story on older Safari, so this page sticks to what ships everywhere.
  • One color at a time. No light and dark pairing, no palette ramp, no token export. Pick your surface here, then check each pairing separately.

Everything runs in the browser. No color is uploaded, and the recent swatch strip lives in your own localStorage, so clearing site data empties it.

Questions about CSS background colors

Notation, contrast, alpha and the parts of the spec worth knowing.

What is the difference between background and background-color?

background is a shorthand that resets color, image, position, size, repeat, attachment, origin and clip in one declaration. Anything you leave out returns to its initial value, so background: red wipes a background-image set earlier in the cascade. background-color touches the fill alone and leaves the other seven properties untouched.

Which contrast ratio does my background need to pass?

WCAG 2.1 level AA asks for 4.5:1 against body text and 3:1 against text that is 24px or larger, or 18.66px bold. Level AAA raises those to 7:1 and 4.5:1. Non-text elements such as input borders and icons need 3:1 under success criterion 1.4.11.

Does an 8-digit hex work in every browser?

Yes in every current release. Safari and Firefox shipped #rrggbbaa in 2016, Chrome followed in 2017, and Edge inherited it with the Chromium rebase in 2020. The remaining gap sits in tooling rather than browsers, since some older preprocessors and email sanitisers strip the last two digits. Switch the notation to RGB when a build step is involved.

Why does my background color ignore the body element?

The background on body propagates to the canvas only while html has no background of its own. Set one on html and body keeps its own fill inside the element box instead, which is why a short page sometimes shows two different colors above and below the fold.

Should I write colors in HSL instead of hex?

HSL makes relationships readable. Hover states, tints and shades come from moving lightness by a fixed step while hue and saturation hold, which is hard to eyeball in hex. Hex stays more compact and copies cleanly between design tools. The notation toggle on this page prints the same color either way.

How do I fade a background without fading the text on top?

Put the alpha in the color, not on the element. rgba(15, 23, 42, 0.6) softens the fill alone. The opacity property applies to the element and every descendant, so text, borders and icons fade with it.

Do gradient backgrounds hurt page performance?

On a static block the cost is negligible, since the browser rasterises once. It matters on elements that animate or repaint constantly, where a large gradient repaints every frame. Animate transform or opacity instead of the gradient stops, or promote the layer with will-change.

What happens to my background color in dark mode?

Nothing automatic. A background color set in CSS stays fixed unless you scope it inside a prefers-color-scheme media query or drive it from a custom property you reassign. Pick your light surface here, run the dark counterpart through the tool separately, and check both ratios.