iOS Safari: Anchors within a fixed positioned elem

2019-05-10 18:00发布

问题:

Please have a look at this fiddle: http://fiddle.jshell.net/ikmac/q7gkx

Use this link to test in the browser: http://fiddle.jshell.net/ikmac/q7gkx/show/

HTML:

<div class="nav">
    <a href="#test1">test1</a>
    <a href="#test2">test2</a>
    <a href="#test3">test3</a>
</div>

<div id="test1" class="test">test1</div>
<div id="test2" class="test">test2</div>
<div id="test3" class="test">test3</div>

CSS:

.nav {
    position: fixed;
    top: 20px;
    left: 0;
    width: 100%;
    height: 20px;
    background: #000;
}

.nav a {
    float: left;
    font-size: 20px;
    color: #fff;
}

#test1 {
    margin-top: 1000px;
    height: 1000px;
    background: red;
}

#test2 {
    height: 1000px;
    background: blue;
}

#test3 {
    height: 1000px;
    background: green;
}

This is what happens in Safari on iOS 5.0 (4.3 doesn't support position fixed):

The first time I click on one of the anchors the page jumps to the correct anchor. After that I cannot click one of the other links anymore. When I scroll up or down a bit the links become clickable again.

All other desktop browsers behave fine.

Does anyone ever had this issue before or knows how to fix it?

回答1:

I have that problem aswell. And I kind of half solved it by letting javascript do the scrolling of the nav when a nav anchor is clicked. And because normal touch-scrolling does not give an event until the finger lets go of the screen, I use position:fixed which makes the touch-scrolling nicer than javascript can, see apples dev-site.

It is not the ultimate solution, but in my opinion it is better than not working at all. This script also checks the width of the window to make sure that it only applies this to smaller screens, well, devices.

Here is my code, and if you find it useful, make it better or find a better solution, please share :)

/* NAV POSITION */

var specScroll = false; // If special scrolling is needed

/* Check what kind of position to use.*/
(function navPos() {
    var width = checkWidth();

    if (width <= 480 || navigator.userAgent.match(/iPad/i) != null) {
        specScroll = true;
    }else{
        specScroll = false;
        window.onscroll = NaN;
    }
})();

$(window).resize( function(){ navPos(); } ); // After resizing, check what to use again.


/* When clicking one of the nav anchors */
$(function() {
    $('a').bind('click',function(e){
        var $anchor = $(this);

        if(specScroll){
            $('#nav').css('position', "absolute");
            window.onscroll = anchorScroll;
        }
        $('html, body').stop().animate({
            scrollTop: $($anchor.attr('href')).offset().top
        }, 700,'easeOutExpo', function(){
            if(specScroll){setTimeout("window.onscroll = touchScroll;", 100);} 
            // the set timeout is needed for not overriding the clickability of the anchors after anchor-scrolling.
        });

        e.preventDefault();
    });
});

/* While the user clicks and anchors in nav */
function anchorScroll() { $('#nav').css('top', window.pageYOffset); }

/* the first time the user scrolls by touch and lift the finger from screen */
function touchScroll() { 
    $('#nav').css('position', 'fixed');
    $('#nav').css('top', 0);
    window.onscroll = NaN;
}

/* CHECK WIDTH OF WINDOW */
function checkWidth() {
    myWidth = 0;
    if( typeof( window.innerWidth ) == 'number' ) {
        myWidth = window.innerWidth;    //Non-IE
    } else if( document.documentElement && ( document.documentElement.clientWidth ) ) {
        myWidth = document.documentElement.clientWidth; //IE 6+ in 'standards compliant mode'
    } else if( document.body && ( document.body.clientWidth ) ) {
        myWidth = document.body.clientWidth;    //IE 4 compatible
    }
    return myWidth;
}

I use this solution on a project page, try it out: dare.niklasek.se



回答2:

I ran into the same issue using a fixed position navigation that scrolls the user around the page using jQuery animation. What I found is that even though the fixed position element is visible at the new position, inspecting it with js reports that it is still back in the original position until the user moves the screen manually. Until then, even though the nav is there visually, it can't be touched in order to interact with it. More information and demo here: http://bit.ly/ios5fixedBug