Engrain by ByteRush

WEB.01.02 Mid-level· 11 minCore — asked often

Parsing HTML and CSS: the DOM, the CSSOM and what blocks them

How the browser turns bytes into the DOM and CSSOM, why CSS blocks rendering and scripts block parsing, what the preload scanner does, and exactly when async, defer and module scripts run.

Comes up in: Web fundamentals, Recruiter screen

Learn#

Karan’s landing page shows a white screen for 3 seconds on 4G, though the HTML arrives in 200 ms. His <head> loads an analytics script and three stylesheets.

The HTML parser reads bytes, splits them into tokens such as start tags and text, and a tree builder turns tokens into the DOM, the tree of nodes JavaScript works with. CSS goes through its own parser into the CSSOM, the browser’s model of every style rule.

The browser will not paint until it has the CSS it knows about: painting first would show unstyled content and then jump. So stylesheets are render-blocking.

A classic <script src> is parser-blocking: the parser stops, fetches and runs it, because the script might call document.write or read the DOM above it.

defer fetches in parallel and runs after parsing, in order. async fetches in parallel and runs as soon as it arrives, in any order. type="module" behaves like defer unless it is also async.

When each kind of script runsStep 1 of 4

Page

  • <head> … ⏸ a.js

Network

  • a.js …

Console

    empty

    The parser builds the DOM from the top. It meets <script src="a.js"> with no attributes and stops: it must fetch and run a.js first.

    Read the steps as text
    1. The parser builds the DOM from the top. It meets <script src="a.js"> with no attributes and stops: it must fetch and run a.js first.
    2. Meanwhile the preload scanner reads ahead and starts fetching b.js (defer) and c.js (async).
    3. a.js runs, and parsing continues. c.js finishes downloading and runs at once, pausing the parser briefly.
    4. Parsing ends. Deferred and module scripts now run in document order, then DOMContentLoaded fires.

    Predict#

    Predict first

    Two deferred scripts: big.js (2 MB) then small.js (2 KB). small.js downloads first. Which runs first?

    Interview angle#

    Say it like this — about 30 seconds

    “The parser turns HTML into the DOM, and CSS becomes the CSSOM. CSS is render-blocking: the browser will not paint until stylesheets load, to avoid a flash of unstyled content. A classic script is parser-blocking, because it might change the document. async downloads in parallel and runs whenever it arrives, in any order. defer downloads in parallel and runs after parsing, in order, before DOMContentLoaded. Module scripts are deferred by default. The preload scanner finds resources early while the parser waits.”

    Stays on your device. Nothing is uploaded.
    Follow-up What is the difference between async and defer?
    Both download without blocking the parser. async runs as soon as it arrives, in any order; defer runs after parsing, in document order.
    Follow-up Why is CSS render-blocking?
    Painting before CSS arrives would show unstyled content, then re-render; the browser waits to paint once.
    Follow-up What does the preload scanner do?
    While the parser is blocked, a lightweight scanner reads ahead in the raw HTML and starts downloading scripts, stylesheets and images.

    Practice#

    Guided

    Write a small audit that finds the scripts and stylesheets that block a page’s first render.

    Done when

    • Plain external scripts are reported; async, defer and module scripts are not.
    • Inline scripts are not reported (they have no src to fetch).
    • Print-only stylesheets are not reported as render-blocking.
    Your solution
    Ctrl/⌘ + Enter

    Remember#

    Try to answer each card before you open it. Then add them to your reviews.

    When does a defer script run?

    After parsing finishes, in document order, before DOMContentLoaded.

    When does an async script run?

    As soon as it downloads, in any order.

    Why is CSS render-blocking?

    Painting before CSS loads would flash unstyled content.

    What does the preload scanner do?

    Reads ahead in the HTML and starts fetching resources while the parser waits.

    How does a module script behave by default?

    Like defer: fetched in parallel, run after parsing in order.

    Go deeper

    Four layers. Stop at the one your interview needs; each ends with a quick check.

    The core ideaEvery round
    The HTML parser never gives up. Missing end tags and misplaced elements are fixed by rules in the HTML Standard, so every browser builds the same DOM from the same broken markup Source: HTML Standard: Parsing HTML documents.
    Check yourself: What happens when HTML has an unclosed tag?

    The parser fixes it using the spec's error-recovery rules; it never stops with an error.

    How it works underneathSenior rounds
    The CSSOM is built from every stylesheet before styles are applied. A classic script also waits for earlier stylesheets, because it might read computed styles, so CSS can block JavaScript too.
    Check yourself: Why does a script wait for earlier stylesheets?

    It might read computed styles, so the browser waits for CSS before running it.

    Edge cases and trapsWhere people slip

    The preload scanner sees only what is in the HTML. Resources added by JavaScript, or referenced from CSS (fonts, background images), are found late Source: web.dev: Don't fight the browser preload scanner.
    Use <link rel="preload"> for those (WEB.01.05).

    Check yourself: Which resources can the preload scanner not find?

    Ones created by JavaScript, or referenced only from CSS, such as background images and fonts.

    In productionStaff-level answers

    Use defer or modules for app code, async for independent scripts such as analytics, and inline only small critical CSS. media="print" stylesheets do not block screen rendering, which some sites use to load non-critical CSS.

    Check yourself: Which scripts should usually be async?

    Independent third-party scripts such as analytics.

    Finished the five steps? Mark it, and its cards join your reviews.

    Last checked 2026-11-01. Spot a mistake? Use “Report an error” below — fixes are listed on the corrections page.

    Interview questions this answers

    • What is the difference between async and defer?
    • Why is CSS render-blocking?
    • What does the preload scanner do?