The best way I've found to solving this issue is to place the element inside an invisible wrapper of the same size. The wrapper should have overflow: hidden
and the element should be pushed outside the edge of the wrapper instead of outside the edge of <body>
.
The trick of this solution is that nothing actually leaves the screen, so the browser doesn't try to increase the viewport size to compensate. Instead the wrapper rests on the edge of the screen and the sidebar is inside it. Think of the wrapper as an opacity map.
The wrapper also has to be resized down to 0 so that it won't lay invisible on top of the document and possibly grab clicks that wasn't meant for it.
Here's an example of the solution in practice. I've used jQuery to manipulate the CSS, but any JavaScript library (or none) will do the trick. Notice that the "clicker" div wouldn't be clickable unless the sidebar wrapper is scaled down.
$('.sidebar-inner').on('click', function() {
$(this).css('right', -250);
$(this).closest('.sidebar-outer').css('width', 0);
});
$('.clicker').on('click', function() {
alert('CLICKED!');
});
body
{
background-color: red;
font: 12pt sans-serif;
}
.sidebar-outer
{
position: absolute;
top: 0px;
right: 0px;
bottom: 0px;
width: 250px;
-webkit-transition: width 0.2s ease-out;
-moz-transition: width 0.2s ease-out;
transition: width 0.2s ease-out;
overflow: hidden;
z-index: 999;
}
.sidebar-inner
{
position: absolute;
top: 0px;
right: 0px;
bottom: 0px;
width: 250px;
padding: 10px;
box-sizing: border-box;
-webkit-transition: right 0.2s ease-out;
-moz-transition: right 0.2s ease-out;
transition: right 0.2s ease-out;
background-color: cornflowerblue;
cursor: pointer;
}
.clicker
{
position: absolute;
width: 50px;
height: 50px;
top: 10px;
right: 10px;
padding: 10px;
background-color: green;
cursor: pointer;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="sidebar-outer">
<div class="sidebar-inner">
Click to hide
</div>
</div>
<div class="clicker">Click me!!</div>