Menu

Tailwind CSS Backdrop Sepia

Backdrop Sepia allows a content’s backdrop to adopt a sepia-toned effect. It is especially useful for enhancing the aesthetic appeal of web interfaces by adding a warm vintage tone to background imagery or video content.

Tailwind CSS provides backdrop-sepia and backdrop-sepia-0 utilities to easily add and remove backdrop sepia effects. In this guide, we will learn how to use backdrop sepia in Tailwind CSS, including conditional applications, customization techniques, and practical code examples.

ClassPropertiesExample
backdrop-sepia-0backdrop-filter: sepia(0);<div className="backdrop-sepia-0"></div>
backdrop-sepiabackdrop-filter: sepia(100%);<div className="backdrop-sepia"></div>

Overview of Backdrop Sepia

Adding the Backdrop Sepia

To apply the sepia tone to an element's backdrop, use the backdrop-sepia utility.

This is a live editor. Play around with it!
export default function BackdropSepiaExample() {
  return (
    <div className="h-screen w-screen bg-cover bg-center" style={{ backgroundImage: `url('https://images.unsplash.com/photo-1508873699372-7aeab60b44ab')` }}>
      <div className="backdrop-sepia bg-white/30 flex items-center justify-center h-screen">
        <p className="text-lg">Backdrop Sepia Effect</p>
      </div>
    </div>
  );
}

Resetting Backdrop Filter

To remove the backdrop sepia from an element, use backdrop-sepia-0 utility. If you want to remove all the backdrop filters, use the backdrop-filter-none utility.

This is a live editor. Play around with it!
export default function NoBackdropFilterExample() {
  return (
    <div className="h-screen w-screen bg-cover bg-center" style={{ backgroundImage: `url('https://images.unsplash.com/photo-1508873699372-7aeab60b44ab')` }}>
      <div className="backdrop-filter-none backdrop-sepia bg-white/30 flex items-center justify-center h-screen">
        <p className="text-lg">No Filters Applied</p>
      </div>
    </div>
  );
}

States and Responsiveness

Hover and Focus States

Tailwind provides state modifiers like hover, focus, etc. to conditionally apply an utility only when these states are active. To apply the backdrop sepia to a certain state, prepend the state modifier to the utility, e.g., hover:backdrop-sepia.

This is a live editor. Play around with it!
export default function HoverStateExample() {
  return (
    <div className="h-screen w-screen bg-cover bg-center" style={{ backgroundImage: `url('https://images.unsplash.com/photo-1508873699372-7aeab60b44ab')` }}>
      <div className="hover:backdrop-sepia bg-white/30 flex items-center justify-center h-screen">
        <p className="text-lg">Hover to add backdrop sepia</p>
      </div>
    </div>
  );
}

Breakpoint Modifiers

Tailwind CSS also provides breakpoint modifiers(sm, md, etc.) to apply or remove the backdrop sepia according to the screen width. To apply the backdrop sepia to a certain breakpoint or above, prepend the breakpoint modifier to the utility, e.g., md:backdrop-sepia.

This is a live editor. Play around with it!
export default function ResponsiveBackdropExample() {
  return (
    <div className="h-screen w-screen bg-cover bg-center" style={{ backgroundImage: `url('https://images.unsplash.com/photo-1508873699372-7aeab60b44ab')` }}>
      <div className="md:backdrop-sepia bg-white/30 flex items-center justify-center h-screen">
        <p className="text-lg text-center px-10">Backdrop sepia is applied on the <code>md</code> breakpoint.</p>
      </div>
    </div>
  );
}

Custom Backdrop Sepia

Extending the Theme

Tailwind lets you customize the theme file to create new utilities beyond the default ones. Inside your tailwind.config.js, modify the backdropSepia property under the theme.extend configuration.

In the below example, you have access to the custom utilities- backdrop-sepia-15 and backdrop-sepia-90:

This is a live editor. Play around with it!
import tailwindConfig from "./tailwind.config.js";
tailwind.config = tailwindConfig;

