11

I'd like an elegant way to "collect" multi-level headers at the top of the window as the user scrolls, and position:sticky gets me 90% of the way there. The snippet below works just as I'd like it to with one exception: when Header 2b reaches the top, Header 3b is still visible. Since Header 3b is meant to be a "child" of Header 2a, I'd like it to either scroll away or somehow be hidden once Header 2b reaches the top. (Predictably, Header 1b and Header 2d both have the same issue.)

I know that what I have here is how the CSS is supposed to work, but is there an elegant way to make it work the way I'm asking? I've tried giving p a background-color of white and messing with z-index but I haven't had any luck.

h1, h2, h3 {
  position: -webkit-sticky;
  position: sticky;
  top: 0px;
}

h1 {
  background-color: red;
  height: 35px;
}
h2 {
  background-color: blue;
  height: 25px;
  top: 35px;
}
h3 {
  background-color: green;
  height: 20px;
  top: 60px;
}
<h1>Header 1a</h1>
<p>Lorem ipsum dolor sit amet, no qui quis eloquentiam.</p>
<h2>Header 2a</h2>
<p>Lorem ipsum dolor sit amet, no qui quis eloquentiam.</p>
<h3>Header 3a</h3>
<p>Lorem ipsum dolor sit amet, no qui quis eloquentiam.</p>
<h3>Header 3b</h3>
<p>Lorem ipsum dolor sit amet, no qui quis eloquentiam.</p>
<h2>Header 2b</h2>
<p>Lorem ipsum dolor sit amet, no qui quis eloquentiam.</p>
<h3>Header 3c</h3>
<p>Lorem ipsum dolor sit amet, no qui quis eloquentiam.</p>
<h3>Header 3d</h3>
<p>Lorem ipsum dolor sit amet, no qui quis eloquentiam.</p>
<h1>Header 1b</h1>
<p>Lorem ipsum dolor sit amet, no qui quis eloquentiam.</p>
<h2>Header 2c</h2>
<p>Lorem ipsum dolor sit amet, no qui quis eloquentiam.</p>
<h3>Header 3e</h3>
<p>Lorem ipsum dolor sit amet, no qui quis eloquentiam.</p>
<h3>Header 3f</h3>
<p>Lorem ipsum dolor sit amet, no qui quis eloquentiam.</p>
<h2>Header 2d</h2>
<p>Lorem ipsum dolor sit amet, no qui quis eloquentiam.</p>
<h3>Header 3g</h3>
<p>Lorem ipsum dolor sit amet, no qui quis eloquentiam.</p>
<h3>Header 3h</h3>
<p>Lorem ipsum dolor sit amet, no qui quis eloquentiam.</p>

2 Answers 2

16

I think the logical way to do this is to consider nested divs like below:

h1,
h2,
h3 {
  position: -webkit-sticky;
  position: sticky;
  top: 0px;
  margin:0;
}

h1 {
  background-color: red;
  height: 35px;
  z-index:3;
}

h2 {
  background-color: blue;
  height: 25px;
  top:35px;
  z-index:2;
}

h3 {
  background-color: green;
  height: 20px;
  top:60px;
  z-index:1;
}
<div>
  <h1>Header 1a</h1>
  <p>Lorem ipsum dolor sit amet, no qui quis eloquentiam.</p>
  <div>
    <h2>Header 2a</h2>
    <p>Lorem ipsum dolor sit amet, no qui quis eloquentiam.</p>
    <div>
      <h3>Header 3a</h3>
      <p>Lorem ipsum dolor sit amet, no qui quis eloquentiam.</p>
      <h3>Header 3b</h3>
      <p>Lorem ipsum dolor sit amet, no qui quis eloquentiam.</p>
    </div>
  </div>
  <div>
    <h2>Header 2b</h2>
    <p>Lorem ipsum dolor sit amet, no qui quis eloquentiam.</p>
    <div>
      <h3>Header 3c</h3>
      <p>Lorem ipsum dolor sit amet, no qui quis eloquentiam.</p>
      <h3>Header 3d</h3>
      <p>Lorem ipsum dolor sit amet, no qui quis eloquentiam.</p>
    </div>
  </div>
</div>
<div>
  <h1>Header 1b</h1>
  <p>Lorem ipsum dolor sit amet, no qui quis eloquentiam.</p>
  <div>
    <h2>Header 2c</h2>
    <p>Lorem ipsum dolor sit amet, no qui quis eloquentiam.</p>
    <div>
      <h3>Header 3e</h3>
      <p>Lorem ipsum dolor sit amet, no qui quis eloquentiam.</p>
      <h3>Header 3f</h3>
      <p>Lorem ipsum dolor sit amet, no qui quis eloquentiam.</p>
    </div>
  </div>
  <div>
    <h2>Header 2d</h2>
    <p>Lorem ipsum dolor sit amet, no qui quis eloquentiam.</p>
    <div>
      <h3>Header 3g</h3>
      <p>Lorem ipsum dolor sit amet, no qui quis eloquentiam.</p>
      <h3>Header 3h</h3>
      <p>Lorem ipsum dolor sit amet, no qui quis eloquentiam.</p>
    </div>
  </div>
</div>

1
  • 2
    Just what I was looking for. I think I had gotten close to this but my nesting was off. Thanks for the help.
    – TobyRush
    Commented May 2, 2019 at 13:01
1

You need to use the 'z-index' tag in order to do so. First header should have lower z-index value than any other header. The last header should have the highest z-index value. z-index tag is used to put the elements below or above any other elements.

2
  • Thanks! I wondered if that might be part of it, but figured I'd have to involve the white space in between the headers to "cover up" the undesired header. Looks like Temani's solution handles that with divs.
    – TobyRush
    Commented May 2, 2019 at 13:00
  • Sometimes it happens, it's not supposed to work like you said. May be other piece of code is interfering with it. Commented May 2, 2019 at 14:24

Not the answer you're looking for? Browse other questions tagged or ask your own question.