Reputation: 2612
I have a UI that has some elements with position: sticky;
on them. They have box shadows so that they look like they're floating over the text beneath them. I want to apply a blend mode to the box shadows, and that's causing me some problems.
What I want is to make it so that shadows never really get darker when they overlap. Currently, in mildly pathological cases, the sticky elements can pile up on top of each other, and the overlapping shadows become unattractively dark; I'd like to fix this. (I am also trying to mitigate those pathological cases, but I still want to fix the shadows.)
I can get the shadows to look the way I want using mix-blend-mode: darken;
, but it's not playing well with position: sticky;
.
Here is a JSBin of a few things I've tried. Each of the six examples contains identical markup; only the CSS is different. Sorry about the painfully teal background — it makes the problem easier to identify.
"badshadow" has the shadows as they are in my UI now. If you scroll the container down, you'll see elements pile up and the shadow becomes disagreeably dark. It's not the end of the world and I'll live if it's never fixed, but it could be better, I think.
"goodshadow" has the shadows as I'd like them to appear. Using mix-blend-mode: darken
on a ::before
, plus an opaque shadow color, seems to be doing a pretty good job of making the shadows "max out" at the desired darkness (they're excessively strong for demo purposes, of course, but you get the idea). But I had to set position: absolute;
to make this look right.
"sticky" is exactly like "goodshadow" except my elements are position: sticky;
, which is what I want. But this cancels my blend mode, so my shadows are now opaque and fully conceal the content that's shadowed, which is no good.
The next container is another "goodshadow" which is only there to demonstrate that Safari is wacky. Try it in Safari for a headscratcher. The behavior in the second "goodshadow" changes when you resize the sticky
container. Very weird, but not the main issue here. Moving on:
"isolated" is identical to "goodshadow" except for isolation: isolate;
on the absolutely-positioned elements. They now blend like sticky
does, so this confirms to me that (one of) the problem(s) is that position: sticky;
creates a new stacking context (per MDN).
"nobefore" has sticky positioning and my shadows working just the way I want, but because I'm no longer using ::before
to confine my mix-blend-mode: darken
to only the box shadows, my element contents are also blending with darken
which is also no good.
And in "doubleblend", I also have the shadows working, with ::before
, but only because I directly applied mix-blend-mode: darken
to the sticky element, which has the same issue as "nobefore".
My interpretation so far is that the sticky elements having their own stacking context means that, instead of the shadow blending with what's behind, the shadow blends with the element, and then the element + shadow blends with what's behind, which vitiates my mix-blend-mode: darken;
on only the shadow since that mix-blend-mode: darken;
is being applied to the blend of the shadow with the element, not the shadow to the background.
I think I understand the problem, but I don't see any great solutions. I suppose I could double all the sticky elements, having one with a shadow and mix-blend-mode: darken
and then one in front of it with no shadow and mix-blend-mode: normal
, but… is there a better way?
Upvotes: 0
Views: 92