0

Example image demonstrating what I need

If you see the image above, There is a parent container that has a background image applied which is a gradient. It is divided into 2 subdivs stacked vertically. one of those divs contains a red div and a blue div that are absolutely positioned. The blue div is supposed to act like a mask that covers the contents only of subdiv2. It is anchored to something else in subdiv2 (not in image) so it moves if that "something" moves. If it happens to cover the red div, it's supposed to hide the red div while retaining the gradient background.Is there a way to achieve this using css ?

If the gradient didn't exist, One would inherit background color down the chain and the blue div would simply hide the red div. If you inherit the background-image, we get a split gradient in the 2 subdivs which is not correct. If we keep the backgrounds of the 2 subdivs transparent, I know of no way for the blue div to hide the red div.

Thanks!

EDIT : Sorry for not specifying earlier. My bad. I've changed the wording to ensure you guys understand the fact that the blue div doesn't ALWAYS cover the red div otherwise the solution would be simple.

Proteen
  • 13
  • 2

3 Answers3

0

You can check this example out. You can use

background: inherit

on the blue div after setting the z-index of the red div as -1.

Using background inherit on the blue div will help it in not loosing transparency and will vanish the red div. And using z-index:-1 on red div will push it behind the blue div.

Rahul
  • 301
  • 1
  • 2
  • 5
  • Thanks for the answer! This would've worked for homogeneous backgrounds. Since I have a gradient background, when the 2 subdivs (and the blue div) inherit it, the gradient gets split and looks completely uneven. So this solution won't work for me. – Proteen Feb 19 '19 at 19:53
0

If the parent div has background:transparent, it will give you the desired effect. The tough part is getting the parent "in front of" the child. I was able to do it by setting a negative z-index on the child, but you might require something else. Without seeing your markup I can't be sure.

document.getElementById('toggle').onclick = () => {
  const inner = document.getElementById('inner');
  const style = window.getComputedStyle(inner);
  const index = style.getPropertyValue('z-index');
  document.getElementById('inner').style.zIndex = index === "-1" ? "0" : "-1";
}
.bg {
  width:600px;
  height:400px;
  background:url(http://placekitten.com/600/400);
}

.div1 {
  height:200px;
  border: 2px solid red;
}

.div2 {
  position:relative;
}

.subdiv2 {
  position:absolute;
  left:40%;
  top:80px;
  height:80px;
  width:200px;
  border: 2px solid blue;
  background:transparent;
}

#inner {
  position:absolute;
  top:10px;
  left:80px;
  width:60px;
  height:60px;
  background:red;
  z-index:-1;
}
<div class="bg">
  <div class="div1"></div>
  <div class="div2">
    <div class="subdiv2">
      <div id="inner"></div>
    </div>
  </div>
</div>
<button id="toggle">toggle z-index</button>
nvioli
  • 4,137
  • 3
  • 22
  • 38
0

z-index seems like a bad solution to this problem. You CAN animate the z-index value BUT it's still going to look kinda funny as the elements change depth and pass between each other.

If the goal is to visually "hide" content with its parent background, isn't transparency the same result? Or am I missing something about the goal?

I would suggest:

// hidden state
.redDiv {
 opacity:0;
 transition: opacity 0.5s linear;
}

// visible state
.redDiv.visibleState {
 opacity:1;
}

You can do real masking in CSS but I tend to reserve that for complex shapes.

Bryce Howitson
  • 7,339
  • 18
  • 40