@@ -170,7 +170,7 @@ function getViewportCollisions(coords, elementWidth, elementHeight) {
170170 // adjusting viewport even though it might be negative because coords
171171 // comparing with are relative to compensated position
172172 var viewportTop = session . scrollTop - session . positionCompensation . top ,
173- viewportLeft = session . scrollLeft - session . positionCompensation . left ,
173+ viewportLeft = session . scrollLeft - session . positionCompensation . left ,
174174 viewportBottom = viewportTop + session . windowHeight ,
175175 viewportRight = viewportLeft + session . windowWidth ,
176176 collisions = Collision . none ;
@@ -206,38 +206,51 @@ function countFlags(value) {
206206}
207207
208208/**
209- * Compute compensating position offsets if body element has non-standard position attribute.
209+ * Compute compensating position offsets if body or html element has non-static position attribute.
210210 * @private
211211 * @param {number } windowWidth Window width in pixels.
212212 * @param {number } windowHeight Window height in pixels.
213213 * @return {Offsets } The top, left, right, bottom offset in pixels
214214 */
215215function computePositionCompensation ( windowWidth , windowHeight ) {
216- var bodyWidthWithMargin ,
217- bodyHeightWithMargin ,
218- offsets ,
219- bodyPositionPx ;
220-
221- switch ( $body . css ( 'position' ) ) {
222- case 'absolute' :
223- case 'fixed' :
224- case 'relative' :
225- // jquery offset and position functions return top and left
226- // offset function computes position + margin
227- offsets = $body . offset ( ) ;
228- bodyPositionPx = $body . position ( ) ;
229- // because element might be positioned compute right margin using the different between
230- // outerWidth computations and add position offset
231- bodyWidthWithMargin = $body . outerWidth ( true ) ;
232- bodyHeightWithMargin = $body . outerHeight ( true ) ;
233- // right offset = right margin + body right position
234- offsets . right = ( bodyWidthWithMargin - $body . outerWidth ( ) - ( offsets . left - bodyPositionPx . left ) ) + ( windowWidth - bodyWidthWithMargin - bodyPositionPx . left ) ;
235- // bottom offset = bottom margin + body bottom position
236- offsets . bottom = ( bodyHeightWithMargin - $body . outerHeight ( ) - offsets . top ) + ( windowHeight - bodyHeightWithMargin - bodyPositionPx . top ) ;
237- break ;
238- default :
239- // even though body may have offset, no compensation is required
240- offsets = { top : 0 , bottom : 0 , left : 0 , right : 0 } ;
216+ // Check if the element is "positioned". A "positioned" element has a CSS
217+ // position value other than static. Whether the element is positioned is
218+ // relevant because absolutely positioned elements are positioned relative
219+ // to the first positioned ancestor rather than relative to the doc origin.
220+ var isPositioned = function ( el ) {
221+ return el . css ( 'position' ) !== 'static' ;
222+ } ;
223+
224+ var getViewportToElementOffset = function ( el ) {
225+ var elWidthWithMargin ,
226+ elHeightWithMargin ,
227+ elPositionPx ,
228+ offsets ;
229+ // jquery offset and position functions return top and left
230+ // offset function computes position + margin
231+ offsets = el . offset ( ) ;
232+ elPositionPx = el . position ( ) ;
233+
234+ // Compute the far margins based off the outerWidth values.
235+ elWidthWithMargin = el . outerWidth ( true ) ;
236+ elHeightWithMargin = el . outerHeight ( true ) ;
237+
238+ // right offset = right margin + body right position
239+ offsets . right = ( elWidthWithMargin - el . outerWidth ( ) - ( offsets . left - elPositionPx . left ) ) + ( windowWidth - elWidthWithMargin - elPositionPx . left ) ;
240+ // bottom offset = bottom margin + body bottom position
241+ offsets . bottom = ( elHeightWithMargin - el . outerHeight ( ) - offsets . top ) + ( windowHeight - elHeightWithMargin - elPositionPx . top ) ;
242+ return offsets ;
243+ } ;
244+
245+ var offsets ;
246+
247+ if ( isPositioned ( $body ) ) {
248+ offsets = getViewportToElementOffset ( $body ) ;
249+ } else if ( isPositioned ( $html ) ) {
250+ offsets = getViewportToElementOffset ( $html ) ;
251+ } else {
252+ // even though body may have offset, no compensation is required
253+ offsets = { top : 0 , bottom : 0 , left : 0 , right : 0 } ;
241254 }
242255
243256 return offsets ;
0 commit comments