position: fixe ne fonctionne pas sur iPad et iPhone

132

J'ai des difficultés avec le positionnement fixe sur iPad depuis un certain temps. Je connais iScroll et cela ne semble pas toujours fonctionner (même dans leur démo). Je sais aussi que Sencha a un correctif pour cela, mais je ne pourrais pas Ctrl+ Fle code source pour ce correctif.

J'espère que quelqu'un aura la solution. Le problème est que les éléments positionnés fixes ne sont pas mis à jour lorsque l'utilisateur effectue un panoramique vers le bas / le haut sur un Safari mobile alimenté par iOS.

La tour
la source
2
On dirait que jQuery Mobile 1.1 a résolu ce problème: jquerymobile.com/blog/2012/04/13/announcing-jquery-mobile-1-1-0
Tower
duplication possible du positionnement fixe dans Mobile Safari
Christian
Reproduction possible de plusieurs questions SO. Voir gist.github.com/avesus/… pour plus de détails.
Brian Haak le

Réponses:

66

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

Le site Quirksmode.org a 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, donc des tableaux comme celui-ci peuvent ne pas rester à jour très longtemps!)

Mise à jour: iOS 5 et Android 4 auraient tous deux une position: support fixe maintenant.

J'ai testé moi-même iOS 5 dans un Apple Store aujourd'hui et je 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é beaucoup plus à jour et utile que celui de quirksmode: http://caniuse.com/#search=fixed

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

Spudley
la source
position:device-fixedserait un peu redondant. position:fixeddevrait juste fonctionner selon les spécifications du W3C.
Talvi Watia
@TalviWatia - la device-fixedsolution ne faisait pas partie de ma réponse. Il peut ou non avoir du mérite en tant que suggestion, mais la raison du lien était l'explication du problème plutôt que sa solution suggérée. Dans tous les cas, les choses ont beaucoup évolué depuis que cette réponse a été publiée (comme je l'ai dit), et de nombreux appareils plus récents prennent en charge fixed. Cependant, vous devez toujours gérer des appareils plus anciens qui ne le font pas.
Spudley
54
Je suis donc curieux de savoir quelle est exactement votre solution au problème actuel? Les liens que vous avez fournis, bien qu'utiles, ne résolvent pas le problème. Ne pas être blasé, mais les gens ont tendance à voter pour des réponses qui ne sont pas réellement des réponses ici sur SO.
Talvi Watia
1
@TalviWatia: Au moment où j'ai écrit la réponse, il n'y avait pas vraiment de bonne solution à la question. Le lien que j'ai donné était la meilleure discussion que je connaissais pour expliquer pourquoi les choses étaient telles qu'elles étaient, ce qui, en l'absence de solution, était aussi bon que je pouvais offrir. Les choses ont changé dans l'intervalle, donc la discussion dans le lien n'est plus pertinente, et il y a des solutions maintenant, mais c'était comme ça à l'époque.
Spudley
En fait, la position: fixe fonctionne pour l'échelle 1, mais lorsque l'utilisateur fait un zoom sur l'ipad, cela ne fonctionne pas correctement. position: appareil fixe existe ?? L'attribut CSS est-il valide pour Safari iOS?
ccsakuweb
37

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

Imaginez que vous ayez 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 partie différente de la page. C'est ainsi que fonctionne iOS.

Maintenant, il y a une feuille de plastique transparent avec un mot dessus, cette feuille de plastique reste immobile quoi qu'il arrive (la position: éléments fixes). Ainsi, lorsque vous déplacez la loupe, l'élément fixe semble bouger.

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

Ainsi, dans iOS, la fenêtre se déplace, dans un navigateur traditionnel, la page Web se déplace. Dans les deux cas, les éléments fixes restent toujours en réalité; bien que sur iOS, les éléments fixes semblent bouger.


Le moyen de contourner ce problème est de suivre les derniers paragraphes de cet article

