Chart

With careful, minimal styling choices, TRMNL can display a variety of numerical or time centric content as charts and graphs.

Usage

Any CDN-enabled JavaScript library may be used to develop charting interfaces, however the examples below leverage Highcharts and Chartkick.

Take care to disable animation effects, otherwise your chart may be only partially captured by TRMNL's screenshot rendering service.

Line Chart

Line charts effectively display trends over time. This example shows a simple line chart with customized styling to match the TRMNL aesthetic.

25,388 Pageviews
4,771 Visitors
2.23 Mins on Page
Charts Line Chart
<!-- import Highcharts + Chartkick libraries -->
<script src="https://code.highcharts.com/highcharts.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/chartkick.min.js"></script>

<!-- markup with empty, ID'd element for chart injection -->
<div class="view view--full">
  <div class="layout layout--col gap--space-between">
    <div class="grid grid--cols-3">
      <div class="item">
        <div class="meta"></div>
        <div class="content">
          <span class="value value--tnums">25,388</span>
          <span class="label">Pageviews</span>
        </div>
      </div>
      <div class="item">
        <div class="meta"></div>
        <div class="content">
          <span class="value value--tnums">4,771</span>
          <span class="label">Visitors</span>
        </div>
      </div>
      <div class="item">
        <div class="meta"></div>
        <div class="content">
          <span class="value value--tnums">2.23</span>
          <span class="label">Mins on Page</span>
        </div>
      </div>
    </div>

    <div id="chart-123" style="width: 100%"></div>
  </div>

  <div class="title_bar">
    <img class="image" src="https://usetrmnl.com/images/plugins/simple-analytics--render.svg" />
    <span class="title">Simple Analytics</span>
    <span class="instance">usetrmnl.com</span>
  </div>
</div>

<script type="text/javascript">
  var data = [["2024-06-09", 975],["2024-06-10", 840],["2024-06-11", 1004],["2024-06-12", 1308],["2024-06-13", 753],["2024-06-14", 600],["2024-06-15", 710],
              ["2024-06-16", 489],["2024-06-17", 510],["2024-06-18", 590],["2024-06-19", 610],["2024-06-20", 671],["2024-06-21", 512],["2024-06-22", 550],
              ["2024-06-23", 421],["2024-06-24", 315],["2024-06-25", 604],["2024-06-26", 672],["2024-06-27", 601],["2024-06-28", 705],["2024-06-29", 800],
              ["2024-06-30", 912],["2024-07-01", 1503],["2024-07-02", 1273],["2024-07-03", 1250],["2024-07-04", 1198],["2024-07-05", 1005],["2024-07-06", 1300],
              ["2024-07-07", 1103],["2024-07-08", 1004],["2024-07-09", 600]];

  // recommended configs to achieve the TRMNL Framework aesthetic
  var createChart = function() {
    new Chartkick["LineChart"](
    "chart-123",
    data,
    {
      adapter: "highcharts", // chartjs, google, etc available
      prefix: "",
      thousands: ",",
      points: false,
      colors: ["black"],
      curve: true,
      library: {
        chart: {
          height: 260
        },
        plotOptions: {
          series: {
            animation: false,
            lineWidth: 4
          }
        },
        yAxis: {
          labels: {
            style: {
              fontSize: "16px",
              color:"#000000"
            }
          },
          gridLineDashStyle: "shortdot",
          gridLineWidth: 1,
          gridLineColor: "#000000",
          tickAmount: 5
        },
        xAxis: {
          type: "daytime",
          labels: {
            style: {
              fontSize: "16px",
              color: "#000000"
            }
          },
          lineWidth: 0,
          gridLineDashStyle: "dot",
          tickWidth: 1,
          tickLength: 0,
          gridLineWidth: 1,
          gridLineColor: "#000000",
          tickPixelInterval: 120
        }
      }
    });
  };

  // ensure your chart loads before plugin render is generated
  if ("Chartkick" in window) {
    createChart();
  } else {
    window.addEventListener("chartkick:load", createChart, true);
  }
</script>

Multi-Series Line Chart

For comparing data across multiple time periods or categories, multi-series line charts are ideal. This example demonstrates a comparison between current and previous period data with distinct styling for each series.

$85,240 Total Sales
32 Pending Orders
Jul 01 - Jul 15
Current
$128 AOV
665 Fulfilled Orders
Jun 15 - Jun 30
Previous
Charts Multi-Series Line Chart
<!-- import required libraries -->
<script src="https://code.highcharts.com/highcharts.js"></script>
<script src="https://code.highcharts.com/highcharts-more.js"></script>
<script src="https://code.highcharts.com/modules/pattern-fill.js"></script>

