Menu

Tailwind CSS Backdrop Contrast

Backdrop Contrast allows you to control the contrast of whatever is visible behind a particular element. It works in conjunction with backdrop-filter, enabling dynamic designs where the background is partially visible yet visually differentiated.

Tailwind CSS simplifies this by providing a comprehensive set of utilities for managing backdrop contrast properties. With these utilities, you can easily manipulate how the background content behind an element is displayed—ensuring creative, impactful designs with minimal effort.

ClassPropertiesExample
backdrop-contrast-0backdrop-filter: contrast(0);<div className="backdrop-contrast-0"></div>
backdrop-contrast-50backdrop-filter: contrast(.5);<div className="backdrop-contrast-50"></div>
backdrop-contrast-75backdrop-filter: contrast(.75);<div className="backdrop-contrast-75"></div>
backdrop-contrast-100backdrop-filter: contrast(1);<div className="backdrop-contrast-100"></div>
backdrop-contrast-125backdrop-filter: contrast(1.25);<div className="backdrop-contrast-125"></div>
backdrop-contrast-150backdrop-filter: contrast(1.5);<div className="backdrop-contrast-150"></div>
backdrop-contrast-200backdrop-filter: contrast(2);<div className="backdrop-contrast-200"></div>

Overview of Backdrop Contrast

Adding the Backdrop Contrast

To start using backdrop contrast in Tailwind CSS, you can apply predefined contrast utilities to your components. Tailwind’s utilities allow smooth manipulation of the backdrop's clarity by varying its contrast levels.

This is a live editor. Play around with it!
export default function BackdropContrastComponent() {
  return (
    <div className="relative h-screen w-screen">
      <img
        src="https://images.unsplash.com/photo-1489269637500-aa0e75768394"
        alt="Backdrop"
        className="absolute h-full w-full object-cover"
      />
      {/* Applying backdrop contrast */}
      <div className="relative h-full w-full backdrop-contrast-50 flex items-center justify-center">
        <p className="text-white text-lg text-center px-10">Backdrop Contrast 50%</p>
      </div>
    </div>
  );
}

The backdrop-contrast-50 class sets the contrast to 50%. Modify the value from 50 to other levels, such as 25, 100, or higher, to experiment with different enhancement intensities.

Resetting Backdrop Filters

You can use backdrop-contrast-100 to reset the backdrop contrast. If you need to disable all backdrop effects, you can use backdrop-filter-none. This ensures no unintended filtering occurs, which is helpful when you are targeting multiple elements within the same container.

This is a live editor. Play around with it!
export default function ResetBackdropFilters() {
  return (
    <div className="relative h-screen w-screen">
      <img
        src="https://images.unsplash.com/photo-1489269637500-aa0e75768394"
        alt="Backdrop"
        className="absolute h-full w-full object-cover"
      />
      {/* Resetting backdrop contrast */}
      <div className="relative h-full w-full backdrop-contrast-50 backdrop-filter-none flex items-center justify-center">
        <p className="text-lg text-center bg-gray-200 rounded-sm px-6">No Backdrop Filters</p>
      </div>
    </div>
  );
}

States and Responsiveness

Hover and Focus States

Tailwind CSS provides utilities that allow you to apply backdrop contrast adjustments only under specific pseudo-classes such as hover and focus. This ensures interactivity and dynamic styling in your UI.

This is a live editor. Play around with it!
export default function HoverBackdropEffect() {
  return (
    <div className="relative h-screen w-screen">
      <img
        src="https://images.unsplash.com/photo-1489269637500-aa0e75768394"
        alt="Backdrop"
        className="absolute h-full w-full object-cover"
      />
      {/* Hover backdrop contrast */}
      <div className="relative h-full w-full hover:backdrop-contrast-50  flex items-center justify-center">
        <p className="text-lg text-center bg-gray-200 rounded-sm px-6">Hover to add Backdrop Contrast</p>
      </div>
    </div>
  );
}

Breakpoint Modifiers

Tailwind’s responsive modifiers enable you to apply backdrop contrast utilities dynamically based on screen sizes.

