简体   繁体   English

用纯javascript的html表冻结列,很少的CSS

[英]html table frozen columns with pure javascript, little CSS

I'm trying to implement making the left three columns of an html horizontally scrolling table 'frozen' or 'fixed'. 我正在尝试实现使html水平滚动表的左三列“冻结”或“固定”。 I've already looked thoroughly at all of the solutions on the web but I have a lot of requirements which make it impossible to find a solution: 我已经仔细研究了网络上的所有解决方案,但是我有很多要求,因此无法找到解决方案:

  1. Make as little CSS changes as possible as this table already has a lot of CSS applied to it. 尽可能少地更改CSS,因为此表已经应用了很多CSS。 This table has a lot of the same features as jQuery DataTables so there's a lot going on. 该表与jQuery DataTables具有很多相同的功能,因此有很多事情要做。
  2. I'm willing to do as much Javascript as needed but it needs to be purely JS, nothing else like jQuery. 我愿意根据需要执行尽可能多的Java脚本,但它必须是纯JS,没有其他像jQuery一样的JavaScript。
  3. Cannot duplicate the table (I've seen solutions that puts one copy of the table on top of another). 无法复制表格(我见过将表格的一个副本放在另一个副本上的解决方案)。
  4. The table must stay completely white, I cannot assign a background color to the frozen columns as a 'fix' to hide the other columns when frozen column scrolls over them. 表格必须保持全白,我无法将背景色分配给冻结列作为“固定”来隐藏其他列(当冻结列在它们上方滚动时)。

Do you guys have any suggestions on how to implement that functionality with Javascript? 你们对如何使用Javascript实现该功能有任何建议吗? It seems like most implementations that apply to an existing table (and not include this feature in a table) depend on changing a lot of CSS. 似乎适用于现有表的大多数实现(并且未在表中包含此功能)取决于更改大量CSS。 Even just some suggestions on how to get started with it in javascript would be helpful. 即使只是一些有关如何开始使用javascript的建议也将有所帮助。 I would think that there should be a way if I utilize the scrolling aspect, but I'm not sure. 我认为如果利用滚动方面,应该有一种方法,但是我不确定。

I have used a fixed-table.js library to implement the solution without jquery. 我使用了fixed-table.js库来实现没有jquery的解决方案。 Try the snippet below. 试试下面的代码片段。

 var fixedTable = fixTable(document.getElementById('fixed-table-container-demo')); function fixTable(container) { // Store references to table elements var thead = container.querySelector('thead'); var tbody = container.querySelector('tbody'); // Style container container.style.overflow = 'auto'; container.style.position = 'relative'; // Add inline styles to fix the header row and leftmost column function relayout() { var ths = [].slice.call(thead.querySelectorAll('th')); var tbodyTrs = [].slice.call(tbody.querySelectorAll('tr')); /** * Remove inline styles so we resort to the default table layout algorithm * For thead, th, and td elements, don't remove the 'transform' styles applied * by the scroll event listener */ tbody.setAttribute('style', ''); thead.style.width = ''; thead.style.position = ''; thead.style.top = ''; thead.style.left = ''; thead.style.zIndex = ''; ths.forEach(function(th) { th.style.display = ''; th.style.width = ''; th.style.position = ''; th.style.top = ''; th.style.left = ''; }); tbodyTrs.forEach(function(tr) { tr.setAttribute('style', ''); }); [].slice.call(tbody.querySelectorAll('td')) .forEach(function(td) { td.style.width = ''; td.style.position = ''; td.style.left = ''; }); /** * Store width and height of each th * getBoundingClientRect()'s dimensions include paddings and borders */ var thStyles = ths.map(function(th) { var rect = th.getBoundingClientRect(); var style = document.defaultView.getComputedStyle(th, ''); return { boundingWidth: rect.width, boundingHeight: rect.height, width: parseInt(style.width, 10), paddingLeft: parseInt(style.paddingLeft, 10) }; }); // Set widths of thead and tbody var totalWidth = thStyles.reduce(function(sum, cur) { return sum + cur.boundingWidth; }, 0); tbody.style.display = 'block'; tbody.style.width = totalWidth + 'px'; thead.style.width = totalWidth - thStyles[0].boundingWidth + 'px'; // Position thead thead.style.position = 'absolute'; thead.style.top = '0'; thead.style.left = thStyles[0].boundingWidth + 'px'; thead.style.zIndex = 10; // Set widths of the th elements in thead. For the fixed th, set its position ths.forEach(function(th, i) { th.style.width = thStyles[i].width + 'px'; if (i === 0) { th.style.position = 'absolute'; th.style.top = '0'; th.style.left = -thStyles[0].boundingWidth + 'px'; } }); // Set margin-top for tbody - the fixed header is displayed in this margin tbody.style.marginTop = thStyles[0].boundingHeight + 'px'; // Set widths of the td elements in tbody. For the fixed td, set its position tbodyTrs.forEach(function(tr, i) { tr.style.display = 'block'; tr.style.paddingLeft = thStyles[0].boundingWidth + 'px'; [].slice.call(tr.querySelectorAll('td')) .forEach(function(td, j) { td.style.width = thStyles[j].width + 'px'; if (j === 0) { td.style.position = 'absolute'; td.style.left = '0'; } }); }); } // Initialize table styles relayout(); // Update table cell dimensions on resize window.addEventListener('resize', resizeThrottler, false); var resizeTimeout; function resizeThrottler() { if (!resizeTimeout) { resizeTimeout = setTimeout(function() { resizeTimeout = null; relayout(); }, 500); } } // Fix thead and first column on scroll container.addEventListener('scroll', function() { thead.style.transform = 'translate3d(0,' + this.scrollTop + 'px,0)'; var hTransform = 'translate3d(' + this.scrollLeft + 'px,0,0)'; thead.querySelector('th').style.transform = hTransform; [].slice.call(tbody.querySelectorAll('tr > td:first-child')) .forEach(function(td, i) { td.style.transform = hTransform; }); }); /** * Return an object that exposes the relayout function so that we can * update the table when the number of columns or the content inside columns changes */ return { relayout: relayout }; } 
 .fixed-table-container { height: 300px; box-sizing: border-box; border: 1px solid #ccc; margin-bottom: 40px; } .fixed-table-container table { border-collapse: collapse; width: 100%; } .fixed-table-container th, .fixed-table-container td { border-right: 1px solid #ccc; border-bottom: 1px solid #ccc; padding: 8px; text-align: left; vertical-align: top; /** * Current implementation doesn't work when * cells in a row have different heights */ white-space: nowrap !important; } .fixed-table-container th { background: #fff; font-size: 12px; line-height: 16px; padding-top: 10px; padding-bottom: 10px; } .fixed-table-container td:first-child { background: #fff; } .fixed-table-container tr:last-child td { border-bottom: 0; } .fixed-table-container th:last-child, .fixed-table-container td:last-child { border-right: 0; } 
 <div id="fixed-table-container-demo" class="fixed-table-container"> <table> <thead> <tr> <th>Name</th> <th>Status</th> <th>Description</th> </tr> </thead> <tbody> <tr> <td>Lorem</td> <td>Lorem ipsum</td> <td>Lorem</td> </tr> <tr> <td>Lorem ipsum dolor sit amet</td> <td>Lorem</td> <td>Dolor</td> </tr> <tr> <td>Lorem ipsum dolor</td> <td>sit</td> <td>Lorem ipsum dolor sit amet ipsum dolor sit amet</td> </tr> <tr> <td>Lorem</td> <td>Lorem ipsum</td> <td>Lorem ipsum dolor sit amet</td> </tr> <tr> <td>Dolor sit amet</td> <td>Dolor sit amet</td> <td>Lorem</td> </tr> <tr> <td>Lorem ipsum dolor</td> <td>Lorem ipsum dolor sit amet ipsum dolor sit amet</td> <td>Sit amet</td> </tr> <tr> <td>Lorem</td> <td>Lorem ipsum</td> <td>Lorem</td> </tr> <tr> <td>Lorem ipsum dolor sit amet</td> <td>Lorem</td> <td>Dolor</td> </tr> <tr> <td>Lorem ipsum dolor</td> <td>sit</td> <td>Lorem ipsum dolor sit amet</td> </tr> <tr> <td>Lorem</td> <td>Lorem ipsum</td> <td>Lorem dolor sit amet</td> </tr> <tr> <td>Dolor sit amet</td> <td>Dolor sit amet</td> <td>Lorem</td> </tr> <tr> <td>Lorem ipsum dolor</td> <td>Lorem ipsum dolor sit</td> <td>Sit amet lorem</td> </tr> </tbody> </table> </div> 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM