Disable body scroll but don't hide scrollbar - javascript

When I click a thumbnail, it opens a div overlay box on top:
.view-overlay {
display:none;
position:fixed;
top:0;
left:0;
right:0;
bottom:0;
overflow-y:scroll;
background-color:rgba(0,0,0,0.7);
z-index:999;
}
For browsers with non-floating scrollbars, disabling scroll with overflow: hidden removes the scrollbar causing the content to shift to the right a bit to make up for the additional space.
I want to keep the scrollbar there so that doesn't happen. There are solutions online but I can't find one that definitively works well in all browsers.
https://stackoverflow.com/a/13891717/4774917 - This answer seems to work well on Chrome, but causes weird glitchy behaviour on Safari OSX 10.10.
https://stackoverflow.com/a/8701977/4774917 - This answer causes the body to scroll back to the top (Chrome).
What's a solution that:
a) disables body scroll when the overlay is opened
b) keeps the body stay put at its original scroll position
c) keeps the scrollbar there so content doesn't shift
d) works on (most/all) browsers without glitchy behaviour?
Example: https://dribbble.com does this and it seems to work on the browsers I've tested it on (including Safari) without glitchy behaviour.

One approach that's both very simple and effective is to not have the main content in the body itself, but a wrapper that's a sibling with the overlay. With this approach you can toggle the overlay whenever necessary without affecting the scroll of the content element.
var e = document.getElementById('overlay');
document.body.onclick = function() {
e.style.display = (!e.style.display || e.style.display === 'block') ? 'none' : 'block';
};
html,
body,
#content {
height: 100%;
margin: 0;
}
#content {
overflow: auto;
}
#high {
height: 800px;
}
#overlay {
position: absolute;
height: 100%;
width: 100%;
background: rgba(0, 0, 0, 0.5);
}
<div id="overlay"></div>
<div id="content">
Long content resides in this container
<div id="high"></div>
And the long content ends here
</div>

Related

Js/CSS Images inside div with overflow:scroll prevent scroll?

I have this strange bug
I have an div #page that I set to overflow :scroll, and i have the body with overflow:hidden because i want to prevent the pull down, and make the site feel like an "app"
html,body {
height: 100vh;
min-height: 100vh;
overflow: hidden;
}
#page {
overflow: scroll;
height: 100vh;
width: 100vw;
top: 0;
bottom: 0;
left: 0;
right: 0;
}
pseudo page
<div #page>
<div .image>
<div .image>
<div .text>
<div .image>
<div .text>
</div>
inside the #page I have divs with images and text like in a long one-pager.
for some strange reason due to knows which conflict, when I scroll the #page it works well until I hover an image , not a text, contained in the page and in that case the scroll-wheel of my mouse wont scroll anymore. almost like the images overwrite the scroll.
I can't use pointer-events:none because of other reasons
add in your code
window.onscroll = () => {
window.scrollTo(0,0);
};
blocked the scroll
for reset:
window.onscroll = ()=>{
}

Is scrollTop, and scrollLeft for overflow hidden elements reliable?

I accidentally discovered that scrollTop, and scrollLeft on an element work even when an element is overflow: hidden. Can this behaviour be relied on?
Supposedly scrollTop, and scrollLeft are supposed to be zero for elements without scrollbars, and setting them on such elements is supposed to have no effect.
Yes, even if an element has CSS overflow set to hidden,
Javascript Element.scrollTop(), Element.scrollLeft() allows you to manipulate the element's scroll position if the element contains overflowing children.
https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollLeft
https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollTop
Here's a quick use case:
Animate gallery using scrollLeft
var GAL = $("#gal"),
n = GAL.find(">*").length;
c = 0;
$("button").on("click", function(){
GAL.animate({ scrollLeft: (++c%n) * GAL.width() });
});
#gal {
height: 40vh;
overflow: hidden; /* !! */
white-space:nowrap;
font-size: 0;
} #gal>* {
font-size: 1rem;
display: inline-block;
vertical-align: top;
width: 100%;
height: inherit;
background: 50% / cover;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="gal">
<div style="background-image:url(//placehold.it/800x600/cf5);"></div>
<div style="background-image:url(//placehold.it/800x600/f0f);"></div>
<div style="background-image:url(//placehold.it/800x600/444);"></div>
</div>
<button>scrollLeft</button>
Not sure yet why Chrome does not do the following but:
Firefox will remember your gallery scroll-position on historyBack (navigating back to the page where you scrolled your gallery)

Position fixed but still scrollable?

