javascript - How do I calculate space between two elements? - Stack Overflow

How can I calculate the amount of space between one element and the next rendered element?I want to fin

How can I calculate the amount of space between one element and the next rendered element?

I want to find out how much space is between a specific hr and whatever shows below it. Visually that could be a paragraph or a heading or an image or anything else, but the hr and the next thing could both be nested within other blocks. So, by "rendered element" I mean the next visible thing on the page.

The reason I need this is that I need to insert an element after the hr, position: relative, and I don't want to shift the content down unless the space I have is shorter than my new element. If the space is shorter, I only want to shift the content down as much as necessary to avoid covering content.

I don't have any control over the generation of the HTML at all. I can only add code to a generated page.

Here's an example of HTML that I'm working with:

<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> 

If it was always like that, the snippet below might work, but the problem is that both the element that I'm starting with and the next element visible on the page might be nested within other blocks in unpredictable ways.

It also occurs to me that the next element might be a sibling. So I need to check if $hr.next() has a value, which I'm not doing in the snippet below.

$(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=".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>

How can I calculate the amount of space between one element and the next rendered element?

I want to find out how much space is between a specific hr and whatever shows below it. Visually that could be a paragraph or a heading or an image or anything else, but the hr and the next thing could both be nested within other blocks. So, by "rendered element" I mean the next visible thing on the page.

The reason I need this is that I need to insert an element after the hr, position: relative, and I don't want to shift the content down unless the space I have is shorter than my new element. If the space is shorter, I only want to shift the content down as much as necessary to avoid covering content.

I don't have any control over the generation of the HTML at all. I can only add code to a generated page.

Here's an example of HTML that I'm working with:

<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> 

If it was always like that, the snippet below might work, but the problem is that both the element that I'm starting with and the next element visible on the page might be nested within other blocks in unpredictable ways.

It also occurs to me that the next element might be a sibling. So I need to check if $hr.next() has a value, which I'm not doing in the snippet below.

$(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./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>

Share Improve this question edited Mar 6, 2020 at 15:09 halfer 20.4k19 gold badges109 silver badges202 bronze badges asked Feb 6, 2016 at 13:16 VinceVince 4,2323 gold badges37 silver badges59 bronze badges 2
  • 1 As you're using jQuery, you have access to offset(), which gets the current coordinates of the element relative to the document. All you really have to do is get the offset of both elements, and subtract – adeneo Commented Feb 6, 2016 at 13:25
  • @adeneo That would get me the space between the tops of the two elements. I need the space between the bottom of the first element and the top of the second. However, using offset() might save me a little work. Maybe I don't need to worry about however the elements are nested if I can accurately measure the height of the element. I've been playing around with this in a pen and it doesn't look like jQuery can do this, but I can get it with the offsetHeight DOM element property. – Vince Commented Feb 7, 2016 at 1:56
Add a ment  | 

2 Answers 2

Reset to default 2

How about:

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./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>

The solution is to use the offset().top values of the two elements (as indicated by @adeneo and @georg) and subtract the height of the first element. I don't need to calculate the borders, margins, and padding myself.

It wasn't as difficult to find the next element as I originally thought it would be.

Determining the height of the first element isn't too tricky, but neither height() nor innerHeight() will do it. I have to use the property offsetHeight on the DOM element.

I need something like this:

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

I wouldn't have been able to figure this out if it weren't for the ment by @adeneo and the answer by @georg, but neither one provided a full solution.

The following example also has a slightly more detailed version at 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./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./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>

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1745273499a4619894.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信