52

I have a div with position:fixed that is my container div for some menus. I've set it to top:0px, bottom:0px to always fill the viewport. Inside that div I want to have 2 other divs, the lower one of which contains lots of lines and has overflow:auto. I would expect that it would be contained within the container div, but if there are too many lines it simply expands outside the fixed div. Below is my code and a screenshot to clarify:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title>MyPlan</title>
    <meta name="X-UA-COMPATIBLE" value="IE=8" />
    <style type="text/css">
        #outerfixed { position:fixed;  width:200px;  background-color:blue; padding:5px; top:0px; bottom:30px;}
        #innerstatic1 { width:100%; background-color:yellow; height:100px;}
        #innerstatic2 { overflow:auto; background-color:red; width:100%;}
    </style>
</head>
<body>
    <div id="outerfixed">
        <h3>OUTERFIXED</h3>
        <div id="innerstatic1">
            <h3>INNERSTATIC1</h3>
        </div>
        <div id="innerstatic2">
            <h3>INNERSTATIC2</h3>
            line<br />
                        ...lots of lines
            line<br />
        </div>
    </div>
</body>
</html>

alt text

Is there any way for me to do this? Again, I want #innerstatic2 to be properly contained within #outerfixed and get scrollbars if it gets bigger than the space it has inside #outerfixed.

I know there are some possibilites to hack around this by also fixing #innerstatic2, but I would really like it to be within the flow inside #outerfixed if possible, so that if I move #outerfixed somewhere, the inner element would come with it.

EDIT: I know I can set overflow:auto on the #outerfixed and get a scrollbar on the whole thing, but I specifically want a scrollbar just on #innerstatic2, it is a grid and I want to scroll just the grid.

Anyone? Possible?

Einar Egilsson
  • 3,438
  • 9
  • 36
  • 47

8 Answers8

54

There's a two-step solution for this, but it comes at something of a cost:

  1. Add overflow-y: scroll; to the css for #innerstatic2.
  2. define a height (or max-height) for #innerstatic2, otherwise it won't overflow, it'll just keep increasing its height (the default for a div is height: auto).


Edited because I just can't stop myself, sometimes.

I've posted a demo on jsbin to show a jQuery implementation of this, which will calculate a height for you (it's not generalised, so it'll only work with your current html).

(function($) {
  $.fn.innerstaticHeight = function() {
        var heightOfOuterfixed = $('#outerfixed').height(),
        offset = $('#innerstatic2').offset(),
        topOfInnerstatic2 = offset.top,
        potentialHeight = heightOfOuterfixed - topOfInnerstatic2;

        $('#innerstatic2').css('height',potentialHeight);
  }
})(jQuery);

$(document).ready(
    function() {
        $('#innerstatic2').innerstaticHeight();
    }
);
David Thomas
  • 249,100
  • 51
  • 377
  • 410
  • 1
    Thank you for the answer. Actually this is pretty much what we have today, calculate the right height for #innerstatic2 and set with jquery. But this is causing problems with a third party component that calculates some sizes incorrectly when we mess with this in document ready, so that's why I really wanted a pure CSS solution. – Einar Egilsson Oct 01 '10 at 07:51
  • So, is there no way to force scroll on #innerstatic2 by setting the height on #outerfixed? From what I've tried it seems not, #innerstatic2 just flows outside if I set an explicit height on #outerfixed, but is that because it is position:fixed? – Einar Egilsson Oct 01 '10 at 07:52
  • It could be. You can also add `overflow: hidden` to the css for `#outerfixed`, but that doesn't *look* particularly pretty, unfortunately. – David Thomas Oct 01 '10 at 07:55
  • I did not use the JQuery. For me was enough by using `overflow-y: auto;` so when the content in, let's say `#innerstatic2` is bigger than max-height, the scroll will render, but not always, which is ugly. That was precisely what I needed. You can inspect the `#searchContainer` within the left sidebar at http://climaenruta.lhdevsolutions.net/ – Juan Ignacio Avendaño Huergo Oct 11 '20 at 10:31
21

I solved it by giving absolute position to the ul and height 100%