export default function CustomSepiaLevels() {
  return (
    <div className="h-screen w-screen bg-cover bg-center" style={{ backgroundImage: `url('https://images.unsplash.com/photo-1508873699372-7aeab60b44ab')` }}>
      <div className="backdrop-sepia-90 bg-white/30 flex items-center justify-center h-screen">
        <p className="text-lg">Custom backdrop sepia effect</p>
      </div>
    </div>
  );
}

Using Arbitrary Values

Tailwind also lets you define arbitrary values directly in your classes for one-off use cases. Just use the square bracket syntax [value] wherever you need it, e.g., backdrop-sepia-[.5].

This is a live editor. Play around with it!
export default function ArbitrarySepiaValue() {
  return (
    <div className="h-screen w-screen bg-cover bg-center" style={{ backgroundImage: `url('https://images.unsplash.com/photo-1508873699372-7aeab60b44ab')` }}>
      <div className="backdrop-sepia-[.5] bg-white/30 flex items-center justify-center h-screen">
        <p className="text-lg">Arbitrary backdrop sepia effect</p>
      </div>
    </div>
  );
}

Real World Examples

A modal photo gallery with a vintage sepia effect applied to the backdrop on click, displaying historical landmark photos with descriptions.

This is a live editor. Play around with it!
import { useState } from "react";

const HistoricalGallery = () => {
  const data = [
        {
      id: 1,
      src: "https://images.unsplash.com/photo-1511739001486-6bfe10ce785f",
      title: "Eiffel Tower, 1889",
      description: "Symbol of Paris during World's Fair",
    },
    {
      id: 2,
      src: "https://images.unsplash.com/photo-1587135941948-670b381f08ce",
      title: "Taj Mahal, 1653",
      description: "Monument of eternal love",
    },
    {
      id: 3,
      src: "https://images.unsplash.com/photo-1552832230-c0197dd311b5",
      title: "Colosseum, 80 AD",
      description: "Ancient Roman amphitheater",
    },
    {
      id: 4,
      src: "https://images.unsplash.com/photo-1615811648503-479d06197ff3",
      title: "Petra, 312 BC",
      description: "Rose city carved in stone",
    },
    {
      id: 5,
      src: "https://images.unsplash.com/photo-1547150492-da7ff1742941",
      title: "Great Wall, 220 BC",
      description: "Ancient Chinese fortification",
    },
    {
      id: 6,
      src: "https://images.unsplash.com/photo-1415804941191-bc0c3bbac10d",
      title: "Machu Picchu, 1450 AD",
      description: "Lost city of the Incas",
    },
  ];

  const [selectedImage, setSelectedImage] = useState(null);

  return (
    <div className="p-4 h-screen overflow-y-auto">
      <div className="grid grid-cols-2 gap-2">
        {data.map((item) => (
          <div
            key={item.id}
            onClick={() => setSelectedImage(item)}
            className="cursor-pointer hover:opacity-80 relative group"
          >
            <div
              className="w-full h-40 bg-cover bg-center rounded transition-transform duration-300 group-hover:scale-105"
              style={{ backgroundImage: `url(${item.src})` }}
            ></div>
          </div>
        ))}
      </div>

      {selectedImage && (
        <div className="fixed inset-0 flex items-center justify-center z-50">
          <div className="absolute inset-0 bg-black/30 backdrop-blur-sm backdrop-sepia transition-opacity duration-300 z-40"></div>
            <div className="relative bg-white p-4 rounded-lg max-w-md shadow-lg z-50">
              <div
                className="w-full h-48 bg-cover bg-center rounded"
                style={{ backgroundImage: `url(${selectedImage.src})` }}
              ></div>
              <h3 className="text-lg font-semibold mt-2">{selectedImage.title}</h3>
              <p className="text-sm text-gray-600">{selectedImage.description}</p>
              <button
                onClick={() => setSelectedImage(null)}
                className="absolute top-2 right-2 text-gray-600 hover:text-gray-800"
              >
                ×
              </button>
            </div>
        </div>
      )}
    </div>
  );
};

export default HistoricalGallery;

Recipe Card Collection

A collection of recipe cards with a sepia-toned backdrop effect when viewing detailed instructions.

This is a live editor. Play around with it!
import {useState} from "react";

