You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

实现固定左列与表头的HTML表格横竖滚动 解决DataTable性能问题

Absolutely! You can totally build a custom table with fixed headers, fixed left columns, and both horizontal/vertical scrolling using plain HTML, CSS, and a touch of jQuery/JavaScript—no heavy DataTables dependency required. This approach will handle large datasets and column show/hide actions smoothly, avoiding the performance bottlenecks you ran into with DataTables.

Core Approach

The key is to split the table into four synchronized sections to handle fixed and scrollable parts independently:

  • Fixed left header (stays put during both horizontal and vertical scroll)
  • Scrollable header (moves horizontally with content, stays fixed vertically)
  • Fixed left column content (stays put horizontally, scrolls vertically with main content)
  • Scrollable main content (scrolls both ways)

Full Implementation

Here's a working, customizable example:

HTML

<div class="table-container">
  <!-- Fixed Left Header -->
  <div class="fixed-left-header">
    <table>
      <thead>
        <tr>
          <th>固定ID</th>
          <th>固定名称</th>
        </tr>
      </thead>
    </table>
  </div>

  <!-- Scrollable Header -->
  <div class="scrollable-header">
    <table>
      <thead>
        <tr>
          <th class="col-a">订单日期</th>
          <th class="col-b">订单金额</th>
          <th class="col-c">客户地区</th>
          <th class="col-d">配送状态</th>
          <th class="col-e">支付方式</th>
          <!-- Add more columns as needed -->
        </tr>
      </thead>
    </table>
  </div>

  <!-- Fixed Left Column Content -->
  <div class="fixed-left-column">
    <table>
      <tbody>
        <tr>
          <td>1001</td>
          <td>张三</td>
        </tr>
        <tr>
          <td>1002</td>
          <td>李四</td>
        </tr>
        <tr>
          <td>1003</td>
          <td>王五</td>
        </tr>
        <!-- Add more rows as needed -->
      </tbody>
    </table>
  </div>

  <!-- Scrollable Main Content -->
  <div class="scrollable-content">
    <table>
      <tbody>
        <tr>
          <td class="col-a">2024-01-15</td>
          <td class="col-b">¥1299</td>
          <td class="col-c">北京</td>
          <td class="col-d">已签收</td>
          <td class="col-e">支付宝</td>
        </tr>
        <tr>
          <td class="col-a">2024-01-16</td>
          <td class="col-b">¥899</td>
          <td class="col-c">上海</td>
          <td class="col-d">配送中</td>
          <td class="col-e">微信支付</td>
        </tr>
        <tr>
          <td class="col-a">2024-01-17</td>
          <td class="col-b">¥2199</td>
          <td class="col-c">广州</td>
          <td class="col-d">待发货</td>
          <td class="col-e">银行卡</td>
        </tr>
        <!-- Add more rows as needed -->
      </tbody>
    </table>
  </div>
</div>

<!-- Column Toggle Controls -->
<div class="column-controls">
  <button class="toggle-column" data-column="col-a">切换订单日期列</button>
  <button class="toggle-column" data-column="col-b">切换订单金额列</button>
  <button class="toggle-column" data-column="col-c">切换客户地区列</button>
</div>

CSS

/* Main Container */
.table-container {
  position: relative;
  width: 90%;
  max-width: 1200px;
  height: 450px;
  margin: 2rem auto;
  border: 1px solid #e0e0e0;
  overflow: hidden;
}

/* Fixed Left Header */
.fixed-left-header {
  position: absolute;
  top: 0;
  left: 0;
  width: 220px; /* Adjust based on your fixed column width */
  height: 60px; /* Adjust based on your header height */
  background-color: #f8f9fa;
  border-right: 1px solid #e0e0e0;
  border-bottom: 1px solid #e0e0e0;
  overflow: hidden;
}

/* Scrollable Header */
.scrollable-header {
  position: absolute;
  top: 0;
  left: 220px;
  right: 0;
  height: 60px;
  background-color: #f8f9fa;
  border-bottom: 1px solid #e0e0e0;
  overflow-x: auto;
  overflow-y: hidden;
  /* Hide scrollbar for cleaner look (optional) */
  scrollbar-width: thin;
}

/* Fixed Left Column Content */
.fixed-left-column {
  position: absolute;
  top: 60px;
  left: 0;
  width: 220px;
  bottom: 0;
  border-right: 1px solid #e0e0e0;
  overflow-y: auto;
  overflow-x: hidden;
  scrollbar-width: thin;
}

/* Scrollable Main Content */
.scrollable-content {
  position: absolute;
  top: 60px;
  left: 220px;
  right: 0;
  bottom: 0;
  overflow: auto;
  scrollbar-width: thin;
}

/* Table Styling */
.table-container table {
  border-collapse: collapse;
  width: 100%;
}

.table-container th, .table-container td {
  padding: 12px 15px;
  border: 1px solid #e0e0e0;
  white-space: nowrap; /* Prevent text wrapping to keep columns aligned */
}

.table-container th {
  font-weight: 600;
  text-align: left;
}

/* Column Toggle Styles */
.column-controls {
  text-align: center;
  margin-bottom: 2rem;
}

.toggle-column {
  margin: 0 0.5rem;
  padding: 0.5rem 1rem;
  border: 1px solid #007bff;
  background-color: white;
  color: #007bff;
  border-radius: 4px;
  cursor: pointer;
  transition: all 0.2s;
}

.toggle-column:hover {
  background-color: #007bff;
  color: white;
}

/* Hidden Column Class */
.hidden-column {
  display: none !important;
}

jQuery/JavaScript

$(document).ready(function() {
  // Debounce function to reduce scroll event frequency (performance boost)
  const debounce = (func, delay = 10) => {
    let timer;
    return (...args) => {
      clearTimeout(timer);
      timer = setTimeout(() => func.apply(this, args), delay);
    };
  };

  // Sync horizontal scrolling between header and main content
  const syncHorizontalScroll = debounce(function() {
    const scrollLeft = $('.scrollable-content').scrollLeft();
    $('.scrollable-header').scrollLeft(scrollLeft);
  });

  // Sync vertical scrolling between fixed left column and main content
  const syncVerticalScroll = debounce(function() {
    const scrollTop = $('.scrollable-content').scrollTop();
    $('.fixed-left-column').scrollTop(scrollTop);
  });

  // Attach scroll event listeners
  $('.scrollable-content').on('scroll', function() {
    syncHorizontalScroll();
    syncVerticalScroll();
  });

  // Reverse sync for header scroll (optional but improves UX)
  $('.scrollable-header').on('scroll', debounce(function() {
    $('.scrollable-content').scrollLeft($(this).scrollLeft());
  }));

  // Column show/hide functionality
  $('.toggle-column').on('click', function() {
    const columnClass = $(this).data('column');
    $(`.${columnClass}`).toggleClass('hidden-column');
  });
});

Performance Optimization Tips

  1. Debounce Scroll Events: The debounce function reduces how often scroll sync logic runs, which is crucial for large datasets.
  2. CSS-Based Column Toggle: Using a CSS class to hide/show columns is far faster than modifying DOM nodes directly.
  3. White-Space NoWrap: Prevents automatic text wrapping, ensuring columns stay aligned without unnecessary reflows.
  4. Virtual Scrolling (For Extreme Datasets): If you have thousands of rows, add logic to only render rows that are visible in the viewport—this drastically reduces DOM nodes and improves performance.

This implementation is lightweight, fully customizable, and avoids the overhead of DataTables for your specific use case.

内容的提问来源于stack exchange,提问作者Avinash

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.12 05:34:01