iframe заставляет родительские элементы прокручиваться в Google Chrome, когда URL содержит фрагмент

в Google Chrome (37.0.2062.122, OSX / Windows) iframe с URL-адресом, содержащим фрагмент, заставляет родительские элементы прокручиваться вверх.

это происходит только в Chrome (протестировано в Safari и Firefox).

вот скрипку показывая вопрос: http://jsfiddle.net/wmz5cu1y/1/ (вы должны нажать Run два раза.)

Как вы можете видеть, все <body> содержащий iframe прокрутился вверх. Заголовок скрыт, потому что теперь он находится над окном, и в нижней части страницы есть неожиданное пустое место.

Как избежать этого ?

Bounty предлагается для обходного пути не-js или более простого html-документа, воспроизводящего проблему.

iframe overflows body

5 ответов


воспроизведение скрипта

нашел минимальный способ воспроизвести ошибку:http://jsfiddle.net/4oytgwon/1/embedded/result/ (Вы можете увидеть, что ошибка происходит после нажатия на "загрузить iframe").

Это также происходит за пределами jsfiddle, используя следующий код:

<!doctype html>
<html>
    <head>
        <style>
            body, html {
                padding: 0;
                border: 0;
                margin: 0;
                height: 100%;
                overflow: hidden;
            }
            #header {
                height: 50px;
                background: blue;
            }
            #content {
                position: absolute;
                top: 50px;
                right: 0;
                bottom: 0;
                left: 0;
            }
            #overflow {
                position: absolute;
                height: 50px;
                bottom: -50px;
            }
        </style>
        <script>
            function loadIframe() {
                var ifr = document.createElement('iframe');
                ifr.src = 'https://en.wikipedia.org/wiki/Stack_overflow#See_also';
                var content = document.getElementById('content');
                while (content.firstChild) {
                    content.removeChild(content.firstChild);
                }
                content.appendChild(ifr);
            }
            window.onload = function () {
                document.getElementById('btn').onclick = loadIframe;
            };
        </script>
    </head>
    <body>
        <div id=header>
            <button id=btn>load iframe</button>
        </div>
        <div id=content>
        </div>
        <div id=overflow>
            overflow
        </div>
    </body>
</html>

как уже упоминалось в других ответах, проблема здесь специфична для JSFiddle. Я могу показать вам это с легкостью, просто включив тот же код в фрагмент StackOverflow по этому вопросу:

iframe {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  width: 100%;
  height: 100%;
}
<iframe src="https://news02ycombinator02com2.mentionusercontent.net/item?id=8357207#up_8360397" width="100%" height="100%"></iframe>

более простой HTML-документ

эта проблема возникает с каждым URL-адресом фрагмента, переданным в iframe на JSFiddle. Из-за этого мы можем реплицировать эту проблему, просто создавая отдельную демонстрацию jsfiddle и ссылка на это в нашем iframe.

я создал эту новую демонстрацию jsfiddle здесь:http://fiddle.jshell.net/JamesD/k5vk2u9h/1/show/light/#test.

как вы можете видеть, фрагмент Здесь #test. Эта проблема теперь воспроизводится в новой демонстрации jsfiddle, используя следующую разметку:

<iframe src="http://fiddle.jshell.net/JamesD/k5vk2u9h/1/show/light/#test"></iframe>

на height и width атрибуты не имеют значения, поскольку проблема не представляется без них.

JSFiddle демо.


решение

другой ответ здесь предполагает, что исправление заключается в изменении собственного HTML JSFiddle для правильной рендеринга страницы. Это не отличное решение, как в реальной ситуации (т. е. при подключении кого-то к демо-версии JSFiddle), у них может не хватить опыта для этого.

