Ошибка относительного / абсолютного позиционирования в IE7 с динамически изменяемым содержимым страницы - PullRequest
30 голосов
/ 18 марта 2010

Мне было интересно, есть ли у кого-нибудь идея, как решить следующую проблему в 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>

Когда вы запустите это в IE7, вы увидите, что элемент «нижнего колонтитула» остается после изменения CSS для «панели». Тот же пример, протестированный в IE8, FF и Chrome, работает точно так же, как и ожидалось.

Я уже пытался обновить класс элемента, но это не работает, если окно браузера было развернуто в максимальном размере и в него не было внесено никаких дополнительных изменений размера (что составляет около 90% случаев использования, которые мы имеем для нашего продукта .... :() Я застрял с решением на основе CSS, однако я думаю, что в этом случае я могу сделать исключение, если его легко сделать специфичным для IE7 (что означает, что другие браузеры будут вести себя стандартным образом с этим).

Пожалуйста, помогите!

Ответы [ 3 ]

68 голосов
/ 18 марта 2010

Это связано с «ошибкой hasLayout» в IE. Относительно расположенный родительский элемент #panel не имеет макета, и, следовательно, IE забывает перерисовывать своих дочерних элементов при изменении размера / изменении положения.

Проблема исчезнет, ​​если вы добавите overflow: hidden; к относительно позиционированному #panel родителю.

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

Подробную информацию об этой ошибке IE можно найти в превосходной справке "При наличии макета" , а затем, в частности, для вашей конкретной проблемы в главе "Относительно расположенные элементы"

Обратите внимание, что position: relative не вызывает hasLayout, что приводит к некоторым ошибкам рендеринга, в основном к исчезновению или неправильному размещению содержимого. Несоответствия могут возникнуть при перезагрузке страницы, изменении размера окна и прокрутке, выборе. С этим свойством IE смещает элемент , но, похоже, забывает отправить «перерисовку» дочерним элементам макета (так как элемент макета правильно отправил бы в сигнальной цепочке событий перерисовки).

Свойство overflow активирует макет элемента, см. Также главу «Откуда берется макет» :

Начиная с IE7, overflow стал триггером размещения.

2 голосов
/ 11 августа 2011

Это решение не обязательно имеет какое-либо отношение к динамическому контенту, но оно сработало для меня (по крайней мере, заставило страницу потерять управление): указать размеры . Я только заметил, что IE7 думал, что div не имеет ширины при использовании дрянного инструмента «Выбрать элемент по клику» (ctrl + B) в инструментах IE.

0 голосов
/ 16 июля 2013

Я создал свою функцию для запуска перерисовки. Возможно, это не правильное решение, но оно работает.

// 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);
    });
}

Пример использования:

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