This is a live editor. Play around with it!
export default function ResponsiveBackdropEffect() {
  return (
    <div className="relative h-screen w-screen">
      <img
        src="https://images.unsplash.com/photo-1489269637500-aa0e75768394"
        alt="Backdrop"
        className="absolute h-full w-full object-cover"
      />
      {/* Responsive backdrop contrast */}
      <div className="backdrop-contrast-50 sm:backdrop-contrast-75 lg:backdrop-contrast-95 relative h-full w-full flex items-center justify-center">
        <p className="text-lg text-center bg-gray-200 rounded-sm px-6">The Backdrop Contrast will change according to the screens</p>
      </div>
    </div>
  );
}

Custom Backdrop Contrast

Extending the Theme

If the default contrast values in Tailwind don’t meet your design needs, you can configure custom levels. Extend the theme in your tailwind.config.js file under the backdropContrast section.

Once added, you can apply these custom levels just like any other utility class.

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

export default function CustomContrastComponent() {
  return (
    <div className="relative h-screen w-screen">
      <img
        src="https://images.unsplash.com/photo-1489269637500-aa0e75768394"
        alt="Backdrop"
        className="absolute h-full w-full object-cover"
      />
      <div className="relative h-full w-full backdrop-contrast-180  flex items-center justify-center">
        <p className="text-lg text-center bg-gray-200 rounded-sm px-6">Custom 180% Backdrop Contrast</p>
      </div>
    </div>
  );
}

Using Arbitrary Values

Tailwind CSS also empowers developers with arbitrary utility values, bypassing the need for configuration where quick adjustments are needed. Use this feature to specify exact contrast levels inline.

In the below example, the backdrop-contrast-[1.75] utility directly sets an 175% backdrop contrast.

This is a live editor. Play around with it!
export default function ArbitraryBackdropContrast() {
  return (
    <div className="relative h-screen w-screen">
      <img
        src="https://images.unsplash.com/photo-1489269637500-aa0e75768394"
        alt="Backdrop"
        className="absolute h-full w-full object-cover"
      />
      <div className="relative h-full w-full backdrop-contrast-[1.75]  flex items-center justify-center">
        <p className="text-lg text-center bg-gray-200 rounded-sm px-6">Arbitrary 175% Backdrop Contrast</p>
      </div>
    </div>
  );
}

Real World Examples

Product Showcase with Category Filters

This example demonstrates a product grid with category filters where backdrop contrast is applied to highlight the active filter.

This is a live editor. Play around with it!
export default function ProductShowcase() {
  const products = [
    {
      id: 1,
      name: "Premium Leather Bag",
      category: "accessories",
      price: "$299",
      src: "https://images.unsplash.com/photo-1547949003-9792a18a2601",
      alt: "Brown leather messenger bag"
    },
    {
      id: 2,
      name: "Wireless Headphones",
      category: "electronics",
      price: "$199",
      src: "https://images.unsplash.com/photo-1505740420928-5e560c06d30e",
      alt: "Black wireless headphones"
    },
    {
      id: 3,
      name: "Smart Watch",
      category: "electronics",
      price: "$299",
      src: "https://images.unsplash.com/photo-1523275335684-37898b6baf30",
      alt: "Modern smartwatch"
    },
    {
      id: 4,
      name: "Running Shoes",
      category: "sports",
      price: "$129",
      src: "https://images.unsplash.com/photo-1542291026-7eec264c27ff",
      alt: "Red running shoes"
    },
    {
      id: 5,
      name: "Vintage Camera",
      category: "electronics",
      price: "$399",
      src: "https://images.unsplash.com/photo-1516035069371-29a1b244cc32",
      alt: "Vintage film camera"
    },
    {
      id: 6,
      name: "Designer Sunglasses",
      category: "accessories",
      price: "$159",
      src: "https://images.unsplash.com/photo-1572635196237-14b3f281503f",
      alt: "Fashionable sunglasses"
    }
  ];

  return (
    <div className="min-h-screen bg-gray-100 p-8">
      <div className="backdrop-contrast-125 bg-white/30 p-6 rounded-lg">
        <div className="grid gap-6">
          {products.map((product) => (
            <div key={product.id} className="relative group">
              <img 
                src={product.src} 
                alt={product.alt}
                className="w-full h-64 object-cover rounded-lg"
              />
              <div className="absolute bottom-0 left-0 right-0 p-4 bg-black/50 backdrop-contrast-200 text-white">
                <h3 className="text-lg font-bold">{product.name}</h3>
                <p>{product.price}</p>
              </div>
            </div>
          ))}
        </div>
      </div>
    </div>
  );
}

