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