web-dev-qa-db-ja.com

CSS:ブラウザのスクロールバーの幅を取得する方法は? (:hover {overflow:auto}の場合は適切なマージン)

タイトルがはっきりしているのかわからないので、説明は少ない。いくつかの小さな要素があります。たとえば、div 's(200px x 400px CONSTANT)としましょう。それぞれの内部には、約20行のテキストを含む段落があります。 もちろん、これはかわいそうなdivには大いに役立ちます。私がしたいのは:

  1. 通常、divにはoverflow: hiddenプロパティがあります。
  2. マウスオーバー(:hover)すると、このプロパティがoverflow: auto;に変更され、スクロールバーが表示されます。

何が問題ですか?段落テキストとスクロールバーの間に少しスペース(パディングまたはマージン)が必要です。段落に対称的なmargin: 20px;があるとします。ただし、:hoverがトリガーされた後、スクロールバーが表示され、段落の右側全体が"scrollbar-width" pxを左に移動します。文は他の行で区切られており、段落全体が異なって見えます。これは非常に煩わしく、ユーザーフレンドリーではありません。 CSSを設定するにはどうすればよいので、ホバーした後の唯一の変更は、スクロールバーの外観になりますか?

言い換えると:

/* 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 */

私はstrongでの問題の説明とともに、少しのスニペットを作成しました。すべてが明確であることを願っています:)約2時間、解決策を探しています、私の質問は非常にユニークで興味深いと思います。

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;
}
<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>
14

すべてのスクロールバーはブラウザとOSによって異なる可能性があるため、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);

だから私はいくつかのjqueryコードをすばやく追加しましたが、JSでしか実行できないと思います。

15
tomtomtom

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;
  }
}

このクラスは、次のように使用できます。

let scrollbox = new TempScrollBox();

console.log(scrollbox.width) //-> 17 (Windows, Chrome)

フィドル: https://jsfiddle.net/nu9oy1bc/

4
Oliver

innerWidthは、スクロールバーを含むブラウザビューポートの幅を返します。

読み取り専用のWindowプロパティinnerWidthは、ウィンドウの内部の幅をピクセル単位で返します。これには、垂直スクロールバーの幅が含まれます(存在する場合)。

clientWidthdocumentのようなルート要素で使用すると、スクロールバーを除くビューポートの幅が返されます。

ルート要素(要素)でclientWidthが使用されている場合(またはドキュメントが互換モードの場合)、ビューポートの幅(スクロールバーを除く)が返されます。

let scrollbarWidth = (window.innerWidth - document.body.clientWidth) + 'px';

2つの値を差し引いて、ほら、スクロールバーの幅がわかります。

この例では、通常、次が返されます:15px

0
gummiost

純粋な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>

scrollbar-width divがvisibility: hiddenでマークされている場合でも、スペースを使用します。

最後に独自のスクロールバーを表示することを決定したら、display: noneを非表示のscrollbar-width divに追加します。これにより、スペースが不要になるため、text divがすべての使用可能なスペースを埋め、広くなります。

確認する場合は、visibility: hidden; divのスタイルからscrollbar-widthを削除します。次に、このプレースホルダーdivが最初にどのようにスペースを使用しているか(上記の「デバッグ用」スタイルに従って赤く表示されます)を確認できます。ホバーすると、非表示になり、テキストdiv-sスクロールバーに置き換えられます。

JSフィドルリンク: https://jsfiddle.net/rb1o0tkn/

0
Roland Pihlakas

私のような誰かが「ブラウザのスクロールバーの幅を取得する方法」をグーグル検索してこの質問を見つけた場合、CSSクラスを追加せずにjQueryを実装しています。

var div = $("<div style='overflow:scroll;position:absolute;top:-99999px'></div>").appendTo("body"),
    width = div.prop("offsetWidth") - div.prop("clientWidth");
div.remove();

console.log(width);

または JSFiddle (必要な場合)。

ありがとう tomtomtomの答え アイデア

0
Yurii Semeniuk