调整窗口

时间:2017-04-26 18:25:55

标签: javascript jquery css css3 firefox

我花了很多时间在这个上面,似乎找不到解决方法。我正在尝试创建一个具有固定标题的表,可以水平和垂直滚动。但是,我偶然发现了一个我无法解释的奇怪的错误。

这个想法很简单。表位于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定位跨度。测试此解决方案的所有其他浏览器都按预期工作。

2 个答案:

答案 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的行为与其他行为不同,因此使用简单的浏览器检测(对不起,仅用于此演示,建议以更合适的方式执行此操作)我得到了它的工作

Updated fiddle

&#13;
&#13;
$('.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;
&#13;
&#13;