overflow:scroll div with position:absolute element inside
Asked Answered
S

3

10

I have a table inside a overflow:scroll container, there are some buttons inside table, when someone click them, they show a contextual/tooltip (position:absolute layer) text.

When I scroll to the right and click the button, it moves outside to the right ignoring scroll:

enter image description here

Making container position relative solves the position problem, but its appear inside the container not showing the menu:

enter image description here

I need help to get the following desired behavior:

enter image description here

This is the snippet:

.container{
  width:200px;
  height:100px;
  overflow:scroll;
  position:relative; /* removing this solves the problem, but .contextual moves to the original position */
}
.board{
  width:400px;
}
.contextual{
  display:none;
  position:absolute;
  width:100px;
  height:100px;
  margin: 20px;
  z-index: 2;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class=container>
    <table class=board>
      <tr><td colspan=2>This board size (200) is bigger than its container size (100).</td></tr>
      <tr>
        <td>this is a button with a contextual element</td>
        <td>
          <input type=button value="click me" onclick="$('.contextual').show();" />
          <div class=contextual>This is a contextual help text.</div>
        </td>
      </tr>
    </table>
</div>
Syrian answered 31/8, 2017 at 21:38 Comment(0)
A
2

Place the contextual div outside of the overflowing div and position it according to the mouse position.

showContext = function() {
    var e = window.event;

    var posX = e.clientX;
    var posY = e.clientY;
    var context = document.getElementById("contextual")
    context.style.top = posY + "px";
    context.style.left = posX + "px";
    context.style.display = "block";
}
.container{
  width:200px;
  height:100px;
  overflow:scroll;
  position:relative; /* removing this solves the problem, but .contextual moves to the original position */
  z-index:1;
}
.board{
  width:400px;
}
#contextual{
  display:none;
  position:absolute;
  width:100px;
  height:100px;
  background-color:grey;
  z-index: 2;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
    <table class="board">
      <tr><td colspan=2>This board size (200) is bigger than its container size (100).</td></tr>
      <tr>
        <td>this is a button with a contextual element</td>
        <td>
          <input type="button" value="click me" onclick="javascript:showContext();" />
          
        </td>
      </tr>
    </table>
</div>
<div id="contextual">This is a contextual help text.</div>
Ambary answered 31/8, 2017 at 22:1 Comment(3)
Long time ago but any suggestion on how to make this work for hover?Aerospace
@Aerospace how about change onclick to onmouseover?Vasta
@Aerospace I would do as suggested in the comment above. And perhaps use addEventListener instead. developer.mozilla.org/en-US/docs/Web/API/HTMLElement/…Ambary
R
6

For people who have this issue, but setting to mouse position won't help

If you have the same problem as me, that the parent container is set to overflow: scroll and the parent's child element is cut off despite position: absolute - do the following

Usecase for instance, building an dropdown

  • Set the element to position: fixed
  • Get the parent element's Viewport positions
  • Set the positions top, left, bottom, right values to the viewport values

you can use the same code as the code snippet from @jfeferman

Rambort answered 2/1, 2021 at 4:5 Comment(1)
In my case, only position: fixed was enough. No more...Corettacorette
A
2

Place the contextual div outside of the overflowing div and position it according to the mouse position.

showContext = function() {
    var e = window.event;

    var posX = e.clientX;
    var posY = e.clientY;
    var context = document.getElementById("contextual")
    context.style.top = posY + "px";
    context.style.left = posX + "px";
    context.style.display = "block";
}
.container{
  width:200px;
  height:100px;
  overflow:scroll;
  position:relative; /* removing this solves the problem, but .contextual moves to the original position */
  z-index:1;
}
.board{
  width:400px;
}
#contextual{
  display:none;
  position:absolute;
  width:100px;
  height:100px;
  background-color:grey;
  z-index: 2;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
    <table class="board">
      <tr><td colspan=2>This board size (200) is bigger than its container size (100).</td></tr>
      <tr>
        <td>this is a button with a contextual element</td>
        <td>
          <input type="button" value="click me" onclick="javascript:showContext();" />
          
        </td>
      </tr>
    </table>
</div>
<div id="contextual">This is a contextual help text.</div>
Ambary answered 31/8, 2017 at 22:1 Comment(3)
Long time ago but any suggestion on how to make this work for hover?Aerospace
@Aerospace how about change onclick to onmouseover?Vasta
@Aerospace I would do as suggested in the comment above. And perhaps use addEventListener instead. developer.mozilla.org/en-US/docs/Web/API/HTMLElement/…Ambary
D
-5

You can use overflow: auto. This will show the scrollbars only when necessary. Also, you can remove the z-index: 2 from .contextual.

Drusilla answered 31/8, 2017 at 21:53 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.