Closed Bug 1258911 Opened 8 years ago Closed 8 years ago

Position fixed not working until reapplied in css inspector

Categories

(Core :: Layout: Positioned, defect)

50 Branch
defect
Not set
normal

Tracking

()

RESOLVED FIXED
mozilla51
Tracking Status
firefox51 --- fixed

People

(Reporter: jay, Assigned: bzbarsky, NeedInfo)

References

Details

(Keywords: testcase)

Attachments

(3 files)

User Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.87 Safari/537.36

Steps to reproduce:

Please watch this video to see the map under the dialog not observing position fixed until after it is reapplied using the css inspector.

https://youtu.be/B01cnZDztYU


Actual results:

The div is not fixed. 


Expected results:

The div should be fixed
I should perhaps also mentioned that this works correctly in all other browsers. IE, Chrome Desktop and Android, and Safari Desktop and iOS tested.
Please provide source code that reproduces this issue. Either as a URL or an attachment https://bugzilla.mozilla.org/attachment.cgi?bugid=1258911&action=enter Without it the bug is incomplete. 


User posted at about the issue. https://www.reddit.com/r/firefox/comments/4bkjq0/firefox_position_fixed_not_working/
Flags: needinfo?(jay)
https://blight.ironhelmet.com
Flags: needinfo?(jay)
sorry here is a version of the app serving uncompressed scripts. 

https://blight.ironhelmet.com/u
Flags: needinfo?(kbrosnan)
I can reproduce this on Mac OS X 10.10 with FF Nightly 50.0a1.
Status: UNCONFIRMED → NEW
Component: Untriaged → CSS Parsing and Computation
Ever confirmed: true
Version: 45 Branch → 50 Branch
Ovidiu, what are the actual steps to reproduce here?  Does reproducing require creation of an account (and if so, do we have a test account that can be used)?
Flags: needinfo?(ovidiu.boca)
In any case, this is very unlikely to be a CSS _parsing_ problem.  More likely a layerization/graphics issue...
Component: CSS Parsing and Computation → Graphics: Layers
Hi Boris,

The steps that I did are:

1. Go to https://blight.ironhelmet.com/u
2. Login with user: mozilla, password:123456 (I already created an account on this site)
3. Start to play
4. you can see the video from reporter description with the actions that are taken https://youtu.be/B01cnZDztYU

The problem now is when I try to reproduce it I can't. I have the same results on Mac OS X 10.10 ussing FF Nightly 50.0a1(2016-06-15), FF Nightly 50.0a1(2016-07), FF 47 release and Chrome. 
I will NI Jay (the reporter) to see if he has some updates. 


Jay can you try testing this issue again and see if you are still able to reproduce it? Also please correct me if I didn't understood the steps.
Flags: needinfo?(ovidiu.boca) → needinfo?(jay)
I added a workaround to the site where every 1 second I apply position absolute, then 1 ms laters apply position fixed again. 

