Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Element.prototype.getPosition does not properly handle elements with fixed position parents #2766

Open
Continuities opened this issue Mar 21, 2016 · 19 comments

Comments

@Continuities
Copy link

Continuities commented Mar 21, 2016

It looks like the intent is for getPosition to return a number relative to the viewport for fixed position elements. If an element is not fixed but nested inside a fixed element, however, getPosition returns a number relative to the document. This is because isFixed (on line 136 of Element.Dimensions.js) only checks the styling of the element itself.

The problem is worse because the behaviour is inconsistent between desktop and iOS. iOS uses a different code-path in getOffsets that correctly returns a number relative to the viewport for elements inside fixed elements.

--- Want to back this issue? **[Post a bounty on it!](https://www.bountysource.com/issues/32112238-element-prototype-getposition-does-not-properly-handle-elements-with-fixed-position-parents?utm_campaign=plugin&utm_content=tracker%2F22067&utm_medium=issues&utm_source=github)** We accept bounties via [Bountysource](https://www.bountysource.com/?utm_campaign=plugin&utm_content=tracker%2F22067&utm_medium=issues&utm_source=github).
@SergioCrisostomo
Copy link
Member

@Continuities thanks for reporting this.

If you could provide a jsFiddle or example that reproduces the problem would be great.

Cheers

@Continuities
Copy link
Author

https://jsfiddle.net/Continuities/bo1zm146/3/

  1. Run fiddle in Chrome on desktop and scroll the view. Note that the number (getPosition().y of the target element) goes up, representing a position relative to the document.
  2. Spoof an iOS useragent (don't actually load jsFiddle on an iPhone. The layout doesn't work properly), and reload. Scroll the view. Note that the number stays 0, representing a position relative to the viewport.

@ciez
Copy link

ciez commented Sep 20, 2016

afaik this is expected behaviour. getPosition is calculated re: relative positioned parent.

CSS behaves smilarly: offset is specified re: relative positioned parent.

@Continuities
Copy link
Author

It's expected that getPosition should behave differently between iOS and desktop Chrome?

@ciez
Copy link

ciez commented Sep 20, 2016

top div is rarely set position:fixed. This may be allowed however this may be causing the issue.

I just tried to wrap entire html in another generic <div> (position:inherited/not set), spoofed IPad and IPhone 6.

behaviour is similar to desk Chrome: the number is updated.

just remember that position get / set works relative to nearest non-fixed parent. This is aligned with CSS.

@Continuities
Copy link
Author

Not the behaviour I'm seeing. Wrapping the entire thing in an unstyled div does nothing to change the inconsistency between desktop and iOS. I know exactly where the bug is, and reported it in the original issue description.

@ciez
Copy link

ciez commented Sep 20, 2016

how do you spoof iOS?

what if you getOffsetParent and pass the parent to getPosition? does it work as you need it?

if position is calculated relative to any parent regardless of their fixed / relative attribute, this would lead to different behaviour from CSS and from how it works now.

@Continuities
Copy link
Author

Chrome dev tools with an iOS user-agent. I don't really care which behaviour you choose (either document-, or viewport-relative), I just want it to be consistent between platforms. It should not be necessary to implement workarounds (like getOffsetParent) to achieve consistency.

@ciez
Copy link

ciez commented Sep 20, 2016

I use toggle device toolbar. Is this the same thing?

actually, even without adding generic div, behaviour is similar.

there may be differences in Chrome versions. Do you use Linux too?

also (just checking) did you disable cache in dev-tools?

@Continuities
Copy link
Author

Continuities commented Sep 20, 2016

Are you reloading between switching devices? The user-agent is only actually updated if you refresh. It's not a Chrome issue, it's caused by the two different code-paths in getOffsets behaving differently:

The first block (inside the if (hasGetBoundingClientRect) conditional) only checks the current element for position:fixed. This is the block that desktop uses. The second block walks up the DOM and adds offsets all the way up. This is the block that iOS uses.

I can fix the issue myself, if necessary. I just don't want to bother cloning the project and making a pull request.

@ciez
Copy link

ciez commented Sep 20, 2016

I tried to reload.

js fiddle code (not your snippet, jsfiddle editor js file) throws an error. Scrolling behaviour after this error is very odd: the scroll hand moves in the opposite direction from cursor. I suppose it may be caused by jsfiddle's error.

As a side note: I am not Mootools library dev - a user like yourself. I remembered I was surprised to find out how position fixed and relative are different. Thought I could help.

To check your code, I need to load your example outside of jsFiddle. Let me do this in the next few days.

If you change the library, please do not change desktop Chrome behaviour.

@Continuities
Copy link
Author

Continuities commented Sep 20, 2016

the scroll hand moves in the opposite direction from cursor

That just sounds like it's switched to touch-based scrolling. There is a jsFiddle error thrown, but it doesn't appear to cause any problems.

If you change the library, please do not change desktop Chrome behaviour.

See, that's the issue. I think iOS is behaving correctly in this instance, and not desktop Chrome. Behaviour could be consolidated to be "wrong" everywhere, but that doesn't feel like the right answer. I'll leave it up to the MooTools dev community.

@ciez
Copy link

ciez commented Sep 20, 2016

just noticed that https://jsfiddle.net/Continuities/bo1zm146/3/ does not use MooTools. Javascript is set to No-library (pure Js)

is this intended? Are we testing MooTools then?

@Continuities
Copy link
Author

It's an external dependency. None of the code would work without MooTools.

@Continuities
Copy link
Author

While trying to write a spec to capture this behaviour, I discovered another interesting quirk: The bug disappears if the scrolling element is any element other than the window (ie, the fixed malarky is inside a div with overflow:scroll instead of directly inside the window). Looks like element scrolls are subtracted out, while html scrolls are not.

@ciez
Copy link

ciez commented Sep 20, 2016

do not iOS capture other event, not scroll?

I modified your code to this

iOS (drag?) behaves similar to desktop scroll
upd: I had forgot to reload. iOS shows 0.

@Continuities
Copy link
Author

That code still exhibits the inconsistent behaviour that I described. I don't think you're properly emulating iOS user-agents.

@ciez
Copy link

ciez commented Sep 20, 2016

I overlooked that sticky has position fixed and thought about absolute vs relative / not set attributes.

I am not sure what getPosition should return for fixed elements and their children. I'd never tried it.

Sorry about the confusion. I can't help.

@Continuities
Copy link
Author

It's alright =)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants