Scroll to specific element

Hi,

Is there a way to scroll to a specific element in ion-content or at least to get specific element’s dimensions in ion-content by id?

There was a simple way to scroll to an element in Ionic 1:
$ionicScrollDelegate.$getByHandle('scroll').anchorScroll("#" + $location.hash(id));

There is no information about this in the docs for Ionic 2 (http://ionicframework.com/docs/v2/api/components/content/Content/).

Thanks!

1 Like

Is there a solution?

I am stuck.

One solution is the method scrollTo(x, y, duration) of Content: http://ionicframework.com/docs/v2/api/components/content/Content/

But you have to figure out the height of the elements by yourself to calculate the y position to scoll to. Unfortunately as far as I know there is no method yet for getting the current scroll position to be able to scroll relatively. Thus you have to calculate the absolute position. Hope this helps!

did u get this work? I looking for a solution too

is it possible to replace this.content with an element ID and scroll to it?

1 Like

Is there a way to implement this in ionic?

My Specific Requirement

  • I have implemented an accordion which dynamically increases the scroll area, no issues there.
  • Is there a way to bring whole of the recently expanded section of the accordion to the view area so that scroll can be avoided.

Something like http://codepen.io/bengtweisse/pen/aKvwE in Ionic v2 is what I have in mind.

I have been binding id properties of JSON obects that I am dynamically displaying via *ngFor to their respective HTML element ids, e.g:

<p *ngFor="let jsonObj of myObjects" [id]="jsonObj.id">

In my page component, I have a method that takes the same id as an argument and gets the offsetTop property of the dom element with this id, which I then use as the y value to scroll to:

  scrollTo(element:string) {
    let yOffset = document.getElementById(element).offsetTop;
    this.content.scrollTo(0, yOffset, 4000)
  }

Currently, this does a nice scroll to the element, although I’m not sure how reliable the offsetTop property will be with more complex layouts. For your need, I think you would first call content.resize() to update the layout, and then use the element id of the target accordion element to get the offsetTop value to scroll to. All pure conjecture of course. :wink:

16 Likes

Thank you so much, intelinc! It works very well.

I’m having trouble using this
do you literally have element: string and this.content in your code or do those stand for other variables specific to the project?
Also, why is scrollTo within itself?

Apologies if this is a dumb question, I am not well versed in coding jargon .

‘element’ should be replaced with the id of the element you want to scroll to. this.content.scrollTo() is a method of the ion-content component: http://ionicframework.com/docs/v2/api/components/content/Content/#scrollTo

I arbitrarily named the method scrollTo() in my page component. You could name this whatever you want. My scrollTo() method is defined on the page component; the ion-content scrollTo() method is part of the ionic API. (perhaps confusingly) named the same, but they are two different methods on two separate components. hth.

1 Like

Hello. You mind posting an example. I’m having a hard time distinguishing your code from what I’m supposed to be using.

I have an isssue with scrollTo element

after element got visible which is hidden i got scrollTo undefined

<ion-card> <img src="img/advance-card-map-madison.png"> <ion-fab right top> <button ion-fab (click)="scrollToElement('firstElement')"> <ion-icon name="pin"></ion-icon> </button> </ion-fab> </ion-card>

<ion-card id="firstElement" [hidden]="!firstView"> <img src="img/advance-card-map-madison.png"> <ion-fab right top> <button ion-fab> <ion-icon name="pin"></ion-icon> </button> </ion-fab> </ion-card>

`@ViewChild(Content) content: Content;

scrollToElement(elementId){
this.firstView = true;
let yOffset = document.getElementById(elementId).offsetTop;
this.content.scrollTo(0, yOffset, 2000)
}`

But in my view initially element is hidden and after element made visible “this.content.scrollTo” getting undefined

When there is no hidden condition at that time scrollTo working absolutely fine

How can i fix this any idea??

I also tried with timeout, but not useful

  1. Wrap the card in a div. Put the [hidden] in the div instead of the card.

  2. Inject ChangeDetectorRef into your constructor.

  3. Call changeDetectorRef.detectChanges() after you change the firstView variable, and before you call document.offsetTop.

  4. Then proceed as before.

Scroll is not smooth in ios if ion-list is used with ngFor in ion-content.

Try using virtual scroll or the other one to make it faster

 let b = document.getElementById('whateverid');
 if (b) b.scrollIntoView({ behavior: "instant" })
3 Likes

This is not supported in WKWebView, in iOS,

scrollIntoView() with parameters objects doesn’t work in Safari:
https://caniuse.com/#search=scrollintoview

hi @Eugene1,

I did it creating a method pointing to my element indicated (i am using ionic 4)

here a simple example

In html code:
I have some buttons that point to different ion-cards


<!-- dont forget put "#content" inside "ion-content" -->

<ion-content padding #content> 

<ion-infinite-scroll >

    <ion-infinite-scroll-content loadingSpinner="null" loadingText=""
      style="align-items: flex-start; text-align: start;">


<ion-grid>

        <ion-row>

          <ion-col >
            <ion-button expand="full" (click)="scrollEmbarcacoes()" >Embarcações</ion-button>
          </ion-col>

          <ion-col>
            <ion-button expand="full"(click)="scrollplataformas()" >Plataformas</ion-button>
          </ion-col>


          <ion-col>
            <ion-button expand="full">Viajantes</ion-button>
          </ion-col>




        </ion-row>

      </ion-grid>



<ion-card class="welcome-card" id="plataformas">
        <ion-card-content>
          <span class="ion-text-left" style="align-items: flex-start;" item-justify>
            <ion-title style="align-items: flex-start;">
              <ion-text text-wrap style="font-size:large;color: black;">
                Plataformas
              </ion-text>
            </ion-title>
          </span>
        </ion-card-content>
      </ion-card>


<ion-card class="welcome-card" id="embarcacoes">
        <ion-card-content>
          <span class="ion-text-left" style="align-items: flex-start;" item-justify>
            <ion-title style="align-items: flex-start;">
              <ion-text text-wrap style="font-size:large;color: black;">
                Plataformas
              </ion-text>
            </ion-title>
          </span>
        </ion-card-content>
      </ion-card>


   </ion-infinite-scroll-content>
  </ion-infinite-scroll>

</ion-content>

In ts code, i put it:

scrollEmbarcacoes(){

 let yOffset = document.getElementById("embarcacoes").offsetTop;
 this.content.scrollToPoint(0, yOffset, 2000);

}


scrollplataformas(){
  let yOffset = document.getElementById("plataformas").offsetTop;
  this.content.scrollToPoint(0, yOffset, 2000);

}

Dont forget to import (in my case) on:

import { Component, OnInit, ViewChild } from '@angular/core';
import { IonContent, Platform } from '@ionic/angular';

and create (before constructor):

  @ViewChild('content', { static: true }) content: IonContent;