jQuery defaultDisplay() can't figure out display of <body> element

RESOLVED WORKSFORME

Status

()

Core
DOM: CSS Object Model
RESOLVED WORKSFORME
5 years ago
2 years ago

People

(Reporter: vlad, Unassigned)

Tracking

(Blocks: 1 bug)

Trunk
x86_64
Windows 7
Points:
---

Firefox Tracking Flags

(Not tracked)

Details

Attachments

(2 attachments)

This may well be a jQuery bug, but Firefox and Chrome behave differently.  For various transitions, jQuery wants to figure out the default value of the 'display' style property.  It does this using a helper function that tries to do two things:

1 - first it creates an element of the given tag name, appends it to the body, and reads its display
2 - if it's none/blank, it creates an iframe with a document consisting of <html><body> and then creates an element with the given tag name, appends it to the iframe doc, and reads the display.

This is all great, except when the element in question is <body>.  It goes down the iframe path which results in |undefined| as the value.  It then tries to do things like set the display to that when doing a transition such as a fade in on the body, which then horks.

Chrome gives back 'block'.  Is the bug in jQuery (it really should be special-casing <body>!) or is it in Firefox (it should be doing... something... for two body elements?)
Ah, the jQuery folks claim this is a Firefox bug:

http://bugs.jquery.com/ticket/10227
https://github.com/jquery/jquery/pull/555

Apparently display: none on <body> causes the <iframe> to display fallback content or somesuch.  I have no idea what should actually be happening here.
What code is jquery actually running in this case?  How is it creating the element?  How is it reading the display?
Ah, so they're doing getComputedStyle on things that are inside a display:none iframe?

Those don't have meaningful computed styles, and can't due to media queries.
Here's a question.  Why are they doing the iframe thing at all?  That part makes absolutely not sense to me.
Also, the jQuery ticket is about cases when "body { display: none; }".  Is that the case in the situation you were dealing with here?
Created attachment 667104 [details]
testcase

Yes, I'm an idiot, I forgot to attach the testcase.  Attached now.

Note that the function is taken straight from the jQuery source; jQuery 1.8.2 gets back 'none' instead of undefined, but same problem continues.
Ok, yes.  So your <body> is "display: none" (why?), and then things are all bad.

There's just no sane way to make what jQuery is trying to do here work in Gecko without completely changing how the style system works.  And even then (if we did it the way WebKit does) it would return bogus answers if there were user or UA style sheets with media queries.

On the other hand, what we _can_ do is just create an API for asking "what is the style if you only look at UA and user sheets?" and jQuery could use that instead of the hackery, yes?

Alternately, if it wants to, it could append the iframe to <html>, not <body>.  It would certainly fix the people who use "display: none" on <body>, at least....
Component: DOM: Core & HTML → DOM: CSS Object Model
Fair enough -- sounds like a weird edge case on both ends.  Appending to <html> is definitely interesting, and I should suggest this to them... I guess I'll modify the testcase to verify that it works and punt it over to them.

(This all came up because altdevblogaday.com does this, and is broken in Firefox, and whoever owns it doesn't seem interested in fixing it and is instead blaming 'Firefox bugs' or something.  So I dug into it to figure out what the heck was actually doing it, and it was all because he wanted a fadeIn() effect on load.)
I developed the approach that jQuery is using in response to user code that overrides the default display for any given nodeName. Neither Firefox nor jQuery should have to accept the added burden, when the user code could just as easily use a css class to achieve exactly the same desired behaviour.
One more thing... Boris, jQuery would absolutely love this: 

> an API for asking "what is the style if you only look at UA and user sheets?" 


:)
This issue doesn't exist in jQuery 1.8.x
(In reply to Rick Waldron from comment #11)
> This issue doesn't exist in jQuery 1.8.x

Hm, seems to from my testing -- only difference is that the defaultDisplay function in 1.8.2 returns 'none' instead of unknown, but it results in equally broken behaviour.  (e.g. loading 1.8.2 in the testcase attached here still has the text not showing up)
Created attachment 668016 [details]
using jquery 1.8.2
Indeed, there was a bug in the test case that I wrote for our core tests. Sorry about that.
This issue is too edge case to warrant refactoring the entire default display algorithm, so we're going with a naive solution in which we pre-cache body:block in the elemdisplay table. 

Friends don't let friends override default displays.
> an API for asking "what is the style if you only look at UA and user sheets?" 

Bug 800983.
Rick, thanks for jumping on this!  Closing this bug off, since a fix went into jQuery.
Status: NEW → RESOLVED
Last Resolved: 5 years ago
Resolution: --- → WORKSFORME
Just for good record keeping:

https://github.com/jquery/jquery/commit/60f546acb1c7136092b4fd01cccff052e468cc72
Blocks: 968240
You need to log in before you can comment on or make changes to this bug.