This example shows a team member gallery with backdrop contrast effects on hover.

This is a live editor. Play around with it!
export default function TeamGallery() {
  const team = [
    {
      id: 1,
      name: "Sarah Johnson",
      role: "CEO",
      src: "https://images.unsplash.com/photo-1494790108377-be9c29b29330",
      alt: "Sarah Johnson CEO portrait"
    },
    {
      id: 2,
      name: "Michael Chen",
      role: "CTO",
      src: "https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d",
      alt: "Michael Chen CTO portrait"
    },
    {
      id: 3,
      name: "Emily Rodriguez",
      role: "Design Director",
      src: "https://images.unsplash.com/photo-1573496359142-b8d87734a5a2",
      alt: "Emily Rodriguez Design Director portrait"
    },
    {
      id: 4,
      name: "David Kim",
      role: "Lead Developer",
      src: "https://images.unsplash.com/photo-1500648767791-00dcc994a43e",
      alt: "David Kim Lead Developer portrait"
    },
    {
      id: 5,
      name: "Lisa Thompson",
      role: "Marketing Manager",
      src: "https://images.unsplash.com/photo-1438761681033-6461ffad8d80",
      alt: "Lisa Thompson Marketing Manager portrait"
    },
    {
      id: 6,
      name: "James Wilson",
      role: "Product Manager",
      src: "https://images.unsplash.com/photo-1472099645785-5658abf4ff4e",
      alt: "James Wilson Product Manager portrait"
    }
  ];

  return (
    <div className="bg-gray-900 p-8">
      <div className="grid gap-8">
        {team.map((member) => (
          <div 
            key={member.id} 
            className="relative group cursor-pointer"
          >
            <div className="overflow-hidden rounded-xl">
              <img 
                src={member.src} 
                alt={member.alt}
                className="w-full h-80 object-cover transition-transform group-hover:scale-110"
              />
              <div className="absolute inset-0 bg-black/40 group-hover:backdrop-contrast-150 transition-all">
                <div className="absolute bottom-0 p-6 text-white">
                  <h3 className="text-xl font-bold">{member.name}</h3>
                  <p className="text-gray-300">{member.role}</p>
                </div>
              </div>
            </div>
          </div>
        ))}
      </div>
    </div>
  );
}

This example showcases recipe cards with backdrop contrast effects for the description overlay.

This is a live editor. Play around with it!
export default function RecipeGallery() {
  const recipes = [
    {
      id: 1,
      name: "Spicy Thai Curry",
      difficulty: "Medium",
      time: "45 mins",
      src: "https://images.unsplash.com/photo-1455619452474-d2be8b1e70cd",
      alt: "Thai red curry with rice"
    },
    {
      id: 2,
      name: "Classic Margherita Pizza",
      difficulty: "Easy",
      time: "30 mins",
      src: "https://images.unsplash.com/photo-1513104890138-7c749659a591",
      alt: "Margherita pizza"
    },
    {
      id: 3,
      name: "Beef Wellington",
      difficulty: "Hard",
      time: "120 mins",
      src: "https://images.unsplash.com/photo-1544025162-d76694265947",
      alt: "Beef Wellington"
    },
    {
      id: 4,
      name: "Sushi Roll Platter",
      difficulty: "Expert",
      time: "90 mins",
      src: "https://images.unsplash.com/photo-1553621042-f6e147245754",
      alt: "Sushi rolls"
    },
    {
      id: 5,
      name: "Mediterranean Salad",
      difficulty: "Easy",
      time: "15 mins",
      src: "https://images.unsplash.com/photo-1540420773420-3366772f4999",
      alt: "Mediterranean salad"
    },
    {
      id: 6,
      name: "Chocolate Soufflé",
      difficulty: "Hard",
      time: "60 mins",
      src: "https://images.unsplash.com/photo-1551024506-0bccd828d307",
      alt: "Chocolate soufflé"
    }
  ];

  return (
    <div className="bg-white p-8">
      <div className="grid gap-8">
        {recipes.map((recipe) => (
          <div 
            key={recipe.id} 
            className="relative overflow-hidden rounded-2xl group"
          >
            <img 
              src={recipe.src} 
              alt={recipe.alt}
              className="w-full h-96 object-cover"
            />
            <div className="absolute inset-0 backdrop-contrast-75 bg-black/20 group-hover:backdrop-contrast-125 transition-all">
              <div className="absolute bottom-0 left-0 right-0 p-6 bg-gradient-to-t from-black/80 to-transparent">
                <h3 className="text-2xl font-bold text-white">{recipe.name}</h3>
                <div className="flex gap-4 mt-2 text-gray-200">
                  <span>{recipe.difficulty}</span>
                  <span>{recipe.time}</span>
                </div>
              </div>
            </div>
          </div>
        ))}
      </div>
    </div>
  );
}

