StealThis .dev
Pages Medium

Wiki — CSR vs SSR (split-screen explainer with load race)

A rendering-strategies explainer built as a literal split screen: the left half argues client-side rendering in amber-on-near-black, the right half argues server-side rendering in teal-on-light, joined by a dashed center seam. Every concept band mirrors the same idea on both sides — request waterfalls, hydration, scorecards, SSG/ISR/streaming/islands — and the centerpiece is a Simulate Page Load race where two fake browser windows load the same shop concurrently, lighting TTFB / FCP / TTI lamps as each side hits its milestones.

Open in Lab
html css vanilla-js
Targets: JS HTML

Code

CSR vs SSR (split-screen explainer with load race)

An educational page whose layout is its argument: the viewport is split down the middle by a dashed seam, with CLIENT (CSR) living on a warm near-black half (amber accent) and SERVER (SSR) on a cool light half (teal accent). Even the sticky top bar is painted half-and-half, carrying a CLIENT vs SERVER wordmark and a row of dot anchors with scrollspy.

Content flows as seven mirrored bands — each explains the same concept from both sides in parallel: what “rendering” actually means (with the empty-shell vs full-HTML response side by side in code panels), the request waterfall as numbered step cards, hydration vs no-hydration, per-side scorecards (TTFB, FCP, TTI, SEO, server cost, best-fit workloads) as dotted spec tables, and the modern spectrum (SSG and ISR on the client half; streaming SSR and islands/RSC on the server half).

The centerpiece band is the load race: a gradient Simulate Page Load button and a shared millisecond clock drive two fake browser windows concurrently. The CSR window receives its empty shell fast, then grinds through a JS-bundle progress bar and a data-fetch spinner before content pops in late; the SSR window paints its full skeleton almost immediately, then flashes a hydration ring when interactivity attaches. Metric lamps (TTFB / FCP / TTI) light with their timings on each side as reached, and a Reset button re-arms everything for another run.

Vanilla JS throughout: a setTimeout schedule on a shared performance.now() clock for the race, IntersectionObserver for the scrollspy, and scrollIntoView interception for the dot anchors (fragment navigation is blocked in sandboxed preview iframes). Below 860px the halves stack — CLIENT above SERVER — and the seam and dots hide.

Illustrative UI only — simulated network timings on a fictional shop.