IMO user agents render absolutely positioned elements within wrappers with overflow
other than visible
this way due to performance issues.
Because they have to redraw (and change the position of) the absolutely positioned elements with the respect to their containing block during scrolling.
The same thing happens in the presence of floats — See:
One possible option could be to let the absolutely positioned element position relative to the initial containing block (where the <html>
element lives) instead.
In order to achieve that, we can remove position: relative
from the #dialog-1
, so the containing block of the absolutely positioned element would be the initial containing block. And also it gets scrolled along with the page.
Example Here
function forAllNodes(nodes, fn) {
Array.prototype.forEach.call(
nodes,
function(node) {
fn.call(node);
}
);
}
var layoutGate = function() {
forAllNodes(
document.querySelectorAll('.dropdown-contents'),
function() {
if (this.classList) this.classList.toggle('hide');
}
);
};
var intervalId = setInterval(layoutGate, 1000);
forAllNodes(
document.querySelectorAll('.toggle-dropdown-btn'),
function() {
var elm = this;
elm.addEventListener('click', function() {
if (intervalId) {
clearInterval(intervalId);
intervalId = null;
}
layoutGate();
}, false);
}
);
.wrapper {
padding-left: 20px;
}
p {
line-height: 1.3em;
}
#dialog-1 {
padding: 10px;
border: 3px solid black;
width: 400px;
min-height: 100px;
max-height: 150px;
overflow-y: auto;
}
.dropdown-control {
/* position: relative; */
margin: 0;
padding: 0;
}
.toggle-dropdown-btn {
padding: 0;
margin: 0;
}
.dropdown-contents {
list-style-type: none;
position: absolute;
/* min-width: 100%; */
width: 400px;
background-color: #81d4fa;
margin: 0;
padding: 0;
border: 1px solid green;
/* top: 100%; */
/* left: 0; */
}
#dialog-2 {
padding: 10px;
border: 3px solid black;
width: 400px;
min-height: 100px;
max-height: 150px;
}
.hide {
display: none;
}
<div class="wrapper">
<h1>Div with overflow-y:</h1>
<div id="dialog-1">
<p>Stuff in Dialog blah blah</p>
<div class="dropdown-control">
<button type="button" class="toggle-dropdown-btn">Toggle Dropdown</button>
<ul class="dropdown-contents">
<li>why</li>
<li>do i </li>
<li>trigger </li>
<li>scroll</li>
</ul>
</div>
</div>
<h1>Normal div, no overflow-y</h1>
<div id="dialog-2">
<p>Stuff in Dialog blah blah</p>
<div class="dropdown-control">
<button type="button" class="toggle-dropdown-btn">Toggle Dropdown</button>
<ul class="dropdown-contents">
<li>this</li>
<li>does not </li>
<li>grow </li>
<li>the div</li>
</ul>
</div>
</div>
</div>