Search code examples
htmlcssflexboxmarkup

How to implement the following markup with sticky header and footer using flexbox?


I'm learning CSS flexbox at the moment and I want to implement this markup:

enter image description here

  1. I want the header and footer to be "sticky" (header is always on top and footer is always in the bottom).
  2. If article or aside1 or aside2 size doesn't fit the page I want the area between header and footer to be scrollable.

So my plan was:

  1. Create the container element with display: flex and column direction for it's items
  2. It will contain 3 items: header, footer and the { aside1, article and aside2 } which will be wrapped into another container.
  3. This another container will have the display: flex itself with row direction for it's items: aside, article and aside2

My markup is very straightforward:

<div class="wrapper">
  <header>This is header</header>
  
  <div class="content">
    <aside>aside1</aside>
    <article>article</article>
    <aside>aside2</aside>
  </div>

  <footer>This is footer</footer>
</div>

And here are the styles:

html, body {
  height: 100%;
}

/* Main wrapper, sizes = 100% to fit the viewport */
.wrapper {
  width: 100%;
  height: 100%;
  display: flex;
  border: solid 1px black;
  flex-direction: column;
}

/* Just some styling, ignore this */
header,
article,
aside,
footer {
  border: solid 1px #888;
  padding: 1rem;
  text-align: center;
}

header {
  background-color: #cfffff;
}

/* flex: 1 makes it "stretch" allowing header and footer
to have their default sizes  */
.content {
  display: flex;
  flex: 1;
  overflow-y: scroll;
}

aside {
  box-sizing: border-box;
  vertical-align: top;
  background-color: #cfffcf;
  width: 250px;
}

article {
  background-color: #ffcfff;
  flex: 1;
}

footer {
  background-color: #ffffcf;
}

The problem is that whenever article content overflows the container, the scrolling is not the way I expect it to be:

enter image description here

I want to understand:

  1. Why this is happening?
  2. What is the correct way to do this?

Solution

  • Use the new Style

    position: sticky;
    

    html, body {
      height: 100vh;
    }
    
    /* Main wrapper, sizes = 100% to fit the viewport */
    .wrapper {
      width: 100%;
      display: flex;
      border: solid 1px black;
      flex-direction: column;
    }
    
    /* Just some styling, ignore this */
    header,
    article,
    aside,
    footer {
      border: solid 1px #888;
      padding: 1rem;
      text-align: center;
    }
    
    header {
      background-color: #cfffff;
      position: sticky;
      top:0;
    }
    
    /* flex: 1 makes it "stretch" allowing header and footer
    to have their default sizes  */
    .content {
      display: flex;
      flex: 1;
    }
    
    aside {
      box-sizing: border-box;
      vertical-align: top;
      background-color: #cfffcf;
      width: 250px;
    }
    
    article {
      background-color: #ffcfff;
      flex: 1;
    }
    
    footer {
    position: sticky;
    bottom:0;
      background-color: #ffffcf;
    }
    <div class="wrapper">
      <header>This is header</header>
      
      <div class="content">
        <aside>aside1</aside>
        <article>article</article>
        <aside>Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.</aside>
      </div>
    
      <footer>This is footer</footer>
    </div>