Search code examples
htmlcss

Have element behave like position sticky, but take it out of the document flow?


This seemed pretty easy to me, but I can't seem to get it working and found no real solution online. I have a page with a header, some content, and a sticky navigation bar, which is displayed as a (collapsed) burger menu on small viewports.

Basically, I want the header to disappear when scrolling down the page, and the sticky navigation bar/burger menu to scroll up below the header and then stay at the top of the page. The burger menu is floating to the right (i did that with flexbox, max-content and margin-left:auto).

Now, I'd like to take the sticky burger menu out of the document's flow in order for it to overlap the content section. This is what I can't get to work. I don't want to use position:fixed, as the burger menu should always stay below the header, and I can't use position:absolute, as the content section is quite long.

I've tried using float:right, but then the content-section and burger menu don't overlap at all. I can't position .sticky-navigation inside .div.content, as the content-section is using display:grid, and the navigation bar is collapsed to the burger menu before the grid is aligned in one column on a smaller breakpoint (as the burger menu would then take up a grid item, right?).

I'm completely clueless to how I can achieve this. I'd like to not use Javascript to achieve this, as it should be possible with just CSS? Also, I'm worried about performance taking a hit, especially on mobile devices. Does anybody have an idea how to get there?

Here's my codepen: https://codepen.io/alessandrov/pen/JjmaEgr

header {
  padding: 1rem;
  background: red;
}

.sticky-navigation {
  padding: 0.5rem;
  background: blue;
  position: sticky;
  display: flex;
  align-items: flex-end;
  justify-content: flex-end;
  max-width: 8rem;
  margin-left: auto;
  top: 1rem;
}

.content {
  background: green;
  padding: 1rem;
  padding-bottom: 15rem;
}

h1 {
  margin-bottom: 3rem;
}
<header>This is the header.</header>
<section class="content-section">
  <div class="sticky-navigation">
    <p class="burger">This is where the burger menu would go</p>
  </div>
  <div class="content">
    <h1>Big title</h1>
    <p>This is where all of the content would go. Repeated to simulate my page. This is where all of the content would go. Repeated to simulate my page. This is where all of the content would go. Repeated to simulate my page.
    </p>
 
</section>


Solution

  • You are close using float:right. You can add shape-outside so that your element doesn't take any place in the flow. inset(50%) will create a 0x0 rectangle

    header {
      padding: 1rem;
      background: red;
    }
    
    .sticky-navigation {
      padding: 0.5rem;
      background: blue;
      position: sticky;
      float: right;
      shape-outside: inset(50%);
      max-width: 8rem;
      margin-left: auto;
      top: 1rem;
    }
    
    .content {
      background: green;
      padding: 1rem;
      padding-bottom: 15rem;
    }
    <header>This is the header.</header>
    <section class="content-section">
      <div class="sticky-navigation">
        <p class="burger">This is where the burger menu would go</p>
      </div>
      <div class="content">
        <h1>Big title</h1>
        <p>This is where all of the content would go. Repeated to simulate my page. This is where all of the content would go. Repeated to simulate my page. This is where all of the content would go. Repeated to simulate my page.
        </p>
     </div>
    </section>