THN Interview Prep

Browser, HTML/CSS & React — from markup to hydration

Core details

1. Browser: from bytes to pixels

The browser is a pipeline. Rough order (same vocabulary as Rendering pipeline & compositing):

  1. Parse HTMLDOM (live tree of nodes: elements, text, comments).
  2. Parse CSSCSSOM (tree of style rules + @-rules).
  3. Style — match selectors to nodes, resolve cascade, produce computed values per element.
  4. Layout (“reflow”) — compute geometry (box model, flow, positioning).
  5. Paint — rasterize pictures (text, colors, images, effects) for regions that changed.
  6. Composite — merge layers into the frame shown on screen (GPU-backed where applicable).
  HTTP response (HTML bytes)


      ┌─────────┐     stylesheets, inline <style>
      │   DOM   │◄────────────────────────────┐
      └────┬────┘                           │
           │                          ┌─────▼─────┐
           │                          │   CSSOM   │
           └──────────┬──────────────┴─────┬─────┘
                      │                      │
                      ▼                      ▼
               computed styles ◄─── cascade (specificity,
                                         order, inherit)


            layout → paint → composite → frame

HTML’s job: encode structure and semantics (<main>, headings, landmarks). Accessibility and SEO lean on honest structure—not only div soup.

CSS’s job: encode presentation (which properties apply to which elements). The cascade decides which declaration wins when several rules target the same property: origin (user agent, author, user) → importantspecificitysource order.

2. HTML loading & script execution (interview soundbite)

Script modeTypical effect
Classic <script src>Blocks HTML parsing until fetched & run (unless async/defer).
deferFetch in parallel; run after HTML parse, in order.
asyncFetch in parallel; run when ready—order not guaranteed vs other async scripts.

Why it matters for React: your bundle must load and execute before hydration can attach event listeners and state to existing HTML.

3. Where React fits (mental model)

Without React (imperative): your code calls document.createElement, appendChild, className = … as data changes—easy to let DOM and in-memory state drift.

With React (declarative): you write functions that return a description of UI (React elements—plain objects: type, props, children). On each render, React compares the new tree to the previous one (reconciliation on the Fiber tree) and commits the minimal DOM mutations needed.

  props + state


  render()  ──►  React element tree (descriptors)


  reconciliation (Fiber) ──► commit ──► DOM updates + effects

React is not “the DOM”—it’s a scheduler + reconciler that owns updates to a DOM subtree (via react-dom). Concurrent React can interrupt low-priority rendering so input stays responsive (details).

4. Hydration — what actually happens

Problem: SSR (or SSG) sends HTML so the user sees content before JS is ready. That HTML is a snapshot: no React event handlers yet.

Hydration: when the client bundle runs, hydrateRoot/HydrationRoot (React 18+) walks the existing DOM, expects it to match what React would render for the same props/state snapshot, attaches internal Fiber state, registers event listeners, and from then on updates are incremental like a normal client app.

StepWhat happens
1Server emitted HTML string (+ sometimes serialized data).
2Browser paints visible content (good LCP / perceived perf).
3JS loads → React hydrates root—reuse nodes where possible.
4After hydration, state updates go through client React as usual.

If server HTML ≠ first client render → hydration mismatch (warnings, broken nodes, duplicate UI). Common causes: Date.now(), Math.random(), window during render, suppressHydrationWarning misused, locale/timezone drift, or invalid HTML nesting that the parser “fixes” differently than React expects.

Loading diagram…

Next.js App Router note: React Server Components change the split: much UI never ships as client component JS—only client boundaries hydrate. See Next.js App Router for RSC vs “classic” SSR + client tree.

5. React core concepts (SDE3 checklist)

ConceptOne sentence
ComponentFunction (or class) that returns elements; capitalize in JSX.
PropsInputs—treat as read-only; prefer key to reset state when identity changes.
StateMutable over time via useState / useReducer; triggers re-render when updated.
Derived dataCompute in render (or useMemo when expensive)—don’t copy props to state without reason.
Effects (useEffect)Sync with systems outside React (fetch, subscriptions, timers)—not a replacement for event handlers.
RefsStable boxes for DOM nodes or values that must not trigger re-render on change.
ContextDependency injection for trees—avoid one mega-context for app-wide churn.
KeysStable identity for list children—wrong keys → state leaks across rows.
Error boundariesCatch render errors in children; event errors need try/catch inside handlers.
Strict Mode (dev)Double-invokes some paths to surface non-idempotent effects.

Deeper Fiber, transitions, Suspense: React — rendering & architecture.

Understanding

The browser does not know React—it only knows DOM + CSS + JS. React’s value is discipline: a single equation UI = f(state, props) with a reconciliation engine that batches and prioritizes work. Hydration is the bridge between fast static HTML and interactive client trees; get the contract wrong and you pay in bugs, not just perf.

Senior understanding

ProbeStrong angle
“Why SSR at all?”TTFB/FCP, SEO, edge caching—not magic if hydration cost dominates
“CSR-only?”Simpler mental model; worse first meaningful paint on slow devices unless shell is tiny
“CSS-in-JS vs modules?”Invalidation cost on hot paths; SSR style extraction; team consistency

Operational: log hydration warnings in staging; treat serialized state like an API with versioning.

Diagram — layers you own in production

┌──────────────────────────────────────────────┐
│  Your product (Next.js / Remix / SPA)      │
│  ├── Routing, data loading, meta-framework │
│  └── Client boundaries / server components  │
├──────────────────────────────────────────────┤
│  React (scheduler, reconciler, hooks model)   │
├──────────────────────────────────────────────┤
│  react-dom (commit to DOM, hydration)       │
├──────────────────────────────────────────────┤
│  Browser: DOM + CSSOM + layout + paint …   │
└──────────────────────────────────────────────┘

See also

Last updated on

Spotted something unclear or wrong on this page?

On this page