Javascript jQuery offset()按主体位置断开:相对与元素边距组合

Javascript jQuery offset()按主体位置断开:相对与元素边距组合,javascript,jquery,css,position,Javascript,Jquery,Css,Position,这不是一个bug,因为在Win7上,FF、Chrome、IE9和Safari的行为是一致的 我正在使用的应用程序是主机页的第三方,因此CSS是不可变的。脚本尝试将新div与现有元素对齐 身体的位置是相对的 页面顶部有一个H1 H1的边距似乎在计算主体0,0的位置发生变化-即使主体上的背景一直延伸到边缘,并且其offsetTop属性报告0 在主体上设置边框可以解决这个问题——看似奇怪的行为,但在浏览器之间是一致的?(不是可行的解决办法) 删除H1页边距可以解决问题(不是可行的解决方案) 在这里

这不是一个bug,因为在Win7上,FF、Chrome、IE9和Safari的行为是一致的

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

  • 身体的位置是相对的
  • 页面顶部有一个H1
  • H1的边距似乎在计算主体0,0的位置发生变化-即使主体上的背景一直延伸到边缘,并且其offsetTop属性报告0
  • 在主体上设置边框可以解决这个问题——看似奇怪的行为,但在浏览器之间是一致的?(不是可行的解决办法)
  • 删除H1页边距可以解决问题(不是可行的解决方案)
在这里的示例中,JS被注释为复制每个案例:

我不认为这是jQuery的一个bug——它似乎是由于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
  })
});

如果您将
叠加
的位置从
绝对
更改为
固定
,则工作正常。这意味着偏移值是正确的。我认为这与
overlay
元素相对于前一个元素的位置有关

我不认为这是jQuery的一个bug——它似乎是由于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
  })
});
是的:主体和h1的边距是相等的,所以不仅h1被其默认边距向下移动,主体也是如此。这就是为什么您能够进行这些观察:

  • 在主体上设置边框可以解决这个问题——看似奇怪的行为,但在浏览器之间是一致的?(不是可行的解决办法)
  • 删除H1页边距可以解决问题(不是可行的解决方案)
无论如何,通过将主体设置为
位置:相对
,您告诉
#overlay
以主体的顶部偏移为原点绝对定位自身。然后,脚本将其相对于
#existing
的偏移量移动。它的
offsetTop
值相对于视口,视口是根据此框的位置计算的。。。它本身是相对于h1的,因为它在正常流量下直接跟随h1

因为h1和body元素的边距正在塌陷,所以它们具有相同的渲染边距。接下来发生的事情有两方面:

  • #现有的
    被h1向下推,作为其正常流中的以下同级。这会增加其与视口的偏移量(在CodePen测试用例中,它位于预览窗格的顶部),从而导致其
    offsetTop
    更大

  • 当主体设置为
    位置:相对时,
    #overlay
    最终被定位,其原点设置为主体的原点,主体本身也由于与h1的边距塌陷而被向下推。这会增加其原点的顶部偏移,如果未定位实体,则不会发生这种情况,因为此时
    #overlay
    使用视口的原点,而视口的原点从不移动

  • 从视口顶部开始的现有距离被添加到从其原点(即主体)开始的覆盖偏移中,从而产生此效果

    总而言之:由于边缘塌陷,浏览器最终不得不考虑h1和body的向下移动。h1影响现有的
    #overlay
    ,反过来影响其
    偏移量
    ,而主体在相对定位时影响
    #overlay
    。因此,移位效应有两个方面

    作为一种快速解决方法,您可以从现有的偏移量中减去h1页边距,以便进行偏移覆盖:

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

    请注意,使用
    $(document.body)
    而不是上面的
    $(“h1”)
    将不起作用。这是因为边距折叠纯粹是一种渲染效果,在您为实体指定自己的边距之前,它实际上不会影响实体的偏移(换句话说,实体边距的计算结果仍然为零,因此DOM仍然不太明智)


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

    • H1的边距似乎在计算主体0,0的位置发生变化-即使主体上的背景一直延伸到边缘,并且其offsetTop属性报告0
    这一点的第一部分和最后一部分已经在上面讨论过

    至于主体背景:虽然它似乎一直延伸到边缘,但这个延伸的背景实际上并不属于主体——它从主体传播到根元素(html)和视口,因此属于根元素(html)和视口。请参阅以获取解释

    哦,还有这个:

    这不是一个bug,因为在Win7上,FF、Chrome、IE9和Safari的行为是一致的


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

    主演这部电影是因为我不小心熬夜太久才弄明白这部电影。谢谢我现在真该睡觉了:)回答得好,谢谢!我提出了一个更通用的解决方案,0,0处的“零点”div:。我仍然不明白为什么在正文中添加边框会删除它的边距?@robC:因为根据规范,边距只有在没有填充、边框或间隙的情况下才可以折叠。通过添加边框,您可以防止边距塌陷,因此h1的边距不会应用于正文。哇,该规范是一些深奥的阅读,我忍不住觉得这种类型的功能没有那么有用,反而令人困惑。感谢您的解释:)好的,但是假设您不能控制站点,当document.body以这种方式偏移时,如何获得任何子元素的准确位置。抵销是错误的。我认为你需要把利润计入会计