LOGO OA教程 ERP教程 模切知识交流 PMS教程 CRM教程 开发文档 其他文档  
 
网站管理员

使用 HTML + JavaScript 实现可调整列宽的表格(附完整代码)

admin
2025年12月17日 15:38 本文热度 1149
在现代 Web 应用中,表格是一种常见的数据展示方式。然而,默认的表格列宽往往不能满足用户的实际需求。本文将介绍如何使用 HTML、CSS 和 JavaScript 实现一个支持列宽调整的交互式表格,让用户能够根据自己的需要自由调整每一列的宽度。

效果演示

这个可调整列宽的表格具有直观的操作体验。当鼠标悬停在表头(th)上时,会在右侧显示出一个可拖动的调整手柄。用户只需按下鼠标左键并向左右拖动,就能实时改变对应列的宽度。这种交互方式使得表格更加灵活易用,特别适用于需要查看长文本内容或者希望优化空间利用的场景。

页面结构

页面通过 .wrap 区域实现了横向滚动条的支持,防止表格溢出屏幕。使用 table-layout: fixed 来固定表格布局,使我们可以控制每列的具体宽度。在每个 th 元素的右边添加了一个伪元素 ::after 作为调整手柄,只有当鼠标悬停时才可见。
<div class="wrap">  <table class="resizable-table" id="resizableTable">    <thead>    <tr>      <th style="width: 80px">姓名</th>      <th>年龄</th>      <th>城市</th>      <th style="width: 150px">邮箱</th>      <th>电话</th>    </tr>    </thead>    <tbody>    <tr>      <td>张三</td>      <td>25</td>      <td>北京</td>      <td>zhangsan@example.com</td>      <td>13800138000</td>    </tr>    <!-- 其他表格内容 -->    </tbody>  </table></div>

核心功能实现

初始化列宽

