Mobiscroll + Samsung Galaxy S3 + position: fixed = Broken scroller? - css

We are using Mobiscroll on our mobile website and it works just fine, except on one device: My boss' Samsung Galaxy S3 (runs stock Samsung fw and stock browser, but Mobiscroll works fine with Chrome). It looks like the z-index of all the elements get messed up.
It looks like this:
http://pix.toile-libre.org/?img=1350013732.png
Everything is dark and hard to read, and the numbers go over the arrows.
I played a bit with the CSS and removed the transparent background of the page, which made all the colors go back to normal (I was not able to make it go behind as it should for some reasons). But the numbers of the wheels still goes in front of the arrows.
I played even more with the CSS and figured out that the -webkit-transform3d makes the wheels go in front of everything, like if it had it's own layer on top of everything.
After a while, I finally found that the problem is caused because my menu bars have "position: fixed;" on them so they stick to the viewport. As soon as put them to something else than "position: static;", the browser seems to mess up everything, including Mobiscroll.
I need to keep these menus fixed, and there are other elements in the page that will get "position: absolute;"
Any idea how I should solve this? Should I hack the CSS and JS of Mobiscroll to get rid of the transform3d and the background so it appears to work not bad, or is there a better solution for that horrible device?
Please tell me if you need anything else!
Thanks!

It appears that this is an android 4.0 bug. There is a bug report on it here:
http://code.google.com/p/mobiscroll/issues/detail?id=96

I face this problem also.. its sucks.
The only solution ive found, is to use mobiscroll onShow & onClose events, to hide and show this position fixed element which cause the overlays problem (in may case that was the footer that was position fixed).

$(".date-picker").mobiscroll().date({
onShow: function(html, inst) {
var header = $('div[data-role="header"]');
if(header) header.css('position', 'absolute');
var footer = $('div[data-role="footer"]');
if(footer) footer.css('position', 'absolute');
},
onClose: function(html, inst) {
var header = $('div[data-role="header"]');
if(header) header.css('position', 'fixed');
var footer = $('div[data-role="footer"]');
if(footer) footer.css('position', 'fixed');
}
});

I know its kind of late. But this did the fix for me,
-webkit-backface-visibility: hidden
on the div

Related

Mobile Webkit reflow issue

