Built with blockbuilder.org
<!DOCTYPE html>
<head>
<meta charset="utf-8">
<script src="https://d3js.org/d3.v4.min.js"></script>
<style>
body {
margin:0
}
</style>
</head>
<body>
<script>
const width = 960;
const height = 1000;
const leftEdge = 25;
const minN = 2;
const maxN = 40;
const svg = d3.select('body').append('svg')
.attr('width', width)
.attr('height', height)
.attr('shape-rendering', 'crispEdges')
const colors = [
'#CCE3F2',
'#99C7E4',
'#66AAD7',
'#338EC9',
'#0072BC',
'#00568D',
'#18375F'
];
const scale = d3.scaleLinear()
.domain(d3.range(colors.length).map(d => d / (colors.length - 1)))
.range(colors);
const xScale = d3.scaleBand()
.range([leftEdge, width]);
const yScale = d3.scaleBand()
.domain(d3.range(minN, maxN + 1))
.range([0, height]);
const data = [];
yScale.domain().forEach(y => {
xScale.domain(d3.range(y));
xScale.domain().forEach(x => {
data.push({
x: xScale(x),
y: yScale(y),
width: Math.ceil(xScale.bandwidth()),
color: scale(x / (y - 1))
});
});
});
svg.selectAll('rect').data(data)
.enter().append('rect')
.attr('x', d => d.x)
.attr('y', d => d.y)
.attr('width', d => d.width)
.attr('height', yScale.bandwidth())
.attr('fill', d => d.color);
svg.selectAll('text').data(yScale.domain())
.enter().append('text')
.attr('x', leftEdge - 4)
.attr('y', yScale)
.attr('dy', '1.2em')
.attr('fill-opacity', 0.26)
.style('font-family', 'sans-serif')
.style('text-anchor', 'end')
.text(d => d);
</script>
</body>