web-dev-qa-db-fra.com

'transform3d' ne fonctionne pas avec la position: enfants fixes

J'ai une situation où, dans des circonstances CSS normales, un div fixe serait placé exactement là où il est spécifié (top:0px, left:0px). 

Cela ne semble pas être respecté si j'ai un parent qui a une transformation translate3d. Est-ce que je ne vois pas quelque chose? J'ai essayé d'autres styles tels que le webkit-transform et les options Origin, mais je n'ai pas eu de chance.

J'ai joint un JSFiddle avec un exemple dans lequel je m'attendrais à ce que la boîte jaune se trouve dans le coin supérieur de la page plutôt qu'à l'intérieur de l'élément conteneur.

Vous trouverez ci-dessous une version simplifiée du violon:

<br>
<div style='position:relative; border: 1px solid #5511FF; 
            -webkit-transform:translate3d(0px, 20px , 0px); 
            height: 100px; width: 200px;'
> 
    <div style='position: fixed; top: 0px; 
                box-shadow: 3px 3px 3px #333; 
                height: 20px; left: 0px;'
    >
        Inner block
    </div>
</div>

Tous les indicateurs permettant de faire en sorte que translate3d fonctionne avec un enfants à position fixe seront appréciés.

120

En effet, la variable transform crée un nouveau système de coordonnées local, conformément à spécification W3C :

Dans l'espace de noms HTML, toute valeur autre que none pour la transformation entraîne la création d'un contexte de pile et d'un bloc contenant. L'objet agit comme un bloc conteneur pour les descendants à positions fixes.

Cela signifie que le positionnement fixe devient lié à l'élément transformé, plutôt qu'à la fenêtre d'affichage. 

À ce que je sache, il n'y a pas actuellement de solution de rechange.

Il est également documenté dans l'article d'Eric Meyer: Suppression d'éléments fixes avec des transformations CSS .

173
saml

Comme suggéré par Bradoergo, obtenez simplement la fenêtre scrollTop et ajoutez-la à la position absolue top comme:

function fix_scroll() {
  var s = $(window).scrollTop();
  var fixedTitle = $('#fixedContainer');
  fixedTitle.css('position','absolute');
  fixedTitle.css('top',s + 'px');
}fix_scroll();

$(window).on('scroll',fix_scroll);

Cela a fonctionné pour moi de toute façon.

12
UzumakiDev

J'avais un scintillement sur le haut de la page de navigation lorsque des éléments de la page utilisaient une transformation, les éléments suivants appliqués à mon haut de page ont résolu le problème du saut/scintillement:

#fixedTopNav {
    position: fixed;
    top: 0;
    transform: translateZ(0);
    -webkit-transform: translateZ(0);
}

Merci à cette réponse sur SO

11
rob.m

Dans Firefox et Safari, vous pouvez utiliser position: sticky; au lieu de position: fixed; mais cela ne fonctionnera pas dans les autres navigateurs. Pour cela, vous avez besoin de javascript.

3
Dušan

Alors,

Ne pas avoir trouvé une méthode satisfaisante pour traiter cela; et faire des choses hors de la sous-fenêtre (nécessitant une traduction) - J'ai creusé un peu et découvert que (du moins pour mon cas d'utilisation) la meilleure méthode pour y remédier consiste à appliquer la même traduction, mais à casser les enfants qui ont besoin de être fixés en dehors de leur élément parent (traduit); puis appliquez la traduction à un div à l'intérieur du wrapper position: fixed.

Les résultats ressemblent à ceci (dans votre cas):

<br>
<div style='position:relative; border: 1px solid #5511FF; 
            -webkit-transform:translate3d(0px, 20px , 0px); 
            height: 100px; width: 200px;'> 

</div>
<div style='position: fixed; top: 0px; 
            box-shadow: 3px 3px 3px #333; 
            height: 20px; left: 0px;'>
    <div style='-webkit-transform:translate3d(0px, 20px, 0px);'>
        Inner block
    </div>
