45 votes

Bug du scroll-snap css iOS 10

J'ai remarqué un étrange bug dans iOS 10 avec le CSS scroll-snap propriétés.

Voici mon css :

#springBoard{
    height: 100%;
    width: 100%;
    font-size: 0px;
    white-space: nowrap;
    overflow: scroll;
    -webkit-overflow-scrolling: touch;
    -webkit-scroll-snap-type: mandatory;
    -webkit-scroll-snap-points-x: repeat(100%);
}

section{
    display: inline-block;
    width: 100%;
    height: 100%;
    vertical-align: top;
    font-size: 16px;
}

Si je fais défiler par programmation jusqu'à un point d'accrochage et que je modifie ensuite le contenu du conteneur scroll-snap, le nav revient au premier point d'accrochage.

// Programatically scroll the scroll-snap container 
$("#springBoard")[0].scrollLeft = 320

Il ne semble pas être lié à la façon dont je déclenche le défilement. Toutes ces méthodes de défilement produisent le même résultat :

$("#springBoard")[0].scrollLeft = 320
$("#springBoard").animate({scrollLeft: 320}, 1)
$("#springBoard > section:eq(1)")[0].scrollIntoView()
window.location.hash = "sectionId"
  1. Le bug ne se produit pas lors du défilement manuel (voir le commentaire de @maxime ci-dessous).
  2. Il est présent depuis la version 10.3.2 d'iOS.
  3. Je ne sais pas si c'est corrigé dans iOS 11.

J'ai passé quelques jours à essayer de résoudre ce problème, mais sans succès jusqu'à présent.

Voici un exemple simplifié de mon système de navigation :

<b>Codepen Demo</b>

Quelqu'un connaît-il un moyen de contourner ce problème ? stupide Un bug ?

2 votes

Si je navigue et que je clique sur l'icône Change Content il reste au même point d'accrochage. Ce n'est que si je clique sur le bouton sans avoir effectué de défilement que le bug survient.

0 votes

Avez-vous essayé de faire défiler la page de manière programmatique ? window.scrollTo(0, 0); //or some variant

0 votes

Merci pour la suggestion, j'ai essayé de faire défiler la fenêtre mais cela ne résout pas le problème.

1voto

David_Gracias Points 21

J'ai créé mon propre scroll-snap HORIZONTAL en jquery qui est déclenché sur chargement de la page , redimensionnement de la fenêtre et défilement du conteneur - cela évite d'avoir recours au css :

$(".container").scroll(function() {

L'instruction if/else suivante est utilisée si vous prévoyez de modifier la largeur de l'objet en fonction de la largeur de la page. Si ce n'est pas le cas, vous pouvez simplement l'effacer et définir var width = votre largeur par défaut

   var width = 1; //100% - default value / small screen
    if(window.innerWidth >= 993) //large screen
         width = 1/4; //25%
    else if(window.innerWidth >= 601) //medium screen
        width = 1/3; //33.333%

    var containerWidth = $(".container").width();
    var sectionWidth = containerWidth * width; //gets the length of each section

    var currentScroll = $(".container").scrollLeft();
    var farOff = currentScroll % sectionWidth; //determines how far user is from the beginning of the current section
    if(farOff == 0) //just for efficiency
        return;

    clearTimeout($.data(this, 'scrollTimer'));

    $.data(this, 'scrollTimer', setTimeout(function() {
        if(farOff >= sectionWidth/2) //scroll-snaps to next section
            $(".container").animate({
                scrollLeft: (currentScroll + sectionWidth - farOff),
            });
        else //scroll-snaps to previous section
            $(".container").animate({
                scrollLeft: (currentScroll - farOff),
            });
    }, 550));
});

Voici la CSS qui accompagne mon exemple de scroll snap

div.container{
    overflow-x: scroll;
    -webkit-overflow-scrolling: touch;
    -o-overflow-scrolling: scroll;
    -moz-overflow-scrolling: scroll;
    overflow-y: hidden;
    white-space: nowrap !important;
}
.container section{
    display: inline-block;
    padding: 10px;
    width:100%;
    vertical-align: top;
    margin-bottom: 10px;
}
.container > section > div{
    overflow: initial;
    white-space: normal;
}
@media (min-width: 601px){ /* medium */
    .container section{
        width: 33.33333333%;
    }
}
@media (min-width: 952px){ /* large */
    .container section{
        width: 25%;
    }
}

-2voto

Essayez comme ceci :

$('#springBoard').animate({scrollLeft: $('#springBoard').position().left + 320},1 );

0 votes

Position().left renverra toujours 0. Par ailleurs, pourquoi animez-vous l'élément pendant 320 ms ? Dans mon code, le 320 correspond à la largeur d'un iPhone SE. Cela n'a aucun sens pour moi.

0 votes

Désolé, j'étais supposé ajouter ça avec la position. mais c'est mon erreur. $('#springBoard').animate({scrollLeft : $('#springBoard').position().left + 320}, 1) ;

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X