Les positions corrigées ne fonctionnent pas lors de l'utilisation de -webkit-transform

155

J'utilise -webkit-transform (et -moz-transform / -o-transform) pour faire pivoter un div. Ajout de la position fixe pour que le div défile vers le bas avec l'utilisateur.

Dans Firefox, cela fonctionne bien, mais dans les navigateurs basés sur un kit Web, il est cassé. Après avoir utilisé la transformation -webkit, la position fixée ne fonctionne plus! Comment est-ce possible?

iSenne
la source
4
Une page de démonstration aide souvent les gens à répondre aux questions - jsbin.com vous permet de créer des pages temporaires pour illustrer le problème si vous ne souhaitez pas créer de lien vers votre site.
Rich Bradshaw le
jsfiddle.net est un autre bon exemple de bac d'édition temporaire.
Kyle le
@Rich Bradshaw jsbin.com est très gentil. Je ne le savais pas jusqu'à présent. La plupart de mes projets sont exécutés localement, je vais donc l'utiliser la prochaine fois. Tnx
iSenne
7
Cela ne fonctionne pas du tout dans Firefox.
vsync
3
Encore un problème en 2017. On dirait qu'ils s'en tiennent toujours au "C'est une fonctionnalité pas un bug!" argument ...
Max

Réponses:

87

Après quelques recherches, il y a eu un rapport de bogue sur le site Web de Chromium à propos de ce problème, jusqu'à présent, les navigateurs Webkit ne peuvent pas rendre ces deux effets ensemble en même temps.

Je suggérerais d'ajouter du Webkit uniquement CSS dans votre feuille de style et de faire de la div transformée une image et de l'utiliser comme arrière-plan.

@media screen and (-webkit-min-device-pixel-ratio:0) {
  /* Webkit-specific CSS here (Chrome and Safari) */

  #transformed_div {
    /* styles here, background image etc */
  }
}

Donc, pour l'instant, vous devrez le faire à l'ancienne, jusqu'à ce que les navigateurs Webkit rattrapent FF.

EDIT: Au 24/10/2012, le bogue n'a pas été résolu.


Cela ne semble pas être un bogue, mais un aspect de la spécification en raison des deux effets nécessitant des systèmes de coordonnées séparés et des ordres d'empilement. Comme expliqué dans cette réponse .

Kyle
la source
34
Encore plus d'années plus tard, toujours pas résolu. Assez triste.
Amalgovinus
9
Selon cette réponse, ce n'est pas un bogue mais une partie de la spécification.
MichaelRushton
15
asseyez-vous et regardez - je parie qu'il vivra jusqu'à son 10e anniversaire
lzl124631x
29
30 août 2017, journal du capitaine. Nous avons également rencontré l'étrange anomalie, qui a été décrite il y a si longtemps par d'autres capitaines. Une solution reste à mettre en œuvre.
Luoruize
14
C'est le bug dont le père de mon père m'a averti.
danjones_mcr
96

La spécification CSS Transforms explique ce comportement. Les éléments avec des transformations agissent comme un bloc contenant pour les descendants à position fixe, donc position: fixed sous quelque chose avec une transformation n'a plus de comportement fixe.

Ils fonctionnent lorsqu'ils sont appliqués au même élément; l'élément sera positionné comme fixe, puis transformé.

smfr
la source
9
C'est la seule réponse utile et correcte. Arrêtez de traduire l'élément parent et traduisez les enfants dont l'élément fixe en fait partie. Voici mon violon: JSFIDDLE
Falk
2
et si je veux aussi transformer un élément fixe?
Marc
7

Pour tous ceux qui trouvent que leurs images d'arrière-plan disparaissent dans Chrome à cause du même problème avec background-attachment: corrigé; - c'était ma solution:

// run js if Chrome is being used
if(navigator.userAgent.toLowerCase().indexOf('chrome') > -1) {
    // set background-attachment back to the default of 'scroll'
    $('.imagebg').css('background-attachment', 'scroll');

    // move the background-position according to the div's y position
    $(window).scroll(function(){

        scrollTop = $(window).scrollTop();
        photoTop = $('.imagebg').offset().top;
        distance = (photoTop - scrollTop);
        $('.imagebg').css('background-position', 'center ' + (distance*-1) + 'px');

    });
}  
Jayden Lawson
la source
6

Quelque chose (un peu hacky) qui a fonctionné pour moi est à la position:stickyplace:

.fixed {
     position: sticky;
}
yckart
la source
5
updates.html5rocks.com/2012/08/… ah ouais .. mais pas bien supporté encore il semble
coiso
1
collant est différent. Le problème principal est qu'avec fixed nous voulons ignorer la position du conteneur (très utile. Pour les animations d'opacité par exemple). Je n'arrive pas à croire que ce bogue soit toujours là des années plus tard. Horrible.
FlorianB
6

Août 2016 et la position fixe et l'animation / transformation sont toujours un problème. La seule solution qui a fonctionné pour moi - était de créer une animation pour l'élément enfant qui prend plus de temps.

défligra
la source
Veuillez répondre aux nouvelles questions. Ces questions ont plus besoin de vous que de la personne qui a posé la question en 2010. Elles doivent avoir résolu le problème maintenant, vous ne pensez pas? Cette question a également déjà une réponse acceptée.
Umair Farooq
5
Nan! C'est toujours un problème ... la personne qui a posé la question a peut-être trouvé une autre solution - mais j'ai trouvé ce fil pour une raison.
defligra
Comme vous le souhaitez. J'ai laissé ce commentaire en passant en revue les premières questions des gens. Et puisque vous vous êtes joint juste aujourd'hui et que c'était votre première réponse et aussi une réponse tardive, c'est pourquoi j'ai laissé ce commentaire. Je n'ai pas voté contre. C'est une bonne chance pour vous.
Umair Farooq
1
@UmairFarooq poser une autre question serait peut-être inutile car elle pourrait être marquée comme dupliquée. Je suis venu ici juste avec une recherche sur google et j'ai trouvé cette question utile, réponse de defligra aussi.
koMah
3

En fait, j'ai trouvé un autre moyen de corriger ce "bug":

J'ai un élément conteneur qui contient une page avec des animations css3. Lorsque la page a terminé l'animation, la propriété css3 a la valeur: transform: translate (0,0) ;. Donc, je viens de supprimer cette ligne, et tout a fonctionné comme il se doit - position: fixed s'affiche correctement. Lorsque la classe css est appliquée pour traduire la page, la propriété translate est ajoutée et l'animation css3 fonctionne également.

Exemple:

.page {
     top: 50px;
     position: absolute;
     transition: ease 0.6s all;
     /* -webkit-transform: translate(0, 0); */
     /* transform: translate(0,0); */
 }
 .page.hide {
     -webkit-transform: translate(100%, 0);
     transform: translate(-100%, 0);    
 }

Démo: http://jsfiddle.net/ZWcD9/

lowselfestemsucks
la source
1
Pour moi, c'était le fait d'avoir ces styles sur le wrapper contenant l'élément fixe qui empêchait le fixe d'être collant: -webkit-perspective: 1000; -webkit-transform-style: conserve-3d; J'ai enlevé ces derniers et tout fonctionne bien. C'étaient de toute façon des optimisations discutables!
Amalgovinus
La suppression de la transformation, par tous les moyens, est probablement la meilleure solution de contournement à ce jour. Quelque chose comme un fondu, une fois terminé, devrait être amovible sans affecter l'apparence de l'élément. En fait, je ne suis pas sûr de ce que le fait d'avoir un transformX (0) traîner ferait sur les performances de rendu, voire rien du tout; il pourrait soit être ignoré, soit nuire aux performances, soit l'améliorer en forçant une sorte d'accélération 3D. Qui sait. Dans tous les cas, une fois qu'une animation est terminée, ou même juste avant qu'un élément fixe ne lui soit ajouté, on peut simplement supprimer les classes CSS de la transformation.
Triynko
1

sur mon projet phonegap, le webkit transform -webkit-transform: translateZ (0); a fonctionné comme un charme. Il fonctionnait déjà dans Chrome et Safari, mais pas dans le navigateur mobile. il peut également y avoir un autre problème si les WRAPPER DIV ne sont pas terminés dans certains cas. nous appliquons une classe claire en cas de DIV flottants.

<div class="Clear"></div> .Clear, .Clearfix{clear:both;}
abksharma
la source
1

Probablement en raison d'un bogue dans Chrome car je ne peux pas répliquer dans Safari ni Firefox, mais cela fonctionne dans Chrome 40.0.2214.111 http://jsbin.com/hacame/1/edit?html,css,output

C'est une structure très particulière, donc ce n'est en aucun cas un correctif css en une seule ligne applicable universellement, mais peut-être que quelqu'un peut le bricoler pour le faire fonctionner dans Safari et Firefox.

Kerry Johnson
la source
1

J'ai eu ce problème en essayant d'implémenter react-color avec react-swipeable-views (rsw). Le problème pour moi était que rsw s'applique translate(-100%, 0)à un panneau d'onglets qui rompt la position fixe par défaut div ajoutée sur le plein écran qui, une fois cliqué, ferme le modèle de sélecteur de couleur.

Pour moi, la solution était d'appliquer la transformation opposée à l'élément fixe (dans ce cas, translate(100%, 0)cela a résolu mon problème. Je ne suis pas sûr que cela soit utile dans d'autres cas, mais je pensais que je partagerais quand même.

Voici un exemple montrant ce que j'ai décrit ci-dessus:

https://codepen.io/relativemc/pen/VwweEez

mrmadhat
la source
0

L'ajout -webkit-transformde l'élément fixe a résolu le problème pour moi.

.fixed_element {
   -webkit-transform: translateZ(0);
   position: fixed;
   ....
} 
Ron
la source
20
Cela n'a pas fonctionné pour moi. Êtes-vous en mesure d'en créer une démonstration?
alex
4
Cela a résolu un problème pour moi dans Chrome, FWIW. Merci Ron.
Chris
3
Merci, cela m'a résolu un problème. Sauvé ma vie!
styke
1
@Neil Monroe, Android 2.3 est une toute nouvelle histoire. Il ne prend pas du tout en charge le positionnement fixe :)
Wiseman
8
Voici un violon où l'utilisation translateZ(0) ne fonctionne PAS . C'est vrai que ça marche parfois, j'ai vu des occasions où ça marchait. Mais je ne peux toujours pas le réduire.
Zequez
0

