finding the DOM scrollbar width - javascript

I would like to find the pixel width of the vertical and horizontal scrollbars.
I know that they are different for different OSes/browsers.
I found this code that attempts to detect it, but alas, it doesnt seem to work on IE7:
function scrollbarWidth() {
var scrollbarWidth = 0;
if ($.browser.msie) {
var $textarea1 = $('<textarea cols="10" rows="2"></textarea>')
.css({ position: 'absolute', top: -1000, left: -1000 }).appendTo('body'),
$textarea2 = $('<textarea cols="10" rows="2" style="overflow: hidden;"></textarea>')
.css({ position: 'absolute', top: -1000, left: -1000 }).appendTo('body');
scrollbarWidth = $textarea1.width() - $textarea2.width() + 2; // + 2 for border offset
$textarea1.add($textarea2).remove();
} else {
var $div = $('<div />')
.css({ width: 100, height: 100, overflow: 'auto', position: 'absolute', top: -1000, left: -1000 })
.prependTo('body').append('<div />').find('div')
.css({ width: '100%', height: 200 });
scrollbarWidth = 100 - $div.width();
$div.parent().remove();
}
return scrollbarWidth;
}

This function should give you the width of the vertical scrollbar:
function scrollbarWidth()
{
var outer = document.createElement("div");
outer.style.visibility = "hidden";
outer.style.width = "100px";
// for win 8
outer.style.msOverflowStyle = "scrollbar";
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;
}
The main steps of this function are the following:
Create an outer div of width 100px
Then forces the scrollbar to appear in the outer div
Create a new inner div and append inside the outer div. Set its height to 100%
Calculate the difference between both widths.
Similarly, you can also get both the width of the vertical scrollbar, and the height of the horizontal scrollbar, setting a given height to the outer div, and calculating also the height difference of both divs, like this:
function scrollbarWidthHeight()
{
var outer = document.createElement("div");
outer.style.visibility = "hidden";
outer.style.width = "100px";
outer.style.height = "100px";
// for win 8
outer.style.msOverflowStyle = "scrollbar";
document.body.appendChild(outer);
var widthNoScroll = outer.offsetWidth;
var heightNoScroll = outer.offsetHeight;
// force scrollbars
outer.style.overflow = "scroll";
// add innerdiv
var inner = document.createElement("div");
inner.style.width = "100%";
inner.style.height = "100%";
outer.appendChild(inner);
var widthWithScroll = inner.offsetWidth;
var heightWithScroll = inner.offsetHeight;
// remove divs
outer.parentNode.removeChild(outer);
return {
width: widthNoScroll - widthWithScroll,
height: heightNoScroll - heightWithScroll
};
}
Tested in chrome, firefox, IE6, IE8, and safari.
It also uses native JavaScript (DOM functions), and doesn't use external dependencies like jQuery :)

Why are you trying to do this? Some context would be nice. If you're trying to make custom theme-able scrollbars, there are many scripts to do this, a good one being jQuery Scrollbars.

Related

Save a specific BoundingClientRect?

I'm using getBoundingClientRect to change an elements position to absolute without changing it's position:
style.position = 'absolute'
style.top = container.getBoundingClientRect().top
style.left = container.getBoundingClientRect().left
style.width = container.offsetWidth
I do this to later transition the element to fullscreen, like this:
style.top = 0
style.left = 0
style.width = '100%'
style.height = '100%'
style.transitionProperty = 'top, left, width, height'
style.transitionDuration = '.2s'
Style is a javascript object that gets converted to css-properties.
Later on I want to close the full-screen-thing and revert the element back to it's original size. I would like to save the values from getBoundingClientRect as they are at the first transition. Can this be done?
Yes, it can be done. Like this:
var bcr = container.getBoundingClientRect();
style.width = '100%';
// later
style.width = bcr.width;
var el = document.querySelector('div');
var bcr = null;
document.querySelector('button').addEventListener('click', function() {
if (bcr) { // Currently fullscreen
el.style.position = '';
el.style.top = bcr.top + 'px';
el.style.left = bcr.left + 'px';
el.style.width = bcr.width + 'px';
el.style.height = bcr.height + 'px';
bcr = null;
} else {
bcr = el.getBoundingClientRect();
el.style.position = 'absolute';
el.style.top = el.style.left = 0;
el.style.width = el.style.height = '100%';
}
});
div {
background: yellow;
height: 100px;
width: 300px;
}
<div>
<button>Toggle fullscreen</button>
</div>
That said, most probably you don't need it, because just assigning the styles to the empty string will do the trick.

Bootstrap modal has a flaw

