A market cap heatmap looks like a weekend project. Fetch the top coins, size each tile by market cap, color it by the 24 hour change, done. The layout algorithm is the famous part, and it is short: the squarified treemap from Bruls, Huizing and van Wijk fits in about forty lines of JavaScript. Its core is one function that scores how square a row of tiles would be:
function worst(row, width) {
const sum = row.reduce((s, r) => s + r.value, 0);
const max = Math.max(...row.map(r => r.value));
const min = Math.min(...row.map(r => r.value));
return Math.max((width ** 2 * max) / sum ** 2, sum ** 2 / (width ** 2 * min));
}
You keep adding tiles to the current row while that number goes down, and start a new row when it goes up. That part worked on the first try. Everything after it was about the data, and every decision came from the numbers below, taken on 8 October 2026 from the top 80 coins by market cap.
One coin is most of the map
Bitcoin was 60.6% of the combined market cap of those 80 coins. Once stablecoins are removed (more on that below) it was 67.4%. So two thirds of your canvas is one tile, and the other 68 coins share the remaining third.
There are two honest ways to handle it. The first is a toggle that removes Bitcoin, so the rest of the market becomes readable. The second is to cap the largest tile, say at half the width, and lay out the rest in the remaining space. The second one breaks the rule that area equals value, so if you do it, say so on the page. A heatmap is read by eye, and people will compare areas.
Stablecoins are a tenth of the map and never change color
Eleven stablecoins were in that top 80, and together they were 10.1% of its market cap. Tether alone was 6.7%, bigger than every coin except Bitcoin and Ethereum, and its 24 hour change was minus 0.04%. On a heatmap that is a large pale rectangle that tells you nothing. Exclude them by default.
How you detect them matters more than I expected. A hand written list of tickers goes stale: Ondo's USDY was in the top 80 that day, trading at 1.15 dollars because it accrues yield, so a list from last year misses it and so does a "price close to one dollar" rule. The price rule also misses EURC, which is pegged to the euro. And two tokens that are not stablecoins at all behaved exactly like them: the gold tokens XAUT and PAXG moved 0.03% and minus 0.04%. What worked best for me was a list for the known ones, plus a volatility check that flags anything whose 24 hour change stays under a tenth of a percent for several days, for a human to review.
The long tail is invisible
After Bitcoin, the long tail gets very thin. The 40 smallest of the remaining 69 coins added up to 1.9% of the total. In my test layout at 1200 by 700 pixels, about forty tiles had a side shorter than 20 pixels, which is too small for a ticker. On a 390 pixel wide phone screen almost nothing outside the top ten could carry a label.
You can fight this with a minimum tile size, but that is the same lie as capping Bitcoin, in the other direction. I found it more honest to show fewer coins on small screens, or to group the tail into a single "others" tile with its own weighted change.
Color is a decision about zero
A continuous red to green scale sounds precise, but most of the market moves a fraction of a percent on a quiet day, so everything ends up the same muddy shade. Discrete buckets read better. Symmetric thresholds at 0.5%, 2% and 5% give four shades each side, and each shade needs its own text color, because white text on a light green tile fails contrast.
Then decide what zero means. Is a coin at plus 0.01% "up"? If your header counts gainers and losers, a dead zone of plus or minus 0.1% keeps flat coins out of both. That day it gave 19 gainers, 46 losers and 4 coins that had not really moved.
function bucket(changePct) {
const steps = [5, 2, 0.5, 0];
const i = steps.findIndex(s => Math.abs(changePct) >= s);
return { up: changePct >= 0, level: steps.length - i };
}
A working example
The one I ended up comparing against most is this cryptocurrency heatmap, which makes two of the choices above visible: stablecoins are off by default, and there is a switch to drop Bitcoin so the rest of the market fills the screen. Toggle Bitcoin off and on once and you will see why the first section of this post exists.
The treemap took an evening. Deciding what to leave off it took the rest of the week.
Top comments (0)