diff --git a/src/dom-utils/getDocumentRect.js b/src/dom-utils/getDocumentRect.js index 815cae59fa..15b1990aea 100644 --- a/src/dom-utils/getDocumentRect.js +++ b/src/dom-utils/getDocumentRect.js @@ -1,17 +1,36 @@ // @flow import type { Rect } from '../types'; import getDocumentElement from './getDocumentElement'; +import getComputedStyle from './getComputedStyle'; +import getWindowScrollBarX from './getWindowScrollBarX'; import getWindowScroll from './getWindowScroll'; +// Gets the entire size of the scrollable document area, even extending outside +// of the `` and `` rect bounds if horizontally scrollable export default function getDocumentRect(element: HTMLElement): Rect { - const winScroll = getWindowScroll(element); const html = getDocumentElement(element); + const winScroll = getWindowScroll(element); const body = element.ownerDocument.body; - const width = Math.max(html.clientWidth, body ? body.clientWidth : 0); - const height = Math.max(html.clientHeight, body ? body.clientHeight : 0); - const x = -winScroll.scrollLeft; + const width = Math.max( + html.scrollWidth, + html.clientWidth, + body ? body.scrollWidth : 0, + body ? body.clientWidth : 0 + ); + const height = Math.max( + html.scrollHeight, + html.clientHeight, + body ? body.scrollHeight : 0, + body ? body.clientHeight : 0 + ); + + let x = -winScroll.scrollLeft + getWindowScrollBarX(element); const y = -winScroll.scrollTop; + if (getComputedStyle(body || html).direction === 'rtl') { + x += Math.max(html.clientWidth, body ? body.clientWidth : 0) - width; + } + return { width, height, x, y }; } diff --git a/src/dom-utils/getViewportRect.js b/src/dom-utils/getViewportRect.js index c14326b036..44421f848a 100644 --- a/src/dom-utils/getViewportRect.js +++ b/src/dom-utils/getViewportRect.js @@ -25,11 +25,13 @@ export default function getViewportRect(element: Element) { // Uses Layout Viewport (like Chrome; Safari does not currently) // In Chrome, it returns a value very close to 0 (+/-) but contains rounding // errors due to floating point numbers, so we need to check precision. - // Safari returns a number <= 0, usually <= 1 when pinch-zoomed - if ( - Math.abs(win.innerWidth / visualViewport.scale - visualViewport.width) < - 0.001 - ) { + // Safari returns a number <= 0, usually < -1 when pinch-zoomed + + // Feature detection fails in mobile emulation mode in Chrome. + // Math.abs(win.innerWidth / visualViewport.scale - visualViewport.width) < + // 0.001 + // Fallback here: "Not Safari" userAgent + if (!/^((?!chrome|android).)*safari/i.test(navigator.userAgent)) { x = visualViewport.offsetLeft; y = visualViewport.offsetTop; }