Это закончилось гораздо большим исследованием, чем код.То, что происходило, было - у меня был код, который изменял размер IFrame на основе содержимого.
Во всех других браузерах это работает нормально и убирает полосы прокрутки.Оказывается, Safari автоматически изменяет размеры Iframe , оставляя свои собственные свитки.В моем приложении нет нулевых статических страниц.Это оставляет меня с проблемой невозможности использовать исправление scrolling=no
, описанное в ссылке.
После точного выяснения того, что происходит, я использовал другой подход к исправлению elm.scrollIntoView()
.Код - это больше комментариев, чем все, кроме важных частей:
- Определение, когда применять исправление Iframe с помощью
RequiresIframeScrollFix
- Использование
elm.getBoundingClientRect().top
для получения нашей позиции прокрутки изнутриiframe. - Общение с родителем для прокрутки с помощью
window.parent.postMessage
- Получение сообщения от родителя с помощью
window.addEventListener('message',...)
Вот как это выглядит.
Сайт Iframe
Наш сайт Iframe в настоящее время прокручивает свои элементы в виде, подобном этому elm.scrollIntoView();
Мы изменили это на следующее.
if (RequiresIframeScrollFix())
window.parent.postMessage(elm.getBoundingClientRect().top, "*"); // Tell IFrame parent to do the scrolling. If this is not a test environment, replace "*" with the parent domain.
else
elm.scrollIntoView(); // If not scroll into view as usual.
Необязательно: исправлено модальное позиционирование начальной загрузки в IFrames IOS с использованием elm.getBoundingClientRect().top
.
$('#modalId').css('top', elm.getBoundingClientRect().top); // This fixes modal not in view on Safari Iframes.
RequiresIframeScrollFix()
в основном состоит из некоторого кода документа скважины, лежащего вокруг SO, чтобы определить, находимся ли мы в Iframeна IPad или IPhone.
// Used to help identify problematic userAgents.
var debugNavigator = false;
// Detects an issue on mobile where the Parent is an iframe which cannot have it's scroll bars removed.
// Presumably not a bug as safari will autosize it's iframes: https://salomvary.com/iframe-resize-ios-safari.html
// Can use "scrolling=no" fix instead if the parent knows the initial size of your iframe.
function RequiresIframeScrollFix() {
try {
// Debug navigator Agent
if (debugNavigator)
alert(navigator.userAgent);
// We know this issue happens inside an IFrame on;
// Safari iPhone
// Safari iPad
// Safari Desktop Works fine.
// Check for safari
var is_safari = navigator.userAgent.indexOf("Safari") > -1;
// Chrome has Safari in the user agent so we need to filter (https://stackoverflow.com/a/7768006/1502448)
var is_chrome = navigator.userAgent.indexOf('Chrome') > -1;
if ((is_chrome) && (is_safari)) { is_safari = false; }
// If we need to narrow this down even further we can use a more robust browser detection (https://stackoverflow.com/questions/5916900)
// Problematic browsers can be adjusted here.
if (is_safari && inIframe() && (
navigator.userAgent.match(/iPad/i) ||
navigator.userAgent.match(/iPhone/i)
))
return true;
else
return false;
} catch (e) {
alert(e.message);
}
}
// (/283115/kak-opredelit-zagruzhaetsya-li-veb-stranitsa-vnutri-iframe-ili-neposredstvenno-v-okne-brauzera)
function inIframe() {
try {
return window.self !== window.top;
} catch (e) {
return true;
}
}
Родительский сайт
Наш родительский сайт содержит IFrame, размер которого автоматически определен Safari Mobile.Поэтому родительский сайт теперь имеет собственные полосы прокрутки, а не IFrame.Мы устанавливаем наш слушатель внутри родительского сайта, чтобы прокручивать себя, когда он получает сообщение от сайта IFramed.
// Safari Mobile Iframe Cross Domain Scroll Fix.
window.onload = function () {
// Calback function to process our postMessages.
function receiveMessage(e) {
try {
// Set the scroll position from our postMessage data.
// Non-Test pages should uncomment the line below.
//if (e.origin.includes("your-iframe-domain.com"))
window.scrollTo(0, e.data);
}
catch (err) {
}
}
// Setup and event to receives messages form our iframe (or window)
window.addEventListener('message', receiveMessage);
}
Надеемся, что это поможет кому-то еще разобрать проблемы Safari Iframe на мобильном телефоне.Кроме того, дайте мне знать, если я пропустил лучшее решение.