How do I calculate space between two elements?
<p>How can I calculate the amount of space between one element and the next rendered element?</p>

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

<p>The reason I need this is that I need to insert an element after the <code>hr</code>, <code>position: relative</code>, 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.</p>

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

<p>Here's an example of HTML that I'm working with:</p>

<pre class="lang-html prettyprint-override"><code>&lt;div class="extra-wrapper"&gt;
    &lt;p&gt;The line that separates the header from the rest of the page is below this.&lt;/p&gt;
    &lt;hr&gt;
&lt;/div&gt;
&lt;p class="top-p"&gt;
    Lorem ipsum dolor...
&lt;/p&gt; 
</code></pre>

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

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

<p><div class="snippet" data-lang="js" data-hide="false" data-console="false" data-babel="false">
<div class="snippet-code">
<pre class="snippet-code-js lang-js prettyprint-override"><code>$(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 &gt; hr_bottom_margin) {
    biggest_margin = extra_wrapper_bottom_margin;
  } else {
    biggest_margin = hr_bottom_margin;
  }

  if (next_element_top_margin &gt; 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);
});</code></pre>
<pre class="snippet-code-css lang-css prettyprint-override"><code>div.extra-wrapper {
  padding: 0.5em 0;
  margin-bottom: 1em;
}
div.extra_wrapper hr {
  margin: 1em;
}
p.top-p {
  margin: 1em;
}</code></pre>
<pre class="snippet-code-html lang-html prettyprint-override"><code>&lt;script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"&gt;&lt;/script&gt;
&lt;div id="header"&gt;
  &lt;p&gt;This is the header content.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="extra-wrapper"&gt;
  &lt;hr&gt;
&lt;/div&gt;
&lt;p class="top-p"&gt;
  Lorem ipsum dolor...
&lt;/p&gt;
&lt;label&gt;Space:
  &lt;input id="space" type="text"&gt;
&lt;/label&gt;</code></pre>
</div>
</div>
</p>