jQuery offset()被正文位置所打破:相对与元素边距相结合

时间:2012-11-14 18:09:22

标签: javascript jquery css position

这不是一个错误,因为Win7上的FF,Chrome,IE9和Safari的行为是一致的。

我正在处理的应用程序是主机页面的第三方,因此CSS是不可变的。脚本尝试将新div与现有元素对齐。

  • 身体是位置:亲属
  • 页面顶部有一个H1
  • 来自H1的边距似乎在计算体0,0的位置发生变化 - 即使身体上的背景一直延伸到边缘,并且它的offsetTop属性报告为0
  • 在身体上设置边框可以解决问题 - 看起来很奇怪但是在浏览器中是一致的吗? (不是一个可行的解决方案)
  • 删除H1边距可以解决问题(不是一个可行的解决方案)

这里的示例,JS被评论为复制每个案例:
 http://codepen.io/anon/pen/EGvlb

我认为这不是jQuery的错误 - 它似乎归结为H1边距和body元素之间的合法关系?

$(function(){

  /* Setting body to position:relative breaks offset()
     because H1 margin moves body down */
  $(document.body).css({position: "relative"});

  /* Strange: putting a border on body fixes things? */
  //$(document.body).css({border: "1px solid #000"});

  /* Removing H1 margin removes problem */
  //$("h1").css({margin: 0});

  $("#overlay").css({
      left: $("#existing").offset().left,
      top: $("#existing").offset().top
  })
});

2 个答案:

答案 0 :(得分:4)

  

我认为这不是jQuery的错误 - 它似乎归结为H1边距和body元素之间的合法关系?

是的:身体的边缘和h1是collapsing,所以不仅h1被默认边缘向下移动,而且身体也是如此。这就是你能够做出这些观察的原因:

  
      
  • 在身体上设置边框可以解决问题 - 看起来很奇怪但是在浏览器中是一致的吗? (不是一个可行的解决方案)
  •   
  • 删除H1边距可以解决问题(不是一个可行的解决方案)
  •   

无论如何,通过将身体设置为position: relative,您告诉#overlay绝对将身体的顶部偏移定位为原点。然后,您的脚本相对于#existing的偏移量移动它。其offsetTop的值相对于视口而言,视口是根据此框的位置计算的...它本身相对于h1,因为它在正常流程中直接跟随h1。

由于h1和body元素的边距正在折叠,因此它们具有相同的渲染边距。那么会发生什么是双重的:

  1. #existing在正常流程中被h1推下为其后续兄弟。这会增加其从视口的偏移量(在CodePen测试用例中,它是预览窗格的顶部),导致其offsetTop更大。

  2. 当身体设置为position: relative时,#overlay最终定位,其原点设置为身体的原点,由于与h1的折叠,身体也被推倒余量。这会增加其原点的顶部偏移量,如果您没有定位主体,则不会发生这种情况,因为#overlay会使用视口的原点而不会移动。

  3. #existing距视口顶部的距离被添加到#overlay与其原点的偏移量(即身体),从而产生此效果。

    总结:由于保证金崩溃,浏览器最终不得不考虑h1和body的向下移动。 h1影响#existing,反过来影响offsetTop,而当你相对定位时,身体影响#overlay。所以转变效应出现了两倍。

    作为一种快速解决方法,您可以从#existing的偏移量中减去h1边距,以便抵消#overlay

      $("#overlay").css({
          left: $("#existing").offset().left - $("h1").offset().left,
          top: $("#existing").offset().top - $("h1").offset().top
      })
    

    Updated example

    请注意,使用上面的$(document.body)代替$("h1")将无效。这是因为边缘坍塌纯粹是一种渲染效果,并且实际上不会影响身体的偏移,直到你给它自己的边缘(换句话说,身体边缘仍然计算为零,所以DOM仍然没有更明智)。 / p>


    与手头的问题没有直接关系,但无论如何都值得解决:

      
        
    • 来自H1的边距似乎在计算体0,0的位置发生变化 - 即使身体上的背景一直延伸到边缘,并且它的offsetTop属性报告为0
    •   

    上面已经讨论了这一点的第一部分和最后部分。

    至于身体背景:虽然看起来一直延伸到边缘,但这个扩展背景实际上并不属于身体 - 它从身体传播到根元素(html),因此属于根元素(html)和视口。有关说明,请参阅this answer

    哦,这个:

      

    这不是一个错误,因为Win7上的FF,Chrome,IE9和Safari的行为是一致的。

    让我微笑。因为有一次,有人说得对。

答案 1 :(得分:0)

如果您将overlay的排名从absolute更改为fixed,那么它运行正常。这意味着偏移值是正确的。我认为它与overlay元素相对于其前一个元素的位置有关。