Closed Bug 687441 Opened 9 years ago Closed 4 months ago

Subframes can cause a flash of unstyled content (FOUC)

Categories

(Core :: CSS Parsing and Computation, defect)

x86
macOS
defect
Not set

Tracking

()

RESOLVED FIXED
mozilla73
Tracking Status
firefox73 --- fixed

People

(Reporter: bzbarsky, Assigned: emilio)

References

(Blocks 1 open bug)

Details

Attachments

(1 file)

Consider a page with this structure:

  <!DOCTYPE HTML>
  <head>
    <link rel="stylesheet" href="slow-server">
  </head>
  <body>
    <iframe src="something"></iframe>
  </body>


Normally, we would hold off starting layout on this document until the stylesheet has loaded.  However in this case when the iframe finishes loading it will try to fire its onload handler, which will flush style on the subframe document (to make sure we kick off background image loads and the like), which will flush layout on the parent document (due to possible media queries), which will start layout on the parent.  If all this happens before the stylesheet is loaded, we get a flash of unstyled content.

Obvious options are:

1)  Do nothing, just deal with it.  The situation where this will come up involves no <script> tags inside the <iframe> and not <script> tags in the parent document before the <iframe>, which is rare.

2)  Stop flushing style before firing onload.

3)  Stop flushing layout on the parent before firing onload.

4)  Stop triggering layout on the parent for layout flushes coming from kids
    firing onload.

5)  Hold off onload on subframes if the parent document has pending stylesheet
    loads.

6)  Block the parser on stylesheets again, now that we have a much better
    speculative parser.  The main drawback here, I think, is that we don't
    speculate some types of loads yet.  In particular, subframe loads.

Thoughts?
My personal preference is probably #5, except for the complexity it adds....
The parser currently has the capability to block only on </script>. Given that this problem isn't seen too often, I'd rather not choose solution #6.

#5 scares me having worked of the about:blank stuff, but maybe it'll be ok.
#5 sounds like a hack. #2 sounds good, but I know you ran into problems trying to avoid the reflow flush before onload...
My preference is also #5 (which I chose immediately after reading through the list, before seeing it was also bz's preference).  But I haven't thought about it much.
robert, the problem with #2 is that we would fire onload before loading CSS background images and the like....

I agree #5 sounds like a hack.  I'm not seeing too many clean solutions here.  :(

Henri, about:blank would not be affected too much.  It's not the load event itself that's a problem; it's the style flush we do in the docloader before firing it.  Synthetic load events from about:blank would not be affected at all.
Another option (call it #7) is to stop style flushes on the frame flushing layout in the parent, when the parent's painting is suppressed. We only do that to get media queries right (right?), and when the parent unsuppresses and reflows we'll fix up the media query results in the frame.
That's basically #4 above, I think.  I might not have described it clearly enough....

The main drawback of that approach is that onload on the subframe could fire before all the background images for the relevant media query that ends up matching are loaded.  This may not be a big worry, of course, esp since in the common case there is no media query.
(In reply to Boris Zbarsky (:bz) from comment #7)
> That's basically #4 above, I think.  I might not have described it clearly
> enough....

#4 doesn't depend on whether the parent's painting is suppressed. Maybe you meant that...
(In reply to Boris Zbarsky (:bz) from comment #7)
> The main drawback of that approach is that onload on the subframe could fire
> before all the background images for the relevant media query that ends up
> matching are loaded.  This may not be a big worry, of course, esp since in
> the common case there is no media query.

Also, while the parent document is incompletely loaded, you don't even know whether the geometry of the frame element that you use to resolve the media queries is its final geometry.
> #4 doesn't depend on whether the parent's painting is suppressed.

Indeed, but it does depend on the parent not having had InitialReflow called.  Since that's what sets up paint suppression, we can effectively assume that painting is "suppressed" before InitialReflow.

The key is to avoid the InitialReflow call on the parent.

Agreed on the parent document being incompletely loaded implying that iframe sizes may well just be bogus.  So maybe #4 is the way to go here....
Blocks: 1404468
Duplicate of this bug: 1420362

I should note that Blink is aiming to do #6, as I understand. :(

Duplicate of this bug: 1601261

This makes subframes don't start layout on the parent document when flushing,
which fixes the FOUC issue.

It does mean that some resource loads triggered by viewport-dependent media
queries might not block onload of the frame, but other style-triggered loads,
fonts, and such would.

This makes same-origin frames act the same way as cross-origin iframes in this
regard if there are stylesheet loads present.

I think the trade-off is worth it here, and this is green on try.

Assignee: nobody → emilio
Attachment #9113583 - Attachment description: Bug 687441 - Make iframes don't cause a FOUC on parent document. r=bzbarsky → Bug 687441 - Make iframes not cause a FOUC on parent document. r=bzbarsky
Pushed by ealvarez@mozilla.com:
https://hg.mozilla.org/integration/autoland/rev/bd5c387d7822
Make iframes not cause a FOUC on parent document. r=bzbarsky
Status: NEW → RESOLVED
Closed: 4 months ago
Resolution: --- → FIXED
Target Milestone: --- → mozilla73
You need to log in before you can comment on or make changes to this bug.