As I was learning bootstrap and trying out the example on the official page, I found a flaw (maybe) with the modal component.
Click the "Launch demo modal", you will notice there is a notable margin on the top right corner, and the navbar will stretch/shrink when the modal dialog disappear/appear.
Is that a bug or intentional? I think it's annoying, How to disable it?
To fix this manually simply add
body.modal-open,
.modal-open .navbar-fixed-top,
.modal-open .navbar-fixed-bottom
{
margin-right: 0px;
}
to a stylesheet that is applied after the bootstrap stylesheets.
If you want to hide the scrollbar as well you can add
.modal
{
overflow-y: auto;
}
as well.
this is the best solution i found:
body.modal-open, .modal-open .navbar-fixed-top, .modal-open .navbar-fixed-bottom {
padding-right: 0px !important;
overflow-y: auto;
}
This is a reported issue to bootstrap: https://github.com/twbs/bootstrap/issues/9855
And this is my temporary quick fix and it's work using fixed top navbar, only using javascript. Load this script along with your page.
$(document.body)
.on('show.bs.modal', function () {
if (this.clientHeight <= window.innerHeight) {
return;
}
// Get scrollbar width
var scrollbarWidth = getScrollBarWidth()
if (scrollbarWidth) {
$(document.body).css('padding-right', scrollbarWidth);
$('.navbar-fixed-top').css('padding-right', scrollbarWidth);
}
})
.on('hidden.bs.modal', function () {
$(document.body).css('padding-right', 0);
$('.navbar-fixed-top').css('padding-right', 0);
});
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);
};
Here is the working example: http://jsbin.com/oHiPIJi/64
Be sure to test for both when the original page already has a scrollbar and does not already have a scrollbar.
This worked for me with v3.1.1.
html, .modal, .modal.in, .modal-backdrop.in {
overflow-y: auto;
}
in addition to this also make sure you have the following
html { overflow-y:auto; }
in your stylesheet to stop it shifting left
I had this issue as well (bootstrap 3.1.1). I was opening a modal and there was a missing space on the backdrop (where a scroll bar will appear if the modal is greater than page height) and the content of the page was resizing and shifting to the left.
My layout uses a fixed navbar.
I added a couple of CSS selectors that seems to prevent the page resizing and ensuring that the modal-backdrop fills the screen
html {
/* This prevents the page from shifting when a modal is opened e.g. search */
overflow-y: auto;
}
.modal,.modal.in,.modal-backdrop.in {
/* These are to prevent the blank space for the scroll bar being displayed unless the modal is > page height */
overflow-y: auto;
}
I still find it a bit odd where you can have two scroll bars if the page and the modal content is more than the screen height but I can live with that.
body, .navbar-fixed-top, .navbar-fixed-bottom {
margin-right: 0 !important;
}
this worked for me
margin-right did not work in my case, I found padding-right to solve the issue.
body.modal-open {
padding-right: 0px;
}
I tried Agni Pradharma's fix, but had to slightly tweak it to make it work.
I got it working using this:
$(document.body)
.on('show.bs.modal', function () {
if (this.clientHeight <= window.innerHeight) {
return;
}
// Get scrollbar width
var scrollbarWidth = getScrollBarWidth()
if (scrollbarWidth) {
$('.navbar-fixed-top').css('margin-right', scrollbarWidth);
}
})
.on('hide.bs.modal', function () {
$('.navbar-fixed-top').css('margin-right', 0);
});
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);
};

Fixed positioned element in overflow:scroll

I'm trying to make an element be always in top-right side of the window.
The problem is that when scrollbar appears, it keeps same position and ignores size of scrollbar.
How it looks now:
How I'd like it to look:
.outer {
position: relative;
height: 100px;
overflow-x: hidden;
overflow-y: auto;
width: 100%;
}
.icon {
position: fixed;
right: 0;
top: 0;
background: red;
width: 10px; height: 10px;
}
​
The fiddle: http://jsfiddle.net/L5YhF/
Are there any hacks how to fix it?
Thank you.
Try making your right attribute:
right: 10px;
or whatever offset you need.
EDIT :
According to aswer to this this question How can I get the browser's scrollbar sizes? you can write a javascript function to put place your icon the way you want in a cross-browser manner. Example in this fiddle:
http://jsfiddle.net/L5YhF/9/
Code:
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);
};
window.onload = function() {
var scrollWidth = getScrollBarWidth ();
var ico = document.getElementById('ico');
ico.style.right = scrollWidth + "px";
};

How to position a DIV in a specific coordinates?

