Can I set overflow: hidden but still show a scrollbar? - html

I want to disable scrolling for when there's a popup, but I hate how the entire page changes size when you add/remove the scrollbar. Is there a way to disable scrolling without hiding the scrollbar?
Kind of like when you set overflow:scroll to an element that doesn't have enough content to scroll: it still shows the scrollbar but it's disabled.
//when popup is open, disable scroll on body
body.popupOpen {
overflow: hidden;
}

Make sure that the overflow (the scroll bar) is on the body element then add an overlay that will simply cover the body and its scroll bar when the popup is shown.
Here is a simplified example with only the overlay where you cannot scroll:
body {
overflow: auto;
margin: 0;
max-height: 100vh; /* no more than the height of the viewport*/
}
html {
overflow: hidden; /* This one is important to avoid the propagation */
}
.overlay {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: 9999;
}
.content {
min-height: 500vh;
}
<div class="overlay">
</div>
<div class="content">
</div>

The answer is no, but you can set 'hidden' and create a element to simulate the scrollbar, but why would you do this, it only makes the user confused.

You can create a div that fullfils the whole page view, and just make it transparent, this way you can just enable/disable the div scroll to mantain a scrollbar:
.theDivInactive {
background: none;
pointer_events: none;
width: 100vw;
height: 100vh;
overflow: hidden;
}
and switch the class when the popup is on the screen:
.theDivActive {
background: none;
pointer_events: none;
width: 100vw;
height: 100vh;
overflow: scroll;
}
`

I have fixed the issue the same way bootstrap does. Just in case other methods doesn't work for you, here's the JS trick to calculate scrollbar width for a given browser. Then on modal open, you can set the padding-right to body element:
const documentWidth = document.documentElement.clientWidth;
const scrollbarWidth = Math.abs(window.innerWidth - documentWidth);
document.body.style.paddingRight = `${scrollbarWidth}px`;
Note: this will only work well if you set overflow-y: scroll to popup bg or put the popup over the white strap that was created as the side effect of the padding-right property.
Note 2: If elements are positioned absolutely relative to body width, they will still "jump" so you need to add padding to them as well or wrap them with div that has position: relative

Related

iOS safari: scrolling is broken inside position: fixed; elements

Inside a position: fixed; element, scrolling elements will "lock" if you try to scroll them the wrong way at the start of a touch.
Example: touch the screen and drag downwards, then back up. The element won't scroll. If you release, wait a few seconds, then try dragging upwards, it will scroll.
http://12me21.github.io/scroll-test.html
body {
position: fixed;
top: 0;
bottom: 0;
left: 0;
right: 0;
}
#scroll-container {
overflow-y: scroll;
height: 100%;
}
#scroller {
height: 200vh;
font-size: 50px;
}
<body>
<div id=scroll-container>
<div id=scroller>Test<br>more text</div>
</div>
</body>
This answer: https://stackoverflow.com/a/51733026/6232794 seems to be the same problem I'm having, but the fix no longer works. It seems to happen inside all fixed elements and isn't caused by -webkit-overflow-scrolling: touch; anymore.
Is there any way to fix this now? Or do I just need to avoid position: fixed; entirely?
Adding overflow: hidden; to <html> or <body> seems to fix it.
I'm not sure why this works, but I assume the problem is that safari is trying to scroll html/body instead of the element you want.
Because the scrollable section is inside a position:fixed element, scrolling the body has no visual effect, so it looks like nothing is happening.
I had a same problem and overflow hidden help to stop scrolling body element, but it also disable scrolling webpage if visitor wants to. So I created JQ solution to add class .overflow-hidden to body element, only when I need it. In my case when sidebars has active class.
$(document).click(function(){
if ($(".siderbar_menu").hasClass("side-menu-active")) {
$("body").addClass("overflow-hidden-mobile");
} else {
$("body").removeClass("overflow-hidden-mobile");
};
});
Works for me.

Full screen nav jumps due to lack of scrollbar

I have a site with a full screen overlay nav, which when triggered hides the overflow on the html element. This is to stop the page behind the nav being scrolled when the nav is open.
Stripped down SCSS (when nav is active) looks like this:
html.nav-is-active {
overflow: hidden
}
nav.active {
display: block;
position: fixed;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
z-index: 1600000;
}
My problem is when the nav is open the scrollbar disappears causing the page to jump - this is especially disorientating as there is a close button on the nav overlay which is supposed to line up with a menu button on the site.
My question is how can I best solve this? I can remove the overflow:hidden from the html element to preserve the scrollbar, but that then means the site can be scrolled unintentionally when the nav is open.
Any help appreciated
Mike
This is really hacky, but it should do what you want...
html {
overflow-y: hidden;
}
body {
overflow-y: scroll; // causes an empty scrollbar
height: auto; //set height = content so body can't overflow
}
You can make your scrollbar visible the same way in the overlay.
OR If you can figure out the width of the scrollbar (typically 15px on Mac and I think similar in Win 10) you can subtract from the overlay size or add padding. This is slightly better than setting the overlay to overflow-y: scroll since it won't cause scrolling INSIDE the overlay on small screens.
nav.active {
width: calc(100vw - 15px); // could be done with javascript
}
An alternative to block scroll without overflow: hidden; is position: fixed; overflow-y:scroll; so simply change this:
html.nav-is-active {
overflow: hidden;
}
with this:
html.nav-is-active {
position: fixed;
overflow-y:scroll;
}
You'll se an empty scroll bar, but the page will not "jump" anymore.

Overflow-x: hidden do not work

I have a problem with oveflow-x in my page. Althought the body has overflow-x hidden, I can still scroll on the page.
<html>
<body>
<div id="content">
<div id="mydiv"></div>
<div>
</body>
</html>
html and body have overflow-x:hidden.
Div "content" has nothing in the css and div "myDiv" has position absolute.
How can I make the "mydiv" not to go out of the page? Because now what happens is that I can still scroll on x.
Fiddle > http://jsfiddle.net/o7dph6sj
Without more code, the best answer I can think of is that your html and body tags do not have any kind of width set so they are inheriting the default width of 100%. Meaning that every child element is going to be inside of that 100%.
Set the body to have a set width and then set overflow to hidden, then check if the elements in your page are exceeding the width.
Example:
body{
width: 1024px;
overflow-x: hidden;
}
Also, the code that you set inside of #content could directly be affecting it as well, some elements will ignore its parents and be rendered outside of them which brings us back to... give us more code.
Because you're using a bad selector for overflow. If you want to avoid VERTICAL SCROLLING you use this:
html, body {
overflow-y: hidden;
}
to avoid HORIZONTAL SCROLLING:
html, body {
overflow-x: hidden;
}
to avoid BOTH
html, body {
overflow: hidden;
}
take a look to your forked fiddle where I avoid BOTH overflow axises and there's no overflow at all
Change "overflow-x: hidden !important;" to be
html, body {
overflow: hidden !important;
}
or
html, body {
overflow-y: hidden !important;
}
In-fact you can ignore "!important" since you use !important to override other rule. And here you were just using the wrong property "overflow-x" which is for "Horizontal scroll"
And it works!!!
Here is the working Fiddle > http://jsfiddle.net/o7dph6sj/1/
Updated the Answer with addition requirement:
You add "overflow: hidden" when you don't want both scrolls,
AND "overflow-y: hidden;" hides the Horizontal Scroll
AND "overflow-x: hidden;" hides the Vertical Scroll
Checkout the updated Fiddle and try on your by commenting and un-commenting this code:
html, body {
overflow-y: hidden; /* Hides Horizontal Scroll*/
/*overflow-x: hidden;*/ /* Hides Vertical Scroll*/
/*overflow: hidden;*/ /* Hides Both Vertical and Horizontal Scroll*/
}
Updated Fiddle "http://jsfiddle.net/o7dph6sj/3/"
Checkout these articles >
https://developer.mozilla.org/en-US/docs/Web/CSS/overflow-y
https://developer.mozilla.org/en-US/docs/Web/CSS/overflow-x
https://developer.mozilla.org/en-US/docs/Web/CSS/overflow
I tried for several hours and I found that the body size needs to be specified, and its attribute position must be set to absolute. Then you can have overflow-x: hidden work well in your code.
in this case, I have a web with a navbar that I want to slide right to hide from the main body in mobile size. I called #media screen and (max-width:576px) to make it run on mobile size. the problem occurred before I specify the max-width the body must be shown: I still can scroll to the right though I specified the overflow-x: hidden
so I added max-width:100vh inside the body style, and voila. it works!
checkout my code:
body{
min-width: 0px;
max-width: 100vh;
position: absolute;
overflow-x: hidden;
}
nav ul {
position: absolute;
right: 0;
width: 40%;
top: 34px;
height: 100vh;
z-index: 1;
background-color: #194ca7;
}

Why does `overflow: auto;` not cause an element to scroll even when its contents overflow?

Why does setting overflow: auto; on an element not cause it to scroll even when its contents overflow?
I have a two column layout with a fixed left column and a scrolling right column. The right column, is set to overflow: auto;, and it has a child div.content. If I set its minimum height taller than the window, the scroll bar will not appear. If I set the minimum height on its child, div.content the scroll bar appears.
Why is this? Why won't the scroll bar appear when the minimum height is set on main?
Here's a fiddle: http://jsfiddle.net/gT8tq/1/
<div class="page-wrapper">
<aside>
<p>Fixed</p>
</aside>
<main>
<section class="content">
<p>Scroll</p>
</section>
</main>
</div>
Styles...
html, body {
height: 100%;
margin: 0; padding: 0;
overflow: hidden;
}
.page-wrapper {
bottom: 0; left: 0; right: 0; top: 0;
position: absolute;
z-index: 100;
}
aside, main {
bottom: 0; top: 0;
padding: 20px;
position: absolute;
}
aside {
background-color: #eee;
left: 0;
width: 30%;
}
main {
background-color: #ccc;
left: 30%; right: 0;
overflow: auto;
/* Here is the issue; uncommenting this breaks scrolling; Why? */
/* min-height: 1000px; */
}
.content {
min-height: 1000px;
}
In your CSS,
html, body {
height: 100%;
margin: 0; padding: 0;
overflow: hidden;
}
It means that no matter how the height overflow the body element, the scroll bar will not appear.
Besides, overflow: auto in main element is required because actually the scroll bar belongs to the main element instead of the default body element.
main {
background-color: #ccc;
left: 30%; right: 0;
overflow: auto;
}
If you do not want overflow: hidden in body element, you must set position:fixed to aside element.
Check it on http://jsfiddle.net/gT8tq/4/
When you set min-height: 1000px on your main element, what ends up happening is that its contents no longer overflow it because it is now 1000 pixels tall. Note that min-height takes precedence even though you anchored the main element to the page bounds using absolute positioning and bottom: 0; top: 0, simply because that results in the main element being less than 1000 pixels tall. What happens then is that the element remains anchored to the top according to its top coordinate and overflows downward, because it's over-constrained thanks to min-height; the details of all this are documented in sections 10.6.4 and 10.7 of the spec.
Since overflow no longer occurs on the main element, it no longer needs to generate a scrollbar for its contents. The main element and its contents still overflow the page as I've described, but since you specified overflow: hidden on html, body, the page will refuse to generate a scrollbar for the main element. The end result, therefore, is that no scrollbar is generated at all.
If you force main to generate a vertical scrollbar even when no overflow occurs, by replacing overflow: auto with overflow-y: scroll, you'll see that the scrollbar actually extends beyond the page bounds such that you no longer see the bottom control(s) — this proves that by adding min-height you have in fact made the main element taller:
main {
background-color: #ccc;
left: 30%; right: 0;
/* overflow: auto; */
overflow-y: scroll;
min-height: 1000px;
}
That is because you set the behavior for a certain element, in this case <main>.
What should <main> do when it's contents are greater than the element itself?
In this case, you say it should create scrollbars in that case.
If you put overflow: auto; on the page-wrapper, it will do what you expect, because then you tell that div what to do when it's contents are overflowing.
Does that make sense or do you need more clarification?
You didn't use position:relative; for .content check this out:
http://jsfiddle.net/gT8tq/2/

HTML Page displays disabled scrollbar

My html page displays empty disabled scrollbar, please see attached screenshot
How can i hide this scrollbar completely?
EDIT:
Sorry my mistake, i didn't mentioned that i am using overflow:hidden, but cannot hide this scroll bar.
i am copying my body code below
body {
color: #000000;
margin-bottom: 0;
margin-left: 0;
margin-right: 0;
margin-top: 0;
overflow-x: hidden;
overflow-y: hidden;
}
I suspect it has nothing to do with overflow on your BODY element.
Even if you set overflow-y and overflow-x it's just like using the shorthand:
overflow: hidden;
same as for your margin, use only:
margin: 0;
// You have also other shorthand variants like:
// margin : top right bottom left;
// margin : topBottom rightLeft;
// margin : top rightLeft bottom;
// helps to keep your CSS file clear as possible.
So the probable issue lies in some most outer common parent element like some wrapper or container that has probably a style set to overflow: scroll;
like in this demo
Set overflow: hidden; in your CSS for the body:
body {
overflow: hidden;
}
Or to handle just the verticle scrollbar
body {
overflow-y: hidden;
}