我试图实现制作一个html水平滚动表的左三列“冻结”#39;或者'固定'。我已经全面了解了网络上的所有解决方案,但我有很多要求,无法找到解决方案:
你们对如何使用Javascript实现该功能有任何建议吗?似乎大多数适用于现有表的实现(并且不包括表中的此功能)依赖于更改大量CSS。即使只是关于如何在javascript中开始使用它的一些建议也会有所帮助。如果我使用滚动方面,我认为应该有一种方法,但我不确定。
答案 0 :(得分:0)
我使用了fixed-table.js库来实现没有jquery的解决方案。试试下面的代码段。
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>
&#13;