web-dev-qa-db-fra.com

CSS: position: fixe à l'intérieur de la position: absolu

Je rencontre des comportements extrêmement étranges et non cohérents sur tous les navigateurs que j'ai testés.

J'ai une mise en page assez complexe, mais le problème principal réside ici:

<div id="drop">
  <div id="header"></div>
</div>

#drop a position:absolute et z-index:100
#header a position:fixed; top:60px;

Lorsque je commence à faire défiler Google Chrome ignore la règle position:fixed. Si je supprime soit des deux styles ci-dessus de #drop, Chrome commence à respecter la règle position:fixed.

n'arrive pas à le faire fonctionner sur Ubuntu Chrome 23.0.1271.97 et observe le même comportement sous Mac Chrome 25.0.1364.99. Mon ami utilise Ubuntu Chrome 25.0.1364.68 beta et cela fonctionne correctement pour lui. Je l'ai testé sur firefox et ça marche un peu (avec d'autres symptômes)

Quelqu'un at-il entendu parler de cette erreur? ou peut-on même le reproduire?

modifier

J'utilise openlayers map comme un autre div avec position:fixed si je supprime ce calque ou du moins le change en display:none, alors ce bogue étrange disparaît.

modifier

A remarqué que lors de la présence de ce bogue, si je change le niveau de zoom dans les deux sens, la position s'adapte au bon comportement. Pour moi, cela indique un problème de Webkit qui ne parvient pas à exécuter une fonction de rappel interne lors du défilement.

Une autre chose extrêmement étrange est que j'ai quelques liens à l'intérieur de #header et qu'ils fonctionnent si je clique simplement sur l'emplacement prévu, même si le div n'y apparaît pas. Globalement J'ai remarqué que c'est seulement le rendu qui est cassé. Si, à un moment donné, je force le navigateur à effectuer un nouveau rendu en redimensionnant la fenêtre, en modifiant le zoom ou en effectuant simplement Sélect-Tous, la barre d’en-tête passe à la position appropriée, mais ne reste pas fixe.

20
Mikhail

Vous avez mentionné dans les commentaires qu'OpenLayers utilise des transformations CSS. Cela étant le cas:

l'élément à positionnement fixe deviendra par rapport à l'élément avec la transformation - pas par rapport à la fenêtre

Jetez un coup d'oeil à la spécification: Le modèle de rendu de transformation

Si vous spécifiez une valeur autre que "none" pour la propriété "transform" , Vous créez un nouveau système de coordonnées local au niveau de l'élément auquel elle est appliquée.

Regardez ceci FIDDLE dans un navigateur webkit pour voir cela en action

<div class="wpr">
    <div class="fixed"></div>
</div>

.wpr
{
    width: 200px;
    height:1000px;
    background: pink;
    position:relative;
    margin: 0 200px;
    -webkit-transform: translateX(0);
    transform: translateX(0);
}
.fixed
{
    width: 200px;
    height:200px;
    margin: 50px;
    position: fixed;    
    top:0;
    left:0;
    background: aqua;
}
25
Danield

Comme le dit la réponse acceptée, il s’agit du comportement souhaité, conforme aux spécifications. Un autre élément important de ceci est ce que signifie utiliser des transformations CSS.

Dans votre cas, cela était dû à OpenLayers, mais cela s’applique également à ceux qui utilisent will-change: transform également (probablement beaucoup de personnes visitant cette question). Cela a été évoqué dans le gestionnaire de bogues Chromium ici , et marqué comme suit: WontFix, car (comme je l’ai dit), il a le comportement voulu. Le commentaire officiel est le suivant:

Ce comportement est requis par la spécification ( http://dev.w3.org/csswg/css-will-change/ ): "Si une valeur non initiale De une propriété obligerait l'élément à générer un bloc contenant pour les éléments à position fixe, en spécifiant que cette propriété dans will-change doit obliger l'élément à générer un bloc contenant pour fixe éléments de position. "

L'idée est qu'une fois que change-change: la transformation est spécifiée, vous devriez Pouvoir ajouter/supprimer/modifier des transformations à moindre coût, sans avoir besoin de Descendants à position fixe pour obtenir une nouvelle présentation.

Notez que l'utilisation d'autres valeurs de will-change (opacité, top, par exemple) ne modifiera pas le positionnement des descendants à position fixe.

Autant que je sache, la seule solution est de rendre le child de l'élément will-change a sibling à la place, afin d'éviter que l'attribut ne soit mis en cascade.

En remarque, dans mon cas particulier, j’ai pu résoudre ce problème en étant plus précis avec l’attribut will-change. Au lieu de l'utiliser sur la variable div contenant l'élément de performance qui nécessitait le déchargement de GPU, je l'ai utilisé directement sur l'élément incriminé. Cela était dû à mon mauvais code d'origine, cependant, cela ne fonctionnerait donc pas dans la plupart des cas.

2
forresthopkinsa

Vous devrez placer header en dehors du conteneur parent drop pour que cela fonctionne.

Par exemple, si vous définissez z-index de header, il atteindra l’indice z du parent dropcontainer.Le z-index de header sera inutile car il se trouve déjà dans un conteneur a un autre z-index.

La même logique de z-index s'applique à la position.

1
Rahul Shah

Je veux ajouter une autre solution possible parce que je luttais avec le chrome en ignorant sa position: résolu depuis un certain temps jusqu'à ce que je trouve enfin le coupable:

-webkit-perspective: 1000;

Cela venait d'un plug-in que j'utilisais et fait en sorte que TOUT la position: les éléments fixes soient ignorés. J'espère que ça aidera quelqu'un.

0
parliament