CSS Mix Blend Mode
mix-blend-mode is one of those CSS features that feels like cheating. You set one property and suddenly
your text, shapes, and overlays start “reacting” to what’s behind them like they’re in Photoshop.
In this tutorial, you’ll learn what mix-blend-mode does, how the most useful modes behave
(multiply, screen, overlay, difference), how to blend text, how
to blend the background only, and what to do when it doesn’t work.
What CSS mix-blend-mode Does
mix-blend-mode controls how an element’s pixels blend with the pixels behind it (its “backdrop”).
That means it’s not just coloring the element. It’s literally mixing two pixel layers:
-
Source: the element you set
mix-blend-modeon - Backdrop: whatever is visually behind it in the final rendering
This is different from background-blend-mode, which blends multiple backgrounds of the same
element.
mix-blend-mode blends the element with its surroundings.
You usually get the best results when there’s obvious contrast behind the element: gradients, photos, colorful blocks, or patterns.
.blender {
mix-blend-mode: normal;
}
.blender {
mix-blend-mode: multiply;
}
.blender {
mix-blend-mode: screen;
}
.blender {
mix-blend-mode: difference;
}
*,
::before,
::after {
box-sizing: border-box;
}
.scene {
max-width: 980px;
padding: 18px;
display: grid;
gap: 14px;
font-family: system-ui, Arial, sans-serif;
}
.backdrop {
position: relative;
min-height: 220px;
border: 3px solid #111;
border-radius: 16px;
overflow: hidden;
display: grid;
place-items: center;
background:
radial-gradient(circle at 20% 20%, rgba(255, 255, 255, 0.8) 0 18%, transparent 19%),
radial-gradient(circle at 70% 70%, rgba(255, 255, 255, 0.7) 0 22%, transparent 23%),
linear-gradient(120deg, #ff7a18 0%, #af002d 40%, #319197 100%);
}
.blender {
font-size: 64px;
font-weight: 800;
letter-spacing: 0.04em;
padding: 10px 18px;
border-radius: 14px;
background: rgba(255, 255, 255, 0.65);
border: 2px solid rgba(0, 0, 0, 0.3);
color: #111;
}
.note {
font-size: 14px;
opacity: 0.85;
line-height: 1.4;
}
BLENDSwitch snippets to see how the same element blends with what’s behind it. normal is your baseline.
CSS mix-blend-mode Text
Blended text is the classic use-case: put bold text on top of a photo or gradient and let it “mix”. The trick is that the text itself should have a strong color (often white or black), and it needs a visible backdrop behind it.
In the playground below, the text sits on top of a “fake photo” (a layered gradient background).
Try difference for that “auto-invert” look, or overlay for punchy contrast.
.title {
mix-blend-mode: normal;
}
.title {
mix-blend-mode: difference;
}
.title {
mix-blend-mode: overlay;
}
.title {
mix-blend-mode: screen;
}
*,
::before,
::after {
box-sizing: border-box;
}
.wrap {
max-width: 980px;
padding: 18px;
display: grid;
gap: 14px;
font-family: system-ui, Arial, sans-serif;
}
.hero {
border: 3px solid #111;
border-radius: 18px;
overflow: hidden;
min-height: 260px;
position: relative;
display: grid;
place-items: center;
background:
radial-gradient(circle at 30% 30%, rgba(255, 255, 255, 0.7) 0 18%, transparent 19%),
radial-gradient(circle at 70% 40%, rgba(0, 0, 0, 0.35) 0 22%, transparent 23%),
linear-gradient(115deg, #2b59c3 0%, #a4161a 50%, #f4d35e 100%);
}
.title {
font-size: 72px;
font-weight: 900;
letter-spacing: 0.06em;
color: #fff;
text-transform: uppercase;
padding: 10px 14px;
line-height: 1;
}
.caption {
font-size: 14px;
opacity: 0.85;
line-height: 1.45;
}
Neon TypeBlended text depends on the backdrop. Try
differencefor a “smart invert” vibe.
CSS mix-blend-mode Multiply
multiply darkens by multiplying colors together. Think: marker on paper, ink on ink, shadows stacking.
It tends to make bright areas more visible and dark areas “sink” nicely.
This is great for:
- Color overlays that “feel” printed onto the background
- Adding texture without destroying the original image
- Making overlapping shapes look richer
.blob.a {
mix-blend-mode: normal;
}
.blob.b {
mix-blend-mode: normal;
}
.blob.a {
mix-blend-mode: multiply;
}
.blob.b {
mix-blend-mode: multiply;
}
.blob.a {
mix-blend-mode: multiply;
}
.blob.b {
mix-blend-mode: screen;
}
*,
::before,
::after {
box-sizing: border-box;
}
.stage {
max-width: 980px;
padding: 18px;
font-family: system-ui, Arial, sans-serif;
display: grid;
gap: 14px;
}
.canvas {
border: 3px solid #111;
border-radius: 18px;
height: 260px;
position: relative;
overflow: hidden;
background:
linear-gradient(90deg, rgba(255, 255, 255, 0.75), rgba(255, 255, 255, 0)),
linear-gradient(135deg, #1b998b 0%, #ed217c 55%, #f2af29 100%);
}
.blob {
position: absolute;
width: 220px;
height: 220px;
border-radius: 999px;
filter: blur(0px);
opacity: 0.92;
}
.blob.a {
left: 90px;
top: 30px;
background: #3a86ff;
}
.blob.b {
left: 220px;
top: 70px;
background: #ff006e;
}
.legend {
font-size: 14px;
opacity: 0.85;
line-height: 1.45;
}
With
multiply, overlaps get darker and feel more “ink-like”.
CSS mix-blend-mode Screen
screen is basically the opposite of multiply. It brightens by “screening” colors together.
Dark parts become more transparent, and lighter parts glow.
This is great for:
- Light leaks, glows, and neon overlays
- Soft highlights on top of photos
- Making shapes feel like light rather than paint
.glow {
mix-blend-mode: normal;
}
.glow {
mix-blend-mode: screen;
}
.glow {
mix-blend-mode: overlay;
}
*,
::before,
::after {
box-sizing: border-box;
}
.wrap {
max-width: 980px;
padding: 18px;
display: grid;
gap: 14px;
font-family: system-ui, Arial, sans-serif;
}
.panel {
border: 3px solid #111;
border-radius: 18px;
overflow: hidden;
min-height: 280px;
position: relative;
background:
radial-gradient(circle at 30% 20%, rgba(255, 255, 255, 0.18) 0 35%, transparent 36%),
radial-gradient(circle at 70% 70%, rgba(0, 0, 0, 0.35) 0 45%, transparent 46%),
linear-gradient(135deg, #0b1320 0%, #3a0ca3 60%, #7209b7 100%);
display: grid;
place-items: center;
}
.glow {
width: 360px;
height: 160px;
border-radius: 999px;
background: radial-gradient(circle at 30% 40%, rgba(255, 255, 255, 0.9), rgba(255, 255, 255, 0) 60%);
opacity: 0.95;
}
.label {
position: absolute;
left: 14px;
bottom: 12px;
padding: 6px 10px;
border-radius: 999px;
font-size: 13px;
background: rgba(255, 255, 255, 0.78);
border: 1px solid rgba(0, 0, 0, 0.25);
}
A “light leak” style overlay
CSS mix-blend-mode Overlay
overlay is a contrast booster. It combines ideas from multiply and screen
depending on the backdrop.
The result often looks “punchy” and high-contrast.
It’s popular for:
- Poster-style effects
- Bringing out texture
- Making overlays feel more integrated than a simple opacity layer
.overlay {
mix-blend-mode: normal;
}
.overlay {
mix-blend-mode: overlay;
}
.overlay {
mix-blend-mode: soft-light;
}
.overlay {
mix-blend-mode: hard-light;
}
*,
::before,
::after {
box-sizing: border-box;
}
.wrap {
max-width: 980px;
padding: 18px;
display: grid;
gap: 14px;
font-family: system-ui, Arial, sans-serif;
}
.card {
border: 3px solid #111;
border-radius: 18px;
overflow: hidden;
min-height: 280px;
position: relative;
background:
repeating-linear-gradient(
90deg,
rgba(255, 255, 255, 0.18) 0 10px,
rgba(255, 255, 255, 0) 10px 20px
),
linear-gradient(120deg, #ff4d6d 0%, #ffd166 55%, #06d6a0 100%);
display: grid;
place-items: center;
}
.overlay {
width: 440px;
height: 220px;
border-radius: 18px;
background:
radial-gradient(circle at 30% 35%, rgba(255, 255, 255, 0.9), rgba(255, 255, 255, 0) 60%),
radial-gradient(circle at 70% 70%, rgba(0, 0, 0, 0.45), rgba(0, 0, 0, 0) 58%),
linear-gradient(135deg, rgba(20, 20, 20, 0.7), rgba(20, 20, 20, 0));
opacity: 0.95;
}
.note {
font-size: 14px;
opacity: 0.85;
line-height: 1.45;
}
overlayis the “turn up the drama” button. Trysoft-lightfor a gentler effect.
CSS mix-blend-mode Difference
difference compares the element color to the backdrop color and displays the “difference” between them.
In practice, it often looks like an invert effect that changes depending on what’s behind it.
This is super useful for:
- Text that stays readable over changing backgrounds
- Cursor-like UI accents that always stand out
- Funky interactive effects (especially on hover)
.badge {
mix-blend-mode: normal;
}
.badge {
mix-blend-mode: difference;
}
.badge {
mix-blend-mode: exclusion;
}
*,
::before,
::after {
box-sizing: border-box;
}
.wrap {
max-width: 980px;
padding: 18px;
display: grid;
gap: 14px;
font-family: system-ui, Arial, sans-serif;
}
.track {
border: 3px solid #111;
border-radius: 18px;
overflow: hidden;
min-height: 240px;
background:
linear-gradient(90deg, #0b1320 0%, #3a86ff 35%, #ff006e 70%, #ffd166 100%);
position: relative;
}
.badge {
position: absolute;
top: 24px;
left: 24px;
padding: 10px 14px;
border-radius: 999px;
background: #fff;
color: #111;
font-weight: 800;
letter-spacing: 0.04em;
border: 2px solid rgba(0, 0, 0, 0.25);
}
.strip {
position: absolute;
inset: auto 0 0 0;
height: 80px;
background:
repeating-linear-gradient(
135deg,
rgba(255, 255, 255, 0.22) 0 10px,
rgba(255, 255, 255, 0) 10px 20px
);
}
.tip {
font-size: 14px;
opacity: 0.85;
line-height: 1.45;
}
AUTO CONTRAST
differencecan help UI labels stand out over noisy backgrounds, but test it carefully for readability.
CSS mix-blend-mode Background Only
A common beginner goal is: “I want the background overlay to blend, but I don’t want my text to blend.” That’s very doable. The idea is simple:
- Put the overlay in a separate element (or pseudo-element)
-
Apply
mix-blend-modeto the overlay layer only - Keep the text above it, not blending
In this playground, the overlay layer blends, but the content stays normal and readable.
.overlay {
mix-blend-mode: multiply;
}
.overlay {
mix-blend-mode: screen;
}
.overlay {
mix-blend-mode: overlay;
}
.overlay {
mix-blend-mode: difference;
}
*,
::before,
::after {
box-sizing: border-box;
}
.wrap {
max-width: 980px;
padding: 18px;
display: grid;
gap: 14px;
font-family: system-ui, Arial, sans-serif;
}
.hero {
border: 3px solid #111;
border-radius: 18px;
overflow: hidden;
position: relative;
min-height: 300px;
background:
linear-gradient(115deg, #00bbf9 0%, #f15bb5 55%, #fee440 100%);
}
.photo {
position: absolute;
inset: 0;
background:
radial-gradient(circle at 30% 35%, rgba(255, 255, 255, 0.65) 0 18%, transparent 19%),
radial-gradient(circle at 70% 70%, rgba(0, 0, 0, 0.35) 0 25%, transparent 26%),
linear-gradient(135deg, rgba(15, 15, 15, 0.55), rgba(15, 15, 15, 0));
}
.overlay {
position: absolute;
inset: 0;
background:
repeating-linear-gradient(
45deg,
rgba(255, 255, 255, 0.25) 0 10px,
rgba(255, 255, 255, 0) 10px 20px
),
radial-gradient(circle at 20% 30%, rgba(255, 255, 255, 0.55), rgba(255, 255, 255, 0) 55%);
opacity: 0.95;
}
.content {
position: relative;
z-index: 1;
padding: 22px;
display: grid;
gap: 10px;
max-width: 520px;
}
.kicker {
display: inline-block;
width: fit-content;
padding: 6px 10px;
border-radius: 999px;
background: rgba(255, 255, 255, 0.82);
border: 1px solid rgba(0, 0, 0, 0.2);
font-weight: 700;
font-size: 13px;
letter-spacing: 0.04em;
}
h3 {
margin: 0;
font-size: 34px;
line-height: 1.1;
}
p {
margin: 0;
line-height: 1.45;
opacity: 0.9;
background: rgba(255, 255, 255, 0.78);
padding: 10px 12px;
border-radius: 14px;
border: 1px solid rgba(0, 0, 0, 0.18);
}
Blend the overlay, not the textReadable content
The overlay layer blends with the backdrop. The content stays normal because it’s on top.
Stacking Context and Why Blend Depends on What’s Behind
Blending is all about the backdrop. If the browser doesn’t consider your intended backdrop as “behind” the element in the same stacking/painting context, the effect can look wrong or do nothing.
Two useful mental notes:
- You blend with what’s behind you, not with your own background.
- Positioning and stacking order matter: layers must actually overlap visually.
In most real layouts, you’ll use position: relative on the container and absolutely-positioned layers
for predictable overlaps (like we did above).
CSS mix-blend-mode Not Working
If mix-blend-mode looks like it’s doing nothing, it’s usually one of these reasons (and the fixes are
thankfully pretty straightforward).
1) There is no visual overlap
If your blended element isn’t actually on top of something, it has nothing to blend with. Make sure it overlaps a backdrop (use positioning, grid/stacking, or negative margins).
2) You are blending the wrong layer
If you want “background only”, don’t put mix-blend-mode on the container that also contains text.
Put it on a dedicated overlay element (or pseudo-element) and keep content above it.
3) A parent is isolating the blend
The isolation property can change the blend behavior. When a parent has
isolation: isolate,
blending is limited to that stacking context. That can be helpful, but it can also surprise you.
Try this rule when you want to keep blending contained inside a component:
use isolation: isolate on the component wrapper.
.page {
background:
linear-gradient(120deg, #03045e 0%, #0077b6 45%, #90e0ef 100%);
}
.component {
isolation: auto;
}
.badge {
mix-blend-mode: difference;
}
.page {
background:
linear-gradient(120deg, #03045e 0%, #0077b6 45%, #90e0ef 100%);
}
.component {
isolation: isolate;
}
.badge {
mix-blend-mode: difference;
}
.page {
background: #ffffff;
}
.component {
isolation: auto;
}
.badge {
mix-blend-mode: difference;
}
.page {
background: #ffffff;
}
.component {
isolation: isolate;
}
.badge {
mix-blend-mode: difference;
}
*,
::before,
::after {
box-sizing: border-box;
}
.wrap {
max-width: 980px;
padding: 18px;
display: grid;
gap: 14px;
font-family: system-ui, Arial, sans-serif;
}
.page {
border: 3px solid #111;
border-radius: 18px;
overflow: hidden;
padding: 18px;
min-height: 260px;
position: relative;
display: grid;
place-items: center;
}
.component {
width: min(720px, 100%);
border-radius: 16px;
padding: 22px;
min-height: 170px;
position: relative;
overflow: hidden;
border: 2px solid rgba(0, 0, 0, 0.35);
background:
repeating-linear-gradient(
90deg,
rgba(255, 255, 255, 0.22) 0 12px,
rgba(255, 255, 255, 0) 12px 24px
),
linear-gradient(115deg, #ff006e 0%, #8338ec 50%, #3a86ff 100%);
display: grid;
place-items: center;
}
.title {
position: absolute;
left: 14px;
bottom: 12px;
padding: 6px 10px;
border-radius: 999px;
background: rgba(255, 255, 255, 0.78);
border: 1px solid rgba(0, 0, 0, 0.2);
font-size: 13px;
font-weight: 700;
}
.badge {
position: relative;
font-size: 64px;
font-weight: 900;
letter-spacing: 0.06em;
line-height: 1;
padding: 12px 18px;
border-radius: 18px;
background: #ffffff;
border: 2px solid rgba(0, 0, 0, 0.25);
color: #111111;
}
.help {
margin: 0;
font-size: 14px;
opacity: 0.9;
line-height: 1.45;
background: rgba(255, 255, 255, 0.78);
border-radius: 14px;
padding: 10px 12px;
border: 1px solid rgba(0, 0, 0, 0.18);
max-width: 780px;
}
BLENDBadge uses mix-blend-mode: differenceThis demo is designed so the difference is obvious: the
.badgeblends with its backdrop. Withisolation: auto, the badge can blend with the page background behind the component. Withisolation: isolate, the blending is contained inside.component(it won’t “reach” the page). Try the snippets that switch.pagebetween a gradient and plain white to make the effect even clearer.
4) You’re testing on a flat background
If your backdrop is just a solid color, some modes can look nearly identical. Try a gradient, an image, or overlapping shapes to make the effect obvious.
5) Opacity can change the feel
It’s common to combine blending with opacity on the blended layer.
If the effect feels too aggressive, reduce opacity.
If it feels invisible, increase opacity and make sure your overlay has a strong color.
Quick Mode Cheat Sheet
- multiply: darkens, “ink on paper”, great for shading and rich overlaps
- screen: brightens, “light leak”, great for glow overlays
- overlay: punchy contrast, great for poster-like looks
- difference: invert-like, great for auto-contrast UI accents (use carefully)
- soft-light: gentler contrast, often a safer “overlay-lite”
Practical Tips and Gotchas
Readability First
Blending can make text unpredictable because it depends on what’s behind it. If it’s UI text (buttons, navigation, form labels), test on all your backgrounds and states. A blended headline in a hero section is usually safer than blended body text.
Contain Blending When Building Components
If you don’t want an element to blend with the entire page, consider using isolation: isolate on the
component wrapper.
That keeps the blend effect “inside the box” of the component.
Use a Dedicated Overlay Layer
For “background only” effects, separate your overlay layer from your content. It’s clearer, easier to control, and avoids “why is my text doing weird things” moments.
Debug by Temporarily Adding Strong Colors
When debugging, give the blended layer an obvious color (pure white or pure black) and ensure it overlaps a colorful backdrop. Once it’s working, refine.
CSS Mix-Blend-Mode Wrap-Up
You now know how mix-blend-mode blends an element with its backdrop, how the most useful modes behave,
how to blend text, how to blend background only overlays, and how to troubleshoot the classic not working cases.
