I need to be able to detect whether there are scrollbars (both vertical and horizontal) on a browser window. I've been using this code but it isn't working reliably in Firefox 5.
JFL.GetScrollbarState = function () {
var myWidth = 0;
var myHeight = 0;
if (document.documentElement && document.documentElement.clientWidth) {
myWidth = document.documentElement.clientWidth;
myHeight = document.documentElement.clientHeight;
} else {
myWidth = document.body.clientWidth;
myHeight = document.body.clientHeight;
}
return ({
vScrollbar: document.body.scrollHeight > myHeight,
hScrollbar: document.body.scrollWidth > myWidth
});
}
Is there a better way to do this that will work cross browser. My browser targets are Firefox 4-5, Chrome, Safari 4+, Opera 10+.
If you're interested in why I need to know if there are scrollbars, it's because I have some spinning CSS3 transitions that (due to the nature of their spinning) may temporarily go beyond the edges of the current document size (thus making the document temporarily larger). If were no scrollbars initially present, the CSS3 transition may cause scrollbars to show up during the transition and then go away when the transition is finished, leading to an ugly scrollbar flash. If I know that there are no scrollbars present, I can temporarily add a class that will set overflow-x or overflow-y to hidden and thus prevent the scrollbar flash during the CSS3 transition. If scrollbars are already present, I don't have to do anything because they may move a little, but they won't go on/off during the transition.
Bonus points if one can actually tell not only if scrollbars would generally be required, but whether they are actually there or not.
After running into flicker problems with the scrolling version proposed by David in some browsers (Safari and IE), I've settled on this code that does not have the flicker problem:
function getScrollBarState() {
var result = {vScrollbar: true, hScrollbar: true};
try {
var root = document.compatMode=='BackCompat'? document.body : document.documentElement;
result.vScrollbar = root.scrollHeight > root.clientHeight;
result.hScrollbar = root.scrollWidth > root.clientWidth;
} catch(e) {}
return(result);
}
It's a derivative of what I was using and the general technique was referenced in the post that fanfavorite posted. It seems to work in every browser I've tried even in IE6. For my purposes, I wanted any failure to return that there was a scrollbar so I've coded the failure condition that way.
Note: this code does not detect if a scrollbar has been forced on or off with CSS. This code detects if an auto-scrollbar is called for or not. If your page might have CSS settings that control the scrollbar, then you can get the CSS and check that first.
Have you taken a look at this other post? How can I detect a Scrollbar presence ( using Javascript ) in HTML iFrame?
It's actually pretty easy. This will work in every modern browser:
// try scrolling by 1 both vertically and horizontally
window.scrollTo(1,1);
// did we move vertically?
if (window.pageYOffset != 0) {
console.log("houston, we have vertical scrollbars");
}
// did we move horizontally?
if (window.pageXOffset != 0) {
console.log("houston, we have horizontal scrollbars");
}
// reset window to default scroll state
window.scrollTo(0,0);
Related
I'm using Bootstrap Markdown on my site. In the demo here, when I enter fullscreen, my browser's scrollbar (Firefox) disappears. However, on my site this does not happen (the scrollbar sticks around). I am wondering how exactly the demo is accomplishing this.
I'm assume this is part of your browsers settings but if you want to accomplish it with javascript it is actually very simple
//Check for fullscreen
if ((window.fullScreen) || (window.innerWidth == screen.width && window.innerHeight == screen.height)){
document.body.style.overflowY = "hidden"
} else {
document.body.style.overflowY = "auto";
}
I used this Checking if browser is in fullscreen post to figure out how to determine if the window was fullscreen so you can refer to that for further information on that.
I have a div that is resized to be at the full height of the viewport on load as well as on resize. The problem that I am having is that on Google Chrome for iOS (I haven't checked Android, but I can imagine that it displays the same erratic behaviours) if I scroll down, as usual the address/tab bar scrolls up. And as it does, it fires resize events. When that happens, the div and its contents jitter and cause scrolling to be come sluggish, as well as causing other oddities with the div below.
JSFiddle: http://jsfiddle.net/mseymour/9PEC4/
I would suggest setting the height of the .home-hero only once on an smartphone, by either checking the height of the window (could cause problems, it's inconstant) or user agent sniffing.
Here are some links:
http://detectmobilebrowsers.com/
What is the best way to detect a mobile device in jQuery?
Detecting a mobile browser
Then set the height only once since on a mobile you cannot really resize the window, and you don't need to resize it on every resize event.
if (isMobile) {
fullScreenSlide(); // resize once
} else {
setResizeEvent(); // Set the event for multiple resizes
}
function setResizeEvent() {
$(window).on("resize", function () {
fullScreenSlide();
}).resize();
}
function fullScreenSlide () {
var browserheight = Math.round($(window).height());
$('.home-hero').height(browserheight);
}
You want to do as little "things" on a smartphone since smartphones are really slow performance wise compared to a desktop
I'm, setting up the mobile side of a website at the moment, and I need custom CSS and Javascript for mobile, so in the CSS I have rules using #media screen and (max-width: 500px) { and in Javascript I was going to use if ($(window).width() < 500.
However, if I resize my browser to the exact pixel the mobile CSS starts being used and I console.log($(window).width()); I get 485.
Is this normal behaviour or am I doing something wrong?
Update:
Using this, the values seem to be in sync, only tested in firefox though at the moment.
var scrollBarWidth = false;
function mobileRules() {
if (!scrollBarWidth) {
var widthWithScrollBars = $(window).width();
$('body').css('overflow', 'hidden');
var widthNoScrollBars = $(window).width();
$('body').css('overflow', 'scroll');
scrollBarWidth = widthNoScrollBars - widthWithScrollBars;
console.log('Width: '+widthWithScrollBars+'. Without: '+widthNoScrollBars+'. Scroll: '+scrollBarWidth);
}
console.log($(window).width()+scrollBarWidth+' vs '+globals.mobile_width);
if ($(window).width()+scrollBarWidth < globals.mobile_width) {
console.log('Running mobile rules in jQuery');
}
}
In firefox, media queries consider the width of the scrollbar to be inside the screen width.
This is what gives you the 15px wider screen width.
In webkit based browsers they don't.
If you're interested in why this thing happens, I'll quote this comment of this article :
A problem with Webkit browsers (that aren't following spec) is that the browser can encounter an infinite loop condition caused by media queries, which leads to a browser crash.
For example: >500px overflow-y: scroll, <500px overflow-y: hidden. Size your browser to 505px window width. Since the scroll bar subtracts 15 or so pixels from the width used by the media query, the media query flips you to < 500, but as soon as you hit <500 the scrollbar goes away, and the media query flips you to >500, and then the fun starts because now you have a scroll bar again and you're <500px and you get that style with no scroll bar... Rinse and repeat until the browser finally dies.
Now, write some javascript to calculate the media query max widths, and you have a page that will crash Chrome/Safari as soon as you load it.
My guess is that the spec was written the way it was to prevent this condition. Firefox & Opera are following spec, it's not really their fault you don't agree with spec.
I created a hobby site a few years ago that started as a convenient compact one-line-entry multi-search site. Later, I added various web tools, one-click radio stations, and other enhancements.
At first, I optimized for 1024x768 screens but tried to accommodate 800x600 screens. However, wide screen format is becoming dominant, so I decided it would be better to optimize things a bit by splitting the code, mostly, but not limited to, CSS changes, based on detecting a minimum 960 pixel width.
Screen widths less than 960 pixels wide redirect to a "mini.php" version.
The javascript code below selects the appropriate URL correctly if the web browser is already open. However, when initially opening a browser, the "mini" version is incorrectly selected regardless of the screen width. I tried delaying detection by using setTimeout() without effect.
var myWidth = 981
function vpWidth() {
return( myWidth = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth );
}
vpWidth(); setTimeout(vpWidth,300);
if(myWidth<960) document.location.href="http://www.gooplusplus.com/mini.php";
Who can provide a solution that always works and not just when the browser is already open?
You're never actually setting myWidth. Also, I replaced your function with how jQuery gets the width internally.
function vpWidth() {
return Math.max(document.documentElement["clientWidth"], document.body["scrollWidth"], document.documentElement["scrollWidth"], document.body["offsetWidth"], document.documentElement["offsetWidth"]);
}
var myWidth = vpWidth();
if(myWidth<960) document.location.href="http://www.gooplusplus.com/mini.php";
Make your website responsive which will help you to cover more number of visitors to your size, as most of the people use their smartphone to browse websites nowdays.
http://alistapart.com/article/responsive-web-design
Further testing this width error upon browser startup showed that it seems limited to Chromium-based browsers where the target tab is not the active one. In such cases, Google Chrome took its window width results from the non-maximized window size even though the window was actually maximized.
Two detection steps were required on the way to a solution:
(1) is the browser Chromium-based? --> navigator.userAgent.indexOf("Chrome/")>0
(2) is the tab inactive? --> document.webkitVisibilityState == "hidden"
test URL: http://www.gooplusplus.com/chrome-bug.html
my working solution:
<script>
var myWidth = 981
var dde = document.documentElement;
var tabVisible = document.webkitVisibilityState;
if(!document.documentElement) dde = document.body; // fix for IE6 and earlier
myWidth = Math.max(dde.scrollWidth,dde.offsetWidth,dde.clientWidth);
if( ( navigator.userAgent.indexOf("Chrome/")<0 || tabVisible!="hidden" ) && myWidth < 960 )
document.location.href="http://www.gooplusplus.com/mini.php";
</script>
The above technique fixed the problem. Although the #theJoeBiz answer turned out to be irrelevant to the ultimate solution, his code was useful. I based my own new myWidth assignment code on his jQuery Math.max code, while noting that his code failed on my non-jQuery web page due to inclusion of pre-IE7 document.body variables (see fix in code above).
I've run into an odd issue with what appears to be various versions of Webkit browsers. I'm trying to position an element on the center of the screen and to do the calculations, I need to get various dimensions, specifically the height of the body and the height of the screen. In jQuery I've been using:
var bodyHeight = $('body').height();
var screenHeight = $(window).height();
My page is typically much taller than the actual viewport, so when I 'alert' those variables, bodyHeight should end up being large, while screenHeight should remain constant (height of the browser viewport).
This is true in
- Firefox
- Chrome 15 (whoa! When did Chrome get to version 15?)
- Safari on iOS5
This is NOT working in:
- Safari on iOS4
- Safari 5.0.4
On the latter two, $(window).height(); always returns the same value as $('body').height()
Thinking it was perhaps a jQuery issue, I swapped out the window height for window.outerHeight but that, too, does the same thing, making me think this is actually some sort of webkit problem.
Has anyone ran into this and know of a way around this issue?
To complicate things, I can't seem to replicate this in isolation. For instance: http://jsbin.com/omogap/3 works fine.
I've determined it's not a CSS issue, so perhaps there's other JS wreaking havoc on this particular browser I need to find.
I've been fighting with this for a very long time (because of bug of my plugin) and I've found the way how to get proper height of window in Mobile Safari.
It works correctly no matter what zoom level is without subtracting height of screen with predefined height of status bars (which might change in future). And it works with iOS6 fullscreen mode.
Some tests (on iPhone with screen size 320x480, in landscape mode):
// Returns height of the screen including all toolbars
// Requires detection of orientation. (320px for our test)
window.orientation === 0 ? screen.height : screen.width
// Returns height of the visible area
// It decreases if you zoom in
window.innerHeight
// Returns height of screen minus all toolbars
// The problem is that it always subtracts it with height of the browser bar, no matter if it present or not
// In fullscreen mode it always returns 320px.
// Doesn't change when zoom level is changed.
document.documentElement.clientHeight
Here is how height is detected:
var getIOSWindowHeight = function() {
// Get zoom level of mobile Safari
// Note, that such zoom detection might not work correctly in other browsers
// We use width, instead of height, because there are no vertical toolbars :)
var zoomLevel = document.documentElement.clientWidth / window.innerWidth;
// window.innerHeight returns height of the visible area.
// We multiply it by zoom and get out real height.
return window.innerHeight * zoomLevel;
};
// You can also get height of the toolbars that are currently displayed
var getHeightOfIOSToolbars = function() {
var tH = (window.orientation === 0 ? screen.height : screen.width) - getIOSWindowHeight();
return tH > 1 ? tH : 0;
};
Such technique has only one con: it's not pixel perfect when page is zoomed in (because window.innerHeight always returns rounded value). It also returns incorrect value when you zoom in near top bar.
One year passed since you asked this question, but anyway hope this helps! :)
I had a similar problem. It had to do with 2 thing:
Box-sizing CSS3 property:
In the .height() jQuery documentation I found this:
Note that .height() will always return the content height, regardless of the value of the CSS box-sizing property. As of jQuery 1.8, this may require retrieving the CSS height plus box-sizing property and then subtracting any potential border and padding on each element when the element has box-sizing: border-box. To avoid this penalty, use .css( "height" ) rather than .height().
This may apply to $('body').height().
Document ready vs Window.load
$(document).ready() is run when the DOM is ready for JS but it's possible that images haven't finished loading yet. Using $(window).load() fixed my problem. Read more.
I hope this helps.
It is 2015, we are at iOS 8 now. iOS 9 is already around the corner. And the issue is still with us. Sigh.
I have implemented a cross-browser solution for the window size in jQuery.documentSize. It stays clear of any kind of browser sniffing and has been heavily unit-tested. Here's how it works:
Call $.windowHeight() for the height of the visual viewport. That is the height of the area you actually see in the viewport at the current zoom level, in CSS pixels.
Call $.windowHeight( { viewport: "layout" } ) for the height of the layout viewport. That is the height which the visible area would have at 1:1 zoom - the "original window height".
Just pick the appropriate viewport for your task, and you are done.
Behind the scenes, the calculation roughly follows the procedure outlined in the answer by #DmitrySemenov. I have written about the steps involved elsewhere on SO. Check it out if you are interested, or have a look at the source code.
Try this :
var screenHeight = (typeof window.outerHeight != 'undefined')?Math.max(window.outerHeight, $(window).height()):$(window).height()
A cross browser solution is set that by jQuery
Use this property:
$(window).height()
This return a int value that represents the size of visible screen height of browser in pixels.