Maybe there kinda is background-opacity?

I was reading Jake’s “Cross-fading any two DOM elements is currently impossible” which is a wonderfully nerdy deep dive into how there is no real way to literally cross-fade elements. Yeah, you can animate both of their opacities, but even that isn’t quite the same. Turns out there is a Chrome/WebKit-only CSS function call called -webkit-cross-fade() that does the trick. MDN says it’s specced, but the implemented version differs, so it’s a bit of a mess… but it does exist:

.el {
  background: -webkit-cross-fade(url(img1.svg), url(img2.svg), 50%);
}

I didn’t even know that was a thing.

The first thing I thought of was: if one of the images was just a blank transparent image, wouldn’t that apply partial transparency to the other one? And thus it’s kind of a proxy for background-opacity (which doesn’t exist but feels like it should).

I gave it a test to see if it would work:

It seems to work! This is the meat of it:

.el {
  background-image: -webkit-cross-fade(
    url(image.jpg),
    url(data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7),
    50%
  );

That’s a 1px transparent GIF Base64 encoded.

It doesn’t work in Firefox but it does in everything else. Plus, you can test for support right in CSS and do something different if this isn’t just an enhancement.

@supports (background: -webkit-cross-fade(url(), url(), 50%)) {

  /* Only apply the idea if supported, do the Firefox fallback outside of this */

}

That’s baked into the demo above.