Skip to main content

Repeating waffle charts

The code for this example can be used in the Markdown visualization to create a series of percentage-filled waffle charts, one for each row in your results. Squares will automatically adjust size and wrap to the next line.

Setup

These charts use the Mustache iterator syntax to draw a shape for each row in the results. Your query should have a dimension that determines the number of pies and their labels and the values for the numerator and denominator to calculate the percentage fill. Then you'll need to add a lot calculations. The following table explains each field used in the example, including the calculation formulas.

This chart is a bit crazy. We're not actually drawing 100 tiny squares for each waffle shape, but instead filling 10 bars per waffle and drawing some dividers on top of them to simulate a waffle.

ColNameDescription or formulaPurpose
ACategoryquery fielddetermines number of waffles to make and their labels
BProducts Countquery fielddenominator for % calculation
CProducts over $50query fieldnumerator for % calculation
D% over $50 (calc_1)=C1 / B1calculation for filling waffle squares, label
E1s (calc_5)=IF(D1 >= 10, 100, 10 * D1)how far to fill the 1s bar
F10s (calc_6)=IF(D1 >= 20, 100, MAX(0, (D1 - 10)) * 10)how far to fill the 10s bar
G20s (calc_7)=IF(D1 >= 30, 100, MAX(0, (D1 - 20)) * 10)how far to fill the 20s bar
H30s (calc_8)=IF(D1 >= 40, 100, MAX(0, (D1 - 30)) * 10)how far to fill the 30s bar
I40s (calc_9)=IF(D1 >= 50, 100, MAX(0, (D1 - 40)) * 10)how far to fill the 40s bar
J50s (calc_10)=IF(D1 >= 60, 100, MAX(0, (D1 - 50)) * 10)how far to fill the 50s bar
K60s (calc_11)=IF(D1 >= 70, 100, MAX(0, (D1 - 60)) * 10)how far to fill the 60s bar
L70s (calc_12)=IF(D1 >= 80, 100, MAX(0, (D1 - 70)) * 10)how far to fill the 70s bar
M80s (calc_13)=IF(D1 >= 90, 100, MAX(0, (D1 - 80)) * 10)how far to fill the 80s bar
N90s (calc_14)=IF(D1 >= 100, 100, MAX(0, (D1 - 90)) * 10)how far to fill the 90s bar

Example code

<style>
h3 {
margin-top: 0;
}
.percent-fill-boxes {
& ul {
list-style: none;
margin: 0;
padding: 0;
display: grid;
grid-template-columns: repeat(auto-fit, minmax(100px, 1fr));
gap: var(--size4);
}
& li {
list-style: none;
margin: 0;
padding: 0;
}
& p {
list-style: none;
margin: 0;
padding: 0;
}
& .big-box {
--grid-background-color: var(--color-background);
width: 100%;
aspect-ratio: 1 / 1;
position: relative;
display: grid;
grid-template-rows: repeat(10, 1fr);
gap: 2%;
}
& .big-box p {
background-color: var(--color-border2);
width: 100%;
position: relative;

& .row-fill {
background-color: var(--color-info);
display: block;
height: 100%;
}
& .row-dividers {
position: absolute;
width: 100%;
height: 100%;
top: 0;
left: 0;
background-image: linear-gradient(
90deg,
var(--grid-background-color) 0%,
var(--grid-background-color) 1%,
transparent 1%,
transparent 9%,
var(--grid-background-color) 9%,
var(--grid-background-color) 11%,
transparent 11%,
transparent 19%,
var(--grid-background-color) 19%,
var(--grid-background-color) 21%,
transparent 21%,
transparent 29%,
var(--grid-background-color) 29%,
var(--grid-background-color) 31%,
transparent 31%,
transparent 39%,
var(--grid-background-color) 39%,
var(--grid-background-color) 41%,
transparent 41%,
transparent 49%,
var(--grid-background-color) 49%,
var(--grid-background-color) 51%,
transparent 51%,
transparent 59%,
var(--grid-background-color) 59%,
var(--grid-background-color) 61%,
transparent 61%,
transparent 69%,
var(--grid-background-color) 69%,
var(--grid-background-color) 71%,
transparent 71%,
transparent 79%,
var(--grid-background-color) 79%,
var(--grid-background-color) 81%,
transparent 81%,
transparent 89%,
var(--grid-background-color) 89%,
var(--grid-background-color) 91%,
transparent 91%,
transparent 99%,
var(--grid-background-color) 99%,
var(--grid-background-color) 100%
);
}
}
& p.label {
text-align: left;
}
}
</style>

<article class="percent-fill-boxes">
<h3>% of products over $50</h3>
<ul>
{{#result}}
<li>
<div class="big-box"">
<p class="d9"><span class="row-fill" style="width: {{calc_14.value}}%"></span><span class="row-dividers"></span></p>
<p class="d8"><span class="row-fill" style="width: {{calc_13.value}}%"></span><span class="row-dividers"></span></p>
<p class="d7"><span class="row-fill" style="width: {{calc_12.value}}%"></span><span class="row-dividers"></span></p>
<p class="d6"><span class="row-fill" style="width: {{calc_11.value}}%"></span><span class="row-dividers"></span></p>
<p class="d5"><span class="row-fill" style="width: {{calc_10.value}}%"></span><span class="row-dividers"></span></p>
<p class="d4"><span class="row-fill" style="width: {{calc_9.value}}%"></span><span class="row-dividers"></span></p>
<p class="d3"><span class="row-fill" style="width: {{calc_8.value}}%"></span><span class="row-dividers"></span></p>
<p class="d2"><span class="row-fill" style="width: {{calc_7.value}}%"></span><span class="row-dividers"></span></p>
<p class="d1"><span class="row-fill" style="width: {{calc_6.value}}%"></span><span class="row-dividers"></span></p>
<p class="d0"><span class="row-fill" style="width: {{calc_5.value}}%"></span><span class="row-dividers"></span></p>
</div>
<p class="label">
<span>{{products.category.value}}&nbsp;&nbsp;{{calc_1.value}}%</span>
</p>
</li>
{{/result}}

</ul>
</article>