</div>

fourchette de violon: https://jsfiddle.net/hju4nws1/

Bien que cela puisse ne pas convenir à certains cas d'utilisation, généralement si vous corrigez une division, vous ne vous soucierez probablement pas de quel élément est son parent/où elle tombe dans l'arbre d'héritage de votre DOM et semble résoudre la plupart des maux de tête. - tout en permettant à translate et position: fixed de vivre en harmonie (relative).

3
reid

J'ai un problème similaire et je pense qu'il y a du travail autour de celui-ci… .. J'utilise snap.js et je souhaite qu'un des div enfants du conteneur de contenu soit fixé à sa position. Toutefois, lorsque le tiroir s'ouvre, le code JavaScript déclenche la propriété transform: translate3d du conteneur parent, ce qui affecte également l'élément enfant fixe (l'élément fixe se déplace avec son parent et reste fixe dans sa nouvelle position).

Cela étant dit, la propriété fixe devient partiellement inutile. Pour résoudre ce problème, un écouteur d'événements peut être ajouté, ce qui déclencherait une transformation distincte: translate3d pour la div enfant fixe. Et la direction de cette traduction devrait être opposée à celle du parent: translate3d.

Le seul problème, c'est que je ne sais pas l'écrire et que ça aurait été cool si quelqu'un s'y était pris.

1
Anson Wakaka

Essayez d'appliquer une transformation opposée à l'élément enfant:

<div style='position:relative; border: 1px solid #5511FF; 
            -webkit-transform:translate3d(0px, 20px , 0px); 
            height: 100px; width: 200px;'> 
    <div style='position: fixed; top: 0px; 
                -webkit-transform:translate3d(-100%, 0px , 0px); 
                box-shadow: 3px 3px 3px #333; 
                height: 20px; left: 0px;'>
        Inner block
    </div>
</div>
0
Mari Do

J'ai une barre latérale de canevas qui utilise -webkit-transform: translate3d. Cela m'empêchait de placer un pied de page fixe sur la page. J'ai résolu le problème en ciblant une classe sur la page html ajoutée à la balise lors de l'initialisation de la barre latérale, puis en écrivant un qualificatif css: not pour indiquer "-webkit-transform: none;" à la balise HTML lorsque cette classe n'est pas présente sur la balise HTML. J'espère que cela aide quelqu'un avec le même problème!

0
WeisbergWeb

Ajouter une classe dynamique pendant que l'élément se transforme .$('#elementId').addClass('transformed'). Continuez ensuite à déclarer en css, 

.translat3d(@x, @y, @z) { 
     -webkit-transform: translate3d(@X, @y, @z); 
             transform: translate3d(@x, @y, @z);
      //All other subsidaries as -moz-transform, -o-transform and -ms-transform 
}

puis 

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

puis

.transformed {
    #elementId { 
        .translate3d(0px, 20px, 0px);
    }
}

Désormais, position: fixed, lorsque les valeurs top et z-index sont associées à un élément enfant, fonctionne parfaitement et reste fixe jusqu'à ce que l'élément parent soit transformé. Lorsque la transformation est annulée, l'élément enfant apparaît de nouveau comme étant corrigé. Cela devrait faciliter la situation si vous utilisez réellement une barre latérale de navigation qui ouvre et ferme en un clic, et vous avez un jeu d'onglets qui doit rester collant lorsque vous faites défiler la page.

0
mr.G

J'ai rencontré le même problème. La seule différence est que mon élément avec 'position: fixed' avait ses propriétés de style 'top' et 'left' définies à partir de JS. J'ai donc pu appliquer un correctif:

var oRect = oElement.getBoundingClientRect();

l'objet oRect contiendra les coordonnées haut/gauche de real (par rapport au port d'affichage). Vous pouvez ainsi ajuster vos propriétés oElement.style.top et oElement.style.left réelles.

0
Mike Dobrin