16

Some times it's nice to be able to slide things out of the viewport to hide them, for example when making hide-able sidebars or panels. But when I push something past the right or bottom edge of the window, the browser (Chrome in my case) automatically adds scrollbars to it. The user can now scroll over to the element I tried to hide. (JSFiddle Example)

I can remove the scrollbars by setting overflow-x: hidden on the body element, but that opens up a bunch of other side effects. For instance, the user can still accidentally click&drag their way past the edge of the screen. The user now sees the "hidden" element and may also be stuck if they don't know how browsers work. (JSFiddle example)

How can I achieve this "disappear off the screen" effect without experiencing these drawbacks?

Hubro
  • 56,214
  • 69
  • 228
  • 381
  • Seems like a good case for "visibility: hidden;" style, instead of forcing the browser to render something that is offscreen, etc. – JMC Jun 07 '12 at 22:26
  • But I specifically want the effect of the element disappearing flying off the screen – Hubro Jun 07 '12 at 22:28

3 Answers3

22

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>
Hubro
  • 56,214
  • 69
  • 228
  • 381
  • Very nice, If it helps anyone, I used pointer-events:none; touch-action: none; on the style of the wrapper div to avoid the clicks and pointer-events:auto; touch-action: auto; on the inside div (menu in my case). That way I didn't have to resize it when my menu is -off screen-. – Dr. Aaron Dishno Jun 19 '17 at 16:24
6

A simple solution (admittedly not always viable) would be to set position:fixed on the sidebar instead of position:absolute.

FIDDLE

$('.sidebar').on('click', function() {
  $(this).css('right', -250);
});
.sidebar {
  position: fixed;
  top: 0px;
  right: 0px;
  bottom: 0px;
  width: 250px;
  -webkit-transition: right 0.2s ease-out;
  -moz-transition: right 0.2s ease-out;
  transition: right 0.2s ease-out;
  cursor: pointer;
  background-color: cornflowerblue;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="sidebar">
  Click to hide
</div>
Danield
  • 121,619
  • 37
  • 226
  • 255
  • In your case, what if the sidebar is greater than the screen size. As the position is fixed, you will not be able to scroll down – ValidfroM May 12 '15 at 17:19
0

That is a bad idea to wrap something invisible, because you should know why your will move it outside screen, it is not just for hidden, if just for hidden there will be a lot of good ways to do. To move outside the screen, the most benefit is when you deal with large picture,video,or other component like News Feed in iframe. That will cache render for it, make significante effective improvement.

gavin
  • 1