09. The Rendering Landscape

Modules 01–03 taught you to draw charts on Canvas. Modules 05–08 taught you to describe charts with Chart.js (which renders to Canvas internally). The next three modules will use D3.js, which renders to SVG. But why does D3 use SVG? Why does Chart.js use Canvas? When should you use CSS, WebGL, or a static image instead? This module answers those questions by examining the five rendering surfaces available in the browser and the architectural dimensions that determine which one to choose.

Connection to the Overview: This module expands on Section 8 of the Data Visualization Overview, which introduces the five rendering surfaces and the decision framework. Here you will see them in action with interactive demos that make the performance differences tangible.

Demo Files

Run: Open the HTML files directly in a browser. No libraries or build steps required.

1. The Five Rendering Surfaces

Every chart in a web browser is ultimately drawn using one of five rendering technologies. Each has a different rendering model that determines its performance characteristics, interactivity story, and accessibility profile:

Surface Model Output Interactivity Accessibility
Static image (PNG/JPEG/SVG-as-file) Pre-rendered Raster/vector file None alt text
CSS Retained (DOM) Styled HTML elements Full DOM events Full semantic HTML
Canvas 2D Immediate (pixels) Opaque bitmap Manual hit-testing Opaque (needs ARIA)
SVG (inline DOM) Retained (DOM) Structured DOM tree Native DOM events per element Traversable by assistive tech
WebGL / WebGPU Immediate (GPU) GPU-rendered pixels Manual (raycasting) Opaque (needs ARIA)

The critical distinction is between immediate mode and retained mode rendering. This single concept explains most of the performance and interactivity trade-offs you will encounter.

2. Immediate vs. Retained Mode

These two rendering models are the architectural foundation of every rendering technology in the browser:

IMMEDIATE MODE (Canvas, WebGL) ─────────────────────────────── Draw command ──► Pixels painted ──► Object gone from memory ctx.fillRect(10, 20, 100, 50); // The rectangle exists as pixels on the bitmap. // There is no "rectangle object" in memory. // To change it: clear the canvas and redraw everything. Memory: O(pixels) — constant regardless of how many shapes you drew. RETAINED MODE (SVG, CSS/HTML) ──────────────────────────── Create element ──► DOM node persists ──► Browser tracks position, style, events svg.append('rect').attr('x', 10).attr('y', 20)... // The rectangle is a live DOM node. // The browser knows its position, style, and event listeners. // To change it: modify the attribute. The browser repaints. Memory: O(elements) — grows linearly with every shape you add.

Why this matters: At 100 elements, the overhead of retained mode is negligible. At 5,000 elements, reflow and style recalculation become measurable. At 50,000 elements, the page freezes — not because rendering is slow, but because DOM bookkeeping is expensive. Every element participates in the CSS cascade, layout, and event dispatch system.

Open the stress test demo and drag the slider from 100 to 50,000 points. Watch the FPS counters: Canvas stays smooth while SVG degrades.

3. Performance Envelopes

Each rendering surface has a comfortable operating range measured in data points or visual elements. Outside that range, performance degrades — sometimes gradually, sometimes catastrophically:

Data Points (log scale) ─────────────────────────────────────────────────────────────── 10 100 1K 5K 10K 50K 100K 1M CSS: ████████████ ~10–100 elements SVG: ████████████████████████████ ~10–5,000 elements (degrades at 10K, unusable at 50K) Canvas: ████████████████████████████████████████████ ~100–100,000 data points WebGL: ██████████████████████████████████ ~10,000–millions

These ranges are approximate and depend on hardware, but the relative order is consistent. The key insight is that there is no single "best" technology — each has a sweet spot determined by its rendering model.

4. SVG Strengths

D3.js defaults to SVG for good reasons. Within its performance envelope, SVG offers advantages that no other rendering surface can match:

Try the hit-testing demo to see SVG's native event handling in action compared to Canvas's manual approach.

5. The DOM Explosion Problem

SVG's strengths come from the DOM. But the DOM is also its weakness. Every SVG element is a full-fledged DOM node that participates in:

Render 10,000 <circle> elements and you have 10,000 DOM nodes. That is roughly 5 MB of memory just for the DOM objects, plus the ongoing cost of style recalculation on every frame. The rendering itself is fast — painting circles is cheap. The bottleneck is the DOM bookkeeping that happens before painting.

This is why Chart.js chose Canvas. Chart.js targets dashboard use cases where re-rendering on data update needs to be fast. With Canvas, updating a chart means clearing the bitmap and redrawing — O(1) DOM operations regardless of data size. With SVG, it would mean updating thousands of DOM nodes, triggering reflow and repaint cascades. The trade-off: Chart.js sacrifices SVG's native accessibility and event handling for consistent performance.

6. Canvas Strengths and Weaknesses

Canvas uses immediate-mode rendering: you issue draw commands and the result is a flat bitmap. Once drawn, shapes have no identity — they are just pixels.

Strengths:

