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.

Modern platform levers: Web Components (Custom Elements, Shadow DOM, templates) can encapsulate browser-native UI; resource hints such as fetchpriority, loading="lazy", rel="preload", and rel="prefetch" control discovery order and must be tied to measured critical-path needs.

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.

React 19-era apps also need fluency with Actions-oriented hooks (useActionState, useOptimistic, useFormStatus), Server Components, and compiler-assisted memoization where the project toolchain enables it.

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.

Practical debugging path

When markup, styling, React, and hydration are all suspects, debug in this order:

  1. Confirm the browser layer first: valid HTML nesting, loaded CSS, script mode, and whether the expected root exists.
  2. Compare the server HTML snapshot with the first client render output before effects run.
  3. Identify whether the issue is DOM structure, CSS cascade, React reconciliation, or hydration contract.
  4. For React-specific bugs, inspect keys, state ownership, effects, and client/server component boundaries.
  5. For hydration bugs, remove nondeterministic inputs or serialize them explicitly rather than patching symptoms after mount.

Interview drill

Question: "Explain where React sits between HTML, CSS, and the browser."

Model answer structure:

  1. The browser owns DOM, CSSOM, style, layout, paint, composite, events, and resource loading.
  2. React produces element descriptions from props/state, reconciles them through Fiber, and commits changes through react-dom.
  3. CSS still resolves through the browser cascade; React does not replace layout or paint.
  4. SSR sends an HTML snapshot; hydration attaches React state and events to matching DOM.
  5. Strong production answers mention deterministic render, bundle cost, accessibility semantics, and telemetry for hydration warnings.

Follow-ups to expect:

  • "Why can invalid HTML cause hydration mismatch?"
  • "What changes with React Server Components?"
  • "Why is SSR not automatically faster?"

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

Mark this page when you finish learning it.

Spotted something unclear or wrong on this page?

On this page