Layout with fixed header and independently scrolling columns

Josh Sherman
3 min read
Software Development CSS

Update April 4th, 2019

Seems at some point between May of 2015 and now, the code in this post went terribly stale. It wasn’t working in either Firefox or Chrome and I’ve since updated the code with a working example.

Many thanks to everybody that blew up my comments about the issue.


My buddy Justin introduced me to flexbox a while back. Admittedly, I pushed off learning about it because it didn’t seem like the support was there at the time. While researching things for a redesign of SceneKids.com recently, I saw support for flexbox had improved dramatically. I’m quite fortunate that the majority of my users use Chrome ;)

Fast forward to a few months into me using flexbox pretty heavily. The running joke between Justin and I was that “you could use flexbox for that”. It was all fun and games until he brought a problem to me that he was trying to solve:

justin [9:01 PM] got a bitch of a CSS challenge

josh [9:01 PM] flexbox

justin [9:01 PM] two columns, that scroll independently, with a row on top

josh [9:02 PM] flexbox?

justin [9:02 PM] lol, don’t think flexbox has a fix for this one :wink:

In the words of Barney Stinson, “CHALLENGE ACCEPTED”. I proceeded to mock something up that satisfied the requirements. The header was to be fixed. There would be two columns of equal width. They also needed to fill the rest of the viewport. Flexbox made this all too easy:

The Markup

<!doctype html>
<html>
  <body>
    <div class="container">
      <div class="top">Fixed Top</div>
      <div class="content">
        <div class="left">
          Column 1...
          <br><br><br><br><br><br><br><br><br><br>
          <br><br><br><br><br><br><br><br><br><br>
          <br><br><br><br><br><br><br><br><br><br>
          <br><br><br><br><br><br><br><br><br><br>
          <br><br><br><br><br><br><br><br><br><br>
          <br><br><br><br><br><br><br><br><br><br>
          <br><br><br><br><br><br><br><br><br><br>
          <br><br><br><br><br><br><br><br><br><br>
          <br><br><br><br><br><br><br><br><br><br>
          ...with a bunch of content
        </div>
        <div class="right">Column 2</div>
      </div>
    </div>
  </body>
</html>

The Styles

body {
  margin: 0;
}
body,
html,
.container {
  height: 100%;
  max-height: 100%;
}
.top {
  background-color: red;
}
.left {
  background-color: green;
}
.right {
  background-color: blue;
}
.top,
.content div {
  padding: 20px;
}
.container,
.content {
  display: flex;
}
.container {
  flex-direction: column;
}
.content {
  overflow: hidden;
}
.content,
.content div {
  flex: 1;
}
.content div {
  overflow: auto;
}

What’s really awesome is that you can have any number of independently scrolling columns inside of .content. Any new div will be flex: 1 and will be distributed evenly with the rest of the columns.

Join the Conversation

Good stuff? Want more?

Weekly emails about technology, development, and sometimes sauerkraut.

100% Fresh, Grade A Content, Never Spam.

About Josh

Husband. Father. Pug dad. Musician. Founder of Holiday API, Head of Engineering and Emoji Specialist at Mailshake, and author of the best damn Lorem Ipsum Library for PHP.

Currently Reading

Parasie Eve

Previous Reads

Buy Me a Coffee Become a Sponsor

Related Articles