I've been experiencing an issue in mobile versions of webkit (specifically Webkit 534.46 on iOS 5.1.1 as mobile Safari, and now Chrome for iOS) which doesn't happen on any desktop browser that I've seen. (i.e. the demos below should be viewed on a mobile version of webkit.)
Here is a live example of the issue. The core of the CSS is extremely straight forward. It positions an alphabet index along the left of the page:
#index {
left:0; margin:0; padding:0; position:fixed; top:0; width:3em;
}
The issue happens when an element is fixed position over the top of the body. It is fully able to be interacted with until the scroll changes and then it stops accepting input. If I (manually) jiggle the scroll even one pixel then it becomes active again. The example was kept as simple as possible and does not use any JavaScript. After really hammering on it, I've discovered that it appears that the element thinks it is scrolled but has been visually fixed. In other words, if you click on 'A' then try to click on 'A' again, sometimes you will get a second click in but it will be further down the list. This seemed like a CSS reflow issue to me. I know that mobile webkit attempts to reduce the number of reflows.
Here is a live example of the workaround.
I am able to use JS to force the CSS of the entire document to reflow on scroll (with a throttle which prevents it from happening until 100ms after scrolling) which seems to workaround this issue in the simple example. Unfortunately, this does not help the real world version of this issue.
This is the code for the issue page and the workaround script.
My question is what is happening here and is there a CSS workaround that I am missing? Specifically, I'm curious if any CSS guru can figure out what the layout situation is that prevents the clicks from hitting the correct place on the fixed element? A better understanding might help find a real fix.
Edit: I forgot to mention that the example explicitly forces the viewport to the size of the window. So the user cannot zoom in/out, meaning that the position:fixed should anchor the element to the left side of the window.
Update (2012-09-20): This appears to be fixed in Mobile Safari on iOS 6 (as well as UIWebView). Any workaround should first check to make sure it is on iOS < 6. For example, using CssUserAgent this would look like:
if (parseFloat(cssua.ua.ios) < 6) { /* ... */ }
The answer that actually solved my particular issue was a variation of a solution found in one of #Paul Sweatte's links:
Essentially, a plain div which is taller than the body is added. When it is removed, it causes the body to effectively scroll or reflow. Setting the delay to 0ms between adding/removing is enough to allow the DOM to recalculate without causing any flickering. This was the minimal script I could find which fully solved the problem for all position:fixed elements on my particular instance of this issue.
var hack = document.createElement("div");
hack.style.height = "101%";
document.body.appendChild(hack);
setTimeout(function(){
document.body.removeChild(hack);
hack = null;
}, 0);
Ironically, my original reflow fix (linked to in the question) is now working in my real app, too. Putting a variant of it here in case is useful to anyone else. It can be called on any container element, or if nothing is passed in it reflows the whole document.
var forceReflow = function(elem){
elem = elem || document.documentElement;
// force a reflow by increasing size 1px
var width = elem.style.width,
px = elem.offsetWidth+1;
elem.style.width = px+'px';
setTimeout(function(){
// undo resize, unfortunately forces another reflow
elem.style.width = width;
elem = null;
}, 0);
};
The nice thing about this is that it doesn't require creating / adding / removing elements, just tweaking the container.
My install of iWebInspector is pretty busted right now, but after messing around with jsfiddle and the iOS sim it seems like your hunch is correct - despite being position:fixed, the browser thinks the page has scrolled, and screws up the click targets.
It looks a lot like this is the same issue as iOS Safari: Anchors within a fixed positioned element only work once, which also hasn't been solved with pure CSS. Also related: Fixed position navbar only clickable once in Mobile Safari on iOS5.
Tangentially, and I'm sure it's been noticed already, it's not possible to scroll the left side, so on an iPhone the index only shows A-M.
Looks like this is a known bug:
the core problem is: if the page moves programatically (i.e. the user didn’t cause the scroll) the elements inside the fix element are unavailable.
Use absolute positioning, change the markup, or use one of the hybrid workarounds.
Here's a variation of McKamey's workaround. It avoids reflowing twice, and may help with flickering (depending on your app):
setTimeout(function(){
document.body.style.borderBottom =
document.body.style.borderBottom === 'none' ? '1px solid white' : 'none';
}, 0);
I believe this is better, and achieves the same effect, allowing links to be clickable in fixed footers. Somehow, doing urlbar hiding causes links in the fixed footer to be unclickable until you scroll a little bit. I have seen this too when focusing inputs, and I attach an event handler to all focus events to fire this off as well. I do this with dojo to attach the events.
if(navigator.userAgent.match(/iPhone/i)){
/* The famous iOS can't-click-links until touch fix, I attach onfocus */
query('input,textarea,select', this.domNode).on('focus', function(el){
document.documentElement.style.paddingRight = '1px';
setTimeout(function () {
document.documentElement.style.paddingRight = '';
}, 0);
});
}

JavaScript to hide browser chrome causes position: fixed bug on iOS

Here is my site:
http://smartpeopletalkfast.co.uk/pos/
There is a div #nav which has a fixed position. The site will be mobile optimized so im hiding the browser chrome with the following JavaScript:
setTimeout(function() {
window.scrollTo(0, 1) },
100);
Ive found a bug when viewing the site in an iPhone 3G, iPhone Retina and iPad. If you click on '1' on the front page to take you to the third section, scroll down the page, and then click '< Map' to go to the map section, the nav which now contains the text '< Filters' is in the wrong place. As soon as you scroll up or down the div jumps to the correct place.
Position fixed is not catered for on iOS4/iPhone3GS.... I had the same issue, a fixed header with a back button on it, went wrong with I used scrollTo. The back wouldn't work but a link underneath the header would be clicked My findings below;
Under further investigation with an iOS man, we have discovered it is a bug in Safari on iOS5.
I tried this;
// $('html,body').animate({ scrollTop: scrollto + 'px' }, 'slow')
window.scroll(0,0);
And saw it actually drew the fixed header further down the screen. With the click working.
So I swapped the code back, and although it drew the header correctly at the top, the active click area was still further down the page, though was invisible, was clickable.
Seems they have resolved it testing on iOS6.
I exhausted all kinds of CSS and DOM manipulation, removing, and re-inserting a new header area... nothing works.
So I am 99% sure to post this an THE ANSWER. lol. Though I realise that doesn't help you.

CSS Fixed-position Nav that slides away at page bottom

