Skip to main content
    Courses/HTML & CSS/Filters & Blend Modes

    Lesson 35 • Advanced Track

    Filters, Blend Modes & Visual Effects

    By the end of this lesson you'll be able to retouch images with pure CSS, build frosted-glass cards, tint photos with blend modes, and combine these into Instagram-style presets and Spotify-style duotones — no Photoshop, no image editing, just a few lines of CSS.

    What You'll Learn

    Apply filter functions: blur, brightness, contrast, grayscale, hue-rotate, drop-shadow
    Chain several filters in one declaration and reason about their order
    Build a frosted-glass card with backdrop-filter and a semi-transparent background
    Tint and combine images with mix-blend-mode
    Blend an element's own background layers with background-blend-mode
    Keep blur effects fast and avoid the z-index surprises filters cause
    Before this lesson: you should be comfortable writing CSS rules and selectors and know how positioning and stacking work, since blend modes layer one element over another. If position, z-index, or stacking contexts feel new, review CSS Positioning first.

    💡 Think of It Like This

    Filters are the Instagram editing screen for a single photo. Slide "blur" up and the photo softens; slide "brightness" up and it glows. You're processing the picture itself, and you can stack several adjustments at once.

    Blend modes are sheets of coloured acetate you lay over the photo — the colour mixes with what's underneath instead of just sitting on top. And backdrop-filter is frosted bathroom glass: the glass itself is clear, but everything behind it turns soft and dreamy. Same idea — three different things to blur: the element, the colours that meet it, or the world behind it.

    1. The filter Property

    The filter property applies graphical effects to an element — the same kinds of adjustments you'd reach for in a photo editor, but in CSS. It works on anything: images, text, a <div>, even a video. You give it one or more filter functions, and they run left to right like a pipeline.

    FunctionTypical rangeEffect
    blur(px)0 and upSoftens with a Gaussian blur
    brightness(n)0 to ∞ (1 = normal)Lightens or darkens
    contrast(n)0 to ∞ (1 = normal)Increases or flattens contrast
    grayscale(%)0% to 100%Removes colour
    hue-rotate(deg)0deg to 360degSpins every colour round the wheel
    drop-shadow(...)x y blur colourShadow that follows the shape, not the box

    Run the worked example. Each card applies one filter, and hovering removes it so you can compare against the untouched image. Read the comment beside every rule to see what value produces what.

    Worked example: the six core filters

    One filter per card; hover to see the original

    Try it Yourself »
    Code Preview
    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <title>CSS filters</title>
      <style>
        body { font-family: system-ui, sans-serif; padding: 20px; background: #0f172a; color: #e5e7eb; }
        .gallery { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 14px; }
        .card { background: #1e293b; border-radius: 12px; overflow: hidden; text-align: center; }
        .card img { width: 100%; height: 110px; object-fit: cover; transition: filter 0.3s; }
        .c
    ...

    2. Chaining Filters (and why order matters)

    You can list several filter functions in one declaration, separated by spaces: filter: grayscale(40%) brightness(1.2) contrast(0.9);. That single line is how the "vintage", "dramatic", and "faded" looks of photo apps are built — a fixed recipe of small adjustments stacked together.

    The functions run left to right, so order changes the result. brightness(1.5) blur(5px) brightens the sharp image first, then blurs the bright pixels; swap them and you blur first, then brighten the soft pixels — a different look. Treat the order as part of the effect.

    Worked example: filter presets

    Several filters chained into reusable photo looks

    Try it Yourself »
    Code Preview
    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <title>Chained filters</title>
      <style>
        body { font-family: system-ui, sans-serif; padding: 20px; background: #0f172a; color: #e5e7eb; }
        .row { display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); gap: 14px; }
        .preset { background: #1e293b; border-radius: 12px; overflow: hidden; text-align: center; }
        .preset img { width: 100%; height: 130px; object-fit: cover; transition: filter 0.4s; }
       
    ...

    3. backdrop-filter — Frosted Glass

    backdrop-filter blurs (or brightens, etc.) whatever is rendered behind an element, while the element's own content stays sharp. This is the "glassmorphism" look: a translucent card floating over a photo, with the photo blurred where it shows through.

    Two things are required, and both are common stumbling blocks. First, the element needs a semi-transparent background like rgba(255,255,255,0.15) — a fully opaque background hides the blur completely. Second, Safari needs the -webkit-backdrop-filter prefix as well, so always write both.

    Worked example: glassmorphism card

    backdrop-filter over a photo for a frosted-glass panel

    Try it Yourself »
    Code Preview
    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <title>backdrop-filter</title>
      <style>
        body { font-family: system-ui, sans-serif; margin: 0; }
        .scene { position: relative; height: 360px; overflow: hidden; }
        .scene img { width: 100%; height: 100%; object-fit: cover; }   /* the background to blur */
    
        .glass {
          position: absolute; bottom: 24px; left: 24px; right: 24px;
          /* 1) SEMI-TRANSPARENT background so the blur behind it is visible. */
          backgr
    ...

    4. Blend Modes — mix-blend-mode & background-blend-mode

    A blend mode decides how the colours of two layers combine instead of one simply covering the other. mix-blend-mode blends an element with whatever sits behind it on the page — drop a coloured <div> over a photo with mix-blend-mode: multiply and the colour soaks into the photo.

    background-blend-mode is the inward-looking cousin: it blends an element's own background layers together — say a background-image with a background-color — without touching anything else on the page. Worth knowing the names: multiply darkens (and makes white vanish), screen lightens, overlay boosts contrast, and color keeps the photo's brightness but takes the overlay's hue — perfect for tinting.

    Worked example: blend modes side by side

    The same overlay colour, six different blend modes

    Try it Yourself »
    Code Preview
    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <title>Blend modes</title>
      <style>
        body { font-family: system-ui, sans-serif; padding: 20px; background: #0f172a; color: #e5e7eb; }
        .grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(170px, 1fr)); gap: 14px; }
    
        .tile { position: relative; height: 130px; border-radius: 12px; overflow: hidden; }
        .tile img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
        /* Thi
    ...

    🎯 Your Turn #1 — Grayscale-on-rest, colour-on-hover

    A classic portfolio effect: thumbnails are black-and-white until you hover, when they bloom into colour. Fill in the blanks marked ___, then run it and check the expected result in the comments.

    Your Turn #1: grayscale to colour on hover

    Use the filter property and a :hover override

    Try it Yourself »
    Code Preview
    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <title>Your Turn 1</title>
      <style>
        /* 🎯 YOUR TURN — fill in the blanks marked ___ */
    
        body { font-family: system-ui, sans-serif; padding: 20px; background: #0f172a; }
        .thumb { width: 200px; border-radius: 12px; overflow: hidden; }
        .thumb img { width: 100%; height: 140px; object-fit: cover; transition: filter 0.3s; }
    
        /* 1) At rest, make the image fully black & white. */
        .thumb img { filter: ___; }      
    ...

    🎯 Your Turn #2 — Build a frosted-glass card

    The card below sits over a photo but currently looks flat — the glass effect is missing. Add the semi-transparent background and the backdrop-filter (with its Safari prefix) to frost the photo behind it. Verify the expected look in the comments.

    Your Turn #2: glassmorphism

    Add a translucent background and backdrop-filter

    Try it Yourself »
    Code Preview
    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <title>Your Turn 2</title>
      <style>
        /* 🎯 YOUR TURN — fill in the blanks marked ___ */
    
        body { font-family: system-ui, sans-serif; margin: 0; }
        .scene { position: relative; height: 320px; overflow: hidden; }
        .scene img { width: 100%; height: 100%; object-fit: cover; }
    
        .glass {
          position: absolute; bottom: 24px; left: 24px; right: 24px;
          border: 1px solid rgba(255,255,255,0.25);
          border-radius:
    ...

    🧩 Mini-Challenge — Duotone effect from scratch

    Support is faded now — only an outline is given. Build the Spotify-style duotone: a greyscaled photo with a coloured gradient blended on top in color mode. Lean on the worked examples in sections 1 and 4 if you get stuck.

    Mini-Challenge: duotone photo

    grayscale filter + gradient overlay with mix-blend-mode: color

    Try it Yourself »
    Code Preview
    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <title>Mini-Challenge</title>
      <style>
        /* 🧩 MINI-CHALLENGE: a two-tone "duotone" image
           1. Make a .duo container with position: relative, fixed size, overflow: hidden
           2. Put an <img> inside it and apply filter: grayscale(100%) contrast(1.1)
              so the photo is black & white
           3. Add a .duo::after pseudo-element that fully covers the container
              (position: absolute; inset: 0; content: '')
        
    ...

    ⚠️ Common Errors (and the fix)

    • backdrop-filter shows no blur. The element's background is opaque, so there's no see-through area for the blurred backdrop to appear in. Fix: use a semi-transparent background like rgba(255,255,255,0.15).
    • Works in Chrome, blank glass in Safari. Safari needs the prefixed property. Fix: add -webkit-backdrop-filter alongside the unprefixed backdrop-filter, with the same value.
    • Filters chained in the wrong order. blur(5px) brightness(1.5) and brightness(1.5) blur(5px) look different because functions run left to right. Fix: decide the order deliberately and test both.
    • multiply makes white disappear. That's by design — anything multiplied by white is unchanged, so light areas drop out. Fix: if you need light areas to survive, use screen or lighten instead.
    • z-index suddenly behaves oddly after adding a filter. Any filter value creates a new stacking context, which can re-order layers. Fix: account for the new context, or move the filter to a child that doesn't need to escape it.
    • The page janks on mobile. A large backdrop-filter: blur() is GPU-heavy. Fix: keep blurred backdrops to small regions (cards, navbars) and avoid animating big blurs.

    📋 Quick Reference

    GoalUse this
    Blur an elementfilter: blur(4px);
    Black & whitefilter: grayscale(100%);
    Lighten / darkenfilter: brightness(1.3);
    Shift coloursfilter: hue-rotate(90deg);
    Shape-following shadowfilter: drop-shadow(2px 2px 4px #000);
    Chain several filtersfilter: grayscale(40%) contrast(1.2);
    Frosted glassbackdrop-filter: blur(14px); (+ webkit)
    Tint a photo with an overlaymix-blend-mode: multiply;
    Blend an element's own layersbackground-blend-mode: multiply;

    ❓ Frequently Asked Questions

    What is the difference between filter and backdrop-filter?

    They blur (or brighten, etc.) different things. filter processes the element it is applied to — put filter: blur(4px) on an image and the image goes blurry. backdrop-filter processes whatever sits behind a semi-transparent element — put it on a translucent card over a photo and the photo shows through frosted, while the card's own text stays sharp. Rule of thumb: filter = blur me; backdrop-filter = blur what's behind me.

    Why is my backdrop-filter doing nothing?

    Almost always one of three things. (1) The element's own background is fully opaque, so there is no see-through area for the blur to appear in — give it a semi-transparent background like rgba(255,255,255,0.15). (2) You are testing in Safari without the prefix — Safari needs -webkit-backdrop-filter as well as backdrop-filter. (3) Nothing is actually behind the element to blur. backdrop-filter only affects pixels rendered behind it, so it needs content underneath and a translucent foreground to reveal it.

    Does the order of filter functions matter?

    Yes. Filters are applied left to right, like a pipeline, so brightness(1.5) blur(5px) brightens the sharp image first and then blurs the bright result, while blur(5px) brightness(1.5) blurs first and then brightens the already-soft pixels. The two give visibly different looks. When you chain functions, treat the order as part of the effect, not an afterthought.

    What is the difference between mix-blend-mode and background-blend-mode?

    mix-blend-mode blends an element with whatever is rendered behind it on the page — one element against other elements. background-blend-mode blends an element's own background layers together (for example a background-image with a background-color, or two stacked images) without involving anything else on the page. Use mix-blend-mode to tint a photo with an overlay div; use background-blend-mode to merge a colour into a single element's background.

    Are filters and blend modes bad for performance?

    Most filters are cheap and run on the GPU, but blur — especially backdrop-filter: blur() spread over a large area — is the expensive one and can drop frame rates on phones. Keep blurred backdrops to small regions like cards and navbars rather than full-screen overlays, avoid animating large blurs, and test on a real mid-range device. A filter also creates a new stacking context, which can quietly change how z-index resolves, so check your layering after adding one.

    Why does mix-blend-mode: multiply ignore my white text or white card?

    That is how multiply works, not a bug. Multiply multiplies the colour channels, and anything multiplied by white (1) stays unchanged, while anything multiplied by black (0) becomes black. So with multiply, white areas vanish into the layer below and dark areas show through strongly — perfect for dropping a logo onto paper, but useless if you expected white to stay white. Pick screen or lighten instead when you want the light areas to survive.

    🎉 Lesson Complete

    You can now retouch images and build rich visual effects with pure CSS. The essentials:

    • filter processes the element itself — blur, brightness, contrast, grayscale, hue-rotate, drop-shadow
    • ✅ Chain filters in one declaration; they run left to right, so order changes the look
    • backdrop-filter frosts what's behind a semi-transparent element (remember the -webkit- prefix)
    • mix-blend-mode blends an element with the page; background-blend-mode blends its own layers
    • ✅ Duotone = grayscale photo + a gradient blended in color mode
    • ✅ Keep big blurs small and remember filters create a new stacking context

    Next up: CSS Architecture, where you'll learn to organise and scale stylesheets so a large codebase stays maintainable.

    Sign up for free to track which lessons you've completed and get learning reminders.

    Previous

    Cookie & Privacy Settings

    We use cookies to improve your experience, analyze traffic, and show personalized ads. You can manage your preferences below.

    By clicking "Accept All", you consent to our use of cookies for analytics and personalized advertising. You can customize your preferences or reject non-essential cookies.

    Privacy PolicyTerms of Service

    Install LearnCodingFast

    Learn faster with the app on your home screen.