Hide scrollable content behind transparent fixed position divs when scrolling the page?

I have a div called header that is set up with a fixed position. The problem is when I scroll the page the content of the page shows up behind the header (the header is transparent).

I know a lot about css, but cannot seem to figure this one out. I have tried setting overflow to hidden, but I knew it wouldn't work (and it didn't).

This is very hard to explain, so I did the best I could.

html:

<div id="header">
    <div id="topmenu">Home | Find Feeds | Subscriptions</div>
</div>
<div id="container">
    <div id="content">
        testing
    </div>
</div>

css:

#header {
    margin:0 auto;
    position: fixed;
    width:100%;
    z-index:1000;
}
#topmenu {
    background-color:#0000FF;
    height:24px;
    filter: alpha(opacity=50);
    opacity: 0.5;
}

#leftlinks {
    padding: 4px;
    padding-left: 10px;
    float: left;
}

#rightlinks {
    padding: 4px;
    padding-right: 10px;
    float: right;
}

#containerfixedtop {
    width: 100%;
    height: 20px;
}

#contentfixedtop {
    margin: 0 auto;
    background-color: #DAA520;
    width: 960px;
    height:20px;
}

#container {
    position: relative;
    top: 68px;
    width: 100%;
    height: 2000px;
    overflow: auto;
}

#content {
    margin: 0 auto;
    background-color: #DAA520;
    width: 960px;
    height: 2000px;
}

Here's a screenshot of the problem:

enter image description here


Just coming to this late, but in case anyone else runs across this in the future, here's your fix.

Your CSS Code:

.wrapper {
    width:100%;
    position:fixed;
    z-index:10;
    background:inherit;
}

.bottom-wrapper {
    width:100%;
    padding-top:92px;
    z-index:5;
    overflow:auto;
}

Your HTML:

<div class="wrapper">
    ...your header here...
</div>
<div class="bottom-wrapper">
    ...your main content here...
</div>

This will provide you with a header that cleanly matches your site, and floats at the top. The main content will scroll free of the header, and disappear when it passes the header. Your .bottom-wrapper padding-top should be the height of your header wrapper's content.

Cheers!


You are probably looking for z-index. It allows you to specify the vertical order of elements on the page, so an element with z-index: 10 is floating above (visually) an element with z-index: 5.

Give the content z-index: 5 and see if it works.


I was having a similar issue, and found a solution for my case. It should apply whether you are using a full screen background image, or a solid color (including white).

HTML

<div id="full-size-background"></div>
 <div id="header">
  <p>Some text that should be fixed to the top</p>
</div>
<div id="body-text">
  <p>Some text that should be scrollable</p>
</div>

CSS

#full-size-background {
z-index:-1;
background-image:url(image.jpg);
background-position:fixed;
position:fixed;
top:0px;
left:0px;
width:100%;
height:100%;
}
#header {
position:fixed;
background-image:url(image.jpg);
height:150px;
width:100%;
}
#body-text {
margin-top:150px;
}

This gives me the look of a full page image with a transparent fixed header and when the body content scrolls, it hides behind the header. The images appear seamless.

You could do the same thing with a solid color background, though, arguably, it would have been easier.

2 notes: the header has a set height, I have only tested in FF and Chrome.


Just came up with a new solution to this type of problem that I'm quite happy with.

Use clip-path on the content that needs to hide behind the transparent element. Then update the clip-path dynamically with js on window scroll.

HTML

<div id="sticky">Sticky content</div>
<div id="content">
  <!-- any html inside here will hide behind #sticky -->
</div>

JS

window.addEventListener("scroll",function(){
  const windowScrollTop = window.scrollTop;
  const elementToHide = document.getElementById("content");

  elementToHide.style.clipPath = `inset(${windowScrollTop}px 0 0 0)`;
});

Dynamic sticky content

In my case I had an element that I switched to position: sticky after scrolling past it. The #sticky content needs to be relative to the dom elements that came before it until we have scrolled far enough. Here's how I accounted for that:

HTML

<div id="otherStuff">Here's some other stuff</div>
<div id="sticky">Sticky content</div>
<div id="content">
  <!-- any html inside here will hide behind #sticky -->
</div>

JS

window.addEventListener("scroll",function(){
  const windowScrollTop = window.scrollTop;
  const stickyElement = document.getElementById("sticky");
  const elementToHide = document.getElementById("content");
  const stickyElementTop = stickyElement.getBoundingClientRect().top

  if(windowScrollTop >= stickyElementTop){
    stickyElement.style.position = "sticky";
    elementToHide.style.clipPath = `inset(${windowScrollTop - stickyElementTop}px 0 0 0)`;
  }
  else {
    stickyElement.style.position = "relative";
    elementToHide.style.clipPath = "none";
  }
});

Does #header have a set height?

#header {position: fixed; height: 100px; }
#container {position: absolute; top: 100px; bottom: 0; overflow: auto; }

Pretty sure this wouldn't work in IE though...