const RetroRecipes = () => {
  const data = [
    {
      id: 1,
      title: "Grandma's Apple Pie",
      time: "90 mins",
      difficulty: "Medium",
      image: "https://images.unsplash.com/photo-1572383672419-ab35444a6934",
      ingredients: ["Apples", "Sugar", "Flour", "Butter", "Cinnamon"],
      instructions: "Mix ingredients, bake at 350°F"
    },
    {
      id: 2,
      title: "Classic Beef Stew",
      time: "180 mins",
      difficulty: "Hard",
      image: "https://images.unsplash.com/photo-1534939561126-855b8675edd7",
      ingredients: ["Beef", "Carrots", "Potatoes", "Onions", "Broth"],
      instructions: "Brown meat, add vegetables, simmer"
    },
    {
      id: 3,
      title: "Chocolate Cookies",
      time: "45 mins",
      difficulty: "Easy",
      image: "https://images.unsplash.com/photo-1499636136210-6f4ee915583e",
      ingredients: ["Chocolate", "Flour", "Sugar", "Eggs", "Vanilla"],
      instructions: "Mix, shape, bake at 375°F"
    },
    {
      id: 4,
      title: "Chicken Soup",
      time: "120 mins",
      difficulty: "Medium",
      image: "https://images.unsplash.com/photo-1547592166-23ac45744acd",
      ingredients: ["Chicken", "Carrots", "Celery", "Noodles", "Herbs"],
      instructions: "Boil chicken, add vegetables"
    },
    {
      id: 5,
      title: "Banana Bread",
      time: "60 mins",
      difficulty: "Easy",
      image: "https://images.unsplash.com/photo-1596241913027-34358037e159",
      ingredients: ["Bananas", "Flour", "Sugar", "Eggs", "Nuts"],
      instructions: "Mash bananas, mix, bake"
    },
    {
      id: 6,
      title: "Tomato Pasta",
      time: "30 mins",
      difficulty: "Easy",
      image: "https://images.unsplash.com/photo-1563379926898-05f4575a45d8",
      ingredients: ["Pasta", "Tomatoes", "Garlic", "Basil", "Olive Oil"],
      instructions: "Boil pasta, make sauce"
    }
  ];

  const [selectedRecipe, setSelectedRecipe] = useState(null);

  return (
    <div className="p-4 h-screen overflow-y-auto">
      <div className="grid grid-cols-2 gap-3">
        {data.map((recipe) => (
          <div
            key={recipe.id}
            className="bg-white rounded-lg shadow-sm p-2 cursor-pointer"
            onClick={() => setSelectedRecipe(recipe)}
          >
            <img
              src={recipe.image}
              alt={recipe.title}
              className="w-full h-24 object-cover rounded"
            />
            <h4 className="text-sm font-semibold mt-1">{recipe.title}</h4>
            <p className="text-xs text-gray-500">{recipe.time}</p>
          </div>
        ))}
      </div>

      {selectedRecipe && (
        <div className="fixed inset-0 flex items-center justify-center">
          <div className="absolute inset-0 backdrop-blur-md backdrop-sepia-[.4]"></div>
          <div className="relative bg-white p-4 rounded-lg max-w-xs shadow-xl border border-dashed border-black/70">
            <img
              src={selectedRecipe.image}
              alt={selectedRecipe.title}
              className="w-full h-32 object-cover rounded"
            />
            <h3 className="text-lg font-semibold mt-2">{selectedRecipe.title}</h3>
            <div className="text-xs mt-2">
              <p className="font-semibold">Ingredients:</p>
              <ul className="list-disc pl-4">
                {selectedRecipe.ingredients.map((ing, idx) => (
                  <li key={idx}>{ing}</li>
                ))}
              </ul>
              <p className="font-semibold mt-2">Instructions:</p>
              <p>{selectedRecipe.instructions}</p>
            </div>
            <button
              onClick={() => setSelectedRecipe(null)}
              className="absolute top-2 right-2 text-gray-600"
            >
              ×
            </button>
          </div>
        </div>
      )}
    </div>
  );
};

export default RetroRecipes;

Product Comparison

A split-screen product comparison where the backdrop-sepia effect helps highlight the selected side.

