Are you tired of static, non-flexible tables that refuse to adapt to your needs? In this tutorial, we'll explore how to transform a standard HTML table into a dynamic and user-friendly powerhouse using a combination of HTML, CSS, and JavaScript.
The Setup
Let's begin with the HTML structure. We have a simple table containing some data about individuals:
<div class="container mt-3">
  <table id="resizeMe" class="resizable-table table table-hover">
    <thead>
       <tr id="header-row">
        <th class="draggable-table" data-column="0">No.</th>
        <th class="draggable-table" data-column="1">First name</th>
        <th class="draggable-table" data-column="2">Last name</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <td>1</td>
        <td>Andrea</td>
        <td>Ross</td>
      </tr>
      <tr>
        <td>2</td>
        <td>Penelope</td>
        <td>Mills</td>
      </tr>
      <tr>
        <td>3</td>
        <td>Sarah</td>
        <td>Grant</td>
      </tr>
      <tr>
        <td>4</td>
        <td>Vanessa</td>
        <td>Roberts</td>
      </tr>
      <tr>
        <td>5</td>
        <td>Oliver</td>
        <td>Alsop</td>
      </tr>
      <tr>
        <td>6</td>
        <td>Jennifer</td>
        <td>Forsyth</td>
      </tr>
      <tr>
        <td>7</td>
        <td>Michelle</td>
        <td>King</td>
      </tr>
      <tr>
        <td>8</td>
        <td>Steven</td>
        <td>Kelly</td>
      </tr>
      <tr>
        <td>9</td>
        <td>Julian</td>
        <td>Ferguson</td>
      </tr>
      <tr>
        <td>10</td>
        <td>Chloe</td>
        <td>Ince</td>
      </tr>
    </tbody>
  </table>
</div>
And the accompanying CSS to style our table:
.table {
  border-collapse: collapse;
  width: 100%;
}
.table,
.table th,
.table td {
  border: 1px solid #ccc;
}
.table th,
.table td {
  padding: 0.5rem;
}
.table th {
  position: relative;
   cursor: grab;
      user-select: none;
}   
   .table th:active {
      cursor: grabbing;
    }
.resizer {
  position: absolute;
  top: 0;
  right: 0;
  width: 5px;
  cursor: col-resize;
  user-select: none;
}
.resizer:hover,
.resizing {
  border-right: 2px solid blue;
}
.dragging {
  background-color: #f0f0f0;
}
The Magic of JavaScript
Now, the real magic happens when we inject JavaScript into the mix. We're using two different approaches here: one with the fantastic interact.js library for dragging and resizing columns and another using a custom implementation.
document.addEventListener('DOMContentLoaded', function () {
  const makeTableResizableAndSortable = function (table) {
    const tableBody = table.querySelector('tbody');
    // Make rows sortable
    const rowsSortable = new Sortable(tableBody, {
      animation: 150,
    });
    // Make columns and table header cells draggable using interact.js
    const headers = table.querySelectorAll('th');
    interact(headers).draggable({
      // Enable both left and right edges for dragging
      edges: { left: true, right: true, bottom: false, top: false },
      listeners: {
        start(event) {
          const target = event.target;
          target.classList.add('dragging');
        },
        move(event) {
          const target = event.target;
          const dx = event.dx;
          target.style.transform = `translate(${dx}px)`;
        },
        end(event) {
          const target = event.target;
          target.style.transform = '';
          target.classList.remove('dragging');
        },
      },
    }).resizable({
      // Enable right edge for resizing
      edges: { right: true },
      restrictEdges: {
        outer: 'parent',
      },
      restrictSize: {
        min: { width: 50 },
      },
      listeners: {
        move(event) {
          const target = event.target;
          const width = parseFloat(target.style.width) || 0;
          target.style.width = width + event.dx + 'px';
        },
      },
    });
  };
  const tables = document.querySelectorAll('.resizable-table');
  tables.forEach(function (table) {
    makeTableResizableAndSortable(table);
  });
});
document.addEventListener('DOMContentLoaded', function () {
const createResizableTable = function (table) {
const cols = table.querySelectorAll('th');
[].forEach.call(cols, function (col) {
// Add a resizer element to the column
const resizer = document.createElement('div');
resizer.classList.add('resizer');
// Set the height
resizer.style.height = `${table.offsetHeight}px`;
col.appendChild(resizer);
createResizableColumn(col, resizer);
});
};
const createResizableColumn = function (col, resizer) {
let x = 0;
let w = 0;
const mouseDownHandler = function (e) {
x = e.clientX;
const styles = window.getComputedStyle(col);
w = parseInt(styles.width, 10);
document.addEventListener('mousemove', mouseMoveHandler);
document.addEventListener('mouseup', mouseUpHandler);
resizer.classList.add('resizing');
};
const mouseMoveHandler = function (e) {
const dx = e.clientX - x;
col.style.width = `${w + dx}px`;
};
const mouseUpHandler = function () {
resizer.classList.remove('resizing');
document.removeEventListener('mousemove', mouseMoveHandler);
document.removeEventListener('mouseup', mouseUpHandler);
};
resizer.addEventListener('mousedown', mouseDownHandler);
};
createResizableTable(document.getElementById('resizeMe'));
});
How It Works
- Sorting Rows 
 The rows become sortable with the help of the Sortable library, allowing you to effortlessly rearrange your data.
- Dragging Columns 
 Thanks to interact.js, column headers become draggable. A simple visual transformation occurs while dragging, making the experience intuitive.
- Resizing Columns 
 Resizing columns is made easy by placing a resizer at the right edge of each column. A smooth resizing effect is achieved with the interact.js library.
Wrapping Up
And there you have it! A brief yet powerful guide on creating a resizable and sortable HTML table. Whether you prefer the simplicity of interact.js or a custom implementation, the end result is a table that bends to your will.
 
 
              
 
    
Top comments (0)