ul {
  overflow-y: scroll;
  position: absolute;
  height: 100%;
}

check out this FIDDLE

Ofir D
  • 808
  • 6
  • 15
7

overflow-y:scroll;

And add this for iOS devices. It does give a better scroll using touch. The overflow-y needs to be scroll! for secure reasons. auto wont work for some people. or at least thats what i heard.

-webkit-overflow-scrolling: touch;

Dyrehauge
  • 71
  • 1
  • 2
4

you should set height for outerfixed and max-height for innerstatic2

see this might be helpful DEMO

Afshin
  • 4,197
  • 3
  • 25
  • 34
1

It is the container div who has to be with the overflow:auto attribute. In this case, the #outerfixed div

Alejandro Martin
  • 5,691
  • 1
  • 17
  • 21
  • Sorry, I should have been more clear. I explicitly want the scrollbar to only be on the #innerstatic2 element. It is a grid and I want to scroll only the grid, not the whole container. – Einar Egilsson Oct 01 '10 at 07:06
1

The only way I figure, is to set innerstatic2 to absolute position (so you can use top and bottom to size it in relation to outerfixed), then inside innerstatic2 create another div where you put your text in. Then you give innerstatic2 the "overflow: auto;" indication. The drawback of this method, that innerstatic2 does not move down, when innerstatic1 grows, since it has to be position absolutely. If it needs to move, it must be "position: relative", but then you need to set a fixed height for it. So either way you have to settle for a compromise.

Once all browsers support the newer CSS3 features, like the calculation support, there will be better options to do this, without these drawbacks.

Eric J. Francois
  • 682
  • 1
  • 7
  • 14
1

Not ideal, but this should get you 90% of they way

<div style="position:fixed; bottom:1px; left:5em; height: 20em; width:20em; background-color:blue;">
        <div style ="width:15em; background-color: green;">
                Title
        </div>
        <div style ="background-color:yellow; max-height:80%; width:15em; overflow:auto;">
                <div style="height:100em; background-color:red; width:10em;">
                        scroll<br/>
                        scroll<br/>
                        scroll<br/>
                </div>  
        </div>  
</div>
SooDesuNe
  • 9,880
  • 10
  • 57
  • 91
0

So I couldn't do with the fixed position but I got the desired effect with the position as relative.

Try this

<div class="parent" style = "overflow: scroll;  position: relative; width: content-box"">

  <div class="scrollable-child" >
   //Your content here
   
  </div>

</div>

I used this in one of my vuejs projects

<template>
  <v-flex class=" d-flex flex-column " style="overflow: scroll;  position: relative; width: content-box">

//FIXED HEAD

    <v-flex class="pt-10" style="position: fixed; background-color: black;width: 25.2em;z-index: 1;border-radius: 20px 20px 0 0">
      <TextView class="mx-4" text="Thur 28, 2021" size="24" bold :color="colors.primaryText"/>
      <TextView   :text="`${order.totalOrder()} Items`" size="24" bold :color="colors.primaryText" class="my-2 mx-4"/>
      <v-divider dark style="height: 5px" class="max-4" />
    </v-flex>
   

//SCROLABLE LIST ITEMS

    <v-flex class=" mx-4 d-flex flex-column justify-end  " style="margin-top: 100px;padding-bottom: 100px; padding-top: 50px">
<!--      <TextView :text="receipt" :color="colors.primaryText"/>-->
        <ProductComponent type="cartItem" v-for="(product,index) in order.products" :key="`order_item_${index}`" :product="product" :invert-theme="true" @onAdd="addOneMore(index)" @onRemove="removeOne(index)" />
    </v-flex>

//BOTTOM FIXED BTN

    <v-flex class="d-flex flex-column justify-end mb-2 xs12 mx-4 " style="max-height: 100px; position: fixed; bottom: 30px; width: 23em"  >
      <v-btn block ref="renderBtn" @click="renderReceipt()" depressed min-height="60" style="border-radius: 20px">
       <TextView text="Order" bold/>
      </v-btn>
    </v-flex>
  </v-flex>
</template>
JPilson
  • 1,075
  • 11
  • 10