Client-side rendering (CSR) is the approach in which a web application’s HTML is generated in the browser by JavaScript rather than on the server. The server sends a minimal HTML shell, usually a nearly empty container element plus script tags, and the browser downloads, parses and executes the application code, fetches data from APIs and then builds the visible interface in the DOM.
In web applications, client-side rendering is the default model of the classic single-page application built with frameworks such as React, Vue.js, Angular or Svelte. It enables rich, app-like interactivity, but it shifts work to the user’s device and delays the first meaningful content until the code has loaded and run.
How client-side rendering builds a page
Client-side rendering follows a fixed sequence of network and CPU steps before the user sees content. Every step must finish before the next can start, which is why CSR performance is dominated by bundle size and device speed.
- The browser requests the URL and receives a small HTML shell with no real content.
- It discovers and downloads the JavaScript bundles and stylesheets referenced in the shell.
- The engine parses, compiles and executes the application code on the main thread.
- The application requests data from one or more APIs, often as JSON.
- The framework renders components into the DOM, and the browser performs layout and paint.
- Later navigations are handled by client-side routing without full page reloads.
After this initial cost, the application is fast and fluid: route changes swap components, only data travels over the network, and state such as form input or scroll position survives between views. This trade of slower start for faster interaction is the defining characteristic of CSR.
Client-side rendering compared with other rendering strategies
Client-side rendering is one point on a spectrum of rendering strategies that differ in where and when HTML is produced. Modern frameworks often mix them per route.
| Strategy | Where HTML is built | When it is built | First content |
|---|---|---|---|
| Client-side rendering | Browser | On every visit, after JavaScript runs | Late |
| Server-side rendering | Server | On every request | Early |
| Static site generation | Build server | At build time | Earliest |
| Incremental static regeneration | Server or edge | At build time, refreshed periodically | Early |
| Islands architecture | Server, with browser islands | Mostly at build or request time | Early |
Server-side rendering usually adds hydration, in which the browser attaches event handlers to server-produced HTML. Hydration still requires downloading and running much of the same JavaScript, so SSR improves time to first content more than time to interactivity.
Performance profile and key metrics
The performance of client-side rendering depends mainly on JavaScript weight, API latency and CPU power. A desktop computer may run a large bundle in a fraction of a second, while a budget phone can take several times longer to parse and execute the same code.
| Metric | Typical CSR behavior | Main driver |
|---|---|---|
| FCP | Delayed until the first render | Bundle download and execution |
| LCP | Often late, after data arrives | Request chain of shell, script and API |
| TTFB | Very low, the shell is static | Server or CDN response time |
| INP after load | Often good on capable devices | Component update cost |
| Total Blocking Time | Often high on first load | Long parse and execution tasks |
A practical guideline is to keep the initial JavaScript for a route well below a few hundred kilobytes compressed, use code splitting so each route loads only what it needs, and start API requests early, for example with preload hints, to shorten the request waterfall.
When client-side rendering is the right choice
Client-side rendering suits long, interactive sessions behind a login, where the initial cost is paid once and then repaid by fast interaction. It suits poorly content pages that depend on search traffic and short visits.
| Application type | Recommended approach | Reason |
|---|---|---|
| Admin dashboard or internal tool | Client-side rendering | No indexing need, long sessions |
| Collaborative editor or design tool | Client-side rendering | Heavy state, constant interaction |
| News site or blog | Static generation or SSR | Fast first content and indexing |
| Online shop | SSR or static with interactive islands | Search visibility and conversion |
| Marketing landing page | Static generation | Minimal JavaScript needed |
CSR also simplifies hosting and scaling: the shell and bundles are static assets that any CDN can serve, and the server only exposes APIs. This separation fits teams with a distinct backend and a frontend deployed independently.
Limitations and common pitfalls
- Search engine visibility is less reliable; crawlers that render JavaScript do so later and with limits, and many social preview bots do not run it at all.
- Blank screens on failure: if a bundle fails to load or throws an error, the user may see nothing without an error boundary or fallback.
- Request waterfalls appear when components fetch data only after they render, adding a round trip per level.
- Accessibility regressions occur when client-side routing does not move focus or announce page changes to screen readers.
- Memory growth in long sessions results from listeners and caches that are never released.
Many of these issues are solvable within CSR through code splitting, prefetching, error boundaries and focus management, but each one requires deliberate engineering rather than framework defaults.
When only a few routes need indexing or fast first content, teams rarely abandon CSR completely. A common compromise is prerendering selected routes to static HTML at build time, or adopting a framework that renders the first view on the server and continues as a client-side application after hydration. The decision should follow measured metrics on real devices, not the default template of a framework.
A non-technical view
Think of buying furniture. With server rendering, the shop delivers a fully assembled table. With client-side rendering, it delivers a flat-pack box and instructions, and you assemble the table at home.
The flat-pack box arrives quickly, but you see nothing useful until assembly is done, and a slow helper takes longer. Once the table stands, though, changing it is easy because all the parts and tools are already at hand. That is the core trade: a slower start in exchange for quick changes afterward.
A concrete example
A logistics company builds an internal dispatch dashboard used by planners for full eight-hour shifts. The application shows a live map, a table of several thousand shipments and drag-and-drop route planning. It is built as a client-side rendered single-page application served from a CDN, with data coming from a separate API.
The first load takes about three seconds on office laptops, which is acceptable because planners open it once per shift. After that, filtering the table, switching views and reassigning drivers happen without page reloads, and updates arrive over a WebSocket. The public tracking page for customers, by contrast, is rendered on the server so that it appears quickly on phones and can be shared as a link with a proper preview.