Dustin Locke
Dustin Locke

Reputation: 141

Absolute-positioned div scrolls inside absolute-positioned parent

I have an absolute-positioned div with two children -- an absolute-positioned div and a static div which will scroll inside the parent. It looks like this:

<div class='frame'>
  <div class='absolute-contents'>This should stay put.</div>
  <div class='static-contents'>This should scroll under it.</div>
</div>

And here's the CSS:

.frame {
  position: absolute;
  top: 40px;
  left: 40px;
  right: 40px;
  bottom: 40px;
  overflow-y: scroll;
}

.absolute-contents {
  position: absolute;
  top: 40px;
  left: 40px;
  right: 40px;
  bottom: 40px;
  z-index: 9999;
  opacity: .9;
  padding: 40px;
}

.static-contents {
  margin: 24px auto;
  width: 400px;
  height: 3000px;
  padding: 40px;
}

I have the absolute child constrained to the edges of the parent, so why does it still scroll, and how can I make it stay put?

Example: https://codepen.io/anon/pen/wqZxXG

Upvotes: 4

Views: 11433

Answers (2)

Dustin Locke
Dustin Locke

Reputation: 141

I resolved by putting the element I wanted to scroll in an absolute-positioned div with overflow-y: scroll like so:

<div class='frame'>
  <div class='fix-me'></div>
  <div class='scroll-me'>
    <div class='long-content'></div>
  </div>
</div>

And styling like this:

.frame {
  background-color: blue;
  position: absolute;
  top: 40px;
  right: 40px;
  left: 40px;
  bottom: 40px;
  overflow-y: hidden;
}

.scroll-me {
  background-color: orange;
  position: absolute;
  top: 40px;
  right: 40px;
  left: 40px;
  bottom: 40px;
  overflow-y: scroll;
}

.fix-me {
  position: absolute;
  z-index: 999;
  top: 40px;
  left: 40px;
  right: 40px;
  height: 56px;
  background-color: purple;
}

.long-content {
  width: 480px;
  background-color: yellow;
  height: 4000px;
  margin: 20px auto;
}

Pen here: https://codepen.io/dustinlocke/pen/vJMzpK

Upvotes: 9

TylerH
TylerH

Reputation: 21087

You should adjust your child div to use position: fixed if you do not want it to move. position: absolute just tells a div that its initial position should be determined absolutely. See my answer here for more info on position: fixed and a similar scenario to yours.

Set the .frame div to position: relative (or a parent of .frame) for this to work. This will set the position: fixed child to be fixed within the position: relative parent of .frame.

You will need to adjust the positioning amounts (top, bottom, left, right) to account for the different stacking contexts.

Something like this: https://codepen.io/anon/pen/brJxVW

body {
  width: 100vw;
}

.frame {
  background-color: green;
  position: relative;
  width: calc(100vw - 80px);
  margin: 0 auto;
  top: 40px;
  bottom: 40px;
  overflow-y: scroll;
}

.absolute-contents {
  background-color: yellow;
  position: fixed;
  top: 40px;
  left: 40px;
  right: 40px;
  bottom: 40px;
  z-index: 9999;
  opacity: .9;
  margin: 40px;
}

.big-contents {
  margin: 24px auto;
  width: 400px;
  height: 3000px;
  background-color: white;
  padding: 40px;
}
<div class='frame'>
    <div class='absolute-contents'>This should stay fixed in the green frame. Why is it scrolling?</div>
    <div class='big-contents'>This should scroll under it.</div>
</div>

Upvotes: 5

Related Questions