How to Use CSS cross-fade() to Blend Backgrounds
The CSS cross-fade() function enables developers to
blend two graphical images together at defined opacity levels directly
in stylesheets, eliminating the need for pre-rendered image files or
stacked HTML elements. This article explains the underlying mechanics of
cross-fade(), its syntax, how pixel blending works
mathematically, and practical implementation considerations for modern
web design.
Understanding the cross-fade() Syntax
The cross-fade() function is used anywhere an
<image> value is accepted in CSS, such as within the
background-image property. It takes two image sources and a
percentage value that determines the balance between them:
.element {
background-image: cross-fade(url("image-a.jpg"), url("image-b.jpg"), 35%);
}In this syntax:
- The first argument is the base image.
- The second argument is the overlay image.
- The percentage defines the opacity of the second image. The opacity
of the first image automatically becomes
100% - percentage. In the example above,image-b.jpgis displayed at 35% opacity, whileimage-a.jpgis displayed at 65% opacity.
Earlier browser implementations, particularly WebKit, supported a
vendor-prefixed syntax (-webkit-cross-fade()), which
accepted a percentage alongside the second image:
.element {
background-image: -webkit-cross-fade(url("image-a.jpg"), url("image-b.jpg"), 0.35);
}How the Blending Process Works
The blending performed by cross-fade() operates via
linear alpha transparency interpolation. Unlike CSS
mix-blend-mode or background-blend-mode, which
apply complex blend modes like multiply,
screen, or overlay based on color luminance,
cross-fade() relies strictly on opacity-based
cross-dissolving.
The browser renders the blend using the following sequence:
- Geometry Normalization: Both images are scaled
according to standard background sizing rules
(
background-size). If dimensions differ, the images are rendered within the context of the container boundaries. - Channel Interpolation: For every overlapping pixel,
the browser calculates the resulting color and alpha channels using the
formula: \[\text{Output} = (\text{Pixel}_A
\times (1 - p)) + (\text{Pixel}_B \times p)\] where \(p\) is the blend percentage converted to a
fraction between
0.0and1.0. - Composite Rendering: The calculated pixels are flattened into a single image layer, preventing extra rendering layers from being composited into the DOM tree.
Supported Image Types
The function is not limited to static raster images (such as JPEG or
PNG). It accepts any valid CSS <image> data type:
- CSS Gradients: Linear, radial, or conic gradients can be blended with photographic backgrounds or with other gradients to generate complex surfaces.
- SVGs: Vector graphics can be combined with bitmap textures.
- Canvas or Element Sources: Any dynamic CSS image sources can be blended programmatically.
.card {
background-image: cross-fade(
url("texture.png"),
linear-gradient(to right, #3498db, #8e44ad),
50%
);
}Practical Use Cases
- State Transitions: Animating the percentage value using CSS transitions creates smooth fades between two images on hover or state change without changing DOM elements.
- Dynamic Theming: Applying a semi-transparent color tint or secondary branding pattern across a standard hero image.
- Progressive Image Loading: Fading from a low-resolution placeholder to a high-resolution asset without layout shifts.
Implementation Considerations
While cross-fade() provides a clean, single-property
solution for image blending, native browser adoption has historically
varied. WebKit and Chromium browsers require the
-webkit-cross-fade() vendor prefix for legacy
compatibility, whereas modern specifications continue to standardize
un-prefixed multi-image syntax. When implementing in production, provide
a standard fallback background-image for older rendering
engines.