<div class="view view--full">
  <div class="layout layout--col gap--space-between">
    <!-- Optional data metrics displayed above chart -->
    <div class="grid">
      <div class="row">
        <div class="grid">
          <div class="item col--span-2">
            <div class="meta"></div>
            <div class="content">
              <span class="value value--large value--tnums">$85,240</span>
              <span class="label">Total Sales</span>
            </div>
          </div>

          <div class="item col--span-1">
            <div class="meta"></div>
            <div class="content">
              <span class="value value--small value--tnums">32</span>
              <span class="label">Pending Orders</span>
            </div>
          </div>

          <div class="item col--span-1">
            <div class="meta"></div>
            <div class="content">
              <span class="value value--xsmall value--tnums">
                <div class="w--14 h--1.5 mb--2 bg--black" style="border-radius: 20px;"></div>
                Jul 01 - Jul 15
              </span>
              <span class="label">Current</span>
            </div>
          </div>
        </div>
      </div>
    </div>

    <div class="border--h-5 w--full"></div>

    <!-- More metrics if needed -->
    <div class="grid">
      <div class="row">
        <div class="grid">
          <div class="item col--span-2">
            <div class="meta"></div>
            <div class="content">
              <span class="value value--tnums">$128</span>
              <span class="label">AOV</span>
            </div>
          </div>

          <div class="item col--span-1">
            <div class="meta"></div>
            <div class="content">
              <span class="value value--small value--tnums">665</span>
              <span class="label">Fulfilled Orders</span>
            </div>
          </div>

          <div class="item col--span-1">
            <div class="meta"></div>
            <div class="content">
              <span class="value value--xsmall value--tnums">
                <div class="w--14 h--1.5 mb--2 bg--gray-5"></div>
                Jun 15 - Jun 30
              </span>
              <span class="label">Previous</span>
            </div>
          </div>
        </div>
      </div>
    </div>

    <!-- Chart container with unique ID -->
    <div id="multi-series-chart" class="w--full"></div>

    <script type="text/javascript">
      // Using same date range for both series to ensure proper overlap
      var currentPeriod = [
        ["2024-07-01", 3500], ["2024-07-02", 4200], ["2024-07-03", 3800],
        ["2024-07-04", 5100], ["2024-07-05", 4800], ["2024-07-06", 3600],
        ["2024-07-07", 2900], ["2024-07-08", 4300], ["2024-07-09", 5200],
        ["2024-07-10", 6100], ["2024-07-11", 5700], ["2024-07-12", 4900],
        ["2024-07-13", 5300], ["2024-07-14", 5800], ["2024-07-15", 6500]
      ];

      // Using same date range but different values for comparison
      var previousPeriod = [
        ["2024-07-01", 2800], ["2024-07-02", 3100], ["2024-07-03", 3400],
        ["2024-07-04", 3900], ["2024-07-05", 4500], ["2024-07-06", 4100],
        ["2024-07-07", 3700], ["2024-07-08", 3300], ["2024-07-09", 4200],
        ["2024-07-10", 4800], ["2024-07-11", 5100], ["2024-07-12", 4700],
        ["2024-07-13", 5400], ["2024-07-14", 5800], ["2024-07-15", 5600]
      ];

      var formattedData = [
        { name: "Current", data: currentPeriod },
        { name: "Previous", data: previousPeriod }
      ];

      // Initialize chart with multiple series
      Highcharts.chart("multi-series-chart", {
        chart: {
          type: "spline",
          height: 203,
          width: null,
          animation: false,
          spacing: [10, 10, 5, 10]
        },
        title: {
          text: null
        },
        plotOptions: {
          series: {
            animation: false,
            enableMouseTracking: false,
            states: {
              hover: { enabled: false }
            },
            marker: {
              enabled: false
            }
          }
        },
        // Define series with different styles
        series: [{
          data: formattedData[0].data,
          lineWidth: 4,
          color: "#000000",
          name: formattedData[0].name,
          zIndex: 2  // Higher zIndex brings this series to front
        }, {
          data: formattedData[1].data,
          lineWidth: 5,
          name: formattedData[1].name,
          zIndex: 1,
          // Pattern fill for second series
          color: {
            pattern: {
              image: "https://usetrmnl.com/images/grayscale/gray-5.png",
              width: 12,
              height: 12
            }
          }
        }],
        tooltip: { enabled: false },
        legend: { enabled: false },
        yAxis: {
          labels: {
            style: { fontSize: "16px", color: "#000000" }
          },
          gridLineDashStyle: "shortdot",
          gridLineWidth: 1,
          gridLineColor: "#000000",
          tickAmount: 5,
          title: {
            text: null
          }
        },
        xAxis: {
          type: "datetime",
          labels: {
            style: { fontSize: "16px", color: "#000000" },
            padding: 5,
            y: 25
          },
          lineWidth: 0,
          gridLineDashStyle: "dot",
          tickWidth: 1,
          tickLength: 0,
          gridLineWidth: 1,
          gridLineColor: "#000000",
          tickPixelInterval: 120,
          title: {
            text: null
          }
        },
        credits: {
          enabled: false
        }
      });
    </script>
  </div>

  <div class="title_bar">
    <img class="image" src="https://usetrmnl.com/images/plugins/trmnl--render.svg" />
    <span class="title">Charts</span>
    <span class="instance">Multi-Series Line Chart</span>
  </div>
</div>

Bar Chart

Bar charts are ideal for comparing discrete categories side by side. This example displays four different metrics across multiple time periods.

$31,883 Revenue
$22,910 Expenses
$8,990 Marketing
$14,930 Operations
Charts Bar Chart
<!-- import Highcharts library -->
<script src="https://code.highcharts.com/highcharts.js"></script>
<script src="https://code.highcharts.com/modules/pattern-fill.js"></script>

<div class="view view--full">
  <div class="layout layout--col gap--space-between">
    <!-- Business metrics displayed above chart -->
    <div class="grid grid--cols-4">
      <div class="item">
        <div class="meta"></div>
        <div class="content">
          <div class="w--14 h--1.5 mb--2 bg--black" style="border-radius: 20px;"></div>
          <span class="value value--tnums">$31,883</span>
          <span class="label">Revenue</span>
        </div>
      </div>
      <div class="item">
        <div class="meta"></div>
        <div class="content">
          <div class="w--14 h--1.5 mb--2 bg--gray-3"></div>
          <span class="value value--tnums">$22,910</span>
          <span class="label">Expenses</span>
        </div>
      </div>
      <div class="item">
        <div class="meta"></div>
        <div class="content">
          <div class="w--14 h--1.5 mb--2 bg--gray-5"></div>
          <span class="value value--tnums">$8,990</span>
          <span class="label">Marketing</span>
        </div>
      </div>
      <div class="item">
        <div class="meta"></div>
        <div class="content">
          <div class="w--14 h--1.5 mb--2 bg--gray-7"></div>
          <span class="value value--tnums">$14,930</span>
          <span class="label">Operations</span>
        </div>
      </div>
    </div>

    <div class="border--h-5 w--full"></div>

    <!-- Chart container with unique ID -->
    <div id="example-bar-chart" class="w--full"></div>

    <script type="text/javascript">
      // Simplified regional data across four quarters
      var revenueData = [
        ["Jan", 5883],
        ["Feb", 5260],
        ["Mar", 4760],
        ["Apr", 5120],
        ["May", 5540],
        ["Jun", 6320]
      ];

      var expensesData = [
        ["Jan", 3580],
        ["Feb", 3210],
        ["Mar", 3620],
        ["Apr", 3950],
        ["May", 4120],
        ["Jun", 4430]
      ];

      var marketingData = [
        ["Jan", 1120],
        ["Feb", 980],
        ["Mar", 1320],
        ["Apr", 1650],
        ["May", 1820],
        ["Jun", 2100]
      ];

      var operationsData = [
        ["Jan", 2240],
        ["Feb", 2170],
        ["Mar", 2380],
        ["Apr", 2520],
        ["May", 2730],
        ["Jun", 2890]
      ];

      var formattedBarData = [
        { name: "Revenue", data: revenueData },
        { name: "Expenses", data: expensesData },
        { name: "Marketing", data: marketingData },
        { name: "Operations", data: operationsData }
      ];

      // Initialize chart with bar/column configuration for 4 series
      Highcharts.chart("example-bar-chart", {
        chart: {
          type: "column",
          height: 284,
          width: null,
          animation: false,
          spacing: [10, 10, 5, 10]
        },
        title: {
          text: null
        },
        plotOptions: {
          series: {
            animation: false,
            enableMouseTracking: false,
            states: {
              hover: { enabled: false }
            },
            pointPadding: 0.05,  // Reduced padding for more bars
            groupPadding: 0.1,
            borderWidth: 0
          }
        },
        // Define all four series with different styles
        series: [{
          data: formattedBarData[0].data,
          color: "#000000",
          name: formattedBarData[0].name,
          zIndex: 4  // Highest zIndex to keep this in front
        }, {
          data: formattedBarData[1].data,
          name: formattedBarData[1].name,
          zIndex: 3,
          color: {
            pattern: {
              image: "https://usetrmnl.com/images/grayscale/gray-3.png",
              width: 12,
              height: 12
            }
          }
        }, {
          data: formattedBarData[2].data,
          name: formattedBarData[2].name,
          zIndex: 2,
          color: {
            pattern: {
              image: "https://usetrmnl.com/images/grayscale/gray-5.png",
              width: 12,
              height: 12
            }
          }
        }, {
          data: formattedBarData[3].data,
          name: formattedBarData[3].name,
          zIndex: 1,
          color: {
            pattern: {
              image: "https://usetrmnl.com/images/grayscale/gray-7.png",
              width: 12,
              height: 12
            }
          }
        }],
        tooltip: { enabled: false },
        legend: { enabled: false },
        yAxis: {
          labels: {
            style: { fontSize: "16px", color: "#000000" }
          },
          gridLineDashStyle: "shortdot",
          gridLineWidth: 1,
          gridLineColor: "#000000",
          tickAmount: 5,
          title: {
            text: null
          }
        },
        xAxis: {
          type: "category",
          labels: {
            style: { fontSize: "16px", color: "#000000" },
            padding: 5,
            y: 25
          },
          lineWidth: 0,
          gridLineDashStyle: "dot",
          tickWidth: 0,
          tickLength: 0,
          gridLineWidth: 1,
          gridLineColor: "#000000",
          title: {
            text: null
          }
        },
        credits: {
          enabled: false
        }
      });
    </script>
  </div>
