Skip to content Skip to sidebar Skip to footer

Horizontal One-page Site: Mobile-webkit Scrolling & Swiping Issues

Here is a basic demo of what I'm working with: http://jsfiddle.net/3N8wY/9/ Issue #1 If you view that link from a stock Android browser, or (more importantly) an iOS device, the we

Solution 1:

Issue #1

Turns out that I didn't have Modernizr installed correctly (hadn't included the no-js class in the html tag), which once rectified, solved the hashing issue I was running into on some stock Android browsers.

After that was fixed, I still ran into the odd scrolling behavior. Often, the page would scroll to the desired location, but then jump back. Upon further research, I came across this: Jquery Animate ScrollLeft doesnt work on ipad.

That seemed to fix the undesired scrolling behavior for some of the poor performers, but not on iOS devices. This could have something to do with it, ScrollLeft and ScrollTop on Ipad using animate chain (jQuery), but I've figured out something else that works (will post below).

So far as I can tell, iOS devices (7+) automatically scroll to top BEFORE any scrollLeft animation. I don't have access to any physical devices, but I do have access to an iMac, where I was able to get ahold of the iOS Simulator and observed the unwanted scrolling behavior. I tried unlinking the two scrolling actions (left & top, as most posts will suggest you try), but that didn't make a difference.

It might have had something to do with what I was scrolling (ie the body or the html), I read that in a few posts, but messing with that rendered no useful results.

As I was testing, I realized that by only scrolling left, my script finally functioned "properly".

The interesting bit is that I noticed that the browser would scroll to top AUTOMATICALLY BEFORE horizontally scrolling to my target. So, if they update their code to make scrollLeft function properly, I'll have to go back and add a scrollTop function. For the the time being...

Not exactly a "fix" (the browser behaving inappropriately working to my "benefit", worrisome), but I'll take it.

Issue #2

Just to clarify, it was especially tricky to tackle this one because the page NEEDS to be able to scroll left and right (what with the horizontal layout and all), but only when I want it to.

As far as attempting to disable swiping, I really came up short. The closest I got there was with a plugin called touchSwipe; however, that broke too much (CSS-layout in some mobile browsers), and I couldn't seem to re-enable the tapping of non-link('a') assets.

What I ended up doing is creating a function that would monitor the horizontal scroll position of the window, and reposition the window if it changed. Seems a little buggy in some browsers, but it seems like I'm close to making 'everybody' happy.

EDIT: Changed the function to the much more compliant window.scrollTo(), just had to fetch positions before I fired it. Haven't tested a browser that didn't like it (so far, fingers crossed).

Side note

Lastly, when I got to RWD testing...

I was spoiled with the 'Resize Window' plugin for Chrome, and didn't realize the lackluster availability of working plugins for other browsers. So, I created a testbed full of 20 or so iframes of differing proportions, set to match the most popular device dimensions.

When I got down to mobile device dimensions, I realized that the browser's scrollbar was skewing my proportions. I'd looked into custom scrollbars before, so I delved back into it to attempt to equalize the variable all across the field.

After trying many different plugins, 'nicescroll' was the only one I could get working properly (http://nicescroll.areaaperta.com/). If you're going to use it, be sure to run a mobile test (http://www.detectmobilebrowsers.com/), and only run it on non-mobile devices (admittedly, this script seems to fail at picking up some mobile browsers, but it's better than nothing). All the mobile browsers I tested already had a similar scrollbar in place (by default), so it's completely unnecessary (plus it breaks some mobile browsers).

Working JS

$(document).ready(function() {

    var loadedTarget = $(window.location.hash);

    functionunbindWindow() { $(window).unbind('scroll'); }

    functionrepositionWin() {
        unbindWindow();
        var targetPosLeft = loadedTarget.offset().left;
        $(window).on('scroll', function(e) {
            var alteredPosLeft = $(window).scrollLeft();
            var alteredPosTop = $(window).scrollTop();
            if (alteredPosLeft != targetPosLeft) {
                window.scrollTo(targetPosLeft, alteredPosTop),
                unbindWindow(),  // MAY BE UNNECESSARY, IOS SCARED ME INTO IT, SAME AS BELOW repositionWin();
            }           
        });
    }

    functionbrowserResult() {
        if (jQuery.browser.mobile === true) {
            $('body').css({"overflow-x":"hidden","overflow-y":"scroll"});
            repositionWin();
        }
        else {
            setTimeout ((function(){
                $("html").niceScroll({
                    cursorcolor: '#231f20',
                    cursoropacitymax: '0.5',
                    scrollspeed: '100',
                    mousescrollstep: '50'
                });
            }), 300);
            setTimeout (repositionWin, 300);
        }
    }
    browserResult();

    $('.main-nav-link').click(function(e) {     
        e.preventDefault();
        var toTarget = $(this).attr('href');
        history.pushState(null, null, toTarget);

         // CODE SPECIFIC TO PROJECT (NAMELY FLEXSLIDER PAUSE/PLAY STUFF) OMITTED

        $(window).triggerHandler('hashchange');         
    });

});

$(window).on('hashchange', function () {

    if(!window.location.hash) return;
    var target = $(window.location.hash);
    var targetHash = window.location.hash;

    var iOS = ( navigator.userAgent.match(/(iPad|iPhone|iPod)/g) ? true : false );

    var currentPosition = $(window).scrollLeft();

    var targetPosLeft = target.offset().left;

    var targetPosTop = target.offset().top;

    functionunbindWindow() { $(window).unbind('scroll'); }

    functionrepositionWin() {
        unbindWindow();
        $(window).on('scroll', function() {
            var alteredPosLeft = $(window).scrollLeft();
            var alteredPosTop = $(window).scrollTop();          
            if (alteredPosLeft != targetPosLeft) {
                window.scrollTo(targetPosLeft, alteredPosTop),
                unbindWindow(),
                repositionWin();
            }           
        });
    }

    functionfadePages() {
        if (targetPosLeft == currentPosition) {
        }
        else {
            functionfadePageOut() {
                $('.page-container').stop(true,false).animate({
                    opacity: "0.25",
                    transition: "opacity 0.1s 0.0s ease"
                });
            }
            functionfadePageIn() {
                $('.page-container').stop(true,false).animate({
                    opacity: "1.0",
                    transition: "opacity 0.3s 0.0s ease"
                });
            }
            fadePageOut();
            setTimeout (fadePageIn, 900);
        }
    }

    functionpageChange() {
        if (jQuery.browser.mobile === true) {
            if (iOS === true) {
                unbindWindow();
                $('html,body').stop(true,false).animate({
                    scrollLeft: targetPosLeft}, 1400);
                    setTimeout (repositionWin, 1500);
            }
            else {
                unbindWindow();
                $('html,body').stop(true,false).animate({
                    scrollLeft: targetPosLeft}, 1200, function() {
                        $(this).stop(true,false).animate({
                            scrollTop: targetPosTop
                        }, 200, repositionWin);
                });
            }
        }
        else {
            fadePages();
            unbindWindow();
            $('html,body').stop(true,false).delay(100).animate({
                scrollLeft: targetPosLeft,
                scrollTop: targetPosTop
            }, 1300, repositionWin);
        }
    }


            // WAITING FOR OTHER ANIMATIONS TO COMPLETE SO THAT MOBILE DEVICES AREN'T TOO OVERLOADEDif ($('#mini-site-menu-button-container').is(':visible') === true && $('#main-menu-wrapper').hasClass('show-main-menu') === true) {
        setTimeout (pageChange, 300)
    }
    if ($('.footer-container').is(':visible') === true) { 
        setTimeout (pageChange, 500)
    }
    if ($('.form-instructions-wrapper').hasClass('expand-form-instruct') === true) {
        setTimeout (pageChange, 500)
    }
    if ($('.quick-quote-container').hasClass('toggle-open') === true) {
        setTimeout (pageChange, 500)
    }
    if ($('#mini-site-menu-button-container').is(':visible') === false && $('.footer-container').is(':visible') === false && $('.form-instructions-wrapper').hasClass('expand-form-instruct') === false && $('.quick-quote-container').hasClass('toggle-open') === false) {
        pageChange();
    }
    if ($('#main-menu-wrapper').hasClass('show-main-menu') === false && $('.footer-container').is(':visible') === false && $('.form-instructions-wrapper').hasClass('expand-form-instruct') === false && $('.quick-quote-container').hasClass('toggle-open') === false) {
        pageChange();
    }

});

Cheers.

I'll update as time goes on, or if I find a better solution to either of the issues. I had zero programming experience actually writing any of my own code (and this isn't all "mine") before this (changing selectors was pretty much the extent of my "skills"), so please excuse any glaring mistakes.

Post a Comment for "Horizontal One-page Site: Mobile-webkit Scrolling & Swiping Issues"