如何获取浏览器的滚动条大小?

Posted

技术标签:

【中文标题】如何获取浏览器的滚动条大小?【英文标题】:How can I get the browser's scrollbar sizes? 【发布时间】:2010-11-02 11:36:27 【问题描述】:

如何在 javascript 中确定水平滚动条的高度或垂直滚动​​条的宽度?

【问题讨论】:

这里是来自 JQuery Dimension 插件作者的 sn-p。 github.com/brandonaaron/jquery-getscrollbarwidth/blob/master/… 给出这个解决方案可能晚了,但对我来说,这似乎是一个更好的解决方案,IMO。 看看这个解决方案:davidwalsh.name/detect-scrollbar-width @GibboK -- 该解决方案失败 -- offsetWidth == clientWidth 所以它总是为零。这是在边缘 IE && Chrome 中测试的。 @beauXjames 很奇怪它在 FF 上对我有用 这个问题出现在滚动条位置错误(屏幕中间某处)的情况下。在这种情况下,您可能不想显示滚动条。在大多数情况下,我发现 iScroll 是解决这种情况的完美设计中立解决方案:iscrolljs.com 【参考方案1】:

来自Alexandre Gomes Blog 没试过。让我知道它是否适合你。

function getScrollBarWidth () 
  var inner = document.createElement('p');
  inner.style.width = "100%";
  inner.style.height = "200px";

  var outer = document.createElement('div');
  outer.style.position = "absolute";
  outer.style.top = "0px";
  outer.style.left = "0px";
  outer.style.visibility = "hidden";
  outer.style.width = "200px";
  outer.style.height = "150px";
  outer.style.overflow = "hidden";
  outer.appendChild (inner);

  document.body.appendChild (outer);
  var w1 = inner.offsetWidth;
  outer.style.overflow = 'scroll';
  var w2 = inner.offsetWidth;
  if (w1 == w2) w2 = outer.clientWidth;

  document.body.removeChild (outer);

  return (w1 - w2);
;

【讨论】:

这个想法是天才,我肯定会在此基础上制作一个 MooTools 类。 是的,我得到了相同的谷歌结果。 :) 我正在努力让您了解情况。 如果您将主题更改为具有不同大小滚动条的主题,计算与实际的偏差是多少? 参见此处进行交叉引用:***.com/questions/3417139/… 返回具有不同页面缩放的不同值。 Win7、Opera、FF。【参考方案2】:

使用 jQuery,您可以将 Matthew Vines 的答案缩短为:

function getScrollBarWidth () 
    var $outer = $('<div>').css(visibility: 'hidden', width: 100, overflow: 'scroll').appendTo('body'),
        widthWithScroll = $('<div>').css(width: '100%').appendTo($outer).outerWidth();
    $outer.remove();
    return 100 - widthWithScroll;
;

【讨论】:

谢谢,这个解决方案很干净!! 如果将 JQuery 的整个源代码复制粘贴到它之前,这个解决方案真的会感觉更干净吗?因为这几乎就是这个解决方案正在做的事情。这个问题在 JQuery 中没有要求答案,完全有可能在不使用库的情况下执行此任务并且高效。 如果你已经在使用 JQuery,那么 Daemon 的注释是无关紧要的。是的,添加 JQuery 只是为了做到这一点是无稽之谈,但对于那些已经在他们的项目中使用 JQuery 的人来说,这是一个比公认的更“简单”的解决方案。【参考方案3】:

如果你在寻找一个简单的操作,只需混合普通的 dom js 和 jquery,

var swidth=(window.innerWidth-$(window).width());

返回当前页面滚动条的大小。 (如果可见,否则返回0)

【讨论】:

如果窗口没有滚动条(大显示器或小页面/应用程序),这将失败 这正是我想要的 对于我们这些不使用 jQuery 的人来说,$(element).width() 是做什么的?没有jQuery怎么写?【参考方案4】:

这是我找到的唯一一个脚本,它在 webkit 浏览器中工作...... :)

$.scrollbarWidth = function() 
  var parent, child, width;

  if(width===undefined) 
    parent = $('<div style="width:50px;height:50px;overflow:auto"><div/></div>').appendTo('body');
    child=parent.children();
    width=child.innerWidth()-child.height(99).innerWidth();
    parent.remove();
  

 return width;
;

最小化版本:

$.scrollbarWidth=function()var a,b,c;if(c===undefined)a=$('<div style="width:50px;height:50px;overflow:auto"><div/></div>').appendTo('body');b=a.children();c=b.innerWidth()-b.height(99).innerWidth();a.remove()return c;

你必须在文件准备好时调用它......所以

$(function() console.log($.scrollbarWidth()); );