I want to position a DIV in a specific coordinates ? How can I do that using Javascript ?
Script its left and top properties as the number of pixels from the left edge and top edge respectively. It must have position: absolute;
var d = document.getElementById('yourDivId');
d.style.position = "absolute";
d.style.left = x_pos+'px';
d.style.top = y_pos+'px';
Or do it as a function so you can attach it to an event like onmousedown
function placeDiv(x_pos, y_pos) {
var d = document.getElementById('yourDivId');
d.style.position = "absolute";
d.style.left = x_pos+'px';
d.style.top = y_pos+'px';
}
You don't have to use Javascript to do this.
Using plain-old css:
div.blah {
position:absolute;
top: 0; /*[wherever you want it]*/
left:0; /*[wherever you want it]*/
}
If you feel you must use javascript, or are trying to do this dynamically
Using JQuery, this affects all divs of class "blah":
var blahclass = $('.blah');
blahclass.css('position', 'absolute');
blahclass.css('top', 0); //or wherever you want it
blahclass.css('left', 0); //or wherever you want it
Alternatively, if you must use regular old-javascript you can grab by id
var domElement = document.getElementById('myElement');// don't go to to DOM every time you need it. Instead store in a variable and manipulate.
domElement.style.position = "absolute";
domElement.style.top = 0; //or whatever
domElement.style.left = 0; // or whatever
well it depends if all you want is to position a div and then nothing else, you don't need to use java script for that. You can achieve this by CSS only. What matters is relative to what container you want to position your div, if you want to position it relative to document body then your div must be positioned absolute and its container must not be positioned relatively or absolutely, in that case your div will be positioned relative to the container.
Otherwise with Jquery if you want to position an element relative to document you can use offset() method.
$(".mydiv").offset({ top: 10, left: 30 });
if relative to offset parent position the parent relative or absolute. then use following...
var pos = $('.parent').offset();
var top = pos.top + 'no of pixel you want to give the mydiv from top relative to parent';
var left = pos.left + 'no of pixel you want to give the mydiv from left relative to parent';
$('.mydiv').css({
position:'absolute',
top:top,
left:left
});
Here is a properly described article and also a sample with code.
JS coordinates
As per requirement. below is code which is posted at last in that article.
Need to call getOffset function and pass html element which returns its top and left values.
function getOffsetSum(elem) {
var top=0, left=0
while(elem) {
top = top + parseInt(elem.offsetTop)
left = left + parseInt(elem.offsetLeft)
elem = elem.offsetParent
}
return {top: top, left: left}
}
function getOffsetRect(elem) {
var box = elem.getBoundingClientRect()
var body = document.body
var docElem = document.documentElement
var scrollTop = window.pageYOffset || docElem.scrollTop || body.scrollTop
var scrollLeft = window.pageXOffset || docElem.scrollLeft || body.scrollLeft
var clientTop = docElem.clientTop || body.clientTop || 0
var clientLeft = docElem.clientLeft || body.clientLeft || 0
var top = box.top + scrollTop - clientTop
var left = box.left + scrollLeft - clientLeft
return { top: Math.round(top), left: Math.round(left) }
}
function getOffset(elem) {
if (elem.getBoundingClientRect) {
return getOffsetRect(elem)
} else {
return getOffsetSum(elem)
}
}
You can also use position fixed css property.
<!-- html code -->
<div class="box" id="myElement"></div>
/* css code */
.box {
position: fixed;
}
// js code
document.getElementById('myElement').style.top = 0; //or whatever
document.getElementById('myElement').style.left = 0; // or whatever
To set the content of a div you can use the following:
document.getElementById(id).style.top = "0px";
document.getElementById(id).style.left = "0px";
Exists other good alternatives in jQuery
I cribbed this and added the 'px';
Works very well.
function getOffset(el) {
el = el.getBoundingClientRect();
return {
left: (el.right + window.scrollX ) +'px',
top: (el.top + window.scrollY ) +'px'
}
}
to call: //Gets it to the right side
el.style.top = getOffset(othis).top ;
el.style.left = getOffset(othis).left ;

Sliding Div to auto height

I have a div that I slide in and out.
To do this I just increase the height by 2px every second until a preset height from a height of 0.
Is there anyway to determine the content height of the div as the content is unpredictible height considering the starting properties of the div are display:none and height:0?
Thank you.
The trick is to temporarily show it, measure the height, then hide it again. And if you use visibility: hidden and position: absolute, it won't change the page layout while you do it.
function getElementHeight(el)
{
var styles = {
visibility: el.style.visibility,
height: el.style.height,
position: el.style.position,
display: el.style.display
};
el.style.visibility = "hidden";
el.style.height = "auto";
el.style.position = "absolute";
el.style.display = "block";
var height = el.offsetHeight;
el.style.display = styles.display;
el.style.position = styles.position;
el.style.height = styles.height;
el.style.visibility = styles.visibility;
return height;
}
If you want to get what the style height should be, you can add these two lines after var height = el.offsetHeight;:
el.style.height = height + "px";
height += (height - el.offsetHeight);

Categories

Resources