Graphics: Adding wow
Some graphics, visualizations, and other dynamic content cannot (easily) be expressed in HTML and CSS alone. For those, it might be worth switching to an alternative technology. As a general rule,
- Start with HTML and CSS
- If you can't render the visualization in HTML, try SVG, which is a richer way to declaratively express grahics and illustrations (including first-class support for animations)
- If SVGs are insufficient, because you need more interaction or graphical filters, canvas provides a full... well, canvas, that you can render on.
SVGs: declarative graphics
While HTML and CSS are a wonderful declarative language to describe documents, they don't work so well for complex graphics. SVG (opens in a new tab) is a declarative, XML format to describe graphics.
Like HTML, SVG provides a handful of primitive tags (opens in a new tab); however, unlike HTML, those primitives are used for drawing (for example, line, rectangle, etc.)
Because it's XML-based, SVGs can:
- Be embedded in HTML
- Rendered with React
At their core, SVGs define shapes on an infinite canvas (somewhat like HTML), and then provide a "viewbox" or rectangle in that canvas that it should render (specified as two pairs of X/Y coordinates).
SVGs can either be inlined (e.g. above), or they can be included as an img
tag (by saving in a separate file and pointing the img
tag's src
attribute to that file).
Unlike HTML, where the syntax is meant to be written by hand, the syntax for SVGs can get complicated quickly. For example, here is the syntax to define a polygon (the points are pairs of X/Y coordinates):
<polygon points="5,5 195,10 185,185 10,195" fill="red" />
For that reason, many people use a library to generate SVGs (or just export them from an image editor).
CSS interop
Because SVG and HTML are so interoperable, CSS can actually effect both. For example,
Embedding HTML
Not only can you embed SVGs in HTML, you can also embd HTML in SVGs using foreignObject
:
SVG animation
SVGs can be animated via the animate
primitive (sometimes called SMIL (opens in a new tab)).
Lottie
Again, while animations can be written by hand, most designers prefer to iterate on them in a graphics editor and later export the animation. Lottie (opens in a new tab) is a format developed by Airbnb to export SVG animations as JSON files.
Canvas: pixel perfect control
While SVGs are powerful, sometimes you really want pixel-perfect control. For that, there is Canvas.
Canvas (opens in a new tab) allows developers to define an area that they can programmatically draw on.
Libraries
Because the Canvas API is so low level, many people use a higher level library (e.g. Pixi (opens in a new tab) and Fabric (opens in a new tab)).
WebGL: GPU performance
If you start to use Canvas for realtime graphics (or games), you'll quickly run into a performance problem. This isn't specific to JavaScript, and why native apps leverage the graphics card for anything intense (a specialized piece of hardware that can quickly do mathematical operations involved in rendering 3D graphics).
WebGL (opens in a new tab) allows JavaScript to use the graphics card.
ThreeJS
The APIs behind WebGL, especially for 3D, are really low level, and as a result, most people interact with it through a library, specifically Three.js (opens in a new tab). Three handles all of the internals of 3D rendering, and provides human-readable primatives for math, shapes, cameras, etc.
React three fiber
Like many Graphics libraries, Three is imperative in nature; because it is not declarative, it can be awkward to use alongside React. React-three-fiber (opens in a new tab) bridges that gap, by providing react primatives for Three concepts.
In addition, it will do all the necessary Three.js cleanup as elements are mounted and unmounted.
WebGPU
While WebGL is very powerful, it's also getting old. GPUs have really advanced in leaps and bounds over the past few years and the WebGPU (opens in a new tab) spec is a successor to WebGL currently being implemented that provides access to new GPU features, and enables developers to leverage the GPU for general-purpose compute.