于 2012 年 3 月 28 日在 Windows 7 上使用最新的 FF、Chrome、IE 和 Safari 进行测试,并且 100% 正常工作。

来源:http://benalman.com/projects/jquery-misc-plugins/#scrollbarwidth

【讨论】:

width 将始终 === 在该代码中未定义。 if (true) ... 更正:width总是 ===未定义第一次函数被调用。在随后调用函数width 时已经设置,该检查只是防止不必要地再次运行计算。 @MartinAnsty 但是 [width] 变量是在函数内部声明的,因此每次调用函数时都会重新创建它。 @MartinAnsty,如果您查看source,它是在外部闭包中声明的。 只是为了强调@sstur 和@TheCloudlessSky 的观点,上面的代码与Ben Alman 的插件中的代码相同,它不会缓存结果在width 中,而是每次都重新计算。它有效,但效率极低。请帮世界一个忙,在 Alman 的插件中使用 correct version。【参考方案5】:

对我来说,最有用的方法是

(window.innerWidth - document.getElementsByTagName('html')[0].clientWidth)

使用原生 JavaScript。

【讨论】:

谢谢@stephen-kendy。问候。 正是我所需要的。一个建议:第二个词可以换成document.documentElement.clientWidthdocumentElement 更清晰干净地表达了获取&lt;html&gt; 元素的意图。 如果您使用 JS,最好、最简单的解决方案!【参考方案6】:
window.scrollBarWidth = function() 
  document.body.style.overflow = 'hidden'; 
  var width = document.body.clientWidth;
  document.body.style.overflow = 'scroll'; 
  width -= document.body.clientWidth; 
  if(!width) width = document.body.offsetWidth - document.body.clientWidth;
  document.body.style.overflow = ''; 
  return width; 
 

【讨论】:

首先尝试了accepted answer,但发现它在 Windows 8 上的 Firefox 中不再适用。切换到此变体,效果很好。 代码比较短,但是浏览器要重绘整个页面,所以很慢。【参考方案7】:

我找到了一个简单的解决方案,它适用于页面内部的元素,而不是页面本身: $('#element')[0].offsetHeight - $('#element')[0].clientHeight

这将返回 x 轴滚动条的高度。

【讨论】:

伟大的!你成就了我的一天 :) 对于 y 轴滚动条,“.offsetWidth”和“.clientWidth”也同样适用。 不幸的是,至少对于宽度而言,这似乎并不完全可靠。 .clientWidth 似乎包括 Linux 下 FireFox 和 Chrome 中滚动条宽度的一半。【参考方案8】:

来自David Walsh's blog:

// Create the measurement node
var scrollDiv = document.createElement("div");
scrollDiv.className = "scrollbar-measure";
document.body.appendChild(scrollDiv);

// Get the scrollbar width
var scrollbarWidth = scrollDiv.offsetWidth - scrollDiv.clientWidth;
console.info(scrollbarWidth); // Mac:  15

// Delete the DIV 
document.body.removeChild(scrollDiv);
.scrollbar-measure 
	width: 100px;
	height: 100px;
	overflow: scroll;
	position: absolute;
	top: -9999px;

在我的网站上给我 17,在 *** 上给我 14。

【讨论】:

【参考方案9】:

您可以使用 jquery + javascript 确定 window 滚动条和 document 如下:

var scrollbarWidth = ($(document).width() - window.innerWidth);
console.info("Window Scroll Bar Width=" + scrollbarWidth );

【讨论】:

请注意,innerWidth 适用于 IE9+。否则很好的解决方案。【参考方案10】:

这应该可以解决问题,不是吗?

function getScrollbarWidth() 
  return (window.innerWidth - document.documentElement.clientWidth);

【讨论】:

【参考方案11】:

如果您已经有一个带有滚动条的元素,请使用:

function getScrollbarHeight(el) 
    return el.getBoundingClientRect().height - el.scrollHeight;
;

如果不存在horzintscrollbar,该函数将返回0

【讨论】:

这是最好的答案。吻。规则所有【参考方案12】:

Antiscroll.js 在其代码中的做法是:

function scrollbarSize () 
  var div = $(
      '<div class="antiscroll-inner" style="width:50px;height:50px;overflow-y:scroll;'
    + 'position:absolute;top:-200px;left:-200px;"><div style="height:100px;width:100%"/>'
    + '</div>'
  );

  $('body').append(div);
  var w1 = $(div).innerWidth();
  var w2 = $('div', div).innerWidth();
  $(div).remove();

  return w1 - w2;
;

代码来自这里:https://github.com/LearnBoost/antiscroll/blob/master/antiscroll.js#L447

【讨论】:

【参考方案13】:
detectScrollbarWidthHeight: function() 
    var div = document.createElement("div");
    div.style.overflow = "scroll";
    div.style.visibility = "hidden";
    div.style.position = 'absolute';
    div.style.width = '100px';
    div.style.height = '100px';
    document.body.appendChild(div);

    return 
        width: div.offsetWidth - div.clientWidth,
        height: div.offsetHeight - div.clientHeight
    ;
,

在 Chrome、FF、IE8、IE11 中测试。

【讨论】:

【参考方案14】:
function getScrollBarWidth() 
    return window.innerWidth - document.documentElement.clientWidth;

大多数浏览器使用 15px 作为滚动条宽度

【讨论】:

当然,这只有在滚动条已经可见的情况下才有效。有时我们需要在显示之前预测大小。此外,移动浏览器不使用 15px 作为滚动条。【参考方案15】:

创建一个空的div 并确保它出现在所有页面上(即,将其放入header 模板中)。

给它这个样式:

#scrollbar-helper 
    // Hide it beyond the borders of the browser
    position: absolute;
    top: -100%;

    // Make sure the scrollbar is always visible
    overflow: scroll;

然后只需使用 Javascript 检查#scrollbar-helper 的大小:

var scrollbarWidth = document.getElementById('scrollbar-helper').offsetWidth;
var scrollbarHeight = document.getElementById('scrollbar-helper').offsetHeight;

无需计算任何内容,因为此div 将始终具有scrollbarwidthheight

唯一的缺点是您的模板中会有一个空的div。但另一方面,您的 Javascript 文件会更干净,因为这只需要 1 或 2 行代码。

【讨论】:

【参考方案16】:
function getWindowScrollBarHeight() 
    let bodyStyle = window.getComputedStyle(document.body);
    let fullHeight = document.body.scrollHeight;
    let contentsHeight = document.body.getBoundingClientRect().height;
    let marginTop = parseInt(bodyStyle.getPropertyValue('margin-top'), 10);
    let marginBottom = parseInt(bodyStyle.getPropertyValue('margin-bottom'), 10);
    return fullHeight - contentHeight - marginTop - marginBottom;
  

【讨论】:

【参考方案17】:

使用 jquery(仅在 firefox 中测试):

function getScrollBarHeight() 
    var jTest = $('<div style="display:none;width:50px;overflow: scroll"><div style="width:100px;"><br /><br /></div></div>');
    $('body').append(jTest);
    var h = jTest.innerHeight();
    jTest.css(
        overflow: 'auto',
        width: '200px'
    );
    var h2 = jTest.innerHeight();
    return h - h2;


function getScrollBarWidth() 
    var jTest = $('<div style="display:none;height:50px;overflow: scroll"><div style="height:100px;"></div></div>');
    $('body').append(jTest);
    var w = jTest.innerWidth();
    jTest.css(
        overflow: 'auto',
        height: '200px'
    );
    var w2 = jTest.innerWidth();
    return w - w2;

但实际上我更喜欢@Steve 的回答。

【讨论】:

【参考方案18】:

这是一个很好的答案: https://***.com/a/986977/5914609

但是在我的情况下它不起作用。我花了几个小时寻找解决方案。 最后我回到了上面的代码并添加了 !important 到每种样式。它奏效了。 我无法在原始答案下方添加 cmets。所以这里是修复:

function getScrollBarWidth () 
  var inner = document.createElement('p');
  inner.style.width = "100% !important";
  inner.style.height = "200px !important";

  var outer = document.createElement('div');
  outer.style.position = "absolute !important";
  outer.style.top = "0px !important";
  outer.style.left = "0px !important";
  outer.style.visibility = "hidden !important";
  outer.style.width = "200px !important";
  outer.style.height = "150px !important";
  outer.style.overflow = "hidden !important";
  outer.appendChild (inner);

  document.body.appendChild (outer);
  var w1 = inner.offsetWidth;
  outer.style.overflow = 'scroll !important';
  var w2 = inner.offsetWidth;
  if (w1 == w2) w2 = outer.clientWidth;

  document.body.removeChild (outer);

  return (w1 - w2);
;

【讨论】:

【参考方案19】:

这个生命黑客决定会让你有机会找到浏览器滚动宽度(原版 JavaScript)。使用此示例,您可以在任何元素上获得 scrollY 宽度,包括那些根据您当前的设计概念不应该有滚动的元素:

getComputedScrollYWidth     (el)  

  let displayCSSValue  ; // CSS value
  let overflowYCSSValue; // CSS value

  // SAVE current original STYLES values
  
    displayCSSValue   = el.style.display;
    overflowYCSSValue = el.style.overflowY;
  

  // SET TEMPORALLY styles values
  
    el.style.display   = 'block';
    el.style.overflowY = 'scroll';
  

  // SAVE SCROLL WIDTH of the current browser.
  const scrollWidth = el.offsetWidth - el.clientWidth;

  // REPLACE temporally STYLES values by original
  
    el.style.display   = displayCSSValue;
    el.style.overflowY = overflowYCSSValue;
  

  return scrollWidth;

