开发者

Cross-Browser Method to Determine Vertical Scroll Percentage in Javascript

How can I find out开发者_开发问答 what percentage of the vertical scrollbar a user has moved through at any given point?

It's easy enough to trap the onscroll event to fire when the user scrolls down the page, but how do I find out within that event how far they have scrolled? In this case, the percentage particularly is what's important. I'm not particularly worried about a solution for IE6.

Do any of the major frameworks (Dojo, jQuery, Prototype, Mootools) expose this in a simple cross-browser compatible way?


Oct 2016: Fixed. Parentheses in jsbin demo were missing from answer. Oops.

Chrome, Firefox, IE9+. Live Demo on jsbin

var h = document.documentElement, 
    b = document.body,
    st = 'scrollTop',
    sh = 'scrollHeight';

var percent = (h[st]||b[st]) / ((h[sh]||b[sh]) - h.clientHeight) * 100;

As function:

function getScrollPercent() {
    var h = document.documentElement, 
        b = document.body,
        st = 'scrollTop',
        sh = 'scrollHeight';
    return (h[st]||b[st]) / ((h[sh]||b[sh]) - h.clientHeight) * 100;
}

If you prefer jQuery (original answer):

$(window).on('scroll', function(){
  var s = $(window).scrollTop(),
      d = $(document).height(),
      c = $(window).height();

  var scrollPercent = (s / (d - c)) * 100;
  
  console.clear();
  console.log(scrollPercent);
})
html{ height:100%; }
body{ height:300%; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>


I think I found a good solution that doesn't depend on any library:

/**
 * Get current browser viewpane heigtht
 */
function _get_window_height() {
    return window.innerHeight || 
           document.documentElement.clientHeight ||
           document.body.clientHeight || 0;
}

/**
 * Get current absolute window scroll position
 */
function _get_window_Yscroll() {
    return window.pageYOffset || 
           document.body.scrollTop ||
           document.documentElement.scrollTop || 0;
}

/**
 * Get current absolute document height
 */
function _get_doc_height() {
    return Math.max(
        document.body.scrollHeight || 0, 
        document.documentElement.scrollHeight || 0,
        document.body.offsetHeight || 0, 
        document.documentElement.offsetHeight || 0,
        document.body.clientHeight || 0, 
        document.documentElement.clientHeight || 0
    );
}


/**
 * Get current vertical scroll percentage
 */
function _get_scroll_percentage() {
    return (
        (_get_window_Yscroll() + _get_window_height()) / _get_doc_height()
    ) * 100;
}


This should do the trick, no libraries required:

function currentScrollPercentage()
{
    return ((document.documentElement.scrollTop + document.body.scrollTop) / (document.documentElement.scrollHeight - document.documentElement.clientHeight) * 100);
}


These worked for me perfectly in Chrome 19.0, FF12, IE9:

function getElementScrollScale(domElement){
        return domElement.scrollTop / (domElement.scrollHeight - domElement.clientHeight);
    }

function setElementScrollScale(domElement,scale){
        domElement.scrollTop = (domElement.scrollHeight - domElement.clientHeight) * scale;
    }


A Typescript implementation.

function getScrollPercent(event: Event): number {
  const {target} = event;
  const {documentElement, body} = target as Document;
  const {scrollTop: documentElementScrollTop, scrollHeight: documentElementScrollHeight, clientHeight} = documentElement;
  const {scrollTop: bodyScrollTop, scrollHeight: bodyScrollHeight} = body;
  const percent = (documentElementScrollTop || bodyScrollTop) / ((documentElementScrollHeight || bodyScrollHeight) - clientHeight) * 100;
  return Math.ceil(percent);
}


If you're using Dojo, you can do the following:

var vp = dijit.getViewport();
return (vp.t / (document.documentElement.scrollHeight - vp.h));

Which will return a value between 0 and 1.


This question has been here for a long time, I know, but I stumbled onto it while trying to solve the same problem. Here is how I solved it, in jQuery:

First, I wrapped the thing I wanted to scroll in a div (not semantic, but it helps). Then set the overflow and height on the wrapper.

<div class="content-wrapper" style="overflow: scroll; height:100px">
    <div class="content">Lot of content that scrolls</div>
</div>

Finally I was able to calculate the % scroll from these metrics:

var $w = $(this),
    scroll_top = $w.scrollTop(),
    total_height = $w.find(".content").height(),        
    viewable_area = $w.height(),
    scroll_percent = Math.floor((scroll_top + viewable_area) / total_height * 100);                

Here is a fiddle with working example: http://jsfiddle.net/prEGf/


Everyone has great answers, but I just needed an answer as one variable. I didn't need an event listener, I just wanted to get the scrolled percentage. This is what I got:

const scrolledPercentage = 
    window.scrollY / (document.documentElement.scrollHeight - document.documentElement.clientHeight)

document.addEventListener("scroll", function() {
  const height = window.scrollY / (document.documentElement.scrollHeight - document.documentElement.clientHeight)

  document.getElementById("height").innerHTML = `Height: ${height}`
})
.container {
  position: relative;
  height: 200vh;
}

.sticky-div {
  position: sticky;
  top: 0;
}
<!DOCType>
<html>

<head>
</head>

<body>
  <div id="container" class="container">
    <div id="height" class="sticky-div">
      Height: 0
    </div>
  </div>
</body>


First attach an event listener to some document you want to keep track

yourDocument.addEventListener("scroll", documentEventListener, false);

Then:

function documentEventListener(){
  var currentDocument  = this;
  var docsWindow       = $(currentDocument.defaultView); // This is the window holding the document
  var docsWindowHeight = docsWindow.height(); // The viewport of the wrapper window
  var scrollTop        = $(currentDocument).scrollTop(); // How much we scrolled already, in the viewport
  var docHeight        = $(currentDocument).height();    // This is the full document height.

  var howMuchMoreWeCanScrollDown = docHeight - (docsWindowHeight + scrollTop);
  var percentViewed = 100.0 * (1 - howMuchMoreWeCanScrollDown / docHeight);
  console.log("More to scroll: "+howMuchMoreWeCanScrollDown+"pixels. Percent Viewed: "+percentViewed+"%");
}


My two cents, the accepted answer in a more "modern" way. Works back to IE9 using @babel/preset-env.

// utilities.js

/**
 * @param {Function} onRatioChange The callback when the scroll ratio changes
 */
export const monitorScroll = onRatioChange => {
  const html = document.documentElement;
  const body = document.body;

  window.addEventListener('scroll', () => {
    onRatioChange(
      (html.scrollTop || body.scrollTop)
      /
      ((html.scrollHeight || body.scrollHeight) - html.clientHeight)
    );
  });
};

Usage:

// app.js
import { monitorScroll } from './utilities';

monitorScroll(ratio => {
  console.log(`${(ratio * 100).toFixed(2)}% of the page`);
});


I reviewed all of these up there but they use more complex approaches to solve. I found this through a mathematical formula; brief.

The formula goes Value/Total * 100. Say Total is 200 u wanna know the percentage of 100 out of 200, you do it 100/200 * 100% = 50% (the value)

pageYOffset = The vertical scroll count without including borders. When you scroll down to bottom you get the maximum count. offsetHeight = The total height of the page including borders! clientHeight = The height in pixels without borders but not to the end of content!

When u scroll to bottom u get pageyoffset of 1000 for example, whereas offsetHeight of 1200 and clientHeight of 200. 1200 - 200(clientheight) now u get paggeYOffset value in offsetHeight and so scrollPosition300(300 of 1000)/1000 * 100 = 30%.

`pageOffset = window.pageYOffset; pageHeight = document.documentElement.offsetHeight; clientHeight = document.documentElement.clientHeight;

percentage = pageOffset / (pageHeight - clientHeight) * 100 + "%";
console.log(percentage)`

The reason why we must do offsetHeight - clientHeight it is because client heights shows all the available content in px without borders, and offsetheight shows the available content including borders, whereas pageYOffset counts the scrolls made; The scrollbar is quite long to count the whole windows it counts the scrolls itself until reaches the end, the available space in scrollbar is in px pageYOffset, so to reach that number you substract offsetHeight - clientHeight to bring to the lower value of pageYOffset.

i'll update when i get on pc, please leave a comment to make it clear so i don't forget! Thanks :)


Using jQuery

$(window).scrollTop();

will get you the scroll position, you can then work out from there what the percentage is based on the window height.

There is also a standard DOM property scrollTop that you can use like document.body.scrollTop however I'm not sure how this behaves cross-browser, I would assume if there are inconsistencies then the jQuery method accounts for these.


var maxScrollTop = messages.get(0).scrollHeight - messages.height();
var scroll = messages.scrollTop() / maxScrollTop; // [0..1]


I found a way to correct a previous answer, so it works in all cases. Tested on Chrome, Firefox and Safari.

(((document.documentElement.scrollTop + document.body.scrollTop) / (document.documentElement.scrollHeight - document.documentElement.clientHeight) || 0) * 100)
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