1

I'm trying to get box-shadows playing nicely with different backgrounds. The standard way seems to be using mix-blend-mode, and applying a fake div behind the real one with the effect.

An example of this technique here (click the + icon in the top right).

If I alter this code slightly to wrap the non-background elements into a container with position: fixed it breaks, example here. Note, position: absolute works fine.

I do need a structure like the example, a parent that's position-fixed and blend that can accommodate variable heights or widths and multiple instances of the .box element. I can hazard a rough guess why it doesn't work (fixed breaks it out of the doc flow and therefore there's nothing to blend), I can't see a way round it though.

Another example I made that reduces things a bit more, note how if you comment out position-fixed it works fine:

.blend {
  height: 100%;
  box-shadow: 0 4px 8px 0 rgba(156, 156, 156, 0.7);
  mix-blend-mode: multiply;
  position: absolute;
  height: 100%;
  width: 100%;
  top: 0;
}

.box {
  background: grey;
  min-height: 10px;
  width: 100%;
  position: relative;
  margin: 0 0 15px;
}

.container {
  /* using absolute works */
  position: absolute;
  /* using fixed does not work */
  position: fixed;
  height: 50%;
  width: 50%;
}

html {
  height: 100%;
}
body {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 100%;
  margin: 0;
}

.column {
  position: relative;
  width: 50%;
  height: 100%;
}

.left {
  background: #2D2D2D;
}

.right {
  background: #f6f6f6;
}
<div class="column left"></div>
<div class="column right"></div>

<div class="container">
  <div class="box">
    text
    <div class="blend"></div>
  </div>
  <div class="box">
    text<br /><br />more text
    <div class="blend"></div>
  </div>
</div>

(I saw a previous question, which looks along similar lines but I couldn't get their example to work to check)

atomictom
  • 1,637
  • 16
  • 14
  • I think your assumption of removing it from the document flow is correct (eg browser doesn't know what to blend), but I can't find any documentation that would prove it. – Bryce Howitson Nov 05 '18 at 16:24

2 Answers2

2

You can move the blend element out of the container and make it fixed with the same dimensions as container.

Checkout the snippet:

<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>

html{
  height:100%;
}

body {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 100%;
  margin: 0;
}

.column {
  position: relative;
  width: 50%;
  height: 100%;
}

.left {
  background: #2D2D2D;
}

.right {
  background: #f6f6f6;
}

.blend {
  box-shadow: 0 4px 8px 0 rgba(156, 156, 156, 0.7);
  mix-blend-mode: multiply;
  position: fixed;
  height: 50%;
  width: 50%;
}

.box {
  background: grey;
  height: 100%;
  width: 100%;
  position: absolute;
}

.container {
  position: fixed;
  height: 50%;
  width: 50%;
}


</style>
</head>
<body>

<div class="column left"></div>
<div class="column right"></div>

<div class="blend"></div>
<div class="container">
 
  <div class="box">
    text
  </div>
</div>

</body>
</html>
  • Thanks for your response, I wasn't clear enough but i need the blend to work with multiple elements, and when it doesn't know the heights/widths etc. I've updated my question to try and clarify that :) – atomictom Nov 05 '18 at 18:43
  • Have you tried the isolation property? Maybe you could find a work arround with it. – Diego Alfaro Nov 05 '18 at 20:54
  • Good tip, I hadn't heard of the property but it's purpose seems to be to stop blending an element _behind_ the element with `mix-blend-mode`, whereas in this case it would be useful to ignore certain child elements in-front. But yeah, I think the issue is to do with Stacking Contexts, but I'm not sure there's a way to manipulate them to my advantage – atomictom Nov 06 '18 at 16:33
1

3.2. Behavior specific to HTML

Everything in CSS that creates a stacking context must be considered an ‘isolated’ group. HTML elements themselves should not create groups. An element that has blending applied, must blend with all the underlying content of the stacking context that that element belongs to.

Eg. position: fixed will create a stacking context (isolated group).

https://drafts.fxtf.org/compositing-1/#csscompositingrules_CSS

Related answer more specific on stacking context: https://stackoverflow.com/a/56545440/7947839

cdoublev
  • 709
  • 6
  • 18