页面加载时元素高度的差异

时间:2015-12-07 18:27:19

标签: jquery css twitter-bootstrap-3

随着这个问题的发展,正确的标题应该是:页面加载时体宽的差异。。它还与在页面中调整大小的图片有关。如果我们删除图片,差异就会消失。

请注意,这个问题不需要实用的解决方案(我可以用setTimeout()延迟脚本执行,问题就解决了)。我在问,因为我想了解这种行为的技术方面。

在这里写一个答案的脚本时,在SO上,我发现如果在页面加载时或以后计算出元素高度的奇怪差异。

以下是片段:



document.initPictures = function() {
  $('.resizeMe').css({
    'height': $('#theContainer .col-sm-6').eq(1).height() + 6,
    'display': 'flex',
    'flex-direction': 'column',
    'transition': 'height .4s cubic-bezier(0.55, 0, 0.55, 0.2)'
  });
  $('.resizeMe img').each(function() {
    var src = $(this).attr('src');
    $('.resizeMe').append('<div style="flex-basis: 50%; background-image: url(' + src + '); background-size:cover; background-position: center center"' + '</div>');
    $(this).remove();
  })
};
document.resizePictures = function() {
  if ($('#theContainer').outerWidth() > 768) {
    $('.resizeMe').css({
      'height': $('#theContainer .col-sm-6').eq(1).height()
    });
  } else {
    $('.resizeMe').css({
      'height': $('.resizeMe').outerWidth()
    });
  }
};
$(window).resize(function() {
  document.resizePictures();
});
document.initPictures();
&#13;
.main-img {
  width: 100%;
  height: auto
}
#theContainer {
  margin-top: 15px;
}
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<!-- Latest compiled and minified CSS -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" integrity="sha384-1q8mTJOASx8j1Au+a5WDVnPi2lkFfwwEAa8hDDdjZlpLegxhjVME1fgjWPGmkzs7" crossorigin="anonymous">

<div class="row-fluid" id="theContainer">
  <div class="col-sm-6 resizeMe">
    <img class="filler" src="http://www.keenthemes.com/preview/metronic/theme/assets/global/plugins/jcrop/demos/demo_files/image1.jpg" />
    <img class="filler" src="http://www.keenthemes.com/preview/metronic/theme/assets/global/plugins/jcrop/demos/demo_files/image2.jpg" />
  </div>
  <div class="col-sm-6">
    <img class="main-img" src="http://joombig.com/demo-extensions1/images/gallery_slider/Swan_large.jpg" />
  </div>
&#13;
&#13;
&#13;

您会注意到我在第一个div中将图像制作成第二个div中图像高度的50%(这是要求)。在页面加载时,第二个div的图像高度很短6px $('#theContainer .col-sm-6').eq(1).height(),我必须在initPictures()函数中进行补偿,但resizePictures()函数中没有必要补偿1}},发生在$(window).resize()上。

我使用的是最新版本的Chrome,但我也在最新的FF中对其进行了测试。同样的行为。

我很高兴能够理解这种差异是什么。它从何而来?是否与使用jQuery的Bootstrap有关?或者用什么?

注意:测试时,我还尝试使用innerheight()outerHeight()希望我可以绕过&#34;错误&#34;。那时他们都是6px短。

另一个注意事项:出于测试目的,我为此做了jsFiddle。当我正常加载它时,作为一个小提琴,它有相同的bug并且补偿是必要的。在full screen mode中查看时,不再需要补偿,实际上由于补偿,左列6px会缩短。

更新:经过使用AvArt记录此操作的一些全面测试后,它全部从body的宽度开始。默认情况下,没有特殊原因,页面加载时它不是100vw

如果在(768 - 17)px以上的视口宽度下加载,您可以结帐this fiddle。出于某种原因,你们中的一些人从来没有经历过这个&#34; bug&#34;,但是我假设有人做了,因为这个问题已被投票了。 但是,如果你取消注释最后一行CSS,bug就会消失。