Voici ce qui fonctionne pour moi sur tous les navigateurs et appareils mobiles testés (Chrome, IE, Firefox, Safari, iPad, iPhone 5 et 6, Android).

img.ui-li-thumb {
    position: absolute;
    left: 1px;
    top: 50%;

    -ms-transform: translateY(-50%);
    -webkit-transform: translateY(-50%);
    -moz-transform: translateY(-50%);
    -o-transform: translateY(-50%);
    transform: translateY(-50%);
}
Murf
la source
2
Pourquoi les votes négatifs? Ce serait bien si vous fournissiez un commentaire sur les raisons pour lesquelles vous avez voté ma réponse?
Murf
0

la position fixe d'un élément est interrompue si vous appliquez la transformation à un ancêtre.

<div style='position:fixed;-.*-transform:scale(2)'>...</div> //ok

<div style='-.*-transform:scale(2)'>
      <div style='position:fixed'>...</div> // broken
</div>
Bortunac
la source
0

Si vous pouvez utiliser javascript comme option, cela peut être une solution de contournement pour positionner un élément fixe de position par rapport à la fenêtre lorsqu'il se trouve à l'intérieur d'un élément transformé:

  let fixedEl // some node that you is position 
              // fixed inside of an element that has a transform

  const rect = fixedEl.getBoundingClientRect()
  const distanceFromWindowTop = rect.top
  const distanceFromWindwoLeft = rect.left
  let top = fixedEl.offsetTop
  let left = fixedEl.offsetLeft

  if(distanceFromWindowTop !== relativeTop) {
    top = -distanceFromWindowTop
    fixedEl.style.top = `${top}px`
  }

  if(distanceFromWindowLeft !== relativeLeft) {
    left = -distanceFromWindowLeft
    fixedEl.style.left = `${left}px`
  }

Certes, vous devrez également ajuster vos hauteurs et votre largeur car fixedElvous calculerez avec en fonction de son conteneur. Cela dépend de votre cas d'utilisation, mais cela vous permettra de définir de manière prévisible la position de quelque chose de fixe, quel que soit son conteneur.

Adrian Adkison
la source
0

Ajoutez une classe dynamique pendant que l'élément se transforme. $('#elementId').addClass('transformed'). Ensuite, déclarez en css,

.translatX(@x) { 
     -webkit-transform: translateX(@X); 
             transform: translateX(@x);
      //All other subsidaries as -moz-transform, -o-transform and -ms-transform 
}

puis

#elementId { 
      -webkit-transform: none; 
              transform: none;
}

puis

.transformed {
    #elementId { 
        .translateX(@neededValue);
    }
}

Maintenant, la position: fixe lorsqu'elle est fournie avec une valeur de propriété top et z-index sur un élément enfant fonctionne correctement et reste fixe jusqu'à ce que l'élément parent se transforme. Lorsque la transformation est annulée, l'élément enfant apparaît à nouveau comme fixe. Cela devrait faciliter la situation si vous utilisez réellement une barre latérale de navigation qui s'ouvre et se ferme en un clic, et que vous avez un ensemble d'onglets qui devrait rester collant lorsque vous faites défiler la page.

mr.G
la source
0

dans mon cas, j'ai découvert que nous ne pouvons pas utiliser transform: translateX () avant transform: translateY (). Si nous voulons utiliser les deux, nous devrions utiliser transform: translate (,).

Fahime Firoozpour
la source
-1

S'il vous plaît, ne votez pas, car ce n'est pas une réponse exacte, mais cela pourrait aider quelqu'un car c'est un moyen rapide de désactiver la transformation. Si vous n'avez vraiment pas besoin de la transformation sur le parent et que vous voulez que votre position fixe fonctionne à nouveau:

#element_with_transform {
  -webkit-transform: none;
  transform: none;
}
makkasi
la source
1
C'est vraiment dans le titre de la question
Eugene Pankov
@EugenePankov Ne voyez pas «aucun» dans le titre. C'est ce qu'il a résolu mon problème et en général personne ne suggère de l'éteindre. Bien que ce ne soit pas une réponse exacte à cette question, cela pourrait aider quelqu'un qui ne veut pas utiliser la transformation et la transformation provient d'une autre bibliothèque. Donc je ne veux pas de votes à la hausse, mais s'il vous plaît, ne votez pas à la baisse. Je modifierai ma question pour dire que je ne veux pas de vote pour la hausse.
makkasi