Layout with fixed header and independently scrolling columns

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 😉

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.

Josh Sherman - The Man, The Myth, The Avatar

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.


If you found this article helpful, please consider buying me a coffee.