2

I would like to calculate the current scroll percentage of my IonContent (it's an Ionic + React app)

The page layout looks like this:

<IonPage>
  <IonHeader>
    <IonToolbar>
      <IonButtons slot="start">
        <IonMenuButton />
      </IonButtons>
      <IonTitle>Page</IonTitle>
    </IonToolbar>
  </IonHeader>
  <IonContentid="main-content"
    scrollEvents={true}
    onIonScroll={(ev) => {
      // ToDo: calculate scroll percentage
      console.log(ev.detail.scrollTop);
    }}>
    {// very long custom component
    }
    <IonFooter>
      <IonLabel>Footer </IonLabel>
    </IonFooter>
  </IonContent>
</IonPage>

From the IonScroll event, I can read out the scrollTop which seems to be the current scroll position.
Now I need to get the maximal scrolling height of the IonContent.

Related questions are:

The accepted answer from the first question seems to provide the most complete approach, by taking the max over a selection of scrolling height values:

var limit = Math.max( document.body.scrollHeight, document.body.offsetHeight, 
                   document.documentElement.clientHeight, document.documentElement.scrollHeight, document.documentElement.offsetHeight );

I've extended this by also adding:

document.scrollingElement.scrollHeight

The problem:

In my scenario, the maximum over these values is around 660. But the logging output from ev.detail.scrollTop goes up to 680.76.
I've connected the debug inspector and tried scrolling from the console, to see what would happen for scroll value around 660. I can still see the content move when scrolling from 660 to 680:

document.getElementById('main-content').scrollToPoint(0, 680);

How can I find the maximum scrolling coordinates?

lhk
  • 27,458
  • 30
  • 122
  • 201

1 Answers1

5

I think I found the solution:

onIonScroll={async (ev) => {
  const elem = document.getElementById("ion-content-id");

  // the ion content has its own associated scrollElement
  const scrollElement = await ( elem as any).getScrollElement()

  const scrollPosition = ev.detail.scrollTop;
  const totalContentHeight = scrollElement.scrollHeight;
  const viewportHeight = elem.offsetHeight;

  const percentage = scrollPosition / (totalContentHeight - viewportHeight);
  console.log(percentage);
}}

I don't understand why this incompatibility was introduced though. Wouldn't it be possible to connect the scrollElement of the IonContent with document.scrollingElement? The standard is still a draft but implemented in all major browsers (expect IE).

lhk
  • 27,458
  • 30
  • 122
  • 201
  • Your answer is really helpful, but was wondering, is the "async" necessary? – Henry Dec 07 '20 at 14:59
  • Nvm, ignore my previous question, I tried removing "async" and it didnt work, keeps getting undefined or NaN. – Henry Dec 08 '20 at 01:26
  • Thanks heaps for this. I wouldn't have found that! I wonder if this is a better calculation for viewportHeight? const viewportHeight = elem.getBoundingClientRect().top + elem.offsetHeight; – Damien Sawyer Jul 02 '21 at 17:27