Home > Blockchain >  How do I calculate how far down a div I'm scrolling based on the viewport and the div's po
How do I calculate how far down a div I'm scrolling based on the viewport and the div's po

Time:12-20

I'm building a blog with a system to see how deep in an article the visitor is currently in, the result is in percentage.

To simplify some elements, I'm tracking the bottom border of the browser and comparing it to the article's actual position. The page itself is composed of a banner with some items inside (title, metadata, etc), then the article itself is displayed under it, but the banner's height is 60vh. The article has no set height, and no overflow: scroll property.

This is how I'm currently doing it:


const getScrollPercent = () => {
    const prose = document.querySelector<HTMLDivElement>('.prose')

    if (prose) {
        // closest way I got the actual div's top side)
        const proseTop = prose.getBoundingClientRect().top   document.documentElement.scrollTop
        const proseBottom = proseTop   prose.offsetHeight
        const browserBottom = window.scrollY   window.innerHeight

        if (browserBottom < proseTop) {
            return 0
        } else if (browserBottom > proseTop && browserBottom < proseBottom) {
            return (browserBottom / proseBottom) * 100
        } else {
            return 100
        }
    } else {
        return 0
    }
}

However, the behavior is a bit off: As long as I don't have the .prose div in my viewport, it displays 0 percent, which is completely ok. However, at the first pixel, the percentage jumps to ~24%, and then it finishes smoothly at 100% once reaching the div's bottom.

I don't really know if it's my way of calculing the div's height that's not good, or how I calculate the progressing percentage.

Edit: Html structure

(It's a Nuxt/VueJS context)


<nav>
<!-- Contains some links-->
</nav>

<main>
  <header>
    <h1>Some article title with a banner in background</h1>
    <div >
      <!-- Some meta infos (tags, creation date, etc) -->
    </div>
  </header>
  <div >
    <span >
      {{ getScrollPercent }}%
    </span>
  </div>

  <article>
    <!-- lots of <p> and <h2> to <h6> tags, about 2200px high) !-->
  </article>

</main>

CodePudding user response:

Dividing by proseBottom is not the right way to do this. If proseTop is 5000, height is 200, proseBottom is going to be 5200. So even when browser bottom is at 5000, you are going to be at 5000/5200 percent, which isn't what you want (right?)

I think what you want is

(proseTop - browserBottom) / proseHeight * 100;

This is how you calculate the percentage of the prose field that is off screen below

CodePudding user response:

You need to get the reference of your div node first. in react most likely use useRef

const yourDivRef = useRef()
//then in your actual div
<div ref={yourDivRef}/>

then you could calculate ur position with code below

const node = yourDivRef.current
const offsetHeight = node.scrollHeight // this is about how height your ref div is
const innerHeight = node.clientHeight // this is how height your browser window is
const scrollTop = node.scrollTop // this is where you scroll position at

for example: if you want to get if you scroll reach the bottom you do

// check if scroll reach within 5px to the bottom 
 const hasReachedBottom = offsetHeight - (innerHeight   scrollTop) <= 5

so as your asked:

(innerHeight   scrollTop) / offsetHeight 

should be the percentage of position where you at in your div

Also don't forget to init the scroll Event listener.

useEffect(() => {
// handleScroll should be the place you do all the math. 
    listenTarget.addEventListener('scroll', handleScroll)
    return () => listenTarget.removeEventListener('scroll', handleScroll)
  }, [node])

I hope you find this is answer your question.

  • Related