pivot table gird with sticky head label

by Maxim_Wolf

HTML

<div class='container'>

  <div class="column-headers">
    headers
  </div>
  <div class="row-labels">
    labels
  </div>
  <div class="data">
    data
  </div>  
  <div class="blank">
  </div>
</div>

CSS

* {
  box-sizing: border-box;
}

html,
body {
  height: 100%;
  margin: 0;
}
.table__row {
    transition: background-color 0.3s ease;
}
.table__row:hover{
   background-color:rgba(111, 138, 231, 0.5);
}
.container {
  display: grid;
  grid-template-columns: 10em 1fr;
  grid-template-rows: 2em 1fr;
  gap: 0.1em 0.1em;
  grid-auto-flow: row;
  justify-content: start;
  align-content: start;
  justify-items: start;
  align-items: start;
  grid-template-areas:
    "b h"
    "l d";
}

.container {
  background: linear-gradient(45deg, rgba(255, 255, 0, 1) 0%, rgba(255, 255, 255, 0.5) 100%);
  margin: 0.2em;
  width:min-content;
}

.blank {
  display: inline-block;
  width: 10em;
  height: 2em;
  background: magenta;
  position: sticky;
  left: 0;
  top: 0;
  /*z-index: 1;*/
}

.column-headers {
  display: inline-block;
  grid-area: h;
  height: 2em;
  position: sticky;
  top: 0;
  background: linear-gradient(90deg, rgba(0, 255, 255, 1) 0%, rgba(255, 255, 255, 0.5) 100%);
}

.row-labels {
  grid-area: l;
  position: sticky;
  background: rgb(127, 208, 255);
  background: linear-gradient(180deg, rgba(127, 208, 255, 1) 0%, rgba(255, 255, 255, 0.5) 100%);
  left: 0;
  width: 10em;
}

.data {
  grid-area: d;
  background: rgb(255, 127, 147);
  background: linear-gradient(45deg, rgba(255, 127, 147, 1) 0%, rgba(255, 255, 255, 0.5) 100%);
}

JavaScript

const COLUMN_COUNT = 20;
const ROW_COUNT = 37;
const MIN_WIDTH = 2.5;
const MAX_WIDTH = 20;
const columns = Array.from({
  length: COLUMN_COUNT
}).map((_, ix) => {
  const columnName = `Column ${ix}`;
  return {
    label: columnName,
    format: (r) => r[columnName],
    width: MIN_WIDTH + Math.floor(Math.random() * (MAX_WIDTH - MIN_WIDTH)),
  }
});

const data = Array.from({
  length: ROW_COUNT
}).map((_, r) => {
  return columns.reduce((a, b) => ({
    ...a,
    [b.label]: `Row: ${r}, ${b.label}`
  }), {});
})

const createElement = (tag, props = {}, children = []) => {
  const rv =
    Object.keys(props).filter((key) => key !== 'style').reduce((a, b) => {
      a[b] = props[b]
      return a;
    }, document.createElement(tag));
  const style = props.style;
  if (typeof style === 'object' && style !== null) {
    Object.keys(style).forEach((s) => rv.style[s] = style[s]);
  }
  return children.reduce((a, c) => {
    a.append(c);
    return a;
  }, rv)
}

const render = (container, content) => {
  container.innerHTML = '';
  container.append(content)
}

const cellContent = (r, column) => {
  return createElement('div', {
      style: {
        'width': `${column.width}em`,
        overflowX: 'hidden',
        whiteSpace: 'nowrap',
        textOverflow: 'ellipsis'
      },
    },
    [column.format(r)],
  )
}

const cell = (r, column) => {
  return createElement('td', {
      'style': {},
      title: column.format(r),
    },
    [cellContent(r, column)],
  );
}

const row = (r, columns) => {
  return createElement('tr', {className:'table__row'}, columns.map((column) => cell(r, column)));
}

const tbody = (data, columns) => {
  return createElement('tbody', {}, data.map((r) => row(r, columns)));
}
const table = (children) => {
  return createElement('table', {
    style: {
      width: '100%'
    }
  }, children)
}
const df = document.createDocumentFragment();

const headRow = (columns) => {
  return createElement('tr', {}, columns.map((column) => cell({}, {
   ...