It might sound like this has been asked a million times before, but I have not found anything that really solves all of the problems I am trying to solve. With this disclaimer out of the way, here is what I am trying to achieve:
- A sidebar, fixed to the right
- A content area, that might be scrollable
- The scrollbar of the content area needs to be to the right of the sidebar
- It should be possible to display an overlay
- The overlay should be scrollable as well
- While the overlay is visible, the underlying content area should not be scrollable
- Showing the overlay with its scrollbar should not result in a re-layout of the underlying content area, e.g. because of
overflow: hidden
The combination of all these requirements breaks each solution that I have tried.
I have two solutions now, that are close but still not good enough:
Solution 1 doesn't solve requirement 7.
Solution 2 has two scrollbars when the overlay is visible.
Solution 1:
function showOverlay() {
var style = document.body.style;
style.overflow = 'hidden';
document.getElementById('overlay').style.display = 'block';
}
function closeOverlay() {
var style = document.body.style;
style['overflow-y'] = 'scroll';
document.getElementById('overlay').style.display = 'none';
}
* {
margin: 0;
box-sizing: border-box
}
html {
}
body {
position: relative;
width: 100%;
overflow-y: scroll;
}
.content {
position: relative;
display: block;
background-color: lightblue;
border: 2px solid white;
width: calc(100% - 60px)
}
.fixed {
position: fixed;
top: 0;
right: 0;
bottom: 0;
z-index: 1000;
background-color: lightgreen;
width: 60px;
border: 2px solid black;
text-align: right;
}
#overlay {
display: none;
position: fixed;
z-index: 10000;
left: 0;
top: 0;
bottom: 0;
right: 0;
background-color: rgba(32,32,32,0.5);
overflow-y: scroll;
}
.overlay-content {
margin: 50px auto;
height: 1000px;
width: 80%;
background-color: yellow;
}
<div class="content">
Body<br/>
Body<br/>
Body<br/>
Body<br/>
Body<br/>
Body<br/>
Body<br/>
Body<br/>
Body<br/>
Body<br/>
Body<br/>
Body<br/>
Body<br/>
Body<br/>
Body<br/>
Body<br/>
Body<br/>
Body<br/>
Body<br/>
Body<br/>
Body<br/>
Body<br/>
Body<br/>
Body<br/>
Body<br/>
Body<br/>
Body<br/>
Body<br/>
Body<br/>
Body<br/>
Body<br/>
Body<br/>
<button onclick="showOverlay()">show overlay</button>
</div>
<div class="fixed">A<br/>B<br/>C</div>
<div id="overlay">
<div class="overlay-content">
<button onclick="closeOverlay()">Close overlay</button>
</div>
</div>
Solution 2:
function showOverlay() {
var style = document.body.style;
style.top = '-' + document.documentElement.scrollTop + 'px';
style.position = 'fixed';
document.getElementById('overlay').style.display = 'block';
}
function closeOverlay() {
var style = document.body.style;
style.position = 'relative';
style.top = 0;
document.getElementById('overlay').style.display = 'none';
}
* {
margin: 0;
box-sizing: border-box
}
html {
}
body {
position: relative;
width: 100%;
overflow-y: scroll;
}
.content {
position: relative;
display: block;
background-color: lightblue;
border: 2px solid white;
width: calc(100% - 60px)
}
.fixed {
position: fixed;
top: 0;
right: 0;
bottom: 0;
z-index: 1000;
background-color: lightgreen;
width: 60px;
border: 2px solid black;
text-align: right;
}
#overlay {
display: none;
position: fixed;
z-index: 10000;
left: 0;
top: 0;
bottom: 0;
right: 0;
background-color: rgba(32,32,32,0.5);
overflow-y: scroll;
}
.overlay-content {
margin: 50px auto;
height: 1000px;
width: 80%;
background-color: yellow;
}
<div class="content">
Body<br/>
Body<br/>
Body<br/>
Body<br/>
Body<br/>
Body<br/>
Body<br/>
Body<br/>
Body<br/>
Body<br/>
Body<br/>
Body<br/>
Body<br/>
Body<br/>
Body<br/>
Body<br/>
Body<br/>
Body<br/>
Body<br/>
Body<br/>
Body<br/>
Body<br/>
Body<br/>
Body<br/>
Body<br/>
Body<br/>
Body<br/>
Body<br/>
Body<br/>
Body<br/>
Body<br/>
Body<br/>
<button onclick="showOverlay()">show overlay</button>
</div>
<div class="fixed">A<br/>B<br/>C</div>
<div id="overlay">
<div class="overlay-content">
<button onclick="closeOverlay()">Close overlay</button>
</div>
</div>
I think that solution 1 is the better one of the two, but is it possible to prevent that relayout from happening?
Please note, that I am trying to find a solution that works without using Javascript to detect the scrollbar width.