мы можем обойти это с помощью JavaScript. Поскольку новый HTML-документ, который я создал, находится в том же домене (http://jshell.net) Мы можем выполнить JavaScript в . Ручная настройка location.hash свойство также вызовет эту проблему, поэтому вместо этого мы можем прокрутить iframe непосредственно к элементу, на котором мы хотим сосредоточиться.

во-первых, удалите фрагмент из URL-адреса в наших iframe:

<iframe src="http://fiddle.jshell.net/JamesD/k5vk2u9h/1/show/light/"></iframe>

как упоминалось выше, фрагмент, который я использовал, является элементом,id - "тест". Это значит самое легкое способ получить наш элемент-выбрать его по его :

var frame = frames[0],
    elem = frame.document.querySelector('#test'),

здесь frame ссылка на наш iframe в нашем собственном документе, и elem наша #test элемент. Мы можем получить позицию нашего сопоставленного элемента, используя getBoundingClientRect():

    position = elem.getBoundingClientRect();

это даст нам объект ClientRect следующим образом:

ClientRect

С этим мы теперь знаем, что наши #test элемент расположен 3034px от верхней части нашего iframe. Используя это, теперь мы можем прокрутить страницу сами в эту позицию, используя window.scrollTo() (где window наших iframe в этом случае проводится в нашем frame переменной):

frame.scrollTo(0, position.top);

демо JSFiddle.

обратите внимание, что это решение будет работать только если iframe указывает на URL-адрес, размещенный в том же домене, или если CORS был включен на странице iframe - это вложение.


лучшие вариант

после всего этого, однако, лучше всего просто уведомить разработчиков JSFiddle, что это ошибка. Я поднял это как проблему в их репозитории GitHub здесь:https://github.com/jsfiddle/jsfiddle-issues/issues/547.


Пересмотренный Ответ

здесь две ошибки отображается здесь.

  1. JSFiddle теряет часть заголовка при загрузке iFrame с фрагментом. Это обсуждается в других ответах и в моем разделе "старый ответ". И был поднят вопрос о github.
  2. iFrames на chrome плохо обрабатывает фрагменты. Они вызывают прокрутку на родителе. (Это может быть желаемое поведение, чтобы быть справедливым).

Chrome iFrame проблема

когда вы запускаете это, ваше окно будет прокручиваться так, что фрагмент в окне в верхней части страницы:

<iframe src="https://news02ycombinator02com2.mentionusercontent.net/item?id=8357207#up_8360397" width="100%" height="100%"></iframe>

как вы можете себе представить, это вызывает проблемы на некоторых веб-сайтах с фиксированной высотой, таких как jsfiddle. Он также уникален для Chrome (я тестировал только на FF, а не IE), Firefox не прокручивает родительское окно. Существует дискуссия о том, что его нет в FF здесь.

Chrome iframe родительская прокрутка исправить

Скрипка

добавьте событие onload в iframe, вызывающее следующую функцию. И не используйте фрагмент в оригинале:

<script>
    function loadorder() {
    document.getElementById("iframename").src= "https://news02ycombinator02com2.mentionusercontent.net/item?id=8357207#up_8360397";
    window.scrollTo(0,0);
}
</script>
<iframe width="830" src="https://news02ycombinator02com2.mentionusercontent.net/item?id=8357207" height="500" id="iframename"  onLoad="loadorder();"></iframe>

как вы можете видеть как в скрипке, так и в приведенном выше фрагменте, родительское окно больше не прокручивается, и поведение теперь одинаково для FF и Chrome.

источник для ремонта.

старый ответ (альтернативное исправление для jsfiddle)

хорошо, поэтому я сделал несколько тестов:

  • выпуск только на Chrome
  • проблема возникает с любым фрагментом связанной страницы:пример
  • проблема специфична для jsfiddle. CodePen и jsbin работать нормально.

так как временное обходное решение или использует одно из тех или впрыскивает это в html jsfiddle:

margin-top: 30px; into the header bar like:

<div id="header" style="margin-top: 30px;">

немного боли хотя, поскольку это нужно делать каждый раз, когда вы загружаете jsfiddle (но не каждый раз, когда вы запустите скрипка).

чтобы устранить проблему, следует сообщить об этом в JSFiddle github страница:https://github.com/jsfiddle/jsfiddle-issues/issues

редактировать

и вот способ автоматизировать его в chrome: загрузите stylebot расширение, и добавьте этот стиль к jsfiddle.com (или конкретные скрипка):

#header {
    margin-top: 30px;
}

он работает довольно хорошо.


проблема не в том, чтобы включить # в url iframe, если вы попытаетесь со следующим url в вашем примере, вы увидите, что нет прокрутки: http://www.w3.org/TR/scxml/#scxml

Итак, я просмотрел страницу, которую вы показываете, чтобы увидеть, есть ли что-то странное: https://news02ycombinator02com2.mentionusercontent.net/item?id=8357207#up_8360397

Если вы проверите JS, у него есть что-то вроде следующего:

      var e = window,
    g = document,
    h = "documentElement",
    k = "CriticalImages",
    l = "scrollTop",
    n = "prototype",
    p = "body",
    q = "getAttribute",

есть функция под названием "scrollTop", которая, я думаю, является хорошим кандидатом для исследования.

Если вы проверите код немного больше, вы увидите, что в какой-то момент JS получает offsetTop и offsetParent:

 u = function(a, b) {
        var c = b[q]("pagespeed_lazy_position");
        if (c) return parseInt(c, 0);
        var c = b.offsetTop,
            d = b.offsetParent;
        d && (c += u(a, d));
        c = Math.max(c, 0);
        b.setAttribute("pagespeed_lazy_position", c);
        return c
    },

вывод: проблема заключается в странице, которую вы пытаетесь показать в своем iframe, а не в fiddle или Chrome или # в URL-адресах.

Я надеюсь, что это поможет.


редактировать

после просмотра примера wiki I смотрите, что это некоторые js в скрипке (так что первый ответ правильный).

чтобы избежать этого с js, вы просто включите это:

$( window.parent ).scroll(function(event) {
   // debugger;
  console.log('SCROLL',event);
  var scrollTop=$(this).scrollTop();
  if(scrollTop>0){
      console.log('fix scroll');
      $(this).scrollTop(0);
  }

});

Пример:
http://fiddle.jshell.net/xbnt3Lu6/21/

я попытаюсь рассмотреть, какой js вызывает проблему.


ну его не только chrome, все браузеры будут иметь ту же проблему, кажется , что сайт имеет тяжелые сценарии js, не знаю, как, но это влияет на сайт, который вы ставите iframe на, самый простой способ его решения-удаление #up_8360397 по ссылке. Второй способ-отключить javascript внутри iframe. но чем вы не сможете автоматически прокрутить его до нужной должности, вам придется установить позиции прокрутки вручную.