Travel Destination Cards

This example displays travel destinations with backdrop contrast effects on the information overlay.

This is a live editor. Play around with it!
export default function TravelDestinations() {
  const destinations = [
    {
      id: 1,
      name: "Santorini, Greece",
      rating: 4.9,
      price: "$1,999",
      src: "https://images.unsplash.com/photo-1570077188670-e3a8d69ac5ff",
      alt: "Santorini white buildings and blue domes"
    },
    {
      id: 2,
      name: "Machu Picchu, Peru",
      rating: 4.8,
      price: "$2,499",
      src: "https://images.unsplash.com/photo-1587595431973-160d0d94add1",
      alt: "Machu Picchu ancient ruins"
    },
    {
      id: 3,
      name: "Tokyo, Japan",
      rating: 4.7,
      price: "$1,799",
      src: "https://images.unsplash.com/photo-1540959733332-eab4deabeeaf",
      alt: "Tokyo cityscape at night"
    },
    {
      id: 4,
      name: "Dubai, UAE",
      rating: 4.6,
      price: "$2,299",
      src: "https://images.unsplash.com/photo-1512453979798-5ea266f8880c",
      alt: "Dubai skyline"
    },
    {
      id: 5,
      name: "Maldives",
      rating: 4.9,
      price: "$3,499",
      src: "https://images.unsplash.com/photo-1514282401047-d79a71a590e8",
      alt: "Maldives water bungalows"
    },
    {
      id: 6,
      name: "Paris, France",
      rating: 4.7,
      price: "$1,899",
      src: "https://images.unsplash.com/photo-1502602898657-3e91760cbb34",
      alt: "Eiffel Tower in Paris"
    }
  ];

  return (
    <div className="bg-gray-100 p-8">
      <div className="grid gap-6">
        {destinations.map((destination) => (
          <div 
            key={destination.id} 
            className="relative group rounded-xl overflow-hidden"
          >
            <img 
              src={destination.src} 
              alt={destination.alt}
              className="w-full h-72 object-cover"
            />
            <div className="absolute inset-0 bg-gradient-to-t from-black/80 via-black/40 to-transparent backdrop-contrast-125 opacity-0 group-hover:opacity-100 transition-opacity">
              <div className="absolute bottom-0 p-6 text-white">
                <h3 className="text-xl font-bold">{destination.name}</h3>
                <div className="flex justify-between items-center mt-2">
                  <span className="flex items-center">{destination.rating}
                  </span>
                  <span className="text-xl font-semibold">{destination.price}</span>
                </div>
              </div>
            </div>
          </div>
        ))}
      </div>
    </div>
  );
}

This example shows a movie poster gallery with backdrop contrast effects for the movie information.