【讨论】:

【参考方案20】:

这里是基于偏移宽度差异的更简洁易读的解决方案:

function getScrollbarWidth(): number 

  // Creating invisible container
  const outer = document.createElement('div');
  outer.style.visibility = 'hidden';
  outer.style.overflow = 'scroll'; // forcing scrollbar to appear
  outer.style.msOverflowStyle = 'scrollbar'; // needed for WinJS apps
  document.body.appendChild(outer);

  // Creating inner element and placing it in the container
  const inner = document.createElement('div');
  outer.appendChild(inner);

  // Calculating difference between container's full width and the child width
  const scrollbarWidth = (outer.offsetWidth - inner.offsetWidth);

  // Removing temporary elements from the DOM
  outer.parentNode.removeChild(outer);

  return scrollbarWidth;


请参阅JSFiddle。

【讨论】:

【参考方案21】:

已经在我的库中编码,所以这里是:

var vScrollWidth = window.screen.width - window.document.documentElement.clientWidth;

我应该提一下,jQuery $(window).width() 也可以用来代替window.document.documentElement.clientWidth

如果你在右边的firefox中打开开发者工具,它不起作用,但如果在底部打开开发者窗口,它就会克服它!

支持window.screenquirksmode.org!

玩得开心!

【讨论】:

【参考方案22】:

似乎可行,但也许有一个更简单的解决方案适用于所有浏览器?

// Create the measurement node
var scrollDiv = document.createElement("div");
scrollDiv.className = "scrollbar-measure";
document.body.appendChild(scrollDiv);

// Get the scrollbar width
var scrollbarWidth = scrollDiv.offsetWidth - scrollDiv.clientWidth;
console.info(scrollbarWidth); // Mac:  15

// Delete the DIV 
document.body.removeChild(scrollDiv);
.scrollbar-measure 
	width: 100px;
	height: 100px;
	overflow: scroll;
	position: absolute;
	top: -9999px;

【讨论】:

【参考方案23】:

我制作了@Matthew Vines 答案的更新版本。

它更容易阅读,更容易理解。它不需要内部元素。为获取滚动条宽度而创建的元素具有 100% 的高度/宽度,因此它不会在低端 PC/手机的主体上创建任何可见的滚动条,这可能需要更多时间来创建元素,获取宽度,最后移除元素。

const getScrollBarWidth = () => 
  const e = document.createElement('div');
  Object.assign(e.style, 
    width: '100%',
    height: '100%',
    overflow: 'scroll',
    position: 'absolute',
    visibility: 'hidden',
    top: '0',
    left: '0',
  );

  document.body.appendChild(e);

  const scrollbarWidth = e.offsetWidth - e.clientWidth;

  document.body.removeChild(e);

  return scrollbarWidth;
;

console.log(getScrollBarWidth());

我确实建议只检查一次滚动条宽度,在页面加载时(除非它不符合您的需要),然后将结果存储在状态/变量中。

【讨论】:

【参考方案24】:

我在 material-ui 代码中找到了该解决方案,它对我有用。

const scrollbarWidth = window.innerWidth -  document.querySelector('body').clientWidth;

【讨论】:

【参考方案25】:

您可以使用此解决方案来查找网页内任何元素的滚动条宽度,而不是网页本身。您还可以通过将其与宽度相关的属性替换为与高度相关的对应属性,将其重写为在水平滚动条的情况下适用于滚动条高度。

offsetWidth 属性返回内容、内边距、边框和滚动条(如果有的话)的总宽度。而clientWidth 属性仅返回内容和填充的总宽度。

所以,如果我们从offsetWidth 中减去clientWidth 和水平边框,我们将得到滚动条的宽度。也就是说,如果有滚动条,我们就会得到滚动条的宽度。但是如果没有滚动条,我们会得到0

const element = document.querySelector("div");
const elementStyle = window.getComputedStyle(element);
const horizontalBorder = parseFloat(elementStyle.borderLeftWidth) + parseFloat(elementStyle.borderRightWidth);
const scrollbarWidth = element.offsetWidth - element.clientWidth - horizontalBorder + "px";

【讨论】:

以上是关于如何获取浏览器的滚动条大小?的主要内容,如果未能解决你的问题,请参考以下文章

jquery如何获取元素的滚动条高度等实现代码

flex4 如何给整个页面添加滚动条?

如何获取网页滚动条滚动事件

如何能快速知道当前网页滚动条的高度?有工具吗?

如何使用滚动条可靠地获取屏幕宽度

echarts滚动条高度和字体大小