CSS:如何获取浏览器滚动条宽度?(for:hover {overflow:auto}不错的边距)

Jac*_*ski 13 html css scrollbar width css3

我不确定标题是否清楚,所以解释的话很少.我有几个小元素,比方说div(200pxx 400px常数).在每个内部,有一个段落有大约20行文本.当然,这对于一个可怜的小div来说很重要.我想做的是:

  1. 通常divoverflow: hidden属性.
  2. 在鼠标over(:hover)上,此属性更改为overflow: auto;,并显示滚动条.

问题是什么?我想在段落文本和滚动条之间留一点空间(填充或边距).让我们说该段有一个对称的margin: 20px;.但是在:hover触发器打开后,会出现滚动条,并且段落的整个右侧都会"scrollbar-width" px向左移动.句子在其他行中被打破,整个段落看起来不同,这非常烦人且不方便用户使用.我怎样才能设置我的CSS,所以悬停后唯一的变化就是scroolbar的外观?

换一种说法:

/* Normally no scrollbar */
div {display: block; width: 400px; height: 200px; overflow: hidden;}
/* On hover scrollbar appears */
div:hover {overflow: auto;}

/* Paragraph margin predicted for future scrollbar on div */
div p {margin: 20px (20px + scrollbarwidth px) 20px 50px;}
/* With scrollbar margin is symmetrical */
div:hover p {margin: 20px;} /* With scrollbar */
Run Code Online (Sandbox Code Playgroud)

我已经为它做了一个小片段,并解决了我的问题strong.我希望一切都很清楚:).我现在正在寻找一个近两个小时的解决方案,所以我认为我的问题非常独特和有趣.

div.demo1 {
  width: 400px;
  height: 200px;
  overflow: hidden;
  background: #ddd;
}
div.demo1:hover {
  overflow: auto;
}
div.demo1 p {
  background: #eee;
  margin: 20px;
}
div.demo2 {
  width: 400px;
  height: 200px;
  overflow: hidden;
  background: #ddd;
}
div.demo2:hover {
  overflow: auto;
}
div.demo2 p {
  background: #eee;
  margin: 20px 40px 20px 20px;
}
div.demo2:hover p {
  margin: 20px 20px 20px 20px;
}
Run Code Online (Sandbox Code Playgroud)
<div class="demo1">
  <p>
    This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text.
    This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text.
    This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text.
    This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text.
    This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text.
  </p>
</div>
<br>
<br>
<strong>As you can see, on hover right side of the paragraph "moves" left. But I want something like:</strong>
<br>
<br>
<div class="demo2">
  <p>
    This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text.
    This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text.
    This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text.
    This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text.
    This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text.
  </p>
</div>

<strong>But with a "perfect" scrollbar width (in this example I used 20px)</strong>
Run Code Online (Sandbox Code Playgroud)

tom*_*tom 13

根据浏览器和操作系统,所有滚动条可能不同,因此您必须使用javascript.

我在这里找到了一个很酷的片段:http://davidwalsh.name/detect-scrollbar-width

这是一个例子:http://jsfiddle.net/a1m6an3u/

js代码创建一个div .scrollbar-measure,查看滚动条的大小并返回它.

它看起来像这样:

var scrollDiv = document.createElement("div");
scrollDiv.className = "scrollbar-measure";
document.body.appendChild(scrollDiv);

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

// Delete the DIV 
document.body.removeChild(scrollDiv);
Run Code Online (Sandbox Code Playgroud)

所以我很快添加了一些jquery代码,但我认为你只能在JS中完成它.

  • 我在 Linux 和 Chrome 上尝试了这段代码,控制台警告显示 0(零)...知道可能出了什么问题吗? (3认同)

Oli*_*ver 12

虽然 tomtomtom 的答案非常有效,但它需要一个似乎有些不必要的外部 CSS 片段,而 Yurii 的答案需要 jQuery,这再次似乎有点矫枉过正。稍微更新和自包含的答案(也可以在 JavaScript 模块设置中使用)是:

class TempScrollBox {
  constructor() {
    this.scrollBarWidth = 0;

    this.measureScrollbarWidth();
  }

  measureScrollbarWidth() {
    // Add temporary box to wrapper
    let scrollbox = document.createElement('div');

    // Make box scrollable
    scrollbox.style.overflow = 'scroll';

    // Append box to document
    document.body.appendChild(scrollbox);

    // Measure inner width of box
    this.scrollBarWidth = scrollbox.offsetWidth - scrollbox.clientWidth;

    // Remove box
    document.body.removeChild(scrollbox);
  }

  get width() {
    return this.scrollBarWidth;
  }
}
Run Code Online (Sandbox Code Playgroud)

然后可以像这样使用这个类:

let scrollbox = new TempScrollBox();

console.log(scrollbox.width) //-> 17 (Windows, Chrome)
Run Code Online (Sandbox Code Playgroud)

小提琴:https : //jsfiddle.net/nu9oy1bc/


gum*_*ost 8

innerWidth返回浏览器视口的宽度,包括滚动条。

只读 Window 属性 innerWidth 返回窗口的内部宽度(以像素为单位)。这包括垂直滚动条的宽度(如果存在)。

clientWidth在用于根元素(如document )时返回视口的宽度,不包括滚动条。

当在根元素(元素)上使用 clientWidth 时(如果文档处于怪癖模式,则为 on),将返回视口的宽度(不包括任何滚动条)。

let scrollbarWidth = (window.innerWidth - document.body.clientWidth) + 'px';
Run Code Online (Sandbox Code Playgroud)

减去这两个值,瞧,你得到滚动条的宽度。

