When and how do browsers render – Praveen Kumar Purushothaman Jun 05 '17 at 14:31

  • See https://stackoverflow.com/questions/3527800/how-do-browsers-read-and-interpret-css – j08691 Jun 05 '17 at 14:42
  • 3 Answers3

    10

    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

    1. <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.
    2. 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. *
    3. 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.

    tao
    • 82,996
    • 16
    • 114
    • 150
    • I'd be curious in finding out why my answer has been downvoted. The subject of this answer/question is one of great importance to me, I have read extensive materials on it and I'm always eager to know more. If anything I've stated is inaccurate, please let me know. I'm really, genuinely interested on this subject. Thank you in advance. – tao Jun 05 '17 at 14:41
    • My answer was downvoted, too. Exactly the same moment I posted it. – Hubert Grzeskowiak Jun 05 '17 at 14:42
    • 1
      Probably someone considering the question has too low quality to be answered. I can't imagine any other reason for downvoting my answer. But hey, this is [SO]. :) Cheers! – tao Jun 05 '17 at 14:43
    • 1
      Thanks Andrei for explaining in details. – tolkinski Jun 05 '17 at 14:44
    • Not my downvote (yet), but this is wrong on at least one point. JS is run as it is encountered in the markup, except when marked as async or defer, not at the end. – Alohci Jun 05 '17 at 15:34
    • @Alohci I'll retest. The last time I did it, it resulted in CSS inside being parsed first and than JS being run. I will re-test. Do you have any resource/test that can shed some light on this particular matter? Also, note most of my tests are done in Webkit, I haven't tested much on Gecko or Trident. – tao Jun 05 '17 at 15:42
    • Here's a simple idea. Before the first `` add ``. The style element won't processed at all. – Alohci Jun 05 '17 at 15:48
    • @Alohci: you're clearly right about `js` being run. The second – tao Jun 05 '17 at 16:05
    • @Alohci: Here's [a statement](https://developers.google.com/web/fundamentals/performance/critical-rendering-path/adding-interactivity-with-javascript) from Google developers that seems to back up what I knew and stated in my answer: *the browser delays script execution and DOM construction until it has finished downloading and constructing the CSSOM*. Is it possible it's delayed, and when the script is ran, CSSOM is being re-built without the (now) commented rules and we don't get to see a FOUC because it all happens inside `` and no actual elements make it to render? – tao Jun 05 '17 at 16:29
    • I think that statement is somewhat misleading. I think it means that if the parser has *already encountered* a style element or stylesheet link, then on encountering the script element, the script will be blocked until those style rules have been downloaded and resolved. Otherwise, it either contradicts what that article says a few paragraphs earlier, or you would get deadlock between the styles and scripts with neither able to proceed. – Alohci Jun 05 '17 at 17:05
    • @Alohci At this point I'm tempted to believe js exec is deferred until `` is met, at which point CSSOM is complete and ***all*** js loaded so far is ran, which can change the CSSOM, in turn. When rendering begins CSSOM has already been altered. I know how to test this: I can make the commented ` – tao Jun 05 '17 at 17:21
    • @Alohci, see the updated answer and also the question I linked on the subject. Turns out you were right. `` parsing is single threaded, and, thinking it through, it makes a lot of sense to be so. Thank you for your help. – tao Jun 05 '17 at 21:03
    3

    Scope of CSS

    A style element applies to the whole document, regardless of its position. It is applied as soon as it's loaded.

    Reason for putting style tags in <body>

    Since every browser has a limited number of threads for downloading a page's files (like JS, CSS, images and asynchronously loaded HTML, JSON or XML), people tend to include CSS files at the end of the body element instead of the classic approach of including them in the head element. This way the rest of the page can be loaded and rendered, and the styling is applied last. You would go this way if your CSS is purely for the looks (i.e. no required element hiding) in order to improve the user experience.

    CSS files vs style rules in HTML

    Including an external CSS file or putting the same rules in a style element have equivalent results regarding layout and styling. The external file has the downside of a little HTTP overhead, but the benefit of being cached for any further request. If your site consists of more than one page, you usually want to have one or more CSS files that are downloaded only once and re-used for most pages. In addition you can have page-specific rules in another file or within the HTML page.

    Hubert Grzeskowiak
    • 15,137
    • 5
    • 57
    • 74
    -6

    So it looks to me that the css is processed when the page is loaded, similar behavior to javascript document ready event. Am I right?

    No. The stylesheet is modified with the new CSS code when that code is added to the DOM. There's no delay until the rest of the DOM has finished loading. If there was you'd see a FOUC.

    which order would multiple <style> tags be processed?

    The order they appear in. Then the normal rules of the cascade apply.

    Quentin
    • 914,110
    • 126
    • 1,211
    • 1,335