64

I have a position: fixed div in a layout, as a sidebar. I've been asked to have part of it's content stay fixed to the top of it (internally), and the rest to scroll if it overflows the bottom of the div.

I've had a look at this answer, however the solution presented there doesn't work with position: fixed or position: absolute containers, which is a pain.

I've made a JSFiddle demonstration of my problem here. The large amount of text should ideally scroll, instead of overflowing into the bottom of the page. The height of the header can vary with content, and may be animated.

body {
    background: #eee;
    font-family: sans-serif;
}

div.sidebar {
    padding: 10px;
    border: 1px solid #ccc;
    background: #fff;
    position: fixed;
    top: 10px;
    left: 10px;
    bottom: 10px;
    width: 280px;
}
div#fixed {
    background: #76a7dc;
    padding-bottom: 10px;
    color: #fff;
}

div#scrollable {
    overlow-y: scroll;
}
<div class="sidebar">
    <div id="fixed">
        Fixed content here, can be of varying height using jQuery $.animate()        
    </div>

    <div id="scrollable">
        Scrolling content<br><br>
        Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse
cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non
proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
        
        Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse
cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non
proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
        Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse
cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non
proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
        Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse
cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non
proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
    </div>
</div>

Without a fixed header, I can simply add overflow-y: scroll to div.sidebar and I can happily scroll all it's content if it overflows the bottom of the container. However, I'm running into issues with having a fixed, variable height header at the top of the sidebar, and having any content underneath that scroll if it's too long to fit into the container.

div.sidebar must stay position: fixed, and I would very much like to do this without any hacks, as well as make it as cross browser as possible. I've attempted various things, but none of them work, and I'm unsure as to what to try from here.

How can I make a div inside a position: fixed container scroll only in the Y direction when it's content overflows the containing div, with a fixed header of varying, indeterminate height? I'd very much like to stay away from JS, but if I have to use it I will.

Liam
  • 27,717
  • 28
  • 128
  • 190
Bojangles
  • 99,427
  • 50
  • 170
  • 208
  • I am not sure if a pure css solution exists for this. Basically your trying to fix the div#fixed, however when you do that your taking it out of the normal flow of the document so the height will not push other elements down the page. – Kevin Bowersox Apr 14 '12 at 14:38
  • Considering the non-scrolling div is at the top of the sidebar's content, it doesn't have to be `position: fixed` - it can just sit in normal flow. I want to know if there's a way to push the top of the `overflow: scroll` element down by the height of the non-scrolling div. It's not actually `position: fixed`. I meant "fixed" as in "does not scroll with overflow". – Bojangles Apr 14 '12 at 14:40
  • it appears you made some progress on your fiddle, if you remove the bottom property on div#sidebar the div will expand to fit the content – Kevin Bowersox Apr 14 '12 at 15:28
  • Why can't the sidebar be absolute or relative position? You want it to scroll with the page right? Not, put scrollbars on the sidebar? – Kevin Bowersox Apr 14 '12 at 15:37
  • Sorry, I forgot to add that in - the sidebar does not scroll, and always stretches to fit the window. – Bojangles Apr 14 '12 at 16:24

5 Answers5

87

It seems to work if you use

div#scrollable {
    overflow-y: scroll;
    height: 100%;
}

and add padding-bottom: 60px to div.sidebar.

For example: http://jsfiddle.net/AKL35/6/

However, I am unsure why it must be 60px.

Also, you missed the f from overflow-y: scroll;

FrogInABox
  • 1,034
  • 1
  • 8
  • 8
  • 1
    It works with `padding-top: 50px` because the blue header is exactly 50px in height. I want to allow that header to be variable in height, although it's becoming apparent the only way I can solve this issue is to use JavaScript, which I'd rather not do. – Bojangles Apr 14 '12 at 17:18
  • this doesn't work with older browsers, such as Mobile Safari for iOS 4.2, or Android 2.3. If anyone has a solution - post it! – mheavers Apr 30 '13 at 15:23
  • 5
    Also, use `overflow: auto` instead as it will only show the scrollbar if there *is* overflow. – Adam Grant Aug 17 '15 at 22:39
  • 3
    For smooth scrolling on ios/android if you are experiencing laggy scrolling ensure you set `-webkit-overflow-scrolling: touch`...useful in cordova base applications or other frameworks. – greaterKing Oct 12 '16 at 16:00
6

What worked for me :

div#scrollable {
    overflow-y: scroll;
    max-height: 100vh;
}
Julien
  • 2,616
  • 1
  • 30
  • 43
  • it works. can someone explain why) it works just exactly the way i need - make overlay have 100% of its content , cover all other divs(be on top) and be scrollable, but i can't understand why this working. max-height: 100% for example denies scrolling – Anton Feb 25 '20 at 14:45
2

I changed scrollable div to be with absolute position, and everything works for me

div.sidebar {
    overflow: hidden;
    background-color: green;
    padding: 5px;
    position: fixed;
    right: 20px;
    width: 40%;
    top: 30px;
    padding: 20px;
    bottom: 30%;
}
div#fixed {
    background: #76a7dc;
    color: #fff;
    height: 30px;
}

div#scrollable {
    overflow-y: scroll;
    background: lightblue;

    position: absolute;
    top:55px; 
    left:20px;
    right:20px;
    bottom:10px;
}

DEMO with two scrollable divs

Dmitri Algazin
  • 3,332
  • 27
  • 30
0

Actually this is better way to do that. If height: 100% is used, the content goes off the border, but when it is 95% everything is in order:

div#scrollable {
    overflow-y: scroll;
    height: 95%;
}
Christian Sirolli
  • 246
  • 1
  • 6
  • 18
Vasil
  • 1
-2

Set the scrollable div to have a max-size and add overflow-y: scroll; to it's properties.

Edit: trying to get the jsfiddle to work, but it's not scrolling properly. This will take some time to figure out.

Harry
  • 1,120
  • 1
  • 12
  • 15
  • 1
    Sorry, I forgot to add that the sidebar always stretches to fit the window, and does not scroll with the page, so `max-size` isn't applicable here. – Bojangles Apr 14 '12 at 16:24