Search code examples
htmlcss

Have a sticky navbar on top of containing blocks


I have now been scratching my head a long time as to how to make a sticky navbar on top of the content of the page.

I have a webpage that contains a header, a main block, and a footer.

I want the main block to have a navbar to navigate easily among the different sections of its content. This navbar needs to be always accessible to the user while they are navigating inside the main block, which is why I want to make it sticky.

What makes it difficult though, is that I want the navbar to be on top of the content of the main block, to allow each section of the main block to have a background-color that extends to the full width of the page.

In the following example, I recreated something approaching what I want, except that each main content block needs to extend to the full width of the page.

How would I go about this?

.header,
.footer {
  background-color: silver;
  height: 40vh;
}

.main {
  display: flex;
}

.nav > .navcontent {
  position: sticky;
  top: 0;
}

.content > .block {
  height: 80vh;
  padding-left: 20%;
  padding-right: 20%;
}

.content > .block.-b1 {
  background-color: aqua;
}

.content > .block.-b2 {
  background-color: teal;
}

.content > .block.-b3 {
  background-color: blue;
}
<header class="header">
  <h1>Header</h1>
</header>
<main class="main">
  <div class="content">
    <div class="block -b1">
      <h1>My content</h1>
      <p>Integer interdum varius diam. Nam aliquam  velit a pede. Vivamus dictum nulla et wisi. Vestibulum a massa.  Donec vulputate nibh vitae risus dictum varius. Nunc suscipit, nunc  nec facilisis convallis, lacus ligula bibendum nulla, ac  sollicitudin sapien nisl fermentum velit. Lorem ipsum dolor sit  amet, consectetuer adipiscing elit. Nullam commodo dui ut augue  molestie scelerisque. Sed aliquet rhoncus tortor. Fusce laoreet,  turpis a facilisis tristique, leo mauris accumsan tellus, vitae  ornare lacus pede sit amet purus. Sed dignissim velit vitae ligula.  Sed sit amet diam sit amet arcu luctus ullamcorper.</p>
    </div>
    <div class="block -b2">
      <p>Integer interdum varius diam. Nam aliquam  velit a pede. Vivamus dictum nulla et wisi. Vestibulum a massa.  Donec vulputate nibh vitae risus dictum varius. Nunc suscipit, nunc  nec facilisis convallis, lacus ligula bibendum nulla, ac  sollicitudin sapien nisl fermentum velit. Lorem ipsum dolor sit  amet, consectetuer adipiscing elit. Nullam commodo dui ut augue  molestie scelerisque. Sed aliquet rhoncus tortor. Fusce laoreet,  turpis a facilisis tristique, leo mauris accumsan tellus, vitae  ornare lacus pede sit amet purus. Sed dignissim velit vitae ligula.  Sed sit amet diam sit amet arcu luctus ullamcorper.</p>
    </div>
    <div class="block -b3">
      <p>Integer interdum varius diam. Nam aliquam  velit a pede. Vivamus dictum nulla et wisi. Vestibulum a massa.  Donec vulputate nibh vitae risus dictum varius. Nunc suscipit, nunc  nec facilisis convallis, lacus ligula bibendum nulla, ac  sollicitudin sapien nisl fermentum velit. Lorem ipsum dolor sit  amet, consectetuer adipiscing elit. Nullam commodo dui ut augue  molestie scelerisque. Sed aliquet rhoncus tortor. Fusce laoreet,  turpis a facilisis tristique, leo mauris accumsan tellus, vitae  ornare lacus pede sit amet purus. Sed dignissim velit vitae ligula.  Sed sit amet diam sit amet arcu luctus ullamcorper.</p>
    </div>
  </div>
  <nav class="nav">
    <ul class="navcontent">
      <li>Link 1
      <li>Link 2
      <li>Link 3
    </ul>
  </nav>
</main>
<footer class="footer">
  <h1>Footer</h1>
</footer>


Solution

  • To solve that, I would probably use display: grid, and define overlapping areas for .content and .nav using grid-template-columns.

    That is likely the most flexible solution regarding the HTML structure and styling.

    And I would use a variable for the width of the navigation so that you could also use it for the padding on the right of your content.

    That variable then could be changed with a media query depending on the screen size.

    :root {
      --nav-width : 150px;
    }
    
    
    .header,
    .footer {
      background-color: silver;
      height: 40vh;
    }
    
    .main {
      display: grid;
      grid-template-columns: [content-start] 1fr [nav-start] var(--nav-width) [content-end nav-end];
    }
    
    .nav {
      grid-area: nav;
    }
    
    .content {
      grid-area: content;
    }
    
    .nav>.navcontent {
      position: sticky;
      top: 0;
    }
    
    .content>.block {
      min-height: 80vh;
      padding-left: 20%;
      padding-right: calc( 20% + var(--nav-width));
    }
    
    .content>.block.-b1 {
      background-color: aqua;
    }
    
    .content>.block.-b2 {
      background-color: teal;
    }
    
    .content>.block.-b3 {
      background-color: blue;
    }
    <header class="header">
      <h1>Header</h1>
    </header>
    <main class="main">
      <nav class="nav">
        <ul class="navcontent">
          <li>Link 1
          <li>Link 2
          <li>Link 3
        </ul>
      </nav>
      <div class="content">
        <div class="block -b1">
          <h1>My content</h1>
          <p>Integer interdum varius diam. Nam aliquam velit a pede. Vivamus dictum nulla et wisi. Vestibulum a massa. Donec vulputate nibh vitae risus dictum varius. Nunc suscipit, nunc nec facilisis convallis, lacus ligula bibendum nulla, ac sollicitudin
            sapien nisl fermentum velit. Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Nullam commodo dui ut augue molestie scelerisque. Sed aliquet rhoncus tortor. Fusce laoreet, turpis a facilisis tristique, leo mauris accumsan tellus, vitae
            ornare lacus pede sit amet purus. Sed dignissim velit vitae ligula. Sed sit amet diam sit amet arcu luctus ullamcorper.</p>
        </div>
        <div class="block -b2">
          <p>Integer interdum varius diam. Nam aliquam velit a pede. Vivamus dictum nulla et wisi. Vestibulum a massa. Donec vulputate nibh vitae risus dictum varius. Nunc suscipit, nunc nec facilisis convallis, lacus ligula bibendum nulla, ac sollicitudin
            sapien nisl fermentum velit. Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Nullam commodo dui ut augue molestie scelerisque. Sed aliquet rhoncus tortor. Fusce laoreet, turpis a facilisis tristique, leo mauris accumsan tellus, vitae
            ornare lacus pede sit amet purus. Sed dignissim velit vitae ligula. Sed sit amet diam sit amet arcu luctus ullamcorper.</p>
        </div>
        <div class="block -b3">
          <p>Integer interdum varius diam. Nam aliquam velit a pede. Vivamus dictum nulla et wisi. Vestibulum a massa. Donec vulputate nibh vitae risus dictum varius. Nunc suscipit, nunc nec facilisis convallis, lacus ligula bibendum nulla, ac sollicitudin
            sapien nisl fermentum velit. Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Nullam commodo dui ut augue molestie scelerisque. Sed aliquet rhoncus tortor. Fusce laoreet, turpis a facilisis tristique, leo mauris accumsan tellus, vitae
            ornare lacus pede sit amet purus. Sed dignissim velit vitae ligula. Sed sit amet diam sit amet arcu luctus ullamcorper.</p>
        </div>
      </div>
    </main>
    <footer class="footer">
      <h1>Footer</h1>
    </footer>