我花了很多时间在这个上面,似乎找不到解决方法。我正在尝试创建一个具有固定标题的表,可以水平和垂直滚动。但是,我偶然发现了一个我无法解释的奇怪的错误。
这个想法很简单。表位于scrollable
父级内部,位于绝对定位的container
内。表格标题放在span
元素内,绝对位于顶部。滚动scrollable
元素时,使用Javascript使用css转换移动span
元素。以下是所用代码的示例代码。
HTML:
<div class="container">
<div class="scrollable">
<table>
<thead>
<tr>
<th><span>Column 1</span></th>
...
</tr>
</thead>
<tbody>
<tr>
<td>Table cell content</td>
...
</tr>
</table>
</div>
</div>
使用Javascript:
$('.scrollable').on('scroll', function() {
scrollX=$(this).scrollLeft();
$(this).find('th span').attr('style', 'transform:translateX(' + -scrollX + 'px)');
})
以下是代码的小提琴: https://jsfiddle.net/rts4gd5x/
代码正常运行,因为它应该在我测试的所有浏览器中(ie11,即edge,chrome,safari),但在Firefox中我只遇到以下问题。
如果您滚动scrollable
元素然后调整窗口大小,span
元素的位置会出现问题,我无法确定是什么令人烦恼。从零滚动调整大小然后滚动可以正常工作。
我已经尝试了我能想到的一切,向父母添加了transform:translateZ(0)
,添加了min-width
等,但是我没有尝试过。在fixed
元素上使用span
定位可以调整以适应这种简化的布局,但我正在处理的实际布局需要absolute
定位跨度。测试此解决方案的所有其他浏览器都按预期工作。
答案 0 :(得分:1)
好的,这个问题让我很感兴趣,所以我继续前进并试图破解它以使其适用于这个特定场景。在查看调整大小后元素的多个属性如何变化后,我发现了一个可以被修改(hack)的元素。如果你看一下表头的偏移坐标,你会注意到在调整大小时(仅在firefox中),左偏移属性会减少滚动量。因此,如果scrollX
值为50
且第一个元素的左侧偏移量为-120
,则在调整大小后,左侧偏移量的值将变为-170
。这是导致错位的原因。
因此修复是在滚动时跟踪第一个th
元素的偏移量。然后在$(window).resize()
函数内;您使用此最后记录的偏移值并将其与当前偏移进行比较。如果它不相同(在一些误差范围内,我使用1px作为此边距,似乎工作)然后遍历所有th
元素并将偏移更新为其先前的值,即它们的当前值+ scrollX
值。
有趣的是,这种偏移不对齐仅发生在第一次调整大小时。所以使用上面的例子;在变为170
之后,任何后续调整大小都不会继续向该值添加50
,它将保留在170
。这意味着此修复只需要应用一次。这就是为什么要检查误差范围的原因。例如,由于此偏移问题不会出现在chrome中,因此检查还会确保不会影响任何渲染。
此外,我注意到使用item.attr('style', 'transform...')
时出现问题,在实施调整大小修复后,重新滚动会导致另一个错位。幸运的是,使用item.css('transform',...)
解决了这个问题。
看看代码:
let scrollX = 0;
let lastOffset = $('.scrollable').find('th span').first().offset();
$('.scrollable').on('scroll', function() {
scrollX=$(this).scrollLeft();
let thList = $('.scrollable').find('th span')
thList.css('transform', 'translateX(' + -scrollX + 'px)');
lastOffset = thList.first().offset();
})
$(window).resize(function(){
//If scrollable hasnt moved, no need to make any changes
if(scrollX == 0){
return;
}
let thList = $('.scrollable').find('th span');
let currentLeftOffset = Math.abs(thList.first().offset().left);
//Check if currentLeftOffset is withing a margin of error
//of last left offset, it it is, no need to proceed with the
//updating th offsets
if((currentLeftOffset - Math.abs(lastOffset.left)) < 1 ){
return;
}
//Iterate through all th elements and apply the offset adjustment
thList.each(function(itm){
let offset = $(this).offset();
offset.left = offset.left + scrollX;
$(this).offset(offset);
});
});
更新了 jsFiddle
答案 1 :(得分:1)
我尝试了两种方法在调整大小时执行刷新,但没有运气,所以这是另一个选项,我使用margin-left
代替。
同样,Firefox的行为与其他行为不同,因此使用简单的浏览器检测(对不起,仅用于此演示,建议以更合适的方式执行此操作)我得到了它的工作
$('.scrollable').on('scroll', function() {
scrollX=$(this).scrollLeft();
// Firefox
if (!(window.mozInnerScreenX == null)) {
$(this).find('thead').attr('style', 'margin-left: ' + -scrollX + 'px');
// the rest
} else {
$(this).find('th span').attr('style', 'margin-left: ' + -scrollX + 'px');
}
})
&#13;
.container {
position:absolute;
top:20px;
right:20px;
left:20px;
height:200px;
padding-top:40px;
overflow:hidden;
}
.scrollable {
width:100%;
height:100%;
overflow-x:auto;
background:white;
}
table {
width:100%;
text-align:left;
}
table th span {
position:absolute;
top:0;
border-left:1px solid #ccc;
display:block;
width:100%;
line-height:40px;
background:#fff;
margin-left:-1px;
}
table td {
white-space:nowrap;
border-left:1px solid #ccc;
}
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
<div class="scrollable">
<table>
<thead>
<tr>
<th><span>Column 1</span></th>
<th><span>Column 2</span></th>
<th><span>Column 3</span></th>
<th><span>Column 4</span></th>
<th><span>Column 5</span></th>
<th><span>Column 6</span></th>
<th><span>Column 7</span></th>
<th><span>Column 8</span></th>
<th><span>Column 9</span></th>
<th><span>Column 10</span></th>
</tr>
</thead>
<tbody>
<tr>
<td>Table cell content</td>
<td>Table cell content</td>
<td>Table cell content</td>
<td>Table cell content</td>
<td>Table cell content</td>
<td>Table cell content</td>
<td>Table cell content</td>
<td>Table cell content</td>
<td>Table cell content</td>
<td>Table cell content</td>
</tr>
<tr>
<td>Table cell content</td>
<td>Table cell content</td>
<td>Table cell content</td>
<td>Table cell content</td>
<td>Table cell content</td>
<td>Table cell content</td>
<td>Table cell content</td>
<td>Table cell content</td>
<td>Table cell content</td>
<td>Table cell content</td>
</tr>
<tr>
<td>Table cell content</td>
<td>Table cell content</td>
<td>Table cell content</td>
<td>Table cell content</td>
<td>Table cell content</td>
<td>Table cell content</td>
<td>Table cell content</td>
<td>Table cell content</td>
<td>Table cell content</td>
<td>Table cell content</td>
</tr>
<tr>
<td>Table cell content</td>
<td>Table cell content</td>
<td>Table cell content</td>
<td>Table cell content</td>
<td>Table cell content</td>
<td>Table cell content</td>
<td>Table cell content</td>
<td>Table cell content</td>
<td>Table cell content</td>
<td>Table cell content</td>
</tr>
<tr>
<td>Table cell content</td>
<td>Table cell content</td>
<td>Table cell content</td>
<td>Table cell content</td>
<td>Table cell content</td>
<td>Table cell content</td>
<td>Table cell content</td>
<td>Table cell content</td>
<td>Table cell content</td>
<td>Table cell content</td>
</tr>
<tr>
<td>Table cell content</td>
<td>Table cell content</td>
<td>Table cell content</td>
<td>Table cell content</td>
<td>Table cell content</td>
<td>Table cell content</td>
<td>Table cell content</td>
<td>Table cell content</td>
<td>Table cell content</td>
<td>Table cell content</td>
</tr>
<tr>
<td>Table cell content</td>
<td>Table cell content</td>
<td>Table cell content</td>
<td>Table cell content</td>
<td>Table cell content</td>
<td>Table cell content</td>
<td>Table cell content</td>
<td>Table cell content</td>
<td>Table cell content</td>
<td>Table cell content</td>
</tr>
<tr>
<td>Table cell content</td>
<td>Table cell content</td>
<td>Table cell content</td>
<td>Table cell content</td>
<td>Table cell content</td>
<td>Table cell content</td>
<td>Table cell content</td>
<td>Table cell content</td>
<td>Table cell content</td>
<td>Table cell content</td>
</tr>
<tr>
<td>Table cell content</td>
<td>Table cell content</td>
<td>Table cell content</td>
<td>Table cell content</td>
<td>Table cell content</td>
<td>Table cell content</td>
<td>Table cell content</td>
<td>Table cell content</td>
<td>Table cell content</td>
<td>Table cell content</td>
</tr>
<tr>
<td>Table cell content</td>
<td>Table cell content</td>
<td>Table cell content</td>
<td>Table cell content</td>
<td>Table cell content</td>
<td>Table cell content</td>
<td>Table cell content</td>
<td>Table cell content</td>
<td>Table cell content</td>
<td>Table cell content</td>
</tr>
</tbody>
</table>
</div>
</div>
&#13;