web-dev-qa-db-fra.com

Chrome. Ancrage de position fixe avec UL dans le corps

Il y a un problème de rendu avec Google Chrome et Opera (pourquoi? =) Avec un tel code:

<html>
<style>
    #content {
        width: 150px;
        background: gray;
    }

    #sidebar {
        position: fixed;
        left: 200px;
        background: gray;
    }
</style>
<body>
    <div id="sidebar">
        <a href="#s1">Link #1</a><br/>
        <a href="#s2">Link #2</a>
    </div>

    <div id="content">
        <div id="s1">
            <a href="#s1">Link #1 TARGET</a>
            <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit,
            sed do eiusmod tempor incididunt ut labore et dolore magna
            aliqua. Ut enim ad minim veniam, quis nostrud exercitation
            ullamco laboris nisi ut aliquip ex ea commodo consequat.
            Duis aute irure dolor in reprehenderit in voluptate velit
            esse cillum dolore eu fugiat nulla pariatur.
            Excepteur sint occaecat cupidatat non proident, sunt in culpa
            qui officia deserunt mollit anim id est laborum.</p>
        </div>
        <div id="s2">
            <a href="#s2">Link #2 TARGET</a>
            <ul>
                <li>Item 1</li>
                <li>Item 2</li>
            </ul>
        </div>
    </div>

    <a href="#">TOP</a>
</body>
</html>

Comme vous pouvez le voir, j'essaie de rendre la barre latérale statique du côté droit. Tout fonctionne bien, jusqu'à ce que vous en ajoutiez <UL> tag sur la page:

http://www.youtube.com/watch?v=zkhH6di2M0c

Le div fixe commence parfois à disparaître lorsque je clique sur des liens d'ancrage.

Que peut-on faire pour éviter un tel comportement?

56
sunsay

Solution Chrome:

L'ajout de -webkit-transform: translateZ(0) au #sidebar A résolu le problème pour moi.

J'ai utilisé translateZ(0) pour corriger de nombreux Chrome bogues d'affichage au fil des ans. La raison est qu'en invoquant la transformation 3D, re-Paint est séparé du reste du CSS douleur pile (je ne peux pas fournir beaucoup plus de détails que cela, c'est à peu près tout grec pour moi). En tout cas, cela semble fonctionner pour moi!

    #sidebar {
        -webkit-transform: translateZ(0);
    }

Solution Opera:

Ce n'est pas une solution générique (devra être modifiée en fonction des exigences de positionnement de l'élément en question). Il fonctionne en forçant des repeints continus (via une animation CSS) sur une propriété qui pourrait affecter la mise en page (forçant d'autres facteurs de mise en page à être calculés et rendus, c'est-à-dire à maintenir un positionnement fixe), mais en pratique non. Dans ce cas, j'ai utilisé margin-bottom, Car il n'y a aucun moyen que cela affecte la mise en page de votre page (mais Opera ne le sait pas!)):

@keyframes noop {
  0%   { margin-bottom: 0; }
  100% { margin-bottom: 1em; }
}

#sidebar {
    animation: noop 1s infinite;
}

Remarque: la solution n'est pas parfaite, dans la mesure où (sur ma machine au moins) les cas de test de bogue entraîneront un scintillement d'une minute comme Opera perd le positionnement et redessine rapidement. Malheureusement, je pense que c'est aussi bon que vous obtiendrez, car comme George le dit dans sa réponse , c'est le comportement naturel d'Opera entre les redessins - en théorie, mon le code redessine pour l'élément en continu, mais en pratique il y aura des lacunes infinitésimales.

EDIT 2 (2013-11-05) : J'ai depuis rencontré des variations de ce bug assez souvent. Bien que le scénario de test réduit de l'affiche originale présente un bogue parfaitement légitime, la plupart des cas se sont produits dans des situations où il y a déjà une transformation 3D opérant sur le corps (ou de manière similaire en haut de l'arbre DOM). Ceci est souvent utilisé comme un hack pour forcer le rendu du GPU, mais conduira en fait à des problèmes de repeinture désagréables comme celui-ci. 2 transformations 3D sans opération ne font pas un droit: si vous en utilisez une plus haut dans l'arborescence, essayez de la supprimer avant d'en ajouter une autre.

EDIT 3 (2014-12-19) : Chrisrapports que translateZ(0) ne fonctionne pas dans certains cas où scale3d(1,1,1) fonctionne.

169
Barney

La clé pour Chrome est:

 html, body {height:100%;overflow:auto}

En ajoutant cela, le problème de position fixe devrait être corrigé.

15
Corneliu

Cela a du sens si vous comprenez comment fonctionne le flux normal du document. Disons que c'est un scénario de cas Edge.

Il n'y a pas de hauteur déclarée dans aucun élément et #sidebar est retiré du flux normal du document en étant position:fixed.

Si vous ajoutez une propriété de hauteur à #sidebar (pixels, pas pourcentages), le problème est résolu.

Je suggère d'inclure Normalize.css, je pense que cela corrigera le bogue.

0
George Katsanos