如何计算两个元素之间的空间?

时间:2016-02-06 13:16:37

标签: javascript jquery

如何计算一个元素与下一个渲染元素之间的空间量?

我想了解特定hr与其下方的任何展示之间的空间大小。视觉上可能是段落或标题或图像或其他任何东西,但hr和下一个东西都可以嵌套在其他块中。因此,“渲染元素”是指页面上的下一个可见元素。

我需要这个的原因是我需要在hrposition: relative之后插入一个元素,我不想将内容向下移动,除非我的空间比我的短新元素。如果空间较短,我只想根据需要调低内容,以避免覆盖内容。

我根本无法控制HTML的生成。我只能将代码添加到生成的页面。

以下是我正在使用的HTML示例:

<div class="extra-wrapper">
    <p>The line that separates the header from the rest of the page is below this.</p>
    <hr>
</div>
<p class="top-p">
    Lorem ipsum dolor...
</p> 

如果它总是那样,下面的代码段可能会起作用,但问题是我开始使用的元素和页面上可见的下一个元素都可能以不可预测的方式嵌套在其他块中。

我也觉得下一个元素可能是兄弟姐妹。所以我需要检查$hr.next()是否有值,我在下面的代码段中没有这样做。

$(function() {
  var $header = $('#header');
  var $hr = $header.siblings('.extra-wrapper').children('hr').filter(':first');
  var $next_element = $hr.parent().next();

  var extra_wrapper_bottom_margin = parseInt($hr.parent().css('margin-bottom'));
  var extra_wrapper_bottom_padding = parseInt($hr.parent().css('padding-bottom'));

  var hr_bottom_margin = parseInt($hr.css('margin-bottom'));
  var hr_bottom_padding = parseInt($hr.css('padding-bottom'));

  var next_element_top_margin = parseInt($next_element.css('margin-top'));
  var next_element_top_padding = parseInt($next_element.css('padding-top'));

  /* Account for collapsing vertical margins. */
  var biggest_margin;
  if (extra_wrapper_bottom_margin > hr_bottom_margin) {
    biggest_margin = extra_wrapper_bottom_margin;
  } else {
    biggest_margin = hr_bottom_margin;
  }

  if (next_element_top_margin > biggest_margin) {
    biggest_margin = next_element_top_margin;
  }

  var space_between = biggest_margin + hr_bottom_padding + extra_wrapper_bottom_padding + next_element_top_padding;

  $('#space').val(space_between);
});
div.extra-wrapper {
  padding: 0.5em 0;
  margin-bottom: 1em;
}
div.extra_wrapper hr {
  margin: 1em;
}
p.top-p {
  margin: 1em;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="header">
  <p>This is the header content.</p>
</div>
<div class="extra-wrapper">
  <hr>
</div>
<p class="top-p">
  Lorem ipsum dolor...
</p>
<label>Space:
  <input id="space" type="text">
</label>

谢谢。

2 个答案:

答案 0 :(得分:1)

怎么样:

next = function($el) {
  while($el.length) {  
    var s = $el.next();
    if (s.length) return s;
    $el = $el.parent();
  }
}

hr = $('hr');

alert(next(hr).offset().top - hr.offset().top)
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<section>
<div>
  <div class="extra-wrapper">
      <p>The line.... this.</p>
      <hr>
    </div>
</div>
</section>

<p class="top-p">
    Lorem ipsum dolor...
</p>

答案 1 :(得分:1)

解决方案是使用两个元素的offset().top值(如@adeneo和@georg所示)并减去第一个元素的高度。我自己不需要计算边框,边距和填充。

找到下一个元素并不像我原先想象的那样困难。

确定第一个元素的高度并不太棘手,但height()innerHeight()都不会这样做。我必须在DOM元素上使用属性offsetHeight

我需要这样的东西:

var space = $next.offset().top - ($hr.offset().top + $hr[0].offsetHeight)`

如果不是@adeneo的评论和@georg的回答,我就无法弄清楚这一点,但是没有人提供完整的解决方案。

以下示例在CodePen上还有一个稍微详细的版本:calculate space between two elements

var find_next = function($el) {
  $next = $el.next();
  while ( !$next.length ) {
    find_next($el.parent());
  }
  return $next;
}

$(window).load(function() {
  var $header = $('#header');
  var $hr = $header.siblings('.extra-wrapper').find('hr');
  var $after_header = find_next($hr);
  
  var hr_top = $hr.offset().top;
  var hr_bottom = $hr[0].offsetHeight + hr_top;
  var after_header_top = $after_header.offset().top;
  var space_between = after_header_top - hr_bottom;
  
  $('.space-between').css({
    'top': hr_bottom,
    'height': space_between,
    'line-height': space_between + 'px'
  });
  $('.space-between .info').text(space_between + 'px');  
});
div.extra-wrapper {
  margin: 1em;
}

div.extra-wrapper hr {
  margin: 1em;
}

p.top-p {
  margin-top: 1.5em;
}

div.space-between {
  position: absolute;
  left: 150px;
  height: 20px;
  width: 20px;
  border-color: #f0f;
  border-style: solid;
  border-width: 1px 0 1px 1px;
  border-radius: 3px;
  white-space: nowrap;
  text-indent: 10px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="header">
  <p>This is the header section with the logo.</p>
  <h1 class="logo"><a href="#0"><img alt="logo" src="http://lorempixel.com/64/64/people"></a></h1>
</div>
<div class="page-divider"></div>
<div class="extra-wrapper">
  <hr>
</div>
<div class="content">
  <p class="top-p">
    Lorem ipsum dolor ...
  </p>
</div>

<div class="space-between">
  <span class="info">Space between: </span>
<div class="show-position-info"></div>