TNS
VOXPOP
How to Optimize AI?
Which is most important for AI workloads: computational performance, cost or portability?
Computational performance
0%
Cost
0%
Portability
0%
No preference
0%
Frontend Development

How to Build SVG Line Charts with React, SSR and Tailwind CSS

A tutorial on how to roll your own SVG Line Charts in React using Server-side rendering, with either Next.js or Gatsby.
Oct 8th, 2022 6:00am by
Featued image for: How to Build SVG Line Charts with React, SSR and Tailwind CSS
Image via Shutterstock.

In this post I’ll be explaining how to “roll your own” SVG Line Charts in React using Server-side rendering. To use Server-side rendering with React, you can use either Next.js or Gatsby.

Svg Line Charts

Screenshots of Gatsby and Nextjs GitHub Repository Activity Line Charts

On the following links you will find a Live Preview and GitHub Repository for the completed Line Charts using both frameworks.

I won’t be covering how to get started with either framework, so please consult the docs if you’re not familiar with these technologies.

I’ve also used Tailwind to style the Charts. If you’d like to do the same, the Tailwind docs have installation guides for both Gatsby and Next.js.

In the demo sites I’ve used the GitHub REST API as a data source, if you’d like to do the same you’ll need a GitHub Personal Access Token; or if you prefer, I’ve provided some sample data on the links below.

Sample Data

You can use either of the sample data Gists below.

Gatsby Page Sample Data Gist

Example usage

Next.js Page Sample Data Gist

Example usage

What Is Server-Side Rendering?

Server-side rendering (SSR) is an application’s ability to convert HTML files on the server into a fully rendered HTML page for the client (the browser). Combining SSR with Server-side data fetching means you can generate the charts on the server with data that’s been “fetched”, also on the server.

Creating charts this way means all data fetching and rendering will work when either JavaScript is disabled in the browser, or before React has hydrated the DOM.

Rendering charts this way means they’ll never appear blank while data is “fetching” and you won’t see a “jump” or layout shift after data has loaded; using this method also ensures your Lighthouse CLS scores aren’t affected.

Anatomy of a Line Chart

In the sections below you’ll be creating a number of different parts that make up a Line Chart. These are described in the diagram below.

Anatomy of a Line Chart

Diagram showing different parts of an Svg Line Chart

Create a Line Chart Component

Create a new component called <LineChart /> and name the file line-chart.js. In the demo sites I’ve saved this file in a directory called “components.”

The <LineChart /> component accepts a prop called data. The shape of the data prop is defined using propTypes.

Render the Line Chart on a Page

Import the <LineChart /> into your page component and return it. The destructured page props will be different depending on if you’re using Gatsby or Next.js. Replace … with the framework-specific props.

Setup Line Chart

In this step, you’ll define the variables that are used to control the different parts of the Line Chart.

Here’s a short explanation for each of the variables.

  1. chartWidth: The width of the SVG viewBox.
  2. chartHeight: The height of the SVG viewBox.
  3. offsetY: Used to position the ticks.
  4. paddingX: The left and right padding around the Line Chart.
  5. paddingY: The top and bottom padding around the Line Chart.
  6. maxY: The maximum total value from the data array.
  7. guides: An empty array that determines the amount of guides.

Line Chart Properties

The properties array is created using a combination of values from the data prop and variables defined in the previous step. Each of the returned values are used in different parts of the Line Chart.

The two important values to look at here are x, and y. These variables are created by combining a number of the variables defined earlier and the index value from the .map.

The total and date values are returned without modification.

Creating the X Coordinate

The x coordinate is used to create a position for the marker, value and the x value for a Polyline point.

The x coordinate is created by using the index value from the .map and dividing it by the length of the data passed in on the data prop. Multiplying it by the chartWidth and subtracting the paddingX value ensures the x coordinate value never exceeds the bounds of the chart width.

Creating the x Coordinate

Diagram showing array .map iteration to create x coordinate

Creating the Y Coordinate

The y coordinate is used to create a position for the marker, value and the y value for a Polyline point.

The y coordinate is created by dividing the total by the maxY value and multiplying it by the chartHeight minus the paddingY value. As an extra step, the paddingY plus the offsetY values are subtracted, this creates some extra space for the ticks at the bottom of the chart.

Creating the y Coordinate

Diagram showing array .map iteration to create y coordinate

Creating the Points Array

The SVG Polyline element can be used to create a line connected by points. To create the points for the Polyline line you can use the x and y values from the properties array and return them as an array of x, y positions.

The points array will return something similar to the below. Each index in the array contains both an x and y coordinate.

Creating an SVG

Create a new <svg /> element, define the viewBox attributes and set the role to presentation.

Creating the Polyline

Create a new <polyline /> element, set the fill to none and add relevant classes to style the stroke. You can also define the strokeWidth using an attribute. Using the points attribute you can pass on the values returned by the points array.

Creating the Markers and Values

Using the returned values from the properties array you can now add and position svg elements to display the total(s) from the data array.

The <circle /> element is positioned using the x and y property using the cx and cy attributes and is given a radius of 12 using the r attribute. You can add your own class names and a value for the strokeWidth to achieve the desired look.

The <text /> element is also positioned using the x and y property using the x and y attributes. The <text /> element accepts children, so add the total property to display it. I’ve added an additional 2.8 to the y to ensure the text is vertically centered within the <circle />. You can add your own class names or attributes to achieve the desired look.

Creating the Ticks

The ticks are created in a slightly different way, you’ll notice the <text /> element is wrapped within a <g />.

This is to create a new coordinate system so that when the rotation is applied to the text, its top / left positions are calculated from the top and left position of the <g /> rather than the <svg /> element.

The <g /> element doesn’t support the x or y attributes, so you’ll use the transform attribute and provide a translate value for both the x and y positions. I’ve also subtracted the paddingY and offsetY values to position the ticks correctly.

Creating the Guides

The guides are the last element to add; but rather than iterating over the properties array, this time you’ll iterate over the guides array.

This is just an empty array and the index is used to provide a key for React. The y coordinate is created in a similar way as before, where a ratio is created to ensure the y positions stay within the bounds and don’t overlap the ticks.

Using the values returned from the properties array, it’s possible to add any number of different SVG elements to help display different values from different types of data.

The x and y properties should be all you need. Whilst it is a little tricky to create them, they create the boundaries for any new elements you’d like to add to the chart.

Thanks for reading, and if you have any questions please come and find me on Twitter: @PaulieScanlon or checkout my site paulie.dev, where I have more React/Jamstack tutorials.

Further Reading

Group Created with Sketch.
TNS DAILY NEWSLETTER Receive a free roundup of the most recent TNS articles in your inbox each day.