<!-- https://css-tricks.com/how-to-create-an-animated-chart-of-nested-squares-using-masks/ -->
html,
body {
    height: 100%;
}

body {
    background: #f0f0f0;
    display: grid;
    place-items: center;
    padding: 16px;
}

svg {
    display: block;
    overflow: visible;
    max-width: 100%;
    height: auto;
}

rect {
    transition: all 0.2s linear;
}

svg:hover > rect {
    opacity: 0.4;
    transform: translate(8px, -8px);
}

svg:hover > rect:hover {
    opacity: 1;
    transform: translate(0);
}

svg:hover > rect:hover ~ rect {
    transform: translate(-8px, 8px);
}
type DataSetEntry = {
    label: string;
    value: number;
};

type DataSet = DataSetEntry[];

const remapValue = (
    value: number,
    fromMin: number,
    fromMax: number,
    toMin: number,
    toMax: number
): number => {
    return toMin + ((value - fromMin) / (fromMax - fromMin)) * (toMax - toMin);
};

const valueRemapper = (
    fromMin: number,
    fromMax: number,
    toMin: number,
    toMax: number
) => {
    return (value: number): number => {
        return remapValue(value, fromMin, fromMax, toMin, toMax);
    };
};

const createSvgNSElement = (element: string): SVGElement => {
    return document.createElementNS("http://www.w3.org/2000/svg", element);
};

const createRect = (
    dimension: number,
    x: number,
    y: number,
    fill: string
): SVGRectElement => {
    const rect: SVGRectElement = createSvgNSElement("rect") as SVGRectElement;

    rect.setAttribute("width", `${dimension}`);
    rect.setAttribute("height", `${dimension}`);
    rect.setAttribute("x", `${x}`);
    rect.setAttribute("y", `${y}`);
    rect.setAttribute("fill", fill);

    return rect;
};

const maskIdForDimension = (dimension: number): string => {
    const fixedDimension = dimension.toFixed();

    return `maskW${fixedDimension}`;
};

const svgDimension: number = 320;

const colors: string[] = [
    "#264653",
    "#2A9D8F",
    "#E76F51",
    "#F4A261",
    "#E9C46A"
];

const fallbackColor: string = "#DDDDDD";

const rawDataSet: DataSet = [
    { label: "Bad", value: 1231 },
    { label: "Beginning", value: 6321 },
    { label: "Developing", value: 10028 },
    { label: "Accomplished", value: 12123 },
    { label: "Exemplary", value: 2120 }
];

const dataSetHighestValue: number = Math.max(
    ...rawDataSet.map((entry: DataSetEntry) => entry.value)
);

const remapDataSetValueToSvgDimension = valueRemapper(
    0,
    dataSetHighestValue,
    0,
    svgDimension
);

const data: DataSet = rawDataSet.sort(
    (a: DataSetEntry, b: DataSetEntry) => b.value - a.value
);

const svg: SVGSVGElement = createSvgNSElement("svg") as SVGSVGElement;

svg.setAttribute("viewBox", `0 0 ${svgDimension} ${svgDimension}`);
svg.setAttribute("width", `${svgDimension}`);
svg.setAttribute("height", `${svgDimension}`);

data.forEach((d: DataSetEntry, index: number) => {
    const mask: SVGMaskElement = createSvgNSElement("mask") as SVGMaskElement;

    const rectDimension: number = remapDataSetValueToSvgDimension(d.value);
    const rect = createRect(
        rectDimension,
        0,
        svgDimension - rectDimension,
        "white"
    );

    mask.setAttribute("id", maskIdForDimension(rectDimension));

    mask.appendChild(rect);

    const smallerRectIndex = index + 1;

    if (data[smallerRectIndex] !== undefined) {
        const smallerRectDimension: number = remapDataSetValueToSvgDimension(
            data[smallerRectIndex].value
        );
        const smallerRect = createRect(
            smallerRectDimension,
            0,
            svgDimension - smallerRectDimension,
            "black"
        );

        mask.appendChild(smallerRect);
    }

    svg.appendChild(mask);
});

data.forEach((d: DataSetEntry, index: number) => {
    const rectDimension: number = remapDataSetValueToSvgDimension(d.value);
    const rect = createRect(
        rectDimension,
        0,
        svgDimension - rectDimension,
        colors[index] ?? fallbackColor
    );

    rect.setAttribute("mask", `url(#${maskIdForDimension(rectDimension)})`);

    svg.appendChild(rect);
});

document.body.appendChild(svg);
View Compiled

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.