Reputation: 3581
I have a small issue trying to keep my html pages at a consistent width on Chrome.
For example, I have a page (1) with lots of contents that overflows the viewport's (right word?) height, so there's a vertical scrollbar on that page (1). On page (2), I have the same layout (menus, divs,...etc) but less content, so no vertical scrollbars in there.
The problem is that on page (1) the scrollbars seem to push elements slightly to the left (adding up to the width?) while everything appears well centered on page (2).
I'm still a beginner in HTML/CSS/JS, and I'm fairly convinced that this isn't so difficult, but I had no luck figuring out the solution. It does work as intended on IE10, and Firefox (non-interfering scroll bars), I only encountered this on Chrome.
Upvotes: 263
Views: 324117
Reputation: 79
If anyone has this issue try setting the parent body of the main items to "container-fluid"
<div class="container-fluid"></>
Upvotes: 0
Reputation: 4147
scrollbar-gutter doesn't support old browser
so here is js solution support old browser
set boxSizing in scrollView style box-sizing: 'border-box"
doesn't work
but when scrollView is rendered, js scrollView.style.boxSizing = "border-box"
, make rendering like scroll-gutter:stable
Upvotes: 0
Reputation: 3675
All you need to do is add:
html {
overflow-y: scroll;
}
in your css file, as this will have the scroller whether it is needed or not, though you just won't be able to scroll.
This means that the viewport will have the same width for both.
Upvotes: 78
Reputation: 173
I had a similar issue. I was trying to have scroll on hover but it kept pushing things off and making an awful UX. I found an easy solution to it. I keep the scrollbar in its place, but make it transparent and bring it back when the cursor hovers on the div. Since the scrollbar is always there it doesn't modify the design of the other elements of the div.
$(document).ready(function() {
$('#list-parent').hover(
function() {
$("#list-parent").removeClass('scrollbar-invisible');
$("#list-parent").addClass('scrollbar');
}, function() {
$("#list-parent").addClass('scrollbar-invisible');
$("#list-parent").removeClass('scrollbar');
});
})
.main-div {
height: 100px;
width: 400px;
overflow: hidden;
}
.list-parent {
height: 100px;
background-color: yellow;
overflow: scroll;
padding:20px;
width:150px;
}
.scrollbar-invisible::-webkit-scrollbar{
border: 3px solid #ffffff00;
width: 5px;
height: 20px;
}
.scrollbar::-webkit-scrollbar {
width: 5px;
height: 20px;
}
.scrollbar::-webkit-scrollbar-thumb {
border-radius: 100vh;
border: 3px solid black;
padding-left: 20px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="app" class='main-div'>
<div id ='list-parent' class='list-parent scrollbar-invisible'>
<div style='background-color:pink'>
<h1> Todos: </h1>
<ol>
<li>Test Item </li>
<li>Test Item </li>
<li>Test Item </li>
<li>Test Item </li>
<li>Test Item </li>
<li>Test Item </li>
<li>Test Item </li>
</ol>
</div>
</div>
</div>
Upvotes: 0
Reputation: 21
I had a similar issue with my Header nav. Most of my pages had enough content to trigger scroll-y, except one page.
My header nav has a flexContainer with 2 children (spaced-between). The flexContainer has a 5rem left & right padding.
header { padding-left: calc(100vw - 100%;)}
Adding this to the header centers the content by adding the scrollbar width to the left. The elements are now centered but we have effectively shrunk the header width by scrollbar width.
flexContainer {padding: 0rem calc(5rem - calc((100vw - 100%)/2));}
Im adding back the scrollbar width by reducing the flexContainer's padding.
This ensures that my content stays in place, regardless of scroll-y being triggered or not.
Upvotes: 1
Reputation: 104
Ran into the same issue of an extra width of a scrollbar on Chrome and Edge (not on a FireFox).
The logic in a project was to stop scrolling after hover on some container. So I added a class to a body:
body.no-scrolling {
overflow: hidden;
}
That's helped to prevent scrolling, but removed a scrollbar. In a FireFox it wasn't a problem, but in Chrome and Edge content was filling the space of a scrollbar and made content of a page to move right.
So a solution that worked for me:
html{
width: 100vw;
}
This rule prevented the content from moving right after scrollbar disappeared, but added an extra width and appeared a scrollbar in a bottom of a page. To hide that extra width I added:
body{
overflow-x: hidden;
}
Let me know if it helped you too.
Upvotes: 0
Reputation: 17
If you have some container that you're using as a wrapper over your website content, like for navigation and footer for example, you can add the following:
min-height: 101vh;
This will 'Lengthen' your page by 1vh to make sure the scrollbar never disappears and the width stays the same.
Upvotes: -2
Reputation: 4084
The 2021 solution is to use scrollbar-gutter
, which adds the space, a scrollbar would use, permanently to an element.
Use
.element-class {
scrollbar-gutter: stable both-edges;
}
both-edges
is optional.
See also https://caniuse.com/mdn-css_properties_scrollbar-gutter and https://developer.mozilla.org/en-US/docs/Web/CSS/scrollbar-gutter
overflow: overlay
is deprecated.
Here is a codepen for clarification on the different possibilities: https://codepen.io/waxolunist/pen/ExweBMz
Upvotes: 106
Reputation: 69
body {
width: calc( 100% );
max-width: calc( 100vw - 1em );
}
works with default scroll bars as well. could add:
overflow-x: hidden;
to ensure horizontal scroll bars remain hidden for the parent frame. unless this is desired from your clients.
Upvotes: 6
Reputation: 179
I solved a similar problem I had with scrollbar this way:
First disable vertical scrollbar by setting it's:
overflow-y: hidden;
Then make a div with fixed position with a height equal to the screen height and make it's width thin to look like scrollbar. This div should be vertically scroll-able. Now inside this div make another div with the height of your document (with all it's contents). Now all you need to do is to add an onScroll function to the container div and scroll body as the div scrolls. Here's the code:
HTML:
<div onscroll="OnScroll(this);" style="width:18px; height:100%; overflow-y: auto; position: fixed; top: 0; right: 0;">
<div id="ScrollDiv" style="width:28px; height:100%; overflow-y: auto;">
</div>
</div>
Then in your page load event add this:
JS:
$( document ).ready(function() {
var body = document.body;
var html = document.documentElement;
var height = Math.max( body.scrollHeight, body.offsetHeight, html.clientHeight, html.scrollHeight, html.offsetHeight);
document.getElementById('ScrollDiv').style.height = height + 'px';
});
function OnScroll(Div) {
document.body.scrollTop = Div.scrollTop;
}
Now scrolling the div works just like scrolling the body while body has no scrollbar.
Upvotes: 0
Reputation: 1893
DISCLAIMER: overlay has been deprecated.
You can still use this if you absolutely have to, but try not to.
This only works on WebKit browsers, but I like it a lot.
Will behave like auto
on other browsers.
.yourContent{
overflow-y: overlay;
}
This will make the scrollbar appear only as an overlay, thus not affecting the width of your element!
Upvotes: 176
Reputation: 43
I can't add comment for the first answer and it's been a long time... but that demo has a problem:
if(b.prop('scrollHeight')>b.height()){
normalw = window.innerWidth;
scrollw = normalw - b.width();
$('#container').css({marginRight:'-'+scrollw+'px'});
}
b.prop('scrollHeight') always equals b.height(),
I think it should be like this:
if(b.prop('scrollHeight')>window.innerHeight) ...
At last I recommend a method:
html {
overflow-y: scroll;
}
:root {
overflow-y: auto;
overflow-x: hidden;
}
:root body {
position: absolute;
}
body {
width: 100vw;
overflow: hidden;
}
Upvotes: 0
Reputation: 41
I had the same issue on Chrome. It only happened for me when the scroll bar is always visible. (found in the general settings) I have a modal and when I open the modal I noticed that...
body {
padding-left: 15px;
}
is added to the body. To stop this from happening I added
body {
padding-left: 0px !important;
}
Upvotes: 0
Reputation: 4869
For containers with a fixed width a pure CSS cross browser solution can be accomplished by wrapping the container into another div and applying the same width to both divs.
#outer {
overflow-y: auto;
overflow-x: hidden;
/*
* width must be an absolute value otherwise the inner divs width must be set via
* javascript to the computed width of the parent container
*/
width: 200px;
}
#inner {
width: inherit;
}
Click here to see an example on Codepen
Upvotes: 7
Reputation: 159
.modal-dialog {
position: absolute;
left: calc(50vw - 300px);
}
where 300 px is a half of my dialog window width.
This is actually the only thing that worked for me.
Upvotes: -1
Reputation: 2432
Webkit browsers like Safari and Chrome subtract the scroll bar width from the visible page width when calculating width: 100% or 100vw. More at DM Rutherford's Scrolling and Page Width.
Try using overflow-y: overlay
instead.
Upvotes: 27
Reputation: 373
I found I could add
::-webkit-scrollbar {
display: none;
}
directly to my css and it would make the scrollbar invisible, but still allow me to scroll (on Chrome at least). Good for when you don't want a distracting scrollbar on your page!
Upvotes: 12
Reputation: 1911
You can get the scrollbar size and then apply a margin to the container.
Something like this:
var checkScrollBars = function(){
var b = $('body');
var normalw = 0;
var scrollw = 0;
if(b.prop('scrollHeight')>b.height()){
normalw = window.innerWidth;
scrollw = normalw - b.width();
$('#container').css({marginRight:'-'+scrollw+'px'});
}
}
CSS for remove the h-scrollbar:
body{
overflow-x:hidden;
}
Try to take a look at this: http://jsfiddle.net/NQAzt/
Upvotes: 52
Reputation: 13013
EDIT: this answer isn't quite right at the moment, refer to my other answer to see what I was attempting to do here. I'm trying to fix it up, but if you can offer assistance do so in the comments, thanks!
Using padding-right
will mitigate the sudden appearance of a scrollbar
As you can see from the dots, the text makes it to the same point in the page before wrapping, regardless of whether or not a scrollbar is present.
This is because when a scrollbar is introduced the padding hides behind it, so the scrollbar doesn't push on the text!
Upvotes: 1
Reputation: 13013
It doesn't seem my other answer is working quite right at the moment (but I'll continue to try to get it operational).
But basically what you'll need to do, and what it was trying to do dynamically, is set the contents' width to slightly less than that of the parent, scrollable pane.
So that when the scrollbar appears it has no affect on the content.
This EXAMPLE shows a more hacky way of attaining that goal, by hardcoding width
s instead of trying to get the browser to do it for us via padding
.
If this is feasible this is the most simplest solution if you don't want a permanent scrollbar.
Upvotes: 3