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. Just 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>

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>