Weaknesses:

7. WebGL and WebGPU

When data volumes exceed 100,000 points, even Canvas struggles with per-frame draw loops. WebGL (and its successor WebGPU) solve this by offloading rendering to the GPU, which can process millions of vertices in parallel.

WebGL is used by mapping libraries (Mapbox GL, deck.gl), scientific visualization tools (regl, three.js), and large-scale charting libraries (Plotly with scattergl). WebGPU, the modern successor, provides even lower-level GPU access with better performance and a cleaner API.

You will not need WebGL for this course. It is included here so you understand when it is appropriate: millions of data points, real-time 3D rendering, or map tile rendering. The learning curve is steep (shaders, buffer objects, GPU memory management), and for the data volumes in your analytics dashboard project, Canvas via Chart.js is more than sufficient.

8. CSS Charting

CSS can render simple charts without any JavaScript at all. Bars are <div> elements whose width or height is set via calc() or custom properties. This approach has unique advantages:

<!-- CSS-only bar chart using custom properties -->
<div class="chart">
  <div class="bar" style="--value: 83">
    <span class="label">/home</span>
    <span class="value">1,250</span>
  </div>
  <div class="bar" style="--value: 29">
    <span class="label">/about</span>
    <span class="value">430</span>
  </div>
</div>

<style>
.bar {
  height: 28px;
  width: calc(var(--value) * 1%);
  background: #16a085;
  margin: 4px 0;
  transition: width 0.5s;
}
</style>

The limitation is that CSS charts are restricted to simple forms — horizontal bars, sparklines, basic progress indicators. Anything requiring axes, gridlines, or complex geometry needs Canvas or SVG. See the CSS bar chart demo for a complete example with progressive JavaScript enhancement.

9. Decision Framework

Choosing a rendering technology is not a single-variable decision. It depends on at least six dimensions. This table maps each dimension to the technologies it favors:

Dimension Static Image CSS Canvas SVG WebGL
Purpose: Explanatory (reports, email) Yes Inline CSS
Purpose: Exploratory (interactive analysis) Yes Yes Yes
Interaction: None Yes
Interaction: Tooltips / hover Yes Possible Yes Possible
Interaction: Complex (filter, zoom, drag) Yes Yes Yes
Data volume: < 50 points Yes Yes
Data volume: 50–5,000 points Yes Yes
Data volume: 5K–100K points Yes
Data volume: > 100K points Yes
Update rate: Static Yes Yes Yes Yes Yes
Update rate: Periodic refresh Yes Yes Yes
Update rate: Real-time streaming Yes Yes
Must work without JS Yes Yes
Must embed in email/PDF Yes Inline only
For the dashboard project: Canvas via Chart.js is the right fit. You have standard chart types (bar, line, doughnut), moderate data volumes (hundreds of aggregated points), interactivity matters (tooltips, hover), but you are not rendering 50,000 raw events on screen. Chart.js handles this sweet spot well. For the D3 modules that follow, SVG is the right fit because you will build custom visualizations with modest element counts where DOM events and CSS styling matter more than raw throughput.

10. Authoritative Comparison

Here is the full comparison across the dimensions that matter for charting:

Dimension CSS Canvas 2D SVG WebGL
Rendering model Retained (DOM) Immediate (pixels) Retained (DOM) Immediate (GPU)
Element limit ~100 ~100K ~5K–10K Millions
Interactivity Native DOM events Manual hit-testing Native DOM events Manual raycasting
Accessibility Full (semantic HTML) Opaque (needs ARIA) Good (title/desc/ARIA) Opaque (needs ARIA)
CSS styling Full None Full None
Resolution independence Yes Requires dpr handling Yes (vector) Requires dpr handling
DevTools inspection Full Bitmap only Full (Elements panel) Bitmap only
Text rendering Real, selectable text Painted pixels Real, selectable text Painted pixels or SDF
Export to PNG Screenshot only toDataURL() Serialize to file toDataURL()
Works without JS Yes No Static SVG yes No

11. Exercises

  1. Stress test observation: Open svg-vs-canvas-stress.html. At what point count does the SVG panel drop below 30 FPS on your machine? How about 10 FPS? Does the Canvas panel ever drop below 30 FPS? Record the numbers.
  2. CSS chart extension: Open css-bar-chart.html. Disable JavaScript in your browser's DevTools. Verify the chart still renders. Then add a sixth bar to the HTML and adjust the --value accordingly.
  3. Hit-testing analysis: Open hit-testing.html. Read the code panel for the Canvas side. How many distance calculations does it perform per mouse move? What is the Big-O complexity? How could you reduce it?
  4. Decision matrix: For each scenario below, identify the best rendering technology and justify your choice:
    • A weekly email report with 5 bar charts
    • A real-time stock ticker showing 500 price points, updating every 100ms
    • An interactive map of 2 million GPS coordinates
    • A dashboard with 6 charts, each showing ~200 aggregated data points

12. Summary