Keep div fixed when it is inside it's container on scroll
This is not really a full answer yet, but after correcting my interpretation of your question (as reflected by comments under it) I keep having some incertainties, and a comment is not wide enough to clearly express them.

Anyway I can already notice some possible improvements, not depending on any further precision:


Cosmetic: the right: 0; property can be suppressed from span.bottom rule, since it doesn't change compared to span one.
Performance:


since their value never changes, declaration of span, div, and divHeight can be moved outside of the scroll() event.
we also can fix $(window) by declaring it as var win at the same level.

Operation: depending on the window size, the initial state may not follow your requirements, e.g.:


When running the code snippet and immediately switching to full page the yellow span should have the bottom class, while it doesn't.
The same happens when toggling between full page and reduced iframe: if the state should change when reaching the new window size, it doesn't till scrolling happens.


Then to avoid that, the computation for affecting/dropping bottom class should occur not only when document.scroll() but also window.resize() event happens.
Additionally, each of those events should be initially fired (although in practice only one is enough).


Here is the so modified snippet:



var span = $('span'),
    div = $('div'),
    win = $(window),
    divHeight = div.height();
$(document).scroll(compute).scroll();
$(window).resize(compute).resize();
  
function compute() {
  var spanHeight = span.outerHeight(),
      spanOffset = span.offset().top + spanHeight,
      divOffset = div.offset().top + divHeight;

  if (spanOffset &gt;= divOffset) {
    span.addClass('bottom');
    var windowScroll = win.scrollTop() + win.height() - 50;
    if (spanOffset &gt; windowScroll) {
      span.removeClass('bottom');
    }
  }
  console.log('spanOffset='+spanOffset, 'windowScroll='+($(window).scrollTop() + $(window).height() - 50));
}
*{margin:0;}
div {
  position: relative;
  background: pink;
  height: 800px;
  margin-bottom: 800px;
}
span {
  position: fixed;
  right: 0;
  bottom: 50px;
  width: 10%;
  height: calc(100vh - 100px);
  background: gold;
}
.bottom {
  position: absolute;
  bottom: 0;
}
&lt;script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js"&gt;&lt;/script&gt;
&lt;div&gt;
  &lt;span&gt;some content&lt;/span&gt;
&lt;/div&gt;




Now let me explain what keeps puzzling me.
Both snippets (yours and mine) have the following wrong behaviour: as of a certain window height (couldn't precisely figure out yet), once switched to bottom the yellow span will never go back when scrolling up.

So before thinking further I'd want to be certain of what is precisely your need. Expressed independently from the current implementation, it seems to me that it is like follows:


as a fundamental requirement, the yellow span height must always be equal to window height minus a given height (say X, in this case 100px), and must not change
if not upset by the rule #3 below, the yellow span must be vertically centered in the window (its bottom is half the above given X)
taking over the rule #2, the yellow span must never cross the pink div (the bottom of the former can't move lower than the latter's one)


For now I remain pending. Thanks for confirming or correcting me.