This is a live editor. Play around with it!
import { useState } from "react";

const ProductComparison = () => {
  const data = [
    {
      id: 1,
      name: "Pro Camera X1",
      brand: "PhotoTech",
      price: "$1299",
      image: "https://images.unsplash.com/photo-1516035069371-29a1b244cc32",
      specs: ["50MP Sensor", "8K Video", "Weather Sealed", "5-axis IBIS"],
      rating: 4.8
    },
    {
      id: 2, 
      name: "Pro Camera X2",
      brand: "CameraPro",
      price: "$1499",
      image: "https://images.unsplash.com/photo-1502920917128-1aa500764cbd",
      specs: ["61MP Sensor", "8K Video", "Weather Sealed", "6-axis IBIS"],
      rating: 4.9
    },
    {
      id: 3,
      name: "Pro Camera X3",
      brand: "PhotoMaster",
      price: "$999",
      image: "https://images.unsplash.com/photo-1500634245200-e5245c7574ef",
      specs: ["45MP Sensor", "4K Video", "Weather Sealed", "4-axis IBIS"],
      rating: 4.7
    },
    {
      id: 4,
      name: "Pro Camera X4",
      brand: "LensKing",
      price: "$1899",
      image: "https://images.unsplash.com/photo-1512790182412-b19e6d62bc39",
      specs: ["70MP Sensor", "12K Video", "Weather Sealed", "7-axis IBIS"],
      rating: 4.6
    },
    {
      id: 5,
      name: "Pro Camera X5",
      brand: "PixelPro",
      price: "$2199",
      image: "https://images.unsplash.com/photo-1510127034890-ba27508e9f1c",
      specs: ["80MP Sensor", "16K Video", "Weather Sealed", "8-axis IBIS"],
      rating: 4.5
    },
    {
      id: 6,
      name: "Pro Camera X6",
      brand: "CamKing",
      price: "$1699",
      image: "https://images.unsplash.com/photo-1516724562728-afc824a36e84",
      specs: ["65MP Sensor", "10K Video", "Weather Sealed", "6-axis IBIS"],
      rating: 4.4
    }
  ];

  const [leftProduct, setLeftProduct] = useState(data[0]);
  const [rightProduct, setRightProduct] = useState(data[1]);
  const [focusedSide, setFocusedSide] = useState(null);

  return (
    <div className="h-screen w-screen relative overflow-hidden">
      <div className="flex h-full">
        {/* Left Side */}
        <div 
          className="w-1/2 p-2 relative"
          onMouseEnter={() => setFocusedSide("left")}
          onMouseLeave={() => setFocusedSide(null)}
        >
          {/* Apply Sepia Only When Hovered */}
          <div
            className={`absolute inset-0 transition duration-300 ${
              focusedSide === "left" ? "backdrop-sepia backdrop-blur-sm" : ""
            }`}
          ></div>
          <div className="relative z-10">
            <select 
              className="w-full mb-2 text-xs"
              onChange={(e) => setLeftProduct(data[e.target.value])}
            >
              {data.map((item, idx) => (
                <option key={item.id} value={idx}>{item.name}</option>
              ))}
            </select>
            <div className="space-y-2">
              <img src={leftProduct.image} alt={leftProduct.name} className="w-full h-32 object-cover rounded" />
              <h3 className="text-sm font-semibold">{leftProduct.name}</h3>
              <p className="text-xs text-gray-600">{leftProduct.brand}</p>
              <p className="text-sm font-bold">{leftProduct.price}</p>
              <div className="text-xs space-y-1">
                {leftProduct.specs.map((spec, idx) => (
                  <p key={idx}>{spec}</p>
                ))}
              </div>
            </div>
          </div>
        </div>

        {/* Divider */}
        <div className="w-px bg-gray-300"></div>

        {/* Right Side */}
        <div 
          className="w-1/2 p-2 relative"
          onMouseEnter={() => setFocusedSide("right")}
          onMouseLeave={() => setFocusedSide(null)}
        >
          {/* Apply Sepia Only When Hovered */}
          <div
            className={`absolute inset-0 transition duration-300 ${
              focusedSide === "right" ? "backdrop-sepia backdrop-blur-sm" : ""
            }`}
          ></div>
          <div className="relative z-10">
            <select 
              className="w-full mb-2 text-xs"
              onChange={(e) => setRightProduct(data[e.target.value])}
            >
              {data.map((item, idx) => (
                <option key={item.id} value={idx}>{item.name}</option>
              ))}
            </select>
            <div className="space-y-2">
              <img src={rightProduct.image} alt={rightProduct.name} className="w-full h-32 object-cover rounded" />
              <h3 className="text-sm font-semibold">{rightProduct.name}</h3>
              <p className="text-xs text-gray-600">{rightProduct.brand}</p>
              <p className="text-sm font-bold">{rightProduct.price}</p>
              <div className="text-xs space-y-1">
                {rightProduct.specs.map((spec, idx) => (
                  <p key={idx}>{spec}</p>
                ))}
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
  );
};

