5

The problem:

What would be the mathematical formula to calculate (regardless of the scrollHeight of the document) how far the bottom of the scrollbar is from it's total bottom (which would be the end of the page). So, for example, when the scrollbar is at the top, I would say the distance in percentages of the bottom of it, from the bottom of the document, would be 0%, and when it's totally scrolled all the way (vertically), it would be 100%.

My goal:

My goal is to calculate how many pixels there are between the bottom and a specific position which is, let's say 3%, relative to the viewport, above that bottom. Again, the document height should mean nothing. 3% are 3% if it's relative to the viewport.

Known variables:

var P              = 3 // in %
var totalHeight    = document.documentElement.scrollHeight;
var viewportHeight = document.documentElement.clientHeight;
Community
  • 1
  • 1
vsync
  • 118,978
  • 58
  • 307
  • 400
  • I believe you're looking for `offset()` => `viewportHeight - document.getElementById('mybottom').offset().top` or something along those lines. – Tim Vermaelen Feb 23 '15 at 15:40
  • @TimVermaelen - you can easily check it in the console if you open it here. using `getElementById` is not related to what I need. imagine there are no nodes at all in the body and it has a dynamic height from the CSS... – vsync Feb 23 '15 at 15:44
  • 1
    http://jsfiddle.net/ywy9ndao/ ? **Edit:** seems to work only in Chrome – blex Feb 23 '15 at 16:02
  • @blex - horrible code. I fixed it - http://jsfiddle.net/ywy9ndao/1/ – vsync Feb 23 '15 at 16:25
  • 1
    @vsync haha, I didn't want to bother fixing it before posting, because I was not even sure that was what you wanted. I just tried something randomly. – blex Feb 23 '15 at 16:33
  • Related: https://stackoverflow.com/questions/2387136/cross-browser-method-to-determine-vertical-scroll-percentage-in-javascript – baptx Jan 24 '21 at 14:07

2 Answers2

20

Returns a number between 0 to 100 relative to scroll position:

document.onscroll = function(){ 
  var pos = getVerticalScrollPercentage(document.body)
  document.body.innerHTML = "<span>" + Math.round(pos) + "%<span>"
}

function getVerticalScrollPercentage( elm ){
  var p = elm.parentNode
  return (elm.scrollTop || p.scrollTop) / (p.scrollHeight - p.clientHeight ) * 100
}
body{ height:2000px }
span{ position:fixed; font:5em Arial; color:salmon; }

Difference between scrollHeight & clientHeight

Limon Monte
  • 52,539
  • 45
  • 182
  • 213
vsync
  • 118,978
  • 58
  • 307
  • 400
1

When you scroll to the bottom, the final position value is equal to the height of your document minus the height of one screen (viewport). So if you compute:

scrollPositionRelative = scrollPosition / (documentHeight - viewportHeight);

The values will be in the range 0-1 as expected.

Here's the function used in the example given at the end.

function getScrollPosition () {
  var viewportHeight = Math.max(document.documentElement.clientHeight, window.innerHeight || 0); // Viewport height (px)
  var scrollPosition = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop; // Current scroll position (px)
  var documentHeight = $(document).height(); // Document height (px)
  var scrollPositionRelative = scrollPosition / (documentHeight - viewportHeight); // The document height is reduced by the height of the viewport so that we reach 100% at the bottom
  return {
    documentHeight: documentHeight,
    relative: scrollPositionRelative,
    absolute: scrollPositionRelative * documentHeight // Yields an "average" pixel position
  };
}

See it in action: http://jsbin.com/tawana/1/

  • Blex already answer that in the comments, and I've modified his solution to be even better. you solution is much worse..so I don't see any reason to post it if it's not improving the quality of the answers already exists in this thread – vsync Mar 09 '15 at 15:24
  • Teach me something today. Tell me why my solution is "much worse". – Nicolas Le Thierry d'Ennequin Mar 10 '15 at 06:44
  • You are using jQuery which unneeded and slow. it makes no sense to use jQuery, but you are using it anyway. This is especially wrong when dealing with events which "hammer" the CPU. also, you are using the `Math` method, which is not needed. – vsync Mar 10 '15 at 14:33
  • Need I tel you that SO is a resource where questions and answers can interest people beyond the original poster? You received an answer in a comment (good for you, and even better because you improved the "horrible code" proposed by @blex). But your question wasn't formally answered, and I wanted to explain a bit (not very much in words, true, but I hope the example was self-explanatory, if not optimized to suit your taste). But I see you are an angry guy with a sermon for everyone. – Nicolas Le Thierry d'Ennequin Mar 10 '15 at 14:50
  • not angry, just don't get it why would you post something that provides almost half the performance as what was established by the comments, with double the code. any person who later would come would see the 4 comments on the thread and be satisfied with the code. only chaos would be achieved by answers which are inferior. (a lot more code which runs a LOT slower) – vsync Mar 10 '15 at 15:50
  • You're talking a whole heap of nonsense, you don't get the point of this site, your "solution" is nowhere to be found on this page, it isn't cross-browser, part of it is useless, it uses the Math object too (I hear you don't like that). I leave you the last word, funny man – Nicolas Le Thierry d'Ennequin Mar 10 '15 at 16:31
  • 1. it does not use `math`. 2. i know point of this website, and talking about points, I have been contributing and editing/reviewing for 5 years, so your claim has no basis. 3. you simply claim it's not cross browser, while i tested it on IE9+, FF and Chrome, and it works, and I see no reason why it shouldn't. If you care that deeply about the comment being posted as an "answer", then I shall submit it as such. – vsync Mar 11 '15 at 18:34