Acemad
Acemad

Reputation: 3581

Prevent scrollbar from adding-up to the width of page on Chrome

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

Answers (21)

kuramura143
kuramura143

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

chikadance
chikadance

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

Neurotransmitter
Neurotransmitter

Reputation: 6797

Probably

html {
    width: 100vw;
}

is just what you want.

Upvotes: 86

Hive7
Hive7

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

doomsday
doomsday

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

Merryl
Merryl

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

Double-w-B
Double-w-B

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

Sargsian
Sargsian

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

Christian
Christian

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

CSS FTW
CSS FTW

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

Arash Esmaeili
Arash Esmaeili

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

simonDos
simonDos

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

jeremy
jeremy

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

NatD
NatD

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

Robbendebiene
Robbendebiene

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

Piotr Siatkowski
Piotr Siatkowski

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

Kyle Dumovic
Kyle Dumovic

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

fuzzy_logic_77
fuzzy_logic_77

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

Lwyrn
Lwyrn

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

Hashbrown
Hashbrown

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

EXAMPLE

chrome devtools showing padding unmoved

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

Hashbrown
Hashbrown

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 widths 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

Related Questions