web-dev-qa-db-fra.com

Bug relatif au positionnement relatif/absolu dans IE7 avec un contenu de page modifié dynamiquement

Je me demandais si quelqu'un avait une idée de la façon de résoudre le problème suivant dans IE7:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <title>IE7 absolute positioning bug</title>
    <style type="text/css">
      #panel { position: relative; border: solid 1px black; } 
      #spacer { height: 100px; } 
      #footer { position: absolute; bottom: 0px; }
    </style>
    <script type="text/javascript"> 
      function toggle() { 
        var spacer = document.getElementById("spacer"); 
        var style = "block"; 
        if (spacer.style.display == "block" || spacer.style.display == "") { 
          style = "none"; 
        }
        spacer.style.display = style;
      }
    </script>
  </head>
  <body>
    <div id="panel">
      <button onclick="toggle();">Click me</button>
      <br /><br /><br />
      <div id="spacer"></div>
      <div id="footer">This is some footer</div>
    </div>
  </body>
</html>

Lorsque vous exécuterez ceci dans IE7, vous verrez que l'élément "footer" reste après la modification du code CSS pour "panel". Le même exemple testé dans IE8, FF et Chrome se comporte exactement comme prévu.

J'ai déjà essayé de mettre à jour la classe de l'élément, mais cela ne fonctionne pas si la fenêtre du navigateur a été ouverte au maximum et qu'aucune autre modification de taille n'a été apportée à la fenêtre (ce qui correspond à environ 90% des cas d'utilisation de notre produit ... . :() Je suis coincé avec une solution basée sur CSS, mais je pense que je peux faire une exception dans ce cas si elle peut facilement être rendue spécifique à IE7 (ce qui signifie que les autres navigateurs se comporteront de manière standard avec ça).

S'il vous plaît aider! 

30
Matthias Hryniszak

Ceci est lié au "bug hasLayout" de IE. Le parent #panel relativement positionné n'a pas de structure et par conséquent, IE oublie de redessiner ses enfants lorsqu'il est redimensionné/repositionné. 

Le problème disparaîtra si vous ajoutez overflow: hidden; au #panel parent relativement positionné.

#panel { position: relative; overflow: hidden; border: solid 1px black; } 

Vous trouverez des informations de fond détaillées sur ce bogue IE dans l'excellente référence "Si vous avez une mise en page" , puis pour votre problème particulier, le chapitre "Éléments placés relativement" :

Notez que position: relative ne déclenche pas hasLayout, ce qui entraîne des erreurs de rendu, principalement du contenu en train de disparaître ou mal placé. Des incohérences peuvent être rencontrées lors du rechargement de la page, du dimensionnement de la fenêtre et du défilement, de la sélection. Avec cette propriété, IE décale l'élément, mais semble oublier d'envoyer un «rafraîchissement» à ses éléments enfants de présentation (car un élément de présentation aurait été correctement envoyé dans la chaîne de signaux des événements de rafraîchissement).

La propriété overflow déclenche la disposition de l'élément, voir aussi le chapitre "D'où provient la disposition" :

À partir de IE7, overflow est devenu un déclencheur de mise en page.

68
BalusC

Cette solution ne concerne pas nécessairement le contenu dynamique, mais elle a fonctionné pour moi (au moins, la page a été bouchée à un degré raisonnable): spécifier les dimensions . J’ai seulement remarqué qu’IE7 pensait qu’une div n’avait pas de largeur lorsqu’elle utilisait l’outil «Sélectionner élément par clic» (ctrl + B) dans les outils IE. 

2
Sebastian Thomas

J'ai créé ma fonction pour déclencher le rafraîchissement. Peut-être que ce n'est pas une bonne solution, mais cela fonctionne.

// Script to fix js positon bug on IE7

// Use that function, recomended delay: 700
function ie7fixElementDelayed(elements, delay) {
    window.setTimeout(
        function () {
            if(navigator.appVersion.indexOf("MSIE 7.") != -1) {
                ie7fixElement(elements);
            }
        },
        delay
    );
}

function ie7fixElement(elements) {
    elements.each(function(i) {
        var element = $(this);
        var orginalDisplayValue = element.css("display");

        element.css("display", "none");
        element.css("display", orginalDisplayValue);
    });
}

Exemple d'utilisation:

ie7fixElementDelayed($('#HandPickedWidget .widget'), 700);
0
MaciejLisCK