cornflakes24 cornflakes24 - 5 months ago 26
CSS Question

Scrollable content with fixed header

I would like to have a container with a fixed header and scrollable content. Here is the HTML and CSS I have set up for this

HTML:

<div class="container">
<div class="header">Header</div>
<div class="content">
<ul>
<li>Content</li>
<li>Content</li>
...
</ul>
</div>
<div>


CSS:

.container {
margin-top: 200px;
}

.header {
position: fixed;
width: 100%;
height: 20px;
background-color: blue;
color: white;
}

.content {
padding-top: 20px;
height: 250px;
background-color: grey;
overflow: auto;
}


Link to codepen: http://codepen.io/robkom/pen/XKMQGM

As you can see, the header is fixed and overlaps the scrollbar (when visible). What I want is for the scrollbar to push the header to the left (like it does with the content) and still remain at the top of the container when I scroll.

Fixed elements are removed from the normal document flow and positioned relative to the viewport, so I'm not sure if a solution using
position: fixed
is viable, but is there any way to achieve this result?

Answer

Here is a trick, using a wrapper in the header.

I forced scroll on the header, making the wrapper size according to content, then I simply increased the header with 50px to make sure all the different browsers' scroll bar sizes are covered and used the same amount on the wrapper to push it back into view.

Doing it like this, you don't have to worry about individual scroll bar width adjustment (or use script).

I also changed the header to absolute position so it positions with the container, but you can of course switch back to fixed if you need that.

Updated

Firefox doesn't show scroll bar for small heights, so adding margin/padding-top as shown below makes it work

html, body {
  margin: 0;
}
.container {
  position: relative;
  overflow-x: hidden;
  margin-top: 0px;
}
.header {
  position: absolute;
  overflow-y: scroll;
  width: calc(100% + 50px);
  height: 20px;
  margin-top: -20px;   /* Firefox doesn't show scrollbar for small   */
  padding-top: 20px;   /* heights, so these two lines make it work  */
}
.header .wrapper {
  width: calc(100% - 50px);
  height: 100%;
  background-color: red;
  color: white;
}

.content {
  padding-top: 20px;
  height: 200px;
  background-color: grey;
  overflow: auto;
}
<div class="container">
  <div class="header">
    <div class="wrapper">
      Header      
    </div>
  </div>
  <div class="content">
    <ul>
      <li>Content</li>
      <li>Content</li>
      <li>Content</li>
      <li>Content</li>
      <li>Content</li>
      <li>Content</li>
      <li>Content</li>
      <li>Content</li>
      <li>Content</li>
      <li>Content</li>
      <li>Content</li>
      <li>Content</li>
      <li>Content</li>
      <li>Content</li>
      <li>Content</li>
      <li>Content</li>
    </ul>
  </div>
<div>