DOMContentLoaded and stylesheets · molily(via DOMContentLoaded - Mozilla event reference | MDN)にて、head 内のスタイルシートと Javascript の配置の違いで、DOMContentLoaded イベントが発生するタイミングが変わるという内容が掲載されています。スタイルシートのあとに Javascript が入っていると、DOMContentLoaded はスタイルシートをロードしたあとに発生して、スタイルシートのあとに Javascript がないと、スタイルシートのロードを待たずに DOMContentLoaded が発生する。
これはParsing の仕様によると、pending parsing-blocking scriptの実行前に、Document が has no style sheet that is blocking scriptsの状態になるまで、event loop を spin させるからということになるみたい。
If the parser’s Document has a style sheet that is blocking scripts or the script’s “ready to be parser-executed” flag is not set: spin the event loop until the parser’s Document has no style sheet that is blocking scripts and the script’s “ready to be parser-executed” flag is set.
つまり、pending parsing-blocking script(HTML パーサーが insert した script タグのうち、defer や async 属性がついていないもの)が実行前に、style sheet that is blocking scripts(HTML パーサーが追加したスタイルシートのうち、ロードされていないもの(style sheet ready flag is not yet set))がある場合、ロードされるまでevent loop をまわす。スタイルシートがロードされ、style sheet ready の状態になると、event loop の「update the rendering」のステップで script での利用が可能な状態になり、他にロード待ちがなければ script の実行に移ると。こうすることで、スタイルシートで指定しているフォントの色なんかの値を、script が適切に受け取ることができると。
DOMContentLoaded のイベントは、8.2.6 The endに記載によれば、HTML のパースが一通り完了して、defer 属性がついた script などを処理したあとに発生する。ので、スタイルシートの後に script がある場合、script がパーサーをブロックしつつスタイルシートのロードを待った上で実行されるため、DOMContentLoaded はスタイルシートがロードされるまで待つことになる。一方、スタイルシートの後に script がない場合は、パーサーをブロックしてロードを待つことがないため、ロードが完了していなくても、HTML パースが完了して DOMContentLoaded のイベントが発生する。と、いうことになる。みたい。
ただ、DOMContentLoaded and stylesheets · molilyのTestcase #2で試した感じでは、Opera は script の実行前にスタイルシートのロードを待たない雰囲気。そのため DOMContentLoaded の実行がロードより早く、getComputedStyle で取得したフォントの色の値にスタイルシートで設定した色が反映できていない(他のブラウザは head の部分でパーサーがブロックされるのでコンテンツが表示されるまでに時間がかかる)。
Opera の動作の差異を気にしないとしても、script の実行時(ダウンロード時ではない)にスタイルシートが available な状態になっていないと、実行はブロックされた状態になるので、スタイルシートのロードをできるだけ先にして、javascript はできるだけ後にする、というのが基本的には良いかもしれない。
script で現在のスタイルの値をまったく参照しないみたいな、スタイルシートと script を独立できるのであれば、script を先に読み込むというのもありかもしれません(その方がロードによるブロックは発生しない)。ただ、Safari(6)と Chrome(24)では、結局スタイルシートがロードし終わるまでコンテンツが表示されなかったですが…(Firefox は表示される)