web-dev-qa-db-fra.com

position: fixe ne fonctionne pas sur iPad et iPhone

Cela fait un moment que je lutte avec le positionnement fixe sur iPad. Je sais iScroll et cela ne semble pas toujours fonctionner (même dans leur démo). Je sais aussi que Sencha a un correctif pour ça, mais je ne pouvais pas Ctrl + F le code source de ce correctif.

J'espère que quelqu'un pourra avoir la solution. Le problème est que les éléments positionnés fixes ne sont pas mis à jour lorsque l'utilisateur effectue un panoramique vertical sur un Safari mobile iOS.

128
Tower

J'ai fini par utiliser le nouveau jQuery Mobile v1.1: http://jquerymobile.com/blog/2012/04/13/announcing-jquery-mobile-1-1-0/

Nous avons maintenant une réécriture solide qui fournit de vraies barres d’outils fixes sur le fichier beaucoup de plates-formes populaires et retombe en toute sécurité à la barre d'outils statique positionnement dans d'autres navigateurs.

La partie la plus cool de cette approche est que, contrairement à solutions qui imposent la physique de défilement non naturelle à travers tous notre défilement se sent 100% natif car il est. Ça signifie ce défilement se sent partout et fonctionne avec le toucher, la molette et saisie au clavier. En prime, notre solution basée sur CSS est super léger et n’affecte pas la compatibilité ou l’accessibilité.

6
Tower

De nombreux navigateurs mobiles ne prennent délibérément pas en charge position:fixed; au motif que des éléments fixes pourraient gêner sur un petit écran.

Le site Quirksmode.org contient un très bon article de blog qui explique le problème: http://www.quirksmode.org/blog/archives/2010/12/the_fifth_posit.html

Consultez également cette page pour un tableau de compatibilité indiquant les navigateurs mobiles pris en charge position:fixed;: http://www.quirksmode.org/m/css.html

(mais notez que le monde des navigateurs mobiles évolue très rapidement, il est donc possible que de tels tableaux ne restent pas à jour très longtemps!)

Mise à jour: IOS 5 et Android 4 ont tous les deux la position indiquée: support corrigé maintenant. 

J'ai testé iOS 5 moi-même dans un Apple Store aujourd'hui et peux confirmer qu'il fonctionne avec une position fixe. Il y a cependant des problèmes avec le zoom avant et le panoramique autour d'un élément fixe.

J'ai trouvé ce tableau de compatibilité bien plus à jour et utile que celui de quirksmode: http://caniuse.com/#search=fixed

Il contient des informations à jour sur Android, Opera (mini et mobile) et iOS.

65
Spudley

Le positionnement fixe ne fonctionne pas sur iOS comme sur les ordinateurs.

Imaginez que vous avez une feuille de papier (la page Web) sous une loupe (la fenêtre), si vous déplacez la loupe et votre œil, vous voyez une autre partie de la page. Voici comment fonctionne iOS.

Maintenant, il y a une feuille de plastique transparent avec un mot dessus, cette feuille de plastique reste immobile quelle que soit la position (la position: éléments fixes). Ainsi, lorsque vous déplacez la loupe, l'élément fixe apparaît pour le déplacer.

