window.getComputedStyle() returns null inside an iframe with display: none

NEW
Unassigned

Status

()

Core
DOM: CSS Object Model
7 years ago
6 months ago

People

(Reporter: Jordan Osete, Unassigned)

Tracking

(Blocks: 2 bugs)

Firefox Tracking Flags

(Not tracked)

Details

(URL)

Attachments

(2 attachments)

(Reporter)

Description

7 years ago
User-Agent:       Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.2) Gecko/20100115 Firefox/3.6
Build Identifier: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.2) Gecko/20100115 Firefox/3.6

getComputedStyle() returns null if the page is loaded in an iframe with display: none;

Reproducible: Always

Steps to Reproduce:
1. go to http://ministeyr.free.fr/testcases/gcs2.htm

Actual Results:  
The page alerts "null"

Expected Results:  
The page should alert something like [object CSSStyleDeclaration]
It happens correctly if the page is not loaded inside an iframe (see http://ministeyr.free.fr/testcases/gcs.htm )

Updated

7 years ago
Component: General → General
Product: Firefox → Core
QA Contact: general → general
If you're display:none then the information needed to compute style (which medium is in use, the size of the CSS viewport, the zoom level, etc) is not present.  So yes, this is the expected behavior given the current style computation implementation in Gecko.

The CSSOM spec might require a different behavior at some point, but in the meantime this is something to bring up with the relevant working group.
Component: General → DOM: CSS Object Model
QA Contact: general → general
(Reporter)

Comment 2

7 years ago
A simple workaround is to style the iframe with
  visibility: hidden;
  position: absolute;
Although "display: none" probably impacts performance less, but this should not be very significant.
Severity: normal → minor
QA Contact: general → style-system

Comment 3

5 years ago
Created attachment 641808 [details]
Test Case

Attached a simple test case for it. It passes on Chrome and Opera while fails with Firefox.

Updated

5 years ago
Attachment #641808 - Attachment mime type: text/plain → text/html

Comment 4

4 years ago
@Boris,

Your statement does not make sense.  Another workaround to this issue is to provide the iframe with a fixed width and height.  If you do that, then even if the style display:none is set, getComputedStyle will not return null.
jonl, I have no idea what you're talking about.  Fixed width and height have no effect on this bug.

Comment 6

4 years ago
I retract my comment.  I have run into this with my own application and thought I had seen different behavior with a fixed size iframe, but appear to be mistaken.

Comment 7

3 years ago
I ran into this bug with a piece of software I'm developing and found a solution to it.

In my code I was dynamically changing the src property of an iframe that was located inside a jquery ui dialog so this might be situational. I set a micro timeout 'window.setTimeout(fuction() { });' around the code that changed the 'src' property of the iframe and it works every time now without throwing this error.

Comment 8

3 years ago
I have make a patch for my application which use jquery.mobile in an iframe.
I did not want change the behaviour of the jquery.mobile to assure the compatibilty with updates of library.
I have overload the getComputedStyle function by checking the result and replace it by an empty object in case it is null.

if (/firefox/i.test(navigator.userAgent)){
   window.oldGetComputedStyle = window .getComputedStyle;
   window.getComputedStyle = function (element, pseudoElt) {
      var t = window.oldGetComputedStyle(element, pseudoElt);
      if (t === null) {
         return {};
      } else{
         return t;
      }
   };
}
Status: UNCONFIRMED → NEW
Ever confirmed: true

Comment 9

3 years ago
We ran into this bug while updating versions of Adobe Captivate. Captivate warns against use of browsers other than chrome/IE/Safari, but it seems whatever issues they had with FF are largely in the past.

Still, when we include a Captivate (versions 7/8, at least) in an unopened iframe until the user clicks to display the iframe in a modal, this issue crops up.

I'm not involved in the spec here enough to _know_ if it's naive of Adobe to be making assumptions (i.e., getComputedStyle(el) will return an object with top/right/bottom/left/marginTop/marginRight/marginBottom/marginLeft/width/height values) but it seems like the spec (http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSview-getComputedStyle) gives no indication that a null return value should be anticipated.
The relevant spec is http://dev.w3.org/csswg/cssom/ for what it's worth.  But yes, returning null is probably wrong, which is why this bug is open.  Fixing it requires pretty significant changes to how style computation works in Gecko, unfortunately.

Comment 11

3 years ago
Thanks for the quick update, Boris.

We used a modified version of Greg's patch above to return a dummy object with values for the necessary keys to cover our case in the near term; largely posting to document the interaction between this issue and Captivate, in case it adds some helpful weight to the case for an eventual fix.

Comment 12

3 years ago
We are seeing window.getComputedStyle() return null for DOM elements that are not inside iframes. This is happening thousands of different sites for millions of users where our scripts are running. FF only behavior; not happening on any other browser. Unfortunately, we haven't been able to isolate a self-contained test case yet. 

Still, for the purposes of considering a fix we wanted to make sure that this use case demonstrating the problem is known.
sim, I'm not aware of a way for getComputedStyle to return null unless the method is being called on a window with no presentation.  That means it's either a display:none iframe (or some iframe that has no box; e.g. a direct child of a non-foreignObject SVG element) or a tab that was somehow hidden by some extension.

Comment 14

3 years ago
(In reply to Boris Zbarsky [:bz] from comment #13)

Well, it's happening with clockwork consistency. While I cannot give you an isolated reproducible case, I'd be happy to screen share and demonstrate. 

Here is an interesting twist, which hopefully sheds some light. The DOM element being manipulated and the window reference come from the main frame of web page (not iframed) but the JavaScript calling the method on that window reference was loaded in a same-domain hidden iframe.
> but the JavaScript calling the method on that window reference was loaded in a
> same-domain hidden iframe.

What does that javascript call look like, exactly?

Comment 16

3 years ago
(In reply to Boris Zbarsky [:bz] from comment #15)

Here is the current code (with a workaround for this FF issue). We got bitten by this issue when attempting to show a hidden DOM element.

The DOM element in question is a DIV in the main frame with display: none. When window.getComputedStyle() returns null, jQuery's fadeIn() fails to make the element appear but show() does alright. 

_makeVisible: function() {
  var domNode = this.$ele.get(0);
  if (window.getComputedStyle(domNode)) {
    this.$ele.fadeIn(200);
  } else {
    this.$ele.show();
  }
}
>  if (window.getComputedStyle(domNode)) {

Is this code running in the display:none iframe?

Comment 18

3 years ago
(In reply to Boris Zbarsky [:bz] from comment #17)

Yes, the code is running in the display: none same-domain iframe. However, window references the top-level frame on the page.
"window" in that function references the window the code is running in, which you say is the display:none iframe, unless the function is closing over some scope with "var window" in it.
http://webcompat.com/issues/300 documents how m.futureshop.ca is unusable due to this bug.
Severity: minor → normal
See Also: → bug 1012413
A test for reading the display property from an element inside a display:none IFRAME (should say 'block') with jQuery: http://jsfiddle.net/zn7akfxg/
Blocks: 974529
Duplicate of this bug: 1075280
Duplicate of this bug: 1079486

Comment 24

2 years ago
If the iframe isn't displayed, couldn't getComputedStyle(node) just return a copy of node.style?
That has quite different behavior from the computed style, unfortunately.  In particular, it doesn't have values for properties that are not actually set in the inline style.

Comment 26

a year ago
I bypassed the problem very easily with JQuery as follows.

        <div>
            <iframe id='linkIframe' width='1200px' height='300px'></iframe>
        </div>
          
          <script>

          $(document).ready(function() 
          {
    	     $("#linkIframe").attr("src", "/iadmin2/plugins/jobcard/externalMedia.php");
          });

         </script>

Comment 27

a year ago
Could an empty object be returned instead of null? This would fix errors as most people typically do stuff like getComputedStyles(obj).color.
See Also: → bug 1206912
So I ran into yet another site today that breaks as a result of this.

I think we have the following options at this point:

1)  Wait for stylo to land, try to fix this on top of stylo.  At that point style computation won't be quite as tied to the presshell, and we might be able to just make it work.  I'm not sure what sort of timeframe this would entail.

2)  Divorce style computation from the presshell.  That is, move the style struct arenas, style set, etc, etc over to the document.  This would take quite a bit of work in its own right...

3)  Hack something together where we return non-null (this part is easy) and either have it throw on access like happens now if you grab a computed style object and then go display:none or have it return some sort of bogus data (e.g. as suggested in comment 27).  The former option does _not_ fix the site I mention above, but the latter one does.  Just returning "" for everything is actually fairly simple to do.

David, thoughts?  Bobby, do we have any sort of firm-ish time estimate for stylo?
Flags: needinfo?(dbaron)
Flags: needinfo?(bobbyholley)
Created attachment 8787509 [details] [diff] [review]
Simple proof of concept of option 3
The comments in the bug don't make it entirely clear what the issue is (and which parts are expected/unexpected per-spec) - Boris, can you elaborate on that?

(I'll be slow to respond, in TPE for stylo meetup)
> Boris, can you elaborate on that?

The issue is that Gecko's style system can't compute style for things in a display:none iframe, because style computation is tied to the presshell, and there isn't one.

Though maybe the answer is that there should in fact be a presshell but frame construction should be suppressed.  (Or allowed, with an assumption of 0x0 size for the presshell; arguably that's what the CSS spec calls for, but it's ridiculously inefficient and I don't think we want to go there.)
I think Stylo doesn't really offer a super-clean way to fix this. Most of the per-document state is set up via presshell initialization, and we can't construct style structs without a prescontext.

So I think the issue is mostly orthogonal. If it's invasive and not urgent I'd still rather we punt on it for now though, since it'll touch a lot of the same code.
Flags: needinfo?(bobbyholley)
OK.  So I talked to dbaron, and he's on board with the plan in comment 31.  I don't think changing that will affect stylo much, if any.

This came up again today in https://github.com/hakimel/reveal.js/issues/1546 though it's not clear to me whether the comment 31 approach will actually fix that site, because it might still result in things looking 0-sized.
See Also: → bug 1306143
Blocks: 1302780
Depends on: 1308675
Yeah, having a pres shell seems like fewer special cases.

That said, maybe it's worth pinging the Chromium folks and seeing if they're interested in trying to change their behavior, given that not constructing things when display:none seems like a more efficient behavior.
Flags: needinfo?(dbaron)
> maybe it's worth pinging the Chromium folks and seeing if they're interested in trying
> to change their behavior

Did that already.  See https://github.com/whatwg/html/issues/1813
This is unfortunately breaking opentable.com, which is something we'd like to fix sooner rather than later. See bug 1302780
> This is unfortunately breaking opentable.com

Yes, that's the site that led me to get back to this in comment 28.

I've been working on this on and off per my plan from comment 31, but what I have so far is _very_ orange on try: see <https://treeherder.mozilla.org/#/jobs?repo=try&revision=88f5506602d5bd66d688fc8cabd3ffa58d9a5916>.  I've slowly been working through some of the failures, but I could drop other things for a bit and really focus on this if we think the opentable breakage is important enough.  Unfortunately it's failures in all sorts of different parts of the code, not just a case of the same failure happening in lots of test suites.  :(
You need to log in before you can comment on or make changes to this bug.