export default ProductComparison;

Before/After Image Slider

A unique implementation of an image slider where dragging reveals the before/after states with a sepia backdrop effect.

This is a live editor. Play around with it!
import { useState, useRef } from "react";

const BeforeAfterSlider = () => {
  const data = [
    {
      id: 1,
      before: "https://images.unsplash.com/photo-1600596542815-ffad4c1539a9",
      after: "https://images.unsplash.com/photo-1600585154340-be6161a56a0c",
      title: "House Renovation",
    },
    {
      id: 2,
      before: "https://images.unsplash.com/photo-1512917774080-9991f1c4c750",
      after: "https://images.unsplash.com/photo-1570129477492-45c003edd2be",
      title: "Exterior Makeover",
    },
    {
      id: 3,
      before: "https://images.unsplash.com/photo-1523039031846-6b3f39302cb8",
      after: "https://images.unsplash.com/photo-1556911220-bff31c812dba",
      title: "Kitchen Remodel",
    },
    {
      id: 4,
      before: "https://images.unsplash.com/photo-1560448204-603b3fc33ddc",
      after: "https://images.unsplash.com/photo-1560448075-bb485b067938",
      title: "Bathroom Update",
    },
    {
      id: 5,
      before: "https://images.unsplash.com/photo-1565776316048-2501a698ba08",
      after: "https://images.unsplash.com/photo-1603024594199-4107b1e69b7d",
      title: "Living Room Transform",
    },
    {
      id: 6,
      before: "https://images.unsplash.com/photo-1516253593875-bd7ba052fbc5",
      after: "https://images.unsplash.com/photo-1462759353907-b2ea5ebd72e7",
      title: "Garden Makeover",
    }
  ];

  const [selectedImage, setSelectedImage] = useState(data[0]);
  const [sliderPosition, setSliderPosition] = useState(50);
  const sliderRef = useRef(null);

  const handleMouseMove = (e) => {
    if (!sliderRef.current) return;
    
    const rect = sliderRef.current.getBoundingClientRect();
    const x = e.clientX - rect.left;
    const percent = (x / rect.width) * 100;
    setSliderPosition(Math.min(Math.max(percent, 0), 100));
  };

  return (
    <div className="h-screen w-screen p-4 bg-gray-100">
      <div className="space-y-4">
        {/* Main Slider */}
        <div 
          ref={sliderRef}
          className="relative h-48 cursor-ew-resize overflow-hidden rounded-lg"
          onMouseMove={handleMouseMove}
        >
          {/* Before Image */}
          <div className="absolute inset-0">
            <img
              src={selectedImage.before}
              alt="Before"
              className="w-full h-full object-cover"
            />
            {/* Applying backdrop-sepia */}
            <div className="absolute inset-0 bg-black/10 backdrop-sepia transition duration-300"></div>
          </div>

          {/* After Image */}
          <div
            className="absolute inset-0 overflow-hidden"
            style={{ width: `${sliderPosition}%` }}
          >
            <img
              src={selectedImage.after}
              alt="After"
              className="w-full h-full object-cover"
            />
          </div>

          {/* Slider Handle */}
          <div
            className="absolute top-0 bottom-0 w-1 bg-white cursor-ew-resize"
            style={{ left: `${sliderPosition}%` }}
          >
            <div className="absolute top-1/2 -translate-y-1/2 -translate-x-1/2 w-6 h-6 bg-white rounded-full shadow-lg"></div>
          </div>
        </div>

        {/* Thumbnails */}
        <div className="grid grid-cols-3 gap-2">
          {data.map((item) => (
            <div
              key={item.id}
              onClick={() => setSelectedImage(item)}
              className={`cursor-pointer relative rounded-md overflow-hidden ${
                selectedImage.id === item.id ? 'ring-2 ring-blue-500' : ''
              }`}
            >
              <img
                src={item.after}
                alt={item.title}
                className="w-full h-16 object-cover"
              />
              <div className="absolute inset-0 bg-black bg-opacity-20">
                <p className="text-white text-xs p-1">{item.title}</p>
              </div>
            </div>
          ))}
        </div>
      </div>
    </div>
  );
};