Would it be possible to have a DIV position: fixed, but if the content of that DIV extend beyond the viewing area of the screen then you could still scroll with the window? I've put everything I have thus far in this...
FIDDLE
This code sits inside a media query that gets triggered when the screen hits a max width and/or a max height, but I don't think that code is relevant to my question. This is the bit of code that I believe I need to modify to work correctly:
.expand {
display: block !important;
position: fixed;
-webkit-backface-visibility: hidden;
top: 50px;
left: 0;
background: rgba(31, 73, 125, 0.8);
width: 100%;
z-index: 999;
}
The reason I want this fixed is so the little hamburger menu stays statically in the upper left hand corner of the screen at all times, as at times the site I'm building could be rather lengthy, so I would like viewers to have a little more ease of access.
Thank you!
Yes, you just need to give the div a fixed height and the overflow: auto setting
(Demo)
.expand {
bottom: 0;
overflow: auto;
}
If you don't want to give it a minimum height, a simple (but not supported by old browsers) option would be to use css calc() like so
.expand {
max-height: calc(100% - 50px); // 100% viewport height minus the height of the nav.
}
I would suggest setting a fallback height before in case the browser does not support calc
JavaScript
To achieve what you really want you need javascript. Here it is.
Check to see if the menu is open, if not...
Define a check to see if the contents are larger than the viewport, if so then set bottom: 0px; and overflow: auto and remove scrolling from the body.
If so...
Remove all styles from the menu and the body that were added when opening the menu.
(Demo)
(function($) {
var menu = $('.responsive-menu'), open;
$('.menu-btn').click(function () {
if(!open) {
if(menu.height() > $(window).height()) {
open = true;
menu.css({'bottom': '0px', 'overflow': 'auto'});
document.body.style.overflow = 'hidden';
}
} else {
open = false;
menu.css({'bottom': '', 'overflow': ''});
document.body.style.overflow = '';
}
menu.toggleClass('expand');
});
})(jQuery);

Div Position: Fixed. Absolute when certain length away?

I'm currently making a website with a "Support is Live" div which will be following the user when scrolling. So I gave it Position: Fixed; and all works fine.
But when the user scrolls back up, I want the Support div to stop so it doesn't "touch" the header.
Here is a picture that hopefully makes it easier to understand:
http://gyazo.com/2694b03181a39c3b6673901b42b5952d
I want the yellow div to stop in line with the orange field on the picture. But when the user starts to scrolling down again, it will follow.
My Best Regards
Philip
This will need some JQuery to work properly:
JSFIDDLE
JQuery
$(document).on("scroll", function() {
if($(document).scrollTop() < 100) {
$('#alert').addClass("absolute");
} else if($(document).scrollTop() > 100) { //100 is the height of your header. Adjust if needed
$('#alert').removeClass("absolute");
}
});
CSS
.absolute {
top: 100px; //same as the value in the conditions
position: absolute;
}
#alert{
background-color: #FF0;
float: left;
height: 400px;
width: 230px;
margin-left: 20px;
position: fixed;
z-index:999;
}
HTML
<div id="alert" class="absolute"> </div>
/!-- add the class so that it doesn't mess up the layout when you load the page --!/
The srolltop function checks how much space is between your viewport and the top of your document. When it reaches the height of the header, a class absolute is applied in order to keep the #alert div in its place.

Element changes place when position fixed applied

When I apply position: fixed with Javascript my element moves a few pixels down and gets fixed in another position, some pixels down, instead of just staying where is was.
Why is this?
// html
<div id="container">
<div id="myDiv"></div>
</div>
// CSS
#container {
height: 2000px;
}
#myDiv {
margin-top: 50px;
width: 100px;
height: 50px;
background-color: #88a;
}
// Javascript
myDiv.style.position = 'fixed';
I find this behaviour at least in Chrome and FF.
http://jsfiddle.net/bSM8h/
When you apply position:fixed, also do:
pin.addEventListener('click', function () {
myDiv.style.position = 'fixed';
myDiv.style.top = '50px';
myDiv.style.marginTop = '0';
});
http://jsfiddle.net/bSM8h/2/
*edit*
By default browsers do body{padding:5px;} that is why a good idea is to html5boilerplate your css's
*end edit*
For some reason (see explanation here), margin-top also pushed the container with it. Once applied position:fixed, the container sprung back to the top of the page (lost the margin) and was positioned 5px from the top of page.
before position:fixed
after position:fixed
Just add this to your CSS:
body {
margin:0;
padding:0;
}
This will prevent the extra padding added by the browser defaults.

Categories

Resources