这个例子通常会返回:15px


Den*_*hin 8

我的解决方案在最新的 Chrome、Mozilla、Edge 和 Opera 中完美运行。不知道 Safari 怎么样

const scrollbarWidth = window.innerWidth - document.documentElement.offsetWidth
Run Code Online (Sandbox Code Playgroud)

更新:在移动设备上,浏览器处理滚动条的方式略有不同,与某些桌面浏览器类似overflow: overlay。因此,这种方式不会给您实际的滚动条宽度,而是html由滚动条引起的元素布局(在上面的示例中)的“移位”。因此,在这种情况下,您可能会得到0,因为元素没有“移位”html,因为滚动条显示在元素上方


Tig*_*rrr 6

我偶然发现了这个问题,我查看了答案,除了 1 个 CSS 答案外,它们都是 JS 答案。我很惊讶没有人正确回答这个问题,所以我假设我误解了这个问题,但如果我没有记错的话,OP想要滚动条宽度的边距......

那么,为什么不这样做:

margin-right: calc(100vw - 100%);
margin-bottom: calc(100vh - 100%);
Run Code Online (Sandbox Code Playgroud)

我认为我什至不需要解释,因为它看起来很明显...... 100vw 将获得屏幕的整个宽度,而 100% 将获得父元素的宽度(为此,将获得父元素的宽度)也需要是 100% - body 标签是默认的),因此减去它会得到应该是滚动条的差异。我们可以将 100% 替换为任何 div(非 body 标签)的固定宽度或高度,我将在下面分叉您的代码片段,以展示我的意思:

div.demo1 {
  width: 400px;
  height: 200px;
  overflow: hidden;
  background: #ddd;
}
div.demo1:hover {
  overflow: auto;
}
div.demo1 p {
  background: #eee;
  margin: 20px;
}
div.demo2 {
  width: 400px;
  height: 200px;
  overflow: hidden;
  background: #ddd;
}
div.demo2:hover {
  overflow: auto;
}
div.demo2 p {
  background: #eee;
  margin: 20px 40px 20px 20px;
}
div.demo2:hover p {
  margin: 20px calc(400px - 100%) 20px 20px;
}
Run Code Online (Sandbox Code Playgroud)
<div class="demo1">
  <p>
    This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text.
    This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text.
    This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text.
    This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text.
    This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text.
  </p>
</div>
<br>
<br>
<strong>As you can see, on hover right side of the paragraph "moves" left. But I want something like:</strong>
<br>
<br>
<div class="demo2">
  <p>
    This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text.
    This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text.
    This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text.
    This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text.
    This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text.
  </p>
</div>

<strong>But with a "perfect" scrollbar width (in this example I used 20px)</strong>
Run Code Online (Sandbox Code Playgroud)

就是这样...它看起来与OP的20px东西相同...已经过去了7年,但答案似乎很简单,我有点希望OP让我知道这是否是他们想要的...


J. *_*ong 6

在 CSS 中使用的完整解决方案

老问题和许多 JS 解决方案,但没有人真正展示如何在 CSS 中使用它。

步骤1。

使用任何其他答案来计算滚动条宽度并将其保存为根样式属性。即在你的 JS 文件中:

document.documentElement.style.setProperty('--scrollbar-width', (window.innerWidth - document.documentElement.offsetWidth) + 'px');
Run Code Online (Sandbox Code Playgroud)

第2步。

在 CSS 中使用新创建的变量。即按照OP的原始方法:

/* Paragraph margin predicted for future scrollbar on div */
div p {margin: 20px (20px + var(--scrollbar-width)) 20px 50px;}
/* With scrollbar margin is symmetrical */
div:hover p {margin: 20px;} /* With scrollbar */
Run Code Online (Sandbox Code Playgroud)

额外提示:解决将相对 DIV 内的子项扩展到屏幕全宽的常见问题。粘贴到您想要展开的子项内:

width: calc(100vw - var(--scrollbar-width));
margin-left: calc(-50vw + 50% + (var(--scrollbar-width)) / 2);
Run Code Online (Sandbox Code Playgroud)


Rol*_*kas 5

纯 CSS 解决方案在这里。
我会在文本 div 的右侧创建一个不可见的 div,里面有强制滚动条:

<div class="container">
  <div class="text">Your very and very long text here</div>
  <div class="scrollbar-width"></div>
</div>
<style>
.container {
   display: flex;
   width: 100px; /* to make scrollbar necessary */
   height: 30px; /* to make scrollbar necessary */
   border: 1px solid blue;
}
.text {
   flex: 1; 
   float: left;
   overflow-y: hidden; 
}
.scrollbar-width {
   float: left; 
   overflow-x: hidden; 
   overflow-y: scroll; 
   visibility: hidden;
}
.scrollbar-width::-webkit-scrollbar { /* for debugging */
  background-color: red;
}
.text:hover {
   overflow-y: scroll; 
}
.text:hover + .scrollbar-width {
  display: none;
}
</style>
Run Code Online (Sandbox Code Playgroud)

scrollbar-widthdiv 被标记时,visibility: hidden它仍然会占用空间。

现在,当您最终决定显示自己的滚动条时,将其添加display: none到不可见的scrollbar-widthdiv,这样它就不再占用空间,因此您的textdiv 会填满所有可用空间并变得更宽。

如果您想验证,请visibility: hidden;scrollbar-widthdiv样式中删除。然后你可以看到这个占位符 div 最初是如何占用空间的(根据上面的“用于调试”样式,它显示为红色)并且在悬停时它消失并被文本 div-s 滚动条替换。

JS小提琴链接:https : //jsfiddle.net/rb1o0tkn/