I will spend a few minutes seeing if I can create simple example case for you outside the game itself.
Jay, a simple example case would be great, obviously, but even an unreduced testcase would be really useful; we can try to create a simple testcase from it ourselves.
(In reply to Jay Kyburz from comment #9)
> I will spend a few minutes seeing if I can create simple example case for
> you outside the game itself.

Jay, it's been 1.5 months, have you made any progress on providing a testcase?
Sorry, I have been very busy. Not long after I posted I did try and simply copy and paste the elements out of the dom and create a simplified page, but the bug has something to do with how I am dynamically creating the elements in javascript. 

I'm using jQuery.createElement to build a hierarchy of "screens" and then applying some css to make it fixed.  

I actually might have some time this afternoon to try and create a script to try again.
<!DOCTYPE html>
<html>
    <head>
        <title>Bug Repro</title>
        <style type="text/css">
            .widget             { position: absolute; }
            .screen_anim        { transform: translate3d(0, 0, 0); }
        </style>
    </head>
    <body>
        <script src="https:blight.ironhelmet.com/scripts/libs/jquery.min.js"></script>
        <script type="text/javascript">

        $(window).ready(function () {
            run()
        });

        function run() {

            // this appScreen object is a top level container.
            // we use translate 3d on here for cool screen transitions!
            var appScreen = jQuery(document.createElement("div"));
            appScreen.addClass("widget");
            appScreen.addClass("screen_anim")
            // appScreen.removeClass("screen_anim")

            // the app has position: fixed elements as children so we want to
            // remove the  class with translate3d(0, 0, 0) in it.
            // in this example, after 2 seconds.
            window.setTimeout(function () {
                appScreen.removeClass("screen_anim")
                console.log("removing class")
            }, 2000)

            // this is a container class we use to attach some dialog boxes
            var interfaceRoot = jQuery(document.createElement("div"));
            interfaceRoot.addClass("widget")  // <---- when this container class has position:absolute
                                              // children elements with position:fixed fail to fix when translate3d(0, 0, 0) removed

            // the map is a child of interfaceRoot that is fixed.
            var map = jQuery(document.createElement("div"));
            map.addClass("widget")
            map.css('background-color', '#880000');
            map.css('position', 'fixed');
            map.css('top', '0px');
            map.css('left', '0px');
            map.css('width', '500px');
            map.css('height', '500px');

            // this is a long dialog that will cause the window to scroll.
            // it sits ontop of the map object.
            // the map object should be fixed while we scroll this long dialog up and down.
            var dialog = jQuery(document.createElement("div"));
            dialog.addClass("widget")
            dialog.css('background-color', '#000000');
            dialog.css('top', '20px');
            dialog.css('left', '20px');
            dialog.css('width', '100px');
            dialog.css('height', '1000px');


            interfaceRoot.append(map);
            interfaceRoot.append(dialog);
            appScreen.append(interfaceRoot);

            jQuery("#content").append(appScreen);
        }

        </script>
        <div id="content" style="width: 100%; margin-right: auto; margin-left: auto;"></div>

    </body>
</html>
It's seems the bug is related to translate3d() and position fixed. 

We understand that the spec calls for position:fixed work work differently as a child of object elements with translate3d. (as read on stack overflow)

However, Firefox fails to reinstate position:fixed to elements when the translate3d is removed from a parent, after time passes, if an intermediate element has position:absolute.

Chrome and IE seem to work as expected, the position fixed elements are fixed in place when the translate3d is removed from parent elements. 

Would be happy to chat more about if this is unclear and my examples are not helpful.
This might not be the exact bug, but I hope it's simple enough that somebody with more knowledge of the system can track it down.
Attached file Minimalish testcase
Jay, thank you.  That helps a _lot_.

Here's a pretty minimal testcase that shows the problem.  In two ways, actually: the fixed-pos thing is scrolling when it should not, and it has the wrong width.  The "position: absolute" is required on both of the parent divs to reproduce.
OK, FrameHasPositionedPlaceholderDescendants is just buggy.  It skips looking inside the fixed and absolute lists of aFrame.  We don't want to look for abs-pos stuff in there (because it will stay in there), but we do want to look for fixed-pos things in there...
Flags: needinfo?(kbrosnan)
Flags: needinfo?(jay)
Instead of skipping the absolute and fixed child lists, we walk all kids of the
frame.  But before recursing down into things that are absolute containing
blocks we ensure that we're only looking for fixed-pos placeholders, so we don't
reframe if we have a relatively positioned descendant with absolutely positioned
kids, for example.  Note that this part is pure optimization attempt, and it
might be cheaper to not do it: IsAbsoluteContainingBlock is not that cheap and
the situations where we avoid reframing due to this optimization are likely
fairly rare.
Attachment #8785002 - Flags: review?(dbaron)
Assignee: nobody → bzbarsky
Status: NEW → ASSIGNED
Ignore those comments; I somehow convinced myself that transform applies to non-replaced inlines.
Flags: needinfo?(bzbarsky)
Comment on attachment 8785002 [details] [diff] [review]
Correctly reframe an absolutely positioned frame that goes from having a transform to not having one and has an abs pos kid with a fixed-pos descendant

r=dbaron

(Was the old stuff that skipped the fixed list bogus, in that fixed frames not parented to the viewport would go on the absolute list anyway?  If not, would it still be worth skipping the fixed list?)

The other optimization that might be worth making is, inside the if (f->IsAbsPosContainingBlock()), test if (f->IsFixedPosContainingBlock()), and if so, continue (rather than looking at its descendants at all).  Feel free to include that if you want.
Attachment #8785002 - Flags: review?(dbaron) → review+
> Was the old stuff that skipped the fixed list bogus, in that fixed frames
> not parented to the viewport would go on the absolute list anyway?

Afaict, yes.

> Feel free to include that if you want.

Will do.  Still not sure whether it's faster that way or not on average, but in some cases it could be a _lot_ faster.
Pushed by bzbarsky@mozilla.com:
https://hg.mozilla.org/integration/mozilla-inbound/rev/6f9fa77780cc
Correctly reframe an absolutely positioned frame that goes from having a transform to not having one and has an abs pos kid with a fixed-pos descendant.  r=dbaron
Component: Graphics: Layers → Layout: R & A Pos
Flags: in-testsuite+
https://hg.mozilla.org/mozilla-central/rev/6f9fa77780cc
Status: ASSIGNED → RESOLVED
Closed: 8 years ago
Resolution: --- → FIXED
Target Milestone: --- → mozilla51
yay, thanks guys!
You're welcome.  Thank you for the testcase!

The fix will ship in Firefox 51, barring unforeseen circumstances.  Should be around late January.
Depends on: 1301500
No longer depends on: 1301500
(In reply to Jay Kyburz from comment #9)
> I added a workaround to the site where every 1 second I apply position
> absolute, then 1 ms laters apply position fixed again. 
> 
> I will spend a few minutes seeing if I can create simple example case for
> you outside the game itself.

I am doing the exactly same thing right now! And it's 2 years later. 
As I see it the bug is still there, and only in firefox. 
In a special combination of having some position fixed elements inside position absolute elements, and then moving the parent through some translate animation by adding/removing classes. This way the position fixed elements get all screwed up, sometimes invisible, sometimes just out of order.
(In reply to raf from comment #29)
> (In reply to Jay Kyburz from comment #9)
> > I added a workaround to the site where every 1 second I apply position
> > absolute, then 1 ms laters apply position fixed again. 
> > 
> > I will spend a few minutes seeing if I can create simple example case for
> > you outside the game itself.
> 
> I am doing the exactly same thing right now! And it's 2 years later. 
> As I see it the bug is still there, and only in firefox. 
> In a special combination of having some position fixed elements inside
> position absolute elements, and then moving the parent through some
> translate animation by adding/removing classes. This way the position fixed
> elements get all screwed up, sometimes invisible, sometimes just out of
> order.

This bug is fixed. If you're seeing a similar problem, mind opening a new bug with a test-case?
Flags: needinfo?(raf)
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: