13

I want to calculate the width of the scrollbar so that I use the result in a CSS calc() declaration.

At the moment, I assume that the width of the scrollbar is always 17px, like this:

body { 
    width:calc(100vw - 17px); 
}
.container { 
    max-width:calc(100vw - 17px); 
}

The problem with this is when you choose a different browser zoom %, the width of the scrollbar changes. So I want to use the result of the calculation to do something along these lines:

body { 
    width:calc(100vw - CALCULATED SCROLL-BAR WIDTH); 
}
.container { 
    max-width:calc(100vw - CALCULATED SCROLL-BAR WIDTH); 
}

EDIT: I've now solved the problem with the help of this question

The JavaScript used to calculate the scrollbar width (though, I have found you require an interval to get it to autoupdate):

function getScrollbarWidth() {
  var outer = document.createElement("div");
  outer.style.visibility = "hidden";
  outer.style.width = "100px";
  outer.style.msOverflowStyle = "scrollbar"; // needed for WinJS apps

  document.body.appendChild(outer);

  var widthNoScroll = outer.offsetWidth;
  // force scrollbars
  outer.style.overflow = "scroll";

  // add innerdiv
  var inner = document.createElement("div");
  inner.style.width = "100%";
  outer.appendChild(inner);        

  var widthWithScroll = inner.offsetWidth;

  // remove divs
  outer.parentNode.removeChild(outer);

  return widthNoScroll - widthWithScroll;
}

My code (which is used to embed the result of the function into a CSS calc() declaration).

$('body').css({ 
  'width':'calc(100vw - ' + getScrollbarWidth() + 'px)' 
});

$('.container').css({ 
  'max-width':'calc(100vw - ' + getScrollbarWidth() + 'px)' 
});
Community
  • 1
  • 1
Bailey280899
  • 151
  • 1
  • 1
  • 5

4 Answers4

18

Actually, you can get the scrollbar width just with css and custom properties (and completely without javascript):

body {
    --scrollbar-width: calc(100vw - 100%);
}

Then you can use this variable in a child element like this:

.container { 
    max-width: calc(100vw - var(--scrollbar-width)); 
}

This is because 100vw is always the inner width of the view, but the 100% of the body does not include the scrollbar.

jonas_jonas
  • 384
  • 3
  • 7
  • 6
    Should be noted that this only works if your body element has a scroll bar. – JaredMcAteer Jun 19 '20 at 14:13
  • 7
    Also note that this will not work if `.container` is not the same width as `body` since the "100%" is relative to where the `--scrollbar-width` variable is used. – Thomas Higginbotham Apr 08 '21 at 18:27
  • The variable can be useful but it's not required, as the value can be calculated with `calc(100vw - (100vw - 100%))` as [answered](https://stackoverflow.com/a/34884924/21849374) a few years earlier – Tim R Aug 22 '23 at 04:26
9

Expanding jonas_jonas's answer, it can work but if .container must have the same width as the body.

If that's not the case, even so you can make it work with vanilla JS, defining a CSS property like this

document.body.style.setProperty(
    "--scrollbar-width",
    `${window.innerWidth - document.body.clientWidth}px`
);

And then you can use it in CSS

.container { 
    max-width: calc(100vw - var(--scrollbar-width)); 
}
Juan Barba
  • 91
  • 1
  • 2
2

Why you need so much code to do that?

The easy way with plain javascript it's:

$('body').css({ 
  'width':'calc(100vw - ' + (window.innerWidth - document.body.clientWidth) + 'px)' 
});
NetVicious
  • 3,848
  • 1
  • 33
  • 47
0

This can be organized with the use of the new container queries with pure CSS on any scrolling area:

    <div style="container-type: inline-size;">
        <div style="overflow-y: auto; height=300px;">
            <div style="padding-right: calc(40px - 100cqw + 100%)">
        </div>
    </div>
Hulk Choi
  • 1,067
  • 2
  • 8
  • 12