DOMContentLoaded gotcha with external stylesheets
Sunday, July 8, 2007 10:26:49 PM
A user came in to the #webapps channel today complaining that Opera didn't show his accordion menu properly. In fact it only worked if the stylesheets he used were included inline, rather than referred to as external stylesheets.
After some digging around, including downloading the source of jQuery and Interface it turned out that the Accordion effect was trying to read CSS attributes and setting them again.
interface/accordion.js:
jQuery(this)
.css('height', jQuery(this).css('height'))
.css('overflow', 'hidden');
Since this was started after DOMContentLoaded which in Opera fires before the CSS is loaded and applied, it made the elements keep the default values rather than those set in the CSS Stylesheet.
The solution to this specific problem was to avoid using DOMContentLoaded event when starting scripts that will eventually use CSS attributes, the startup was then wrapped in
(MSIE),window.onload
(Firefox) orwindow.addEventListener("load",function,false);
DOM compliant browsers.document.addEventListener("load",function,false);
The moral I guess, is to watch out when using $(foo).ready in jQuery, and probably go for (on)load for anything that relies on CSS attributes being applied
Correct behaviour?
The question here is though. when should DOMContentLoaded really be fired. The scarce Mozilla documentation states:
DOMContentLoaded Fired on a Window object when a document's DOM content is finished loaded, but unlike "load", does not wait till all images are loaded. Used for example by GreaseMonkey to sneak in to alter pages before they are displayed. Does not appear to be dispatched to a Browser object (why?)
Which only explicitly mentions images, so I guess waiting for external styles is correct behaviour.
The HTML5 documentation at http://www.whatwg.org/specs/web-apps/current-work/#the-end doesn't seem to mention anything about wether or when style attributes should be appended to the elements in the documen before the DOMContentLoaded event is fired.
The name doesn't really indicate that one should wait for CSS -- Except when CSS is used to alter content of the DOM, like the content:-attribute -- Or possibly when using pseudo elements, so again, probably correct to also wait for external stylesheets.
However, I haven't peeked into the Mozilla Firefox code to see what it really waits for, and the original intention to have something else than onload that would fire before external data is loaded would suggest that DOMContentLoaded would fire before external CSS is loaded.
So, should Opera change behaviour, should Mozilla Firefox change behaviour, should the various events throughout a loading process be more fine-grained, and maybe throw events when various types of externally linked elements are being loaded? Suggestions?
Here's a test that says the Mozilla Firefox way is correct: http://people.opera.com/nicolasm/test/domcontentloaded.html















Fatimahzenya # Sunday, July 8, 2007 10:56:05 PM
Also Opera would be used as IE not now.
I know changes are growing however, why ruin something good
Nicolas Mendozanicomen # Sunday, July 8, 2007 10:57:01 PM
Fatimahzenya # Sunday, July 8, 2007 10:59:49 PM
now it's very difficult to make changes using their templates.
My online friend Diem use to do my blog theme for me since he is trained in grapic art and doing web pages and when I changed to the new template I have now he could not use the same CSS as it won't work with the new templates
Also before Opera would be reconized as IE now it isn't as far as I can see.
Nicolas Mendozanicomen # Sunday, July 8, 2007 11:05:31 PM
The second issue is quite easy to fix: Press right mouse button on any page and select Edit Site preferences. There you can tell Opera to identify as MSIE or Mozilla Firefox for any given site. Useful for some pages. But of course, if a page doesn't work in Opera because of browser sniffing, you shuold file a bug to the website.
Oh, btw. both issues are off-topic ;-P
Fatimahzenya # Sunday, July 8, 2007 11:11:50 PM
I just liked the option of not having sidebars and to have a full window for photos not the side window for my album photos showing.
I am sorry if I am interrupting you, that's why I wrote a pm not to take up your blog time..
BTW I won't post in the forums since some of the people in there have huge egos and lack of tollerance
Nicolas Mendozanicomen # Monday, July 9, 2007 12:11:20 AM
This time I just copy-pasted your pm though, thanks again
David Håsätherhzr # Monday, July 9, 2007 4:50:37 PM
Just a small comment. CSS does not alter the DOM in any way, even when using the
contentproperty.Anonymous # Monday, July 9, 2007 5:40:04 PM
Hallvord R. M. Steenhallvors # Tuesday, July 10, 2007 3:36:27 PM
Anonymous # Tuesday, July 10, 2007 4:15:49 PM
Nicolas Mendozanicomen # Tuesday, July 10, 2007 5:31:01 PM
http://www.mail-archive.com/public-webapi@w3.org/msg02176.html
João EirasxErath # Tuesday, July 10, 2007 7:58:21 PM
I think Opera fires the event when it should. When DOMContentLoaded fires, the browser may not have loaded any styles, external content, or reflown the document. If a script needs to wait for it, then it should wait for load. If the browser waits for styles then it'll introduce more lag.
_Grey_ # Tuesday, July 10, 2007 10:35:13 PM
And stylesheets are part of the DOM, as you can access them from it. So... there still is the question if browsers should wait for the stylesheets to be loaded, but that CSS doesn't chnage the DOM at all... I think that's too strong a statement...
James Justin HarrellHeroreV # Wednesday, July 11, 2007 4:45:29 AM
But on topic, why not give developers an option? I don't see why browsers should only provide one or the other if it's not too difficult to implement both. Create something like a StylingApplied event that fires after the DOM has been constructed and CSS has been applied to everything. Options are good!
Anonymous # Wednesday, July 11, 2007 2:38:24 PM
Andrew Gregory # Friday, July 13, 2007 3:13:58 AM
If it's important to know when stylesheets have loaded, then separate "onload" type event handlers need to be registered. Images already support that, so I don't see why stylesheets couldn't either. Maybe they already do?
That gives much more precise and fine-grained control. If it is decided that DOMContentLoaded should wait for stylesheets to load, then that simply means that another event that does what DOMContentLoaded is supposed to do would be needed. Which would be quite perverse, IMO!
Anonymous # Friday, July 13, 2007 9:43:59 AM
Simon Houstonshoust # Tuesday, July 17, 2007 1:03:17 PM
AyushAyushJ # Monday, July 23, 2007 5:58:37 PM
Some sites like Yahoo! etc. have very big stylesheets so waiting for CSS files before DCL event will only slow down things. You can already use load event if you want to make sure CSS files are loaded but what if you want to run script as soon as the DOM is loaded (in userjs etc.) ? Then there will be no solution
Monroelittle_lemur # Tuesday, July 24, 2007 9:20:49 PM
Monroelittle_lemur # Tuesday, July 24, 2007 9:21:47 PM
David Anderssonliorean # Saturday, July 28, 2007 9:44:33 AM
If people find a use case for finding when the CSSOM is finished from external sources, then browsers should try to provide a separate event for that. Say a DOMCSSLoaded event...
Why do I say that? Because I've found a need for DOM manipulation (particularly adding events on stuff) far more common than a need to work on the style sheets, and for some sites the style sheets can be unproportionally large compared to the HTML source.