Alternativement, au lieu de déplacer la loupe, vous déplacez le papier (la page Web), tout en maintenant la feuille de plastique et la loupe. Dans ce cas, le mot sur la feuille de plastique semblera rester fixe et le reste du contenu semblera bouger (parce que c'est le cas). Il s'agit d'un navigateur de bureau traditionnel.

Ainsi, dans iOS, la fenêtre d'affichage est déplacée, dans un navigateur traditionnel, la page Web est déplacée. Dans les deux cas, les éléments fixes restent dans la réalité; bien que sur iOS, les éléments fixes semblent bouger.


Pour contourner ce problème, suivez les derniers paragraphes de cet article

(En gros, désactivez le défilement, placez le contenu dans un div séparé (voir la boîte bleue en haut de l'article lié), et l'élément fixe positionné absolument)


"position: fixed" fonctionne maintenant comme prévu dans iOS5.

37
Jonathan.

position: fixed fonctionne sur Android/iphone pour le défilement vertical. Mais vous devez vous assurer que vos balises META sont complètement définies. par exemple

<meta name="viewport" content="width=device-width, height=device-height, initial-scale=1.0, user-scalable=0, minimum-scale=1.0, maximum-scale=1.0">

De même, si vous prévoyez de faire fonctionner la même page sous Android avant la version 4.0, vous devez également définir la position la plus haute, sinon une petite marge sera ajoutée pour une raison quelconque.

22
Jason D.

maintenant Apple prend en charge que

overflow:hidden;
-webkit-overflow-scrolling:touch;
17
Uğur Özpınar

Pied de page fixe (ici avec jQuery):

if (navigator.platform == 'iPad' || navigator.platform == 'iPhone' || navigator.platform == 'iPod' || navigator.platform == 'Linux armv6l') 
{
    window.ontouchstart = function () 
    {
        $("#fixedDiv").css("display", "none");
    }

    window.onscroll = function() 
    { 
        var iPadPosition = window.innerHeight + window.pageYOffset-45; // 45 is the height of the Footer
         $("#fixedDiv").css("position", "absolute");
         $("#fixedDiv").css("top", iPadPosition);
         $("#fixedDiv").css("display", "block");
    }
}

// in the CSS file should stand:
#fixedDiv {position: fixed; bottom: 0; height: 45px;  whatever else}

J'espère que ça aide.

14
Martin

J'ai eu ce problème sur Safari (iOS 10.3.3) - le navigateur n'était pas redessiné tant que l'événement touchend n'était pas déclenché. Les éléments fixes ne sont pas apparus ou ont été coupés.

L'astuce pour moi était d'ajouter transform: translate3d (0,0,0); à mon élément de position fixe.

.fixed-position-on-mobile {
  position: fixed;
  transform: translate3d(0,0,0);
}

EDIT - Je sais maintenant pourquoi la transformation résout le problème: l'accélération matérielle. L'ajout de la transformation 3D déclenche l'accélération du processeur graphique pour une transition en douceur. Pour plus d'informations sur l'accélération matérielle, consultez cet article: http://blog.teamtreehouse.com/increase-your-sites-performance-with-hardware-accelerated-css

9
kenecaswell

Eviter sur la même case en utilisant transform: --- et position: fixed. L'élément restera en position: statique s'il y a une transformation.

7
Becario Senior

en utilisant jQuery je suis capable de venir avec cela. il ne fait pas défiler en douceur, mais il fait le tour. vous pouvez faire défiler vers le bas, et la div fixe apparaît sur le dessus.

Le CSS

<style type="text/css">
    .btn_cardDetailsPg {height:5px !important;margin-top:-20px;}
    html, body {overflow-x:hidden;overflow-y:auto;}
    #lockDiv {
  background-color: #fff;
  color: #000;
  float:left;
  -moz-box-shadow: 0px 4px 2px 2px #ccc;-webkit-box-shadow: 0px 4px 2px 2px #ccc;box-shadow:0px 4px 2px 2px #ccc;
  }
#lockDiv.stick {
  position: fixed;
  top: 0;
  z-index: 10000;
  margin-left:0px;
  }
</style>

Le HTML

<div id="lockSticky"></div>
<div id="lockDiv">fooo</div>

Le jQUERY

<script type="text/javascript">
    function sticky_relocate() {
        var window_top = $(window).scrollTop();
        var div_top = $('#lockSticky').offset().top;
        if (window_top > div_top)
            $('#lockDiv').addClass('stick')
        else
            $('#lockDiv').removeClass('stick');
    }
    $(function() {
        $(window).scroll(sticky_relocate);
        sticky_relocate();
    });
</script>

Enfin, nous souhaitons déterminer si l’iPod touch en mode paysage ou portrait s’affiche en conséquence.

<script type="text/javascript">
    if (navigator.userAgent.match(/like Mac OS X/i)) {
        window.onscroll = function() {

        if (window.innerWidth > window.innerHeight) {
            //alert("landscape [ ]");
            document.getElementById('lockDiv').style.top =
            (window.pageYOffset + window.innerHeight - 268) + 'px';
        }

        if (window.innerHeight > window.innerWidth) {
            //alert("portrait ||");
            document.getElementById('lockDiv').style.top =
            (window.pageYOffset + window.innerHeight - 418) + 'px';
        }
        };
    }
</script>
1
abdullah

Même si l'attribut CSS {position:fixed;} semble (principalement) fonctionner sur les appareils iOS les plus récents, il est possible que cet appareil soit bizarre et qu'il retombe à {position:relative;} à l'occasion et sans cause. Habituellement, vider la mémoire cache aidera, jusqu'à ce que quelque chose se produise et que le caprice se reproduise.

