TL;DR:
In short, the answer to your question is: once a <style>
tag is met inside <body>
everything stops and the CSSOM is being rebuilt and re-applied to all existing rendered (painted) content.
Placing <style>
tags inside <body>
is considered bad practice because it can create FOUC. But if your <style>
tag only contains rules for elements placed after it in DOM, placing it in body is perfectly fine, as no FOUC can happen.
The render process of a page is quite complex. But, overly-simplified, here's what happens
<head>
is read and CSSOM is built. All CSS is render blocking, unless explicitly specified otherwise by use of @media
queries. The non-blocking CSS is still loaded, it's not entirely skipped.
- DOM building and CSSOM building are ran in paralel,
but all <script>
execution is deferred until CSSOM has been built (on </head>
tag met), at which point all loaded <script>
s are ran, blocking DOM building. JS can make changes to CSSOM at this point. *
- Placing
<style>
tags inside <body>
interrupts everything (JS execution and DOM building), CSSOM is being updated and applied to the already rendered content, if any. Everything is resumed after.
* On further testing it appears <head>
parsing is single threaded. CSSOM building does block javascript execution but it's done is stages, as each <link />
and <style>
tags are met (a <script>
placed after a <link>
will only execute after the <link />
was resolved and applied to CSSOM). <script>
tags placed in between CSS resources are not deferred until all CSS resources in <head>
are parsed, as I initially thought.
And, of course js
can make changes to CSSOM at run time. See this question I asked for more on how js
execution is blocked by CSSOM building.
All the above apply to the normal loading, without considering async
, which adds a whole new layer of complexity to it.
If you're interested in more details, I recommend going through the Performance chapter of Web Fundamentals, provided by Google.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…