This is a live editor. Play around with it!
export default function MovieGallery() {
  const movies = [
    {
      id: 1,
      title: "The Dark Universe",
      genre: "Sci-Fi",
      rating: "PG-13",
      src: "https://images.unsplash.com/photo-1536440136628-849c177e76a1",
      alt: "Dark Universe movie poster"
    },
    {
      id: 2,
      title: "Lost in Time",
      genre: "Adventure",
      rating: "PG",
      src: "https://images.unsplash.com/photo-1535016120720-40c646be5580",
      alt: "Lost in Time movie poster"
    },
    {
      id: 3,
      title: "The Last Stand",
      genre: "Action",
      rating: "R",
      src: "https://images.unsplash.com/photo-1497124401559-3e75ec2ed794",
      alt: "The Last Stand movie poster"
    },
    {
      id: 4,
      title: "Summer Dreams",
      genre: "Romance",
      rating: "PG-13",
      src: "https://images.unsplash.com/photo-1517604931442-7e0c8ed2963c",
      alt: "Summer Dreams movie poster"
    },
    {
      id: 5,
      title: "Urban Legends",
      genre: "Horror",
      rating: "R",
      src: "https://images.unsplash.com/photo-1478720568477-152d9b164e26",
      alt: "Urban Legends movie poster"
    },
    {
      id: 6,
      title: "The Great Journey",
      genre: "Drama",
      rating: "PG",
      src: "https://images.unsplash.com/photo-1500462918059-b1a0cb512f1d",
      alt: "The Great Journey movie poster"
    }
  ];

  return (
    <div className="bg-black p-8">
      <div className="grid gap-8">
        {movies.map((movie) => (
          <div 
            key={movie.id} 
            className="relative group cursor-pointer"
          >
            <div className="overflow-hidden rounded-lg">
              <img 
                src={movie.src} 
                alt={movie.alt}
                className="w-full h-96 object-cover transition-transform group-hover:scale-105"
              />
              <div className="absolute inset-0 bg-black/50 backdrop-contrast-150 opacity-0 group-hover:opacity-100 transition-opacity">
                <div className="absolute bottom-0 p-6 text-white">
                  <h3 className="text-2xl font-bold">{movie.title}</h3>
                  <div className="flex gap-4 mt-2">
                    <span className="px-2 py-1 bg-white/20 rounded">{movie.genre}</span>
                    <span className="px-2 py-1 bg-white/20 rounded">{movie.rating}</span>
                  </div>
                </div>
              </div>
            </div>
          </div>
        ))}
      </div>
    </div>
  );
}

Customization Examples

Dynamic Product Showcase

This example demonstrates a product card with a hover effect that adjusts the backdrop contrast of the background image.

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

export default function ProductShowcase() {
  return (
    <div className="relative w-full h-screen flex items-center justify-center bg-gray-900">
      <div className="group relative w-96 h-[500px] overflow-hidden rounded-xl transition-all duration-300">
        <img
          src="https://images.unsplash.com/photo-1523275335684-37898b6baf30"
          alt="Product"
          className="absolute w-full h-full object-cover"
        />
        <div className="absolute inset-0 backdrop-contrast-125 group-hover:backdrop-contrast-175 backdrop-blur-sm bg-black/30 transition-all duration-300">
          <div className="p-8 text-white absolute bottom-0">
            <h2 className="text-3xl font-bold mb-2">Premium Watch</h2>
            <p className="text-gray-200">Limited Edition Collection</p>
            <button className="mt-4 px-6 py-2 bg-white text-black rounded-full hover:bg-gray-200">
              View Details
            </button>
          </div>
        </div>
      </div>
    </div>
  )
}

Interactive News Portal

This example shows a news portal layout with varying backdrop contrast levels for different content sections.

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