因此,如果在页面加载时身体在短时间内具有不同的宽度,.col-sm-6的宽度会受到影响,从而影响所包含图像的auto高度,从而影响列高。 6px差异(有时是7)来自图像&#39;特定的高宽比,但身体宽度的起始差异为17px。

现在,问题仍然存在:为什么body元素在页面加载时的宽度与100vw的宽度差异为17px,这应该是默认值,宽度大于(768) - 17)PX

有趣的是 与图片有关,因为如果我们从HTML删除图片,差异就会消失!

是否有人熟悉浏览器的工作原理以及最初如何应用CSS来解释这种行为?

对于冗长的解释感到抱歉,它只是我几天都无法理解的东西,所以我只需要询问并找出答案。

更新了jsFiddle here

3 个答案:

答案 0 :(得分:4)

问题是Javascript执行顺序。在检查体宽之前必须执行initPictures()Fiddle

答案 1 :(得分:3)

您看到的17px差异是滚动条宽度

文档的宽度未知,直到所有资源都已完全加载,因此它为可能的滚动条保留了一些空间。实际上,这意味着window.onLoad仅在加载所有图像时执行。虽然jQuery的ready事件会在加载DOM后立即触发。

我创建了一个新的小提琴(http://jsfiddle.net/u7zgz25u/3/)来演示这种行为。 (要清除缓存中的图像,只需更改其网址中的1种颜色)。

在查看http://jsfiddle.net/o1g5x5m6/20/(您的示例没有图片)时,readywindow.onLoad事件在(几乎)同时执行,然后才进行实际渲染,因此页面尺寸为浏览器所知。

PS: 我发现一个有趣的小提琴演示了浏览器渲染时考虑的滚动条宽度,尽管有足够大的padding-right可用:http://jsfiddle.net/9pAcp/2/

更新

某些浏览器实现了渲染延迟(例如Firefox documentation),因此加载了图像后初始宽度和宽度之间的差异。如果在初始渲染延迟之前加载图像,或者没有图像,则浏览器可以计算正确的高度,但是,如果图像尚未加载,并且它们没有已知尺寸,则浏览器需要等待图像加载之前它可以计算它们的大小。因此,估计的文档大小(为滚动条保留的空间)与window.onLoad之后的实际文档大小之间可能存在差异。

有关在HTML中为图像定义固定高度时会发生什么情况的演示,请参阅http://jsfiddle.net/u7zgz25u/4/。 17px的差异不再存在。

答案 2 :(得分:0)

我没有这个案例的确认来源,但正如我可以看到做一些实验,Flex框有渲染问题。

  

用具有div的div替换具有真实高度的2个图像   图像作为背景,所以它失去了它的高度。

     

弹性容器   重新计算这两个图像div的高度,但有一些渲染   问题可能是由于滚动条需要占用一些空间的事实(如在评论上写的那样)。

     

jQuery在不使用滚动条$(window).width()的情况下计算宽度,而使用javascript的window.innerWidth本机可以看到视口的有效宽度,这比jquery宽度多17倍。

     

对于某些渲染原因,jquery的高度是使用可见的滚动条计算的,如下面的示例中所示,我用overflow:scroll替换了主体宽度。

jsfiddle

我在不使用弹性框的情况下完成了与此编辑类似的工作:

$('.resizeMe,.cover-img').css({
  'height': $('#theContainer .col-sm-6').eq(1).height(),
  'transition': 'height .4s cubic-bezier(0.55, 0, 0.55, 0.2)'
});
$('.resizeMe img').each(function() {
    var src = $(this).attr('src');
    $('.resizeMe').append('<div class="cover-img" style="background-image: url(' + src + '); height: '+$(this).height()+'px;"' + '</div>');
    $(this).remove();
});

使用具有高度的div,效果相同但没有近似问题。

jsfiddle有可能的解决方案。

另一个没有渲染问题的例子,留下img标签而不用div替换它们而不用js计算高度:

jsfiddle