CSS: How to get browser scrollbar width? (for :hover {overflow: auto} nice margins)
Scrollbar widths can vary between browsers and operating systems, and unfortunately CSS does not provide a way to detect those widths: we need to use JavaScript.
Other people have solved this problem by measuring the width of the scrollbar on an element:
- http://davidwalsh.name/detect-scrollbar-width (original post)
- http://jsfiddle.net/a1m6an3u/ (live example)
We create a div .scrollbar-measure
, add a scrollbar, and return its size.
// Create the div
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);
// Delete the div
document.body.removeChild(scrollDiv);
This is fairly straightforward, but it is (obviously) not pure CSS.
Getting scroll bar width using JavaScript
This function should give you width of scrollbar
function getScrollbarWidth() {
// 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;
}
Basic steps here are:
- Create hidden div (outer) and get it's offset width
- Force scroll bars to appear in div (outer) using CSS overflow property
- Create new div (inner) and append to outer, set its width to '100%' and get offset width
- Calculate scrollbar width based on gathered offsets
Working example here: http://jsfiddle.net/slavafomin/tsrmgcu9/
Update
If you're using this on a Windows (metro) App, make sure you set the -ms-overflow-style property of the 'outer' div to scrollbar
, otherwise the width will not be correctly detected. (code updated)
Update #2
This will not work on Mac OS with the default "Only show scrollbars when scrolling" setting (Yosemite and up).
How can I detect the scroll width and differentiate between the mobile and the desktop versions?
I managed to do it by testing the scroll width in the ngOnInit as suggested in this answer (I edited a little for convenience), to test if it was mobile or not:
testIsMobile() {
var scrollbox = document.createElement('div');
scrollbox.style.overflow = 'scroll';
document.body.appendChild(scrollbox);
var scrollWidth = scrollbox.offsetWidth - scrollbox.clientWidth;
document.body.removeChild(scrollbox);
this.isMobile = scrollWidth == 0
}
Then I added the correct class through [ngClass]="fixedHeaderClass"
if (this.isMobile)
this.fixedHeaderClass = "fixed-header-mobile";
else
this.fixedHeaderClass = "fixed-header";
CSS 100% width but avoid scrollbar
Use overflow: scroll
instead of overflow: auto
- that'll force a scrollbar to always appear.
Make scrollbars only visible when a Div is hovered over?
div {
height: 100px;
width: 50%;
margin: 0 auto;
overflow: hidden;
}
div:hover {
overflow-y: scroll;
}
<div>
<p>Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It
has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop
publishing software like Aldus PageMaker including versions of Lorem Ipsum.
</p>
</div>
Rounded scrollbar that hovers over content
.list {
position: relative;
display: flex;
max-height: 200px;
max-width: 200px;
flex-direction: column;
overflow-y: overlay;
border: 1px solid black;
}
.list::-webkit-scrollbar {
width: 22px;
}
.list::-webkit-scrollbar-track {
width: 20px;
}
.list::-webkit-scrollbar-thumb {
height: 73px;
width: 24px;
background-clip: padding-box;
background-color: rgba(0, 0, 0, 0.25);
border-radius: 15px;
border: 8px solid rgba(0, 0, 0, 0);
}
.list::-webkit-scrollbar-corner {
background-color: transparent;
}
.list::-webkit-scrollbar-corner {
background-color: transparent;
}
<ul class="list">
<li>item 1</li>
<li>item 2</li>
<li>item 3</li>
<li>item 4</li>
<li>item 5</li>
<li>item 6</li>
<li>item 7 is pretty long so it goes under</li>
<li>item 8</li>
<li>item 9</li>
<li>item 10</li>
<li>item 11</li>
<li>item 12</li>
<li>item 13</li>
<li>item 14</li>
<li>item 15</li>
<li>item 16</li>
<li>item 17</li>
</ul>
How to prevent scrollbar from repositioning web page?
overflow-y:scroll is correct, but you should use it with the html tag, not body or else you get a double scrollbar in IE 7
So the correct css would be:
html {
overflow-y: scroll;
}
Showing scrollbars only when mouseover div
You can make overflow hidden until the mouse is over it, then make it auto.
This is what I did ... note the 16px padding assumes a scrollbar is 16px wide, and is there so the text doesn't re-wrap when the scrollbar appears.
div.myautoscroll {
height: 40ex;
width: 40em;
overflow: hidden;
border: 1px solid #444;
margin: 3em;
}
div.myautoscroll:hover {
overflow: auto;
}
div.myautoscroll p {
padding-right: 16px;
}
div.myautoscroll:hover p {
padding-right: 0px;
}
See it in action at this fiddle - you'll want to widen the right side "result" window to see the whole box, or reduce the width in the css.
Edit 2014-10-23
There is now more variation in how systems and browsers display scrollbars, so my 16px
space may need to be adjusted for your case. The intent of that padding is to prevent the text from being re-flowed as the scrollbar appears and disappears.
Some systems, such as newer versions of Mac OS X (10.8.x at least), don't show scrollbars until you start scrolling which could throw this whole technique off. If the scrollbar doesn't show you may have no reason to hide it until hover, or you may want to leave overflow as auto
or even scroll
rather than toggling it.
Related Topics
How to Handle HTML5 Constraint Validation Pop-Up Using Selenium
How to Use the Z-Index Properly
Possible to Style the CSS3 Resize Function
Internet Explorer 11 Word Wrap Is Not Working
Chrome Could Play HTML5 Mp4 Video But HTML5Test Said Chrome Did Not Support Mp4 Video Codec
Width 100% with White Borders Around It. Why
How to Use Multiple Itemprops in a Span Tag for Schema.Org Rich Snippets
Div with Triangle at the Bottom with Background Image
How to Make a Sticky Footer Using Flexbox in Ie11
How to Stop the Browser from Url-Encoding Form Values on Get
Bootstrap Grid, Do I Need a Container
Removing Border Style Changes Page Layout