export default BeforeAfterSlider;

Vintage Cinema Listings

A movie showtime display with a sepia backdrop effect when viewing movie details.

This is a live editor. Play around with it!
import { useState } from 'react';

const CinemaListings = () => {
  const [selectedMovie, setSelectedMovie] = useState(null);

  const movieData = [
    {
      id: 1,
      title: "The Grand Escape",
      poster: "https://images.unsplash.com/photo-1542204165-65bf26472b9b",
      director: "Edward Mitchell",
      year: "1935",
      runtime: "1h 45m",
      genre: "Mystery/Thriller",
      showtime: ["2:00 PM", "5:30 PM", "8:00 PM"],
      cast: "James Stewart, Grace Kelly",
      description: "A thrilling tale of mystery and intrigue in the golden age of cinema."
    },
    {
      id: 2,
      title: "Midnight Waltz",
      poster: "https://images.unsplash.com/photo-1536440136628-849c177e76a1",
      director: "Maria Hernandez",
      year: "1942",
      runtime: "2h 10m",
      genre: "Romance/Drama",
      showtime: ["1:30 PM", "4:45 PM", "7:15 PM"],
      cast: "Katherine Hepburn, Cary Grant",
      description: "A romantic drama set in the glamorous world of ballroom dancing."
    },
    {
      id: 3,
      title: "Desert Storm",
      poster: "https://images.unsplash.com/photo-1594909122845-11baa439b7bf",
      director: "Robert Wilson",
      year: "1939",
      runtime: "1h 55m",
      genre: "Adventure",
      showtime: ["3:15 PM", "6:00 PM", "8:45 PM"],
      cast: "Clark Gable, Vivien Leigh",
      description: "An epic adventure across the scorching desert landscapes."
    },
    {
      id: 4,
      title: "City Lights",
      poster: "https://images.unsplash.com/photo-1478720568477-152d9b164e26",
      director: "Charles Chapman",
      year: "1938",
      runtime: "1h 30m",
      genre: "Comedy",
      showtime: ["2:30 PM", "5:00 PM", "7:30 PM"],
      cast: "Charlie Chaplin, Virginia Cherrill",
      description: "A heartwarming comedy about life in the big city."
    },
    {
      id: 5,
      title: "The Last Train",
      poster: "https://images.unsplash.com/photo-1535443274868-756b0f070b6e",
      director: "John Ford",
      year: "1941",
      runtime: "2h 05m",
      genre: "Drama/War",
      showtime: ["1:00 PM", "4:00 PM", "7:00 PM"],
      cast: "Humphrey Bogart, Ingrid Bergman",
      description: "A gripping war drama about love and sacrifice."
    },
    {
      id: 6,
      title: "Morning Glory",
      poster: "https://images.unsplash.com/photo-1533928298208-27ff66555d8d",
      director: "Alfred Hitchcock",
      year: "1937",
      runtime: "1h 50m",
      genre: "Mystery/Romance",
      showtime: ["3:30 PM", "6:30 PM", "9:00 PM"],
      cast: "Joan Crawford, Henry Fonda",
      description: "A mysterious romance that unfolds at sunrise."
    }
  ];

  return (
    <div className="w-screen h-screen bg-stone-100 p-4 overflow-y-auto">
      <h1 className="text-2xl font-serif font-bold mb-4">Grand Palace Cinema</h1>
      <div className="space-y-4">
        {movieData.map((movie) => (
          <div
            key={movie.id}
            className="flex gap-3 cursor-pointer hover:bg-stone-200 p-2 rounded transition-colors"
            onClick={() => setSelectedMovie(movie)}
          >
            <img
              src={movie.poster}
              alt={movie.title}
              className="w-20 h-28 object-cover rounded"
            />
            <div>
              <h3 className="font-medium">{movie.title}</h3>
              <p className="text-xs text-gray-600">{movie.year} • {movie.runtime}</p>
              <p className="text-xs text-gray-600 mt-1">{movie.genre}</p>
              <div className="flex gap-2 mt-2">
                {movie.showtime.map((time, index) => (
                  <span key={index} className="text-xs bg-stone-200 px-2 py-1 rounded">
                    {time}
                  </span>
                ))}
              </div>
            </div>
          </div>
        ))}
      </div>

      {selectedMovie && (
        <div className="fixed inset-0 flex items-center justify-center">
          <div 
            className="absolute inset-0 backdrop-blur-sm backdrop-sepia bg-stone-900/30"
            onClick={() => setSelectedMovie(null)}
          />
          <div className="relative z-10 bg-stone-100 p-6 rounded-lg max-w-md w-full mx-4 ">
            <img
              src={selectedMovie.poster}
              alt={selectedMovie.title}
              className="w-full h-24 object-cover rounded-lg mb-4"
            />
            <h2 className="text-md font-serif font-bold">{selectedMovie.title}</h2>
            <p className="text-xs text-gray-600">{selectedMovie.year} • {selectedMovie.runtime}</p>
            <p className="text-xs font-medium mt-2">Director: {selectedMovie.director}</p>
            <p className="text-xs font-medium">Cast: {selectedMovie.cast}</p>
            <p className="text-xs mt-2">{selectedMovie.description}</p>
            <div className="mt-4 text-xs">
              <h3 className="font-medium mb-2">Today's Showtimes</h3>
              <div className="flex gap-2">
                {selectedMovie.showtime.map((time, index) => (
                  <span key={index} className="text-xs bg-stone-200 px-3 py-1 rounded">
                    {time}
                  </span>
                ))}
              </div>
            </div>
          </div>
        </div>
      )}
    </div>
  );
};

export default CinemaListings;

Customization Examples

Custom Sepia Profile Card

A profile card component with a custom sepia backdrop effect that creates a vintage photography look for user profiles.

This is a live editor. Play around with it!
import tailwindConfig from "./tailwind.config.js";
tailwind.config = tailwindConfig;

// App.js
export default function VintageProfileCard() {
  return (
    <div className="flex items-center justify-center min-h-screen bg-gray-100">
      <div className="relative w-80 h-96 overflow-hidden rounded-xl">
        <img
          src="https://images.unsplash.com/photo-1544005313-94ddf0286df2"
          className="absolute w-full h-full object-cover"
          alt="Profile"
        />
        <div className="absolute inset-0 backdrop-sepia-vintage bg-white/30" />
        <div className="absolute bottom-0 w-full p-6 text-white">
          <h3 className="text-2xl font-semibold">Sarah Anderson</h3>
          <p className="text-sm opacity-90">Vintage Photography Expert</p>
        </div>
      </div>
    </div>
  )
}

A gallery showcase with varying sepia intensities for an artistic image display.

This is a live editor. Play around with it!
import tailwindConfig from "./tailwind.config.js";
tailwind.config = tailwindConfig;

// App.js
export default function SepiaGallery() {
  const images = [
    {
      url: "https://images.unsplash.com/photo-1501785888041-af3ef285b470",
      sepia: "backdrop-sepia-light"
    },
    {
      url: "https://images.unsplash.com/photo-1449034446853-66c86144b0ad",
      sepia: "backdrop-sepia-medium"
    },
    {
      url: "https://images.unsplash.com/photo-1470071459604-3b5ec3a7fe05",
      sepia: "backdrop-sepia-heavy"
    }
  ]

  return (
    <div className="grid grid-cols-3 gap-4 p-8 bg-gray-900 h-screen">
      {images.map((image, index) => (
        <div key={index} className="relative group overflow-hidden rounded-lg">
          <img
            src={image.url}
            className="w-full h-full object-cover"
            alt={`Gallery ${index + 1}`}
          />
          <div className={`absolute inset-0 ${image.sepia} transition-all duration-300 group-hover:backdrop-blur-sm`} />
        </div>
      ))}
    </div>
  )
}

Sepia Hero Banner

A hero banner with custom sepia effect and interactive hover states.

This is a live editor. Play around with it!
import tailwindConfig from "./tailwind.config.js";
tailwind.config = tailwindConfig;

// App.js
export default function SepiaHeroBanner() {
  return (
    <div className="relative h-screen w-full overflow-hidden">
      <img
        src="https://images.unsplash.com/photo-1501785888041-af3ef285b470"
        className="absolute w-full h-full object-cover"
        alt="Hero"
      />
      <div className="absolute inset-0 backdrop-sepia-subtle transition-all duration-500 backdrop-blur-sm bg-black/20" />
      
      <div className="relative z-10 flex flex-col items-center justify-center h-full text-white">
        <h1 className="text-6xl font-bold mb-4 text-center">Timeless Memories</h1>
        <p className="text-xl max-w-2xl text-center">
          Experience the beauty of vintage aesthetics through our carefully curated collection
        </p>
        <button className="mt-8 px-8 py-3 bg-white/10 backdrop-blur-md rounded-full hover:bg-white/20 transition-all duration-300">
          Explore Collection
        </button>
      </div>
    </div>
  )
}

Best Practices

Maintain Design Consistency

When applying backdrop sepia in Tailwind CSS, maintaining a consistent design language across your project is essential. To achieve this consistency, define a limited set of global sepia intensity levels in your Tailwind configuration file, such as backdrop-sepia-25 or backdrop-sepia-75. Then, apply these utilities consistently across all components where sepia effects are needed.

Consistency also involves adhering to a harmonious color palette that complements sepia tones. For example, pair warm hues like amber or beige with sepia filters for a vintage aesthetic.

Lastly, validate your design by conducting visual audits, particularly in scenarios with multiple layered elements or transparency overlaps. Ensure the underlying backdrop elements do not clash with the sepia filter, and verify that the filtered content aligns visually with your branding guidelines.

Leverage Utility Combinations

For more creative and visually appealing designs, you can combine backdrop-sepia with other Tailwind CSS utilities like backdrop-blur, backdrop-contrast, backdrop-brightness, etc. This allows you to refine how backdrop elements appear, making them softer, sharper, or more dramatic.

You can also use backdrop-sepia in interactive elements like hoverable cards, buttons, or modals. By applying it with hover (hover:backdrop-sepia) or focus (focus:backdrop-sepia) states, you can make UI components dynamically change based on user interaction. This technique helps guide user attention while maintaining a visually appealing and engaging experience.

Accessibility Considerations

Enhance Readability and Navigability

The sepia effect introduces a warm, vintage tone that can soften contrasts and impact text clarity. To counteract this, use highly legible fonts along with an appropriate text size. Additionally, add proper line spacing for better readability and reduced eye strain.

Navigability also plays a key role in accessibility when applying sepia backgrounds. Users with color vision deficiencies or general visual impairments may struggle to differentiate elements if the sepia tone is too intense. To maintain clarity, use well-defined borders and shadows to provide clear separation between UI elements.

Focus on High Contrast

Low contrast between text and the background can be problematic for users with visual impairments, making it difficult to read content or distinguish between UI components. A good practice is to test contrast ratios using accessibility tools like the WebAIM Contrast Checker to ensure compliance with WCAG (Web Content Accessibility Guidelines) standards. If text on a sepia backdrop does not meet contrast requirements, adjust its color utilities.

Another approach to preserving contrast is to limit the intensity of the sepia effect (e.g., backdrop-sepia-[0.5]) instead of applying a full sepia filter. Additionally, ensure the accompanying overlay (e.g., bg-black/40, bg-white/30) maintains sufficient contrast for text and interactive elements.