页面加载完成后会执行 initColumnWidths() 函数来初始化各列的宽度。该函数首先获取表格总宽度,然后遍历所有表头单元格。如果某列已经设置了具体宽度,则将其记录下来;对于没有指定宽度的列,则平均分配剩余的空间;最后调用 updateTableWidth() 应用这些初始宽度值。
function initColumnWidths() {  tableWidth = table.offsetWidth;  var remainingWidth = tableWidth - 1;  var unsetColumns = [];  // 第一步:处理已设置宽度的列  headers.forEach((th, index) => {    if (th.style.width) {      var width = parseInt(th.style.width);      columnWidths[index] = Math.max(50, width);      remainingWidth -= columnWidths[index];    } else {      unsetColumns.push(index);    }  });  // 第二步:为未设置宽度的列均分剩余空间  if (unsetColumns.length > 0) {    var avgWidth = Math.max(50, remainingWidth / unsetColumns.length);    unsetColumns.forEach(index => {      columnWidths[index] = avgWidth;    });  }  updateTableWidth();}

鼠标事件处理

为了响应用户的拖拽行为,我们对每个 th 元素绑定了 mousedown 事件监听器。当检测到点击发生在靠近右边缘的位置时(即调整区域内),就会启动拖拽流程。
headers.forEach((th, index) => {  th.addEventListener('mousedown'function (e) {    // 检查是否点击在调整区域    var rect = th.getBoundingClientRect();    if (e.clientX < rect.right - 6return;    e.preventDefault();    currentResizer = th;    startX = e.clientX;    columnIndex = index;    // 获取当前列的宽度    startWidth = th.offsetWidth;    // 添加活动状态样式    th.style.opacity = '1';    // 添加事件监听器    document.addEventListener('mousemove', handleMouseMove);    document.addEventListener('mouseup', handleMouseUp);  });});

动态更新表格尺寸

每当列宽发生变化时,都会触发 updateTableWidth() 方法重新计算并应用最新的尺寸信息。
function updateTableWidth() {  // 计算表格总宽度  var totalWidth = columnWidths.reduce((sum, width) => sum + width, 0);  // 更新表格宽度  table.style.width = totalWidth + 'px';  // 更新每列的宽度  var headers = table.querySelectorAll('th');  headers.forEach((th, index) => {    th.style.width = columnWidths[index] + 'px';  });  // 同步tbody中的td宽度  var rows = table.querySelectorAll('tbody tr');  rows.forEach(row => {    var cells = row.querySelectorAll('td');    cells.forEach((td, index) => {      td.style.width = columnWidths[index] + 'px';    });  });}

扩展建议

  • 持久化配置:增加 localStorage 支持,记住用户自定义的列宽设置,下次访问时自动恢复

  • 键盘快捷键支持:允许用户通过 Ctrl + 左/右箭头快速微调选定列的宽度

  • 列顺序调整:允许用户通过拖拽改变列的顺序

  • 列显隐控制:提供选项让用户选择显示或隐藏某些列

完整代码

git地址:https://gitee.com/ironpro/hjdemo/blob/master/table-resizable/index.html
<!DOCTYPE html><html lang="zh-CN"><head>  <meta charset="utf-8">  <meta name="viewport" content="width=device-width, initial-scale=1.0">  <title>可调整列宽的表格</title>  <style>      * {          margin0;          padding0;          box-sizing: border-box;      }      body {          background#f5f5f5;          min-height100vh;          padding20px;      }      .container {          max-width600px;          margin0 auto;          background: white;          border-radius15px;          box-shadow0 20px 40px rgba(0,0,0,0.1);          overflow: hidden;      }      .header {          background#007bff;          color: white;          padding20px;          text-align: center;      }      .header h1 {          font-size24px;          font-weight500;      }      .main {          padding30px;          min-height300px;      }      .wrap {          overflow-x: auto;          width100%;          min-width0;      }      table {          table-layout: fixed;          border-collapse: collapse;          width100%;      }      thtd {          border1px solid #999;          padding6px 8px;      }      th {          position: relative;      }      th::after {          content'';          position: absolute;          top0;          right0;          width5px;          height100%;          cursor: col-resize;          background-color#999;          opacity0;          transition: opacity 0.2s ease;      }      th:hover::after {          opacity1;      }      thtd {          border1px solid #999;          padding6px 8px;          white-space: nowrap;          overflow: hidden;          text-overflow: ellipsis;          box-sizing: border-box;      }  </style></head><body><div class="container">  <div class="header">    <h1>可调整列宽的表格</h1>  </div>  <div class="main">    <div class="wrap">      <table class="resizable-table" id="resizableTable">        <thead>        <tr>          <th style="width: 80px">姓名</th>          <th>年龄</th>          <th>城市</th>          <th style="width: 150px">邮箱</th>          <th>电话</th>        </tr>        </thead>        <tbody>        <tr>          <td>张三</td>          <td>25</td>          <td>北京</td>          <td>zhangsan@example.com</td>          <td>13800138000</td>        </tr>        <tr>          <td>李四</td>          <td>30</td>          <td>上海</td>          <td>lisi@example.com</td>          <td>13900139000</td>        </tr>        <tr>          <td>王五</td>          <td>28</td>          <td>广州</td>          <td>wangwu@example.com</td>          <td>13700137000</td>        </tr>        </tbody>      </table>    </div>  </div></div>
<script>  var table = document.getElementById('resizableTable');  var headers = table.querySelectorAll('thead th');  var columnCount = headers.length;  var columnWidths = new Array(columnCount);
  var currentResizer = null;  var startX = 0;  var startWidth = 0;  var columnIndex = -1;  var tableWidth = 0;
  function initColumnWidths() {    tableWidth = table.offsetWidth;    var remainingWidth = tableWidth - 1;    var unsetColumns = [];    // 第一步:处理已设置宽度的列    headers.forEach((th, index) => {      if (th.style.width) {        var width = parseInt(th.style.width);        columnWidths[index] = Math.max(50, width);        remainingWidth -= columnWidths[index];      } else {        unsetColumns.push(index);      }    });    // 第二步:为未设置宽度的列均分剩余空间    if (unsetColumns.length > 0) {      var avgWidth = Math.max(50, remainingWidth / unsetColumns.length);      unsetColumns.forEach(index => {        columnWidths[index] = avgWidth;      });    }    updateTableWidth();  }
  headers.forEach((th, index) => {    th.addEventListener('mousedown'function (e) {      // 检查是否点击在调整区域      var rect = th.getBoundingClientRect();      if (e.clientX < rect.right - 6return;      e.preventDefault();      currentResizer = th;      startX = e.clientX;      columnIndex = index;      // 获取当前列的宽度      startWidth = th.offsetWidth;      // 添加活动状态样式      th.style.opacity = '1';      // 添加事件监听器      document.addEventListener('mousemove', handleMouseMove);      document.addEventListener('mouseup', handleMouseUp);    });  });
  function handleMouseMove(e) {    if (!currentResizer) return;    var diff = e.clientX - startX;    // 更新对应列的宽度    columnWidths[columnIndex] = Math.max(50, startWidth + diff); // 最小宽度50px    updateTableWidth();  }
  function handleMouseUp() {    // 移除事件监听器    document.removeEventListener('mousemove', handleMouseMove);    document.removeEventListener('mouseup', handleMouseUp);    // 重置变量    currentResizer = null;    columnIndex = -1;  }
  function updateTableWidth() {    // 计算表格总宽度    var totalWidth = columnWidths.reduce((sum, width) => sum + width, 0);    // 更新表格宽度    table.style.width = totalWidth + 'px';    // 更新每列的宽度    var headers = table.querySelectorAll('th');    headers.forEach((th, index) => {      th.style.width = columnWidths[index] + 'px';    });    // 同步tbody中的td宽度    var rows = table.querySelectorAll('tbody tr');    rows.forEach(row => {      var cells = row.querySelectorAll('td');      cells.forEach((td, index) => {        td.style.width = columnWidths[index] + 'px';      });    });  }  initColumnWidths();</script></body></html>


阅读原文:https://mp.weixin.qq.com/s/44uHl-l535g-WKUmC1A_Gw


该文章在 2025/12/18 9:28:57 编辑过
关键字查询
相关文章
正在查询...
点晴ERP是一款针对中小制造业的专业生产管理软件系统,系统成熟度和易用性得到了国内大量中小企业的青睐。
点晴PMS码头管理系统主要针对港口码头集装箱与散货日常运作、调度、堆场、车队、财务费用、相关报表等业务管理,结合码头的业务特点,围绕调度、堆场作业而开发的。集技术的先进性、管理的有效性于一体,是物流码头及其他港口类企业的高效ERP管理信息系统。
点晴WMS仓储管理系统提供了货物产品管理,销售管理,采购管理,仓储管理,仓库管理,保质期管理,货位管理,库位管理,生产管理,WMS管理系统,标签打印,条形码,二维码管理,批号管理软件。
点晴免费OA是一款软件和通用服务都免费,不限功能、不限时间、不限用户的免费OA协同办公管理系统。
Copyright 2010-2026 ClickSun All Rights Reserved