export default function NewsPortal() {
  return (
    <div className="grid grid-cols-2 gap-4 p-8 bg-gray-100">
      <div className="relative h-[600px] col-span-2 rounded-2xl overflow-hidden">
        <img
          src="https://images.unsplash.com/photo-1585829365295-ab7cd400c167"
          alt="Featured News"
          className="absolute w-full h-full object-cover"
        />
        <div className="absolute inset-0 backdrop-contrast-140 backdrop-brightness-75 bg-gradient-to-t from-black/60 to-transparent">
          <div className="absolute bottom-8 left-8 text-white">
            <span className="bg-red-600 px-4 py-1 rounded-full text-sm">Breaking</span>
            <h1 className="text-4xl font-bold mt-4 mb-2">Latest Headlines</h1>
            <p className="text-xl max-w-2xl">Your daily dose of current events and breaking news coverage</p>
          </div>
        </div>
      </div>
      
      {[1, 2].map((item) => (
        <div key={item} className="relative h-[300px] rounded-xl overflow-hidden">
          <img
            src={`https://images.unsplash.com/photo-${item === 1 ? '1495020689067-958852a7765e' : '1542831371-29b0f74f9713'}`}
            alt={`News ${item}`}
            className="absolute w-full h-full object-cover"
          />
          <div className="absolute inset-0 backdrop-contrast-80 hover:backdrop-contrast-190 transition-all duration-300 bg-black/20">
            <div className="p-6 text-white absolute bottom-0">
              <h3 className="text-2xl font-semibold">News Category {item}</h3>
              <p className="mt-2">Brief description of the news article</p>
            </div>
          </div>
        </div>
      ))}
    </div>
  )
}

This example creates an interactive gallery with different backdrop contrast effects based on user interaction.

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

export default function GalleryViewer() {
  return (
    <div className="min-h-screen bg-gray-900 p-12">
      <div className="grid gap-6">
        {[
          'photo-1501854140801-50d01698950b',
          'photo-1496449903678-68ddcb189a24',
          'photo-1501446529957-6226bd447c46'
        ].map((photoId, index) => (
          <div 
            key={index}
            className="group relative aspect-square rounded-lg overflow-hidden cursor-pointer"
          >
            <img
              src={`https://images.unsplash.com/${photoId}`}
              alt={`Gallery ${index + 1}`}
              className="absolute w-full h-full object-cover"
            />
            <div className="absolute inset-0 backdrop-contrast-85 group-hover:backdrop-contrast-165 transition-all duration-500">
              <div className="opacity-0 group-hover:opacity-100 transition-opacity duration-300 h-full flex flex-col justify-end p-6 bg-gradient-to-t from-black/60 to-transparent">
                <h3 className="text-white text-xl font-bold">Location {index + 1}</h3>
                <p className="text-gray-200 mt-2">Captured by Photographer {index + 1}</p>
                <div className="flex gap-2 mt-4">
                  <button className="px-4 py-2 bg-white/90 rounded-full text-sm hover:bg-white">
                    View Details
                  </button>
                  <button className="px-4 py-2 bg-black/50 text-white rounded-full text-sm hover:bg-black">
                    Save
                  </button>
                </div>
              </div>
            </div>
          </div>
        ))}
      </div>
    </div>
  )
}

Best Practices

Maintain Design Consistency

When you apply Backdrop Contrast utilities in Tailwind CSS, maintain a uniform design approach across your project to ensure a consistent look and feel. Avoid overusing multiple contrast levels within the same context, as this can dilute your design's hierarchy. For instance, if you're highlighting modal dialogs, choose one backdrop contrast level to distinguish that component and apply it consistently.

Additionally, align your Backdrop Contrast settings with your project's design system or style guide. For example, if you’re using a specific contrast level for overlays, ensure all overlays adhere to the same setting to align with brand guidelines. Consistency makes your UI more predictable and professional.

Lastly, test your design under varying conditions—such as different screen brightness settings or with contrasting background visuals—to ensure that your Backdrop Contrast choices retain their intended effect across environments.

Accessibility Considerations

Enhance Readability and Navigability

Backdrop Contrast directly impacts how text and visuals appear over background content. Always ensure sufficient contrast ratios between text and the backdrop to guarantee readability, especially for users with visual impairments. Combining backdrop-contrast with utilities like text-white or text-black can enhance legibility in most scenarios.

This is a live editor. Play around with it!
export default function ReadableCard() {
  return (
    <div className="bg-gray-700 p-8 h-screen grid place-items-center">
      <div className="relative w-80 h-48 bg-black/[0.7] backdrop-contrast-150 text-white p-6">
        <h2 className="text-xl font-bold">Readable Overlay</h2>
        <p className="text-gray-300 mt-2">Ensure text remains legible over intricate backdrops.</p>
      </div>
    </div>
  );
}

Evaluate your designs under different conditions (light/dark modes, high brightness) to ensure they retain usability for all audiences.