resizable table

by Richard Hunter

HTML

<div id="table" class="table">
  <div class="header row">
    <div class="cell">
      property
      <div id="handler" class="handler"></div>
    </div>
    <div class="cell">
      value
    </div>
  </div>
  <div class="row">
    <div class="cell">
      foo
    </div>
    <div class="cell">
      bar
    </div>
  </div>
    <div class="row">
    <div class="cell">
      foo sfsf sjfs fsfjskfj sfjskfjsk fskjfsk jfks fjskjfksjfsk fjskfj skfjskfjsk fjskfjskfj skjfsf
    </div>
    <div class="cell">
      bar
    </div>
  </div>
    <div class="row">
    <div class="cell">
      foo
    </div>
    <div class="cell">
      bar
    </div>
  </div>
    <div class="row">
    <div class="cell">
      foo
    </div>
    <div class="cell">
      bar
    </div>
  </div>
    <div class="row">
    <div class="cell">
      foo
    </div>
    <div class="cell">
      bar
    </div>
  </div>

  <div class="row">
    <div class="cell">
      foo
    </div>
    <div class="cell">
      bar
    </div>
  </div>


</div>

CSS

html {
  box-sizing: border-box;
}

*,
*:before,
*:after {
  box-sizing: inherit;
}

.table {
  background: pink;
  --colWidth: 200px;
  display: grid;
  grid-auto-rows: 20px;
  gap: 2px;
  padding: 2px;
}

.row {
  display: grid;
  
  grid-template-columns: var(--colWidth) 1fr;
  gap: 2px;
}

.cell {
  background: white;
  padding: 0 10px;  
  white-space: nowrap;
  overflow-x: scroll;
}

.dropdown {
  border-radius: 0;
  border: 0;
  outline: none;
  width: 100%;
  height: 100%;
  background: orange;
}

.input {
  border: 0;
  height: 100%;
  width: 100%;
  outline: none;
  background: transparent;
}

.inner {
  height: 100%;
}

.focus {
  box-shadow: 0 0 0 2px grey;
}

.header .cell {
  position: relative;
  background: darkblue;
  
  color: white;
  font-family: arial;
}

.handler {
  opacity: 0;
  background: navajowhite;
  z-index: 3;
  width: 4px;
  position: absolute;
  left: 100%;
  transform: translateX(-1px);
  top: 0;
  bottom: 0;
  cursor: ew-resize;

  
}

.handler:hover {
  opacity: 1;
}

JavaScript

const handlerEl = document.getElementById('handler');

let prevX = -1;
let colWidth = 200;
let maxWidth = 500;
const table = document.querySelector('#table');

function adjustColumns(diff) {
  colWidth = Math.min(maxWidth, Math.max(50, colWidth + diff));

  table.style.setProperty('--colWidth',colWidth + 'px');
  console.log(colWidth);
}

adjustColumns(0);

function mousemove(event) {
  event.preventDefault();
  const currentX = event.clientX;
  const diff = currentX - prevX;
  prevX = currentX;
  adjustColumns(diff);
}

function mouseup() {
  window.removeEventListener('mousemove', mousemove);
  prevX = -1;
}

function mousedown(event) {
  event.preventDefault();
  prevX = event.clientX;

  window.addEventListener('mousemove', mousemove);
  window.addEventListener('mouseup', mouseup, {
    once: true
  });
}

handlerEl.addEventListener('mousedown', mousedown);