</div>

Gauge Chart

Gauge charts can effectively display single metrics or scores. This example shows multiple gauges in a row with a main summary gauge, perfect for displaying daily and weekly metrics like sleep quality scores.

Monday
Tuesday
Wednesday
Thursday
Friday
Saturday
Sunday
18% REM Sleep
23% Deep Sleep
12m Time to Sleep
7h 32min Sleep Duration
8 Toss & Turns
0.5% Snoring
Charts Gauge Chart
<!-- import Highcharts libraries -->
<script src="https://code.highcharts.com/highcharts.js"></script>
<script src="https://code.highcharts.com/highcharts-more.js"></script>
<script src="https://code.highcharts.com/modules/pattern-fill.js"></script>

<div class="view view--full">
  <div class="layout layout--col gap--none">
    <div class="grid grid--cols-7 mb--5">
      <div class="h--32">
        <div id="day_0" class="h--24"></div>
        <span class="description text--center">Monday</span>
      </div>
      <div class="h--32">
        <div id="day_1" class="h--24"></div>
        <span class="description text--center">Tuesday</span>
      </div>
      <div class="h--32">
        <div id="day_2" class="h--24"></div>
        <span class="description text--center">Wednesday</span>
      </div>
      <div class="h--32">
        <div id="day_3" class="h--24"></div>
        <span class="description text--center">Thursday</span>
      </div>
      <div class="h--32">
        <div id="day_4" class="h--24"></div>
        <span class="description text--center">Friday</span>
      </div>
      <div class="h--32">
        <div id="day_5" class="h--24"></div>
        <span class="description text--center">Saturday</span>
      </div>
      <div class="h--32">
        <div id="day_6" class="h--24"></div>
        <span class="description text--center">Sunday</span>
      </div>
    </div>

    <div class="w-full b-h-gray-5"></div>

    <div class="grid">
      <div class="col--span-1 col--center">
        <div id="day_all" class="w-[340px] mt--5"></div>
      </div>
      <div class="col--span-1 gap--large">
        <div class="flex flex--col gap--medium w--full flex--center">
          <div class="grid grid--cols-2">
            <div class="item">
            <div class="meta"></div>
            <div class="content">
                <span class="value value--tnums">18%</span>
                <span class="label">REM Sleep</span>
            </div>
          </div>
            <div class="item">
              <div class="meta"></div>
              <div class="content">
                <span class="value value--tnums">23%</span>
                <span class="label">Deep Sleep</span>
        </div>
      </div>
    </div>
          <div class="b-h-gray-5 w-full"></div>
          <div class="grid grid--cols-2">
            <div class="item">
              <div class="meta"></div>
              <div class="content">
                <span class="value value--small value--tnums">12m</span>
                <span class="label">Time to Sleep</span>
  </div>
          </div>
            <div class="item">
              <div class="meta"></div>
              <div class="content">
                <span class="value value--small value--tnums">7h 32min</span>
                <span class="label">Sleep Duration</span>
        </div>
          </div>
          </div>
          <div class="b-h-gray-5 w-full"></div>
          <div class="grid grid--cols-2">
            <div class="item">
                            <div class="meta"></div>
                            <div class="content">
                <span class="value value--small value--tnums">8</span>
                <span class="label">Toss & Turns</span>
                            </div>
                          </div>
            <div class="item">
              <div class="meta"></div>
              <div class="content">
                <span class="value value--small value--tnums">0.5%</span>
                <span class="label">Snoring</span>
                            </div>
                            </div>
                            </div>
                            </div>
                          </div>
                        </div>
                      </div>
                    </div>

                    <script type="text/javascript">
  var dailyScores = [92, 95, 81, 56, 81, 72, 85];
  var weeklyScore = 82;

  function createGauge(score, day, opts) {
    opts ||= {
      title: null,
      height: "80%",
      labels: {
        distance: 15,
        style: {
          fontSize: "16px"
        }
      },
      series: {
        fontSize: "3em"
      },
      yAxis: {
        title: textRating(score)
      }
    };

    Highcharts.chart(`day_${day}`, {
                        chart: {
        type: "gauge",
        height: opts.height
      },

                        title: {
        text: opts.title
      },

      pane: {
        startAngle: -150,
        endAngle: 150,
        background: {
          backgroundColor: "transparent",
          borderWidth: 0
        }
      },

                        plotOptions: {
        gauge: {
                            animation: false,
          pivot: {
            backgroundColor: "transparent"
          },
          dial: {
            backgroundColor: "transparent",
            baseWidth: 0,
          },
        }
      },

      yAxis: {
        min: 0,
        max: 100,
        minorTickInterval: 0,
        tickColor: "#ffffff",
        tickLength: 40,
        tickPixelInterval: 40,
        tickWidth: 0,
        lineWidth: 0,
        title: {
          text: opts.yAxis.title,
          style: {
            color: "#000000",
            fontFamily: "NicoPups",
            fontSize: "16px"
          }
        },
        labels: {
          ...opts.labels,
          style: {
            fontSize: "16px"
          }
        },
        plotBands: [{
          from: 1,
          to: score,
                          color: {
                            pattern: {
              image: "https://usetrmnl.com/images/grayscale/gray-2.png",
                              width: 12,
                              height: 12
                            }
          },
          innerRadius: "82%",
          borderRadius: "50%"
                        }, {
          from: score + 1,
          to: 100,
                          color: {
                            pattern: {
              image: "https://usetrmnl.com/images/grayscale/gray-5.png",
                              width: 12,
                              height: 12
            }
          },
          innerRadius: "82%",
          borderRadius: "50%",
        }]
      },

      series: [{
        name: "Score",
        data: [score],
        dataLabels: {
          borderWidth: 0,
          style: {
            fontSize: opts.series.fontSize,
            fontWeight: opts.series.fontWeight || "400",
            fontFamily: opts.series.fontFamily || "inherit"
                            }
                          }
                        }],

      credits: {
        enabled: false
      }
    });
  }

  function textRating(score) {
    if (score <= 50) {
      return "Low";
    } else if (score <= 65) {
      return "Pay Attention";
    } else if (score < 80) {
      return "Fair";
    } else {
      return "Good";
    }
  }

  // Create small daily gauges
  dailyScores.forEach((score, idx) => {
    let opts = {
      title: null,
      labels: { enabled: false },
      series: {
        fontSize: "16px",
        fontWeight: "400",
        fontFamily: "NicoClean"
      },
                        yAxis: {
        title: null
      }
    }
    createGauge(score, idx, opts);
  });

  // Create main weekly gauge
  createGauge(weeklyScore, "all", {
    title: null,
    height: "80%",
                          labels: {
      distance: 15
    },
    series: {
      fontSize: "3em",
      fontWeight: "550"
    },
    yAxis: {
      title: textRating(weeklyScore)
    }
  });
</script>