Plus précisément, sur Apple Préparation de votre contenu Web pour iPad :

Safari sur iPad et Safari sur iPhone ne disposent pas de fenêtres redimensionnables. Dans Safari sur iPhone et iPad, la taille de la fenêtre est définie sur la taille du fichier écran (moins les contrôles de l'interface utilisateur Safari), et ne peut pas être modifié par l'utilisateur. Pour se déplacer sur une page Web, l’utilisateur modifie le niveau de zoom et la position de la fenêtre lorsqu’ils tapent deux fois ou pincent pour effectuer un zoom avant ou ou en touchant et en faisant glisser pour déplacer la page. En tant qu'utilisateur change le niveau de zoom et la position de la fenêtre dans laquelle ils se trouvent dans un zone de contenu visible de taille fixe (c'est-à-dire la fenêtre). Ça signifie les éléments de page Web dont la position est "fixée" dans la fenêtre de visualisation peut se retrouver en dehors de la zone de contenu visualisable, hors écran.

Ce qui est ironique, les appareils Android ne semblent pas avoir ce problème. En outre, il est tout à fait possible d'utiliser {position:absolute;} lorsque vous faites référence à la balise body et de ne pas avoir de problèmes.

J'ai trouvé la cause fondamentale de ce caprice; qu'il s'agit de l'événement de défilement ne jouant pas à Nice lorsqu'il est utilisé conjointement avec les balises HTML ou BODY. Parfois, il n’aime pas que l’événement soit déclenché ou vous devrez attendre que l’événement de défilement de déroulement soit terminé pour le recevoir. Plus précisément, la fenêtre est redessinée à la fin de cet événement et les éléments fixes peuvent être repositionnés ailleurs dans la fenêtre.

Donc, voici ce que je fais: (évitez d’utiliser la fenêtre de visualisation et restez fidèle au DOM!)

<html>
  <style>
    .fixed{
      position:fixed;
      /*you can set your other static attributes here too*/
      /*like height and width, margin, etc.*/
      }
    .scrollableDiv{
      position:relative;
      overflow-y:scroll;
      /*all children will scroll within this like the body normally would.*/
      } 
    .viewportSizedBody{
      position:relative;
      overflow:hidden;
      /*this will prevent the body page itself from scrolling.*/
      } 
  </style>
  <body class="viewportSizedBody">
    <div id="myFixedContainer" class="fixed">
       This part is fixed.
    </div>
    <div id="myScrollableBody" class="scrollableDiv">
       This part is scrollable.
    </div>
  </body>
  <script type="text/javascript" src="{your path to jquery}/jquery-1.7.2.min.js"></script>
  <script>
    var theViewportHeight=$(window).height();
    $('.viewportSizedBody').css('height',theViewportHeight);
    $('#myScrollableBody').css('height',theViewportHeight);
  </script>
</html>

Essentiellement, cela fera en sorte que le CORPS soit de la taille de la fenêtre et ne puisse pas défiler. La DIV à défilement imbriquée à l'intérieur défilera comme le CORPS le ferait normalement (moins l'effet Swing, le défilement s'arrête donc au toucher.) La DIV fixe reste fixe sans interférence.

En remarque, une valeur z-index élevée sur la DIV fixée est importante pour que la DIV qui défile apparaisse derrière elle. J'ajoute normalement dans la fenêtre des événements de redimensionnement et de défilement, également pour assurer la compatibilité entre navigateurs et résolution d'écran alternative.

Si tout échoue, le code ci-dessus fonctionnera également avec les DIV fixes et défilables définies à {position:absolute;}

1
Talvi Watia

Le moyen simple de résoudre ce problème consiste simplement à saisir la propriété de transformation pour votre élément. et ce sera corrigé. Bonne codage :-)

.classname{
  position: fixed;
  transform: translate3d(0,0,0);
}

Aussi, vous pouvez essayer son chemin aussi bien c'est aussi bien travailler.

.classname{
      position: -webkit-sticky;
    }
0
Amit Verma

Dans mon cas, le défilement a montré l’élément position: fixed qui n’a pas été visible lorsqu’il a été ajouté au DOM. Donc, je viens de déclencher manuellement l'événement de défilement qui à son tour a déclenché un redessin et le tour est joué.

window.scrollTo(window.scrollX, window.scrollY);
0
Eran Goldin