(fondamentalement, désactivez complètement le défilement, placez le contenu dans un div de défilement séparé (voir la boîte bleue en haut de l'article lié) et l'élément fixe positionné de manière absolue)


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

Jonathan.
la source
Il y a des choses étranges qui se produisent avec la position: corrigé lorsque vous zoomez sur l'IOS. Voir stackoverflow.com/questions/52085998/…
Peter Hollingsworth
23

position: fixe fonctionne sur Android / iPhone pour le défilement vertical. Mais vous devez vous assurer que vos balises meta sont entièrement 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 plus, si vous prévoyez d'avoir la même page de travail sur Android pré 4.0, vous devez également définir la position supérieure, sinon une petite marge sera ajoutée pour une raison quelconque.

Jason D.
la source
Cela a fonctionné pour moi. Avant, la position: fixée sur un élément d'entrée caché (voir navigation hors écran en pure css) provoquait le crash du navigateur sur l'iphone ios 8.3 mais pas sur la tablette. Après cela fonctionne bien.
Stephen Smith
Ne fonctionne pas sur iPad iOS 10.3, horizontal dans le support Square. L'auteur reconnu dit que cette approche est pour les "téléphones".
SushiGuy
2
La désactivation de l'utilisateur pour zoomer user-scalable=0, minimum-scale=1.0, maximum-scale=1.0peut rendre la page moins accessible pour de nombreux utilisateurs. Il serait utile d'ajouter un avertissement à ce sujet dans votre réponse
neiya
22

maintenant Apple prend en charge cela

overflow:hidden;
-webkit-overflow-scrolling:touch;
Uğur Özpınar
la source
C'est exactement ce que je cherchais à résoudre mon background-size: coveret fixedquestion sur l'iPad
andyb
Cela fonctionne sur Mobile Safari dans iOS 7. Remarque: cela ne fonctionnera pas pour les utilisateurs qui n'ont pas encore mis à niveau vers cette version.
Neil Monroe
Ensuite, il doit y avoir d'autres variables à l'œuvre. J'ai testé sur iOS 6 et cela ne fonctionnait pas, puis sur iOS 7 et ça l'était.
Neil Monroe
@NeilMonroe hmm peut-être. Je suis sûr que je l'ai fait sur iOS 6 sans problème, mais j'ai peut-être utilisé une autre variable. ne me souviens pas
Uğur Özpınar
cela a été vraiment utile, mais il semble, overflowdoit être défini surscroll
19

J'ai eu ce problème sur Safari (iOS 10.3.3) - le navigateur n'était pas en train de redessiner jusqu'à ce que l'événement touchend soit 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 GPU 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 .

Kenecaswell
la source
Cela a en fait résolu mon problème de défilement, il rebondissait sur les appareils iOS lors de l'utilisation fixed, a ajouté le transformet cela a été corrigé.
vonUbisch
17

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.

Martin
la source
7

Évitez sur la même boîte d'utiliser transform: --- et position: fixed. L'élément restera en position: statique s'il y a une transformation.

Becario Senior
la source
6

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 véritables barres d'outils fixes sur les nombreuses plates-formes populaires et revient en toute sécurité au positionnement de la barre d'outils statique dans d'autres navigateurs.

La partie la plus intéressante de cette approche est que, contrairement aux solutions basées sur JS qui imposent une physique de défilement non naturelle sur toutes les plates-formes, notre défilement semble 100% natif car il l' est . Cela signifie que le défilement se sent partout et fonctionne avec la saisie tactile, la molette de la souris et le clavier. En prime, notre solution basée sur CSS est super légère et n'a aucun impact sur la compatibilité ou l'accessibilité.

La tour
la source
Cette méthode pour autoriser les objets fixes sur iOS sans utiliser jQuery ou JavaScript (utilise uniquement CSS) est également assez élégante (mais certainement une solution de contournement ). C'est assez universellement applicable. Si vous souhaitez qu'un position:fixedélément "flottant" apparaisse devant votre page défilante, il vous suffit de lui donner une z-indexvaleur plus élevée pour qu'il reste devant.
Slink
cela ne répond certainement pas à la question.
Gustavo Siqueira
1

en utilisant jquery, je suis capable de trouver ceci. il ne défile pas facilement, mais il fait l'affaire. vous pouvez faire défiler vers le bas et le div fixe apparaît en haut.

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 voulons déterminer si l'iPod touch en mode paysage ou portrait doit s'afficher 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>
Abdullah
la source
1

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

Plus précisément, depuis Apple lui-même Préparation de votre contenu Web pour iPad :

Safari sur iPad et Safari sur iPhone n'ont pas de fenêtres redimensionnables. Dans Safari sur iPhone et iPad, la taille de la fenêtre est définie sur la taille de l'écran (moins les commandes de l'interface utilisateur Safari) et ne peut pas être modifiée par l'utilisateur. Pour se déplacer dans une page Web, l'utilisateur modifie le niveau de zoom et la position de la fenêtre en appuyant deux fois ou en pinçant pour effectuer un zoom avant ou arrière, ou en touchant et en faisant glisser pour faire un panoramique de la page. Lorsqu'un utilisateur modifie le niveau de zoom et la position de la fenêtre, il le fait dans une zone de contenu visible de taille fixe (c'est-à-dire la fenêtre). Cela signifie que les éléments de page Web dont la position est «fixée» par rapport à la fenêtre d'affichage peuvent se retrouver hors de la zone de contenu visible, hors écran.

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

J'ai trouvé la cause profonde de cette bizarrerie; que c'est l'événement de défilement qui ne joue pas bien lorsqu'il est utilisé en conjonction avec la balise HTML ou BODY. Parfois, il n'aime pas déclencher l'événement, ou vous devrez attendre la fin de l'événement de swing de défilement pour recevoir l'événement. 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.

Voici donc ce que je fais: ( évitez d'utiliser la fenêtre, et restez avec le 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>

En substance, cela fera que le BODY aura la taille de la fenêtre et ne pourra pas faire défiler. Le DIV déroulant imbriqué à l'intérieur défilera comme le ferait normalement le CORPS (moins l'effet de swing, donc le défilement s'arrête au toucher.) Le DIV fixe reste fixe sans interférence.

En remarque, une z-indexvaleur élevée sur le DIV fixe est important pour que le DIV défilable semble être derrière. J'ajoute normalement des événements de redimensionnement et de défilement de la fenêtre également pour la compatibilité entre les navigateurs et la résolution alternative de l'écran.

Si tout le reste échoue, le code ci-dessus fonctionnera également avec les DIV fixe et défilable définis sur {position:absolute;}.

Talvi Watia
la source
1

La manière simple de résoudre ce problème tape simplement la propriété de transformation pour votre élément. et ce sera réparé. Codage heureux :-)

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

Vous pouvez également essayer son chemin, cela fonctionne également très bien.

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

Cela ne s'applique peut-être pas à tous les scénarios, mais j'ai trouvé que la position: sticky(même chose avec position: fixed) ne fonctionne que sur les anciens iPhones lorsque le conteneur de défilement n'est pas le corps, mais à l'intérieur d'autre chose.

Exemple de pseudo html:

body                         <- scrollbar
   relative div
       sticky div

Le div sticky sera collant sur les navigateurs de bureau, mais avec certains appareils, testés avec: Chromium: outils de développement: émultation d'appareil: iPhone 6/7/8, et avec Android 4 Firefox, ce ne sera pas le cas.

Ce qui fonctionnera, cependant, est

body
    div overflow=auto       <- scrollbar
        relative div
            sticky div
phil294
la source
0

Dans mon cas, c'était parce que l'élément fixe était affiché à l'aide d'une animation. Comme indiqué dans ce lien :

dans Safari 9.1, avoir une position: élément fixe à l'intérieur d'un élément animé peut faire en sorte que position: élément fixe n'apparaisse pas.

nnimis
la source
-2

voici ma solution à cela ...

CSS

#bgimg_top {
    background: url(images/bg.jpg) no-repeat 50% 0%; 
    position: fixed; 
    top:0; 
    left: 0; 
    right:0 ; 
    bottom:0;
}

HTML

<body>
<div id="bgimg_top"></div>
....
</body>

L'explication est que la position fixée pour le div gardera le div en arrière-plan à tout moment, puis nous étirons le div pour aller sur tous les coins du navigateur (à condition que la marge du corps = 0) en utilisant le (gauche, droite, haut, bas ) simultanément.

Veuillez vous assurer de ne pas utiliser la largeur et la hauteur car cela remplacera les options en haut, à gauche, à droite et en bas.

Val
la source