I'm working on my website, http://www.perezfox.com, which features a fixed-position navigation menu. I'm happy with how this operates, but there is a problem with vertically-challenged browser windows. Users who scroll to the bottom will see the nav overlapping with the footer because their browsers don't have enough vertical space to accommodate both.
Is there a way to "push" the otherwise-static nav menu up as the page bottom approaches? Perhaps specify a distance-to-bottom that will override the position: fixed style? A friend has suggested that I need to monitor the page position and "fire an event", but I'm not sure what that means in practical terms.
I'm comfortable with CSS and HTML, but more of a beginning with Javascript and jQuery. Any advice is graciously appreciated, keeping that in mind. For example, you might have to say something to the effect of "put this within a script tag within your site head ..."
Thanks in advance!
EDIT
I found a few examples of this behaviour, but most of them are reversed. For example:
http://www.madebyparachute.com/products
On this site, the [left column] navigation elements start scrollable, become fixed. I want to have mine start fixed, become scrollable. Also, this one concerns the top, whereas mine concerns the bottom. But I image it's similar functionality at work, no?
I appreciate everyone leaving feedback but after a very frustrating day with this stuff, I must beg and plead that you please, please, don't just throw code at me. I need a bit of instruction, especially if there are script, CSS, and HTML components working in concert.
Also, note that I'm using the HTML5 elements for <nav> and <footer>, and not the traditional <div id="whatever">.
Thanks!!!
If you don't mind not supporting older browsers, you can use CSS3 Media Queries to change the styling when the window gets too short. It might look something like:
#media screen and (max-height:300px) {
navigation-element {
position:relative;
}
}
Note that for IE this only works in 9+. Other browsers are fine, i think.
Edit
If you need older browser support, you could do something like:
window.onresize = funciton() {
var sidebar = document.getElementById("idOfSidebar");
sidebar.style.position="relative";
//other styling stuff here
}
You can use jquery to set the nav to have relative positioning if the height of the browser is too small using the css function.
It might look something like this:
$(window).resize(function() {
if($(document).height() <= someNumber){
$("#nav").css('position', 'static');
} else {
$("#nav").css('position', 'fixed');
}
});

Scroll returns to default after display:none in Chrome/IE

Here's the example: http://jsfiddle.net/sammy/RubNy/
Scroll down in the div container. Then click anywhere in the window to hide the element. Then click once more to show the element. You'll notice in Chrome/IE that the scroll is reset, but in Firefox, the scroll remains how you left it.
Which is the standards behavior, Chrome/IE or Firefox? Should I report this to the Chrome issue tracker?
Thanks in advance for any help on this, and happy new year, and thanks again, and cheers, and stuff. =D
Although I'm not sure which of the two browsers (Chrome or Firefox) is following the standard on this one, I'll blame Chrome for being incorrect for not "remembering" the scroll position. In other words, I favor Firefox's behavior, but I'm unsure which is correct (standardized).
Until someone points out which is correct according to standard documentation, I'll continue to blame Chrome. I'll report this bug to the Chrome issue tracker if I haven't already. :P
You can save current element.scrollTop to some bufferVar before display: none. When display: block you reset element.scrollTop back to bufferVar.
But this approach won't work immediately for some reasons not obvious to me. Use something like this to make it work:
setTimeout(() => { element.scrollTop = bufferVar; }, 100);
I don't know which are right however this works:
var offset = 0;
$(document).click(function(){
if($('div:visible').length) {
offset = $('div').scrollTop();
}
$('div').toggle().scrollTop(offset);
});
I hope somebody has a better solution =/
Its just a quirk in how the browsers render the div when the display changes...
Essentially, the browsers reflow the text when the display property changes...
This causes the same quirk...
$(document).click(function(){
$('div').style.display = "block";
});
If you want the scroll to remain the same in all browsers, the easiest thing to use is visibility instead of display...

z-index issue in ie

i know this issue is well documented but i cant find a working solution from what ive been reading. I have a pretty large site and i want a div to sit ontop of everything else on the site. now ive tried giving the div "position:absolute; z-index:99999;", this will work in everything apart from ie. How can i do this in ie?
You can try:
position: fixed; z-index: 9999;
This will make the div to appear on top of the others. (and follow as you scroll down)
so i tried this jquery script i found
$(function () {
var zIndexNumber = 1000;
$('div').each(function () {
$(this).css('zIndex', zIndexNumber);
zIndexNumber -= 10;
});
});
i added another wrapper around it to check if the broswer is ie before hand. this seems to fix the issue but does mean pages are slower loading in ie as every div is being treated. when the page loads.
This isn't what should happen. Without seeing the HTML & CSS, it's difficult to identify why. Some standard debugging techniques...
Setting the z-index to a very high number should render that element in front of everything else**. If it's not being rendered in front, then something is setting the z-index of the other elements to something higher. This could be set in CSS or by script. The quick check is to turn off scripting. To investigate this, use firebug to find the z-index of the element in front. To find it, edit any scripts, even minified ones, and simply search for "z-index".
It sounds like a quick "back to basics" re-examination of the problem may yeild the cause.
Normally one would use low z-index numbers - 2 is higher than 1, why use more?!? Some plug-in developers have been known to use stupidly high z-index numbers.
.
** IE 6 has a well-known bug where replaced form elements (e.g. select) will 'shine' through. The fix is to put an iframe in front of it.

Resources