72

What I want to achieve is a click to and do a smooth scroll to bottom / specified div area which i define with hashtag just like i think it should be like this.

here is the live example in the w3school example which is written for JQuery: https://www.w3schools.com/jquery/tryit.asp?filename=tryjquery_eff_animate_smoothscroll

What I do is peek from this answer: Angular2 Routing with Hashtag to page anchor

but i don't really understand the answer, the answer is looked like this :

this part is HTML part :

<a [routerLink]="['somepath']" fragment="Test">Jump to 'Test' anchor </a>

and below this, the router.navigate is where should I put the code? component.ts right? but how do i access this function? should i implement (click)?

this._router.navigate( ['/somepath', id ], {fragment: 'test'});

and below this, i get it, which it should write in my component.ts :

** Add Below code to your component to scroll**

  import {ActivatedRoute} from '@angular/router'; // <-- do not forget to import

  private fragment: string;

  constructor(private route: ActivatedRoute { }

  ngOnInit() {
    this.route.fragment.subscribe(fragment => { this.fragment = fragment; });
  }

  ngAfterViewInit(): void {
    try {
      document.querySelector('#' + this.fragment).scrollIntoView();
    } catch (e) { }
  }

what is the "somepath" mean? I should add a route in my routes.ts right? usually, i add a new path in here for example like this :

export const routes: Routes = [
  { path: '', redirectTo: '/home', pathMatch: 'full' },
  { path: 'product', redirectTo: '/product' },
  ...homeRoutes,
  ...productRoutes
];

can anyone provide me with full example code in HTML, routes, and component?

Ke Vin
  • 3,478
  • 11
  • 60
  • 91
  • from what i read and what i search, it will be a hell of a code for just a SMOOTH SCROLL its not simply like JQuery i think, so i decided to use this plugins which is work perfectly : https://www.npmjs.com/package/@nicky-lenaers/ngx-scroll-to feel free to use it – Ke Vin Oct 11 '17 at 08:41

15 Answers15

125

I was looking for a similar solution and tried to use the ngx-scroll-to package and found that its not working in latest version of angular (angular 6+) so decided to look into other option and found a solution which uses the browser's native scrollIntoView and this seems to be the best solution so far

HTML code :

<button (click)="scrollToElement(target)"></button>
<div #target>Your target</div>

Ts code :

scrollToElement($element): void {
    console.log($element);
    $element.scrollIntoView({behavior: "smooth", block: "start", inline: "nearest"});
  }
Simon_Weaver
  • 140,023
  • 84
  • 646
  • 689
Joel Joseph
  • 5,889
  • 4
  • 31
  • 36
  • 5
    Super! Right now the best solution. You would also need a Polyfill in order support more browsers: https://github.com/iamdustan/smoothscroll – Florian D. Aug 22 '18 at 23:48
  • It seems to me that this, with the polyfill, is the correct answer. – Karptonite Nov 20 '18 at 15:43
  • A simple and "native" solution that doesn't require an external library seems to be the best one – azakgaim Dec 17 '18 at 17:19
  • 2
    Note that unfortunately this doesn't work on iOS Safari - seems that `scrollIntoViewOptions` isn't supported at all. – Simon_Weaver Apr 21 '19 at 05:37
  • 2
    *IMPORTANT* now Nicky Lenaers ngx-scroll-to supports Angular 8! – Philipp Wirth Sep 16 '19 at 08:16
  • how can we combine `scrollIntoView` function with a fixed header? – chris Nov 03 '19 at 19:50
  • It's not obvious from your example what are you passing in `target` variable to `scrollToElement()` function. Can you please explain? – A. David Aug 10 '20 at 12:55
  • It should be noted that this solution (and all the other solutions except for the CSS one which is not widely supported), will not update the router and browser URL history. This means there's no back/forward navigation, and scroll to fragment using URL functionality. – ktsangop Apr 20 '21 at 11:26
43

CSS only solution

html {
  scroll-behavior: smooth;
}

It works even after navigation or page reload.

Please note that it does not work in IE, Edge or Safari.

Ilker Cat
  • 1,862
  • 23
  • 17
  • 2
    This can break a lot of stuff. We had to disable it because of a 3rd party modal no longer working property (due to auto-focus). Be very very careful – Spock Mar 04 '22 at 08:24
25

You can simply do this in your component.

const element = document.querySelector("#destination")
if (element) element.scrollIntoView({ behavior: 'smooth', block: 'start' })

Ref: https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollIntoView

Haroon Yousuf
  • 504
  • 4
  • 9
  • Didn't work for me but when I switched the first line in the above code example to: const element = document.getElementById("#destination"); then it worked. – StackOverflowUser Jun 28 '21 at 06:56
8

In new Angular versions the solution is:

component.html

<p (click)="scrollTo()">scroll</p>
   .
   .
   .
<form id="myForm">
   .
   .
   .
</form>

component.ts

constructor(private viewportScroller: ViewportScroller) {}

scrollTo() {
    this.viewportScroller.scrollToAnchor('myForm');
}

your-general-styles.css

html {
  scroll-behavior: smooth;
}
beanic
  • 539
  • 6
  • 22
5
 // you can use ViewportScroller calss
 constructor(
        private viewPortscroller: ViewportScroller
        ) {}

scrollingTop() {
    this.viewPortscroller.scrollToPosition([0 , 0]);
  }

// and for smoothly scroll you can do that

html, body {
     height: 100%;
     scroll-behavior: smooth;
 }
Sherif Fahd
  • 91
  • 1
  • 2
5

you have to add the flowing:

1- in app-routing.module.ts :

@NgModule({
  imports: [RouterModule.forRoot(routes,
      {
        useHash: true,
        scrollPositionRestoration: 'top',
        anchorScrolling: 'enabled',
        scrollOffset: [0, 64],
        relativeLinkResolution: 'legacy'
      }
    )],
  exports: [RouterModule]
})
export class AppRoutingModule { }

2- in style.scss :

body, html {
  overflow-x: hidden;
  scroll-behavior: smooth !important;
}

3- in the .html file :

<li>
    <a routerLink="home">Home</a>
</li>
<li>
    <a routerLink="." fragment="about">About</a>
</li>

OR like this:

<div class="mt-4">
      <a class="main-button" style="margin-left: 0px;" routerLink="." fragment="testimonials">
           testimonials
       </a>
</div>
Suliman Farzat
  • 1,197
  • 11
  • 12
  • Just to add on to this for those wondering, you also need to give your element an `id` of whatever the `fragment` name is. In this example, `about` is the fragment, so the about section (anchor) needs to have `id="about"` – ntgCleaner May 03 '23 at 03:09
3

I just used ngx-page-scroll. It can be as simple as:

<a class="nav-link nav-item-text" pageScroll href="#categories">Categorias</a>

....

<section id="categories">

Visit the package page for more information: https://www.npmjs.com/package/ngx-page-scroll

It also provides mechanisms to configure scrolling process, or event implement custom behavior through a service that controls the scrolling from the component's controller.

1

Try removing the square brackets:

class="startScroll" scrollTo="'#firstDiv'" scrollBoxID="'#scrollBox'"
Graham
  • 7,431
  • 18
  • 59
  • 84
Gmak
  • 19
  • 1
1

I got it work by doing this, consider that top-page is the id that you want to scroll to.

document.getElementById("top-page").scrollTo({ behavior: "smooth", top: 0 });
Hoang Minh
  • 1,066
  • 2
  • 21
  • 40
1

you could use css with this :

html {
  scroll-behavior: smooth;
}
jadar_m
  • 39
  • 3
1

document.getElementById("top-page").scrollIntoView({ behavior: "smooth" });

Anonymous
  • 21
  • 3
1

You can do it with the help of ViewportScroller which defines a scroll position manager. First of all, you have to inject it in the constructor like the following:

import { ViewportScroller } from '@angular/common';
...
constructor(
   ...
   private readonly _viewportScroller: ViewportScroller){}
...

Then

this._viewportScroller.scrollToPosition([0, 0])

NOTE

Add this style to your CSS or SCSS file to add a smooth scroll effect in your app.

html {
  scroll-behavior: smooth;
}

Methods

ScrollToPosition

/**
 * Scrolls to a specified position.
 * @param position A position in screen coordinates (a tuple with x and y values).
 */
abstract scrollToPosition(position: [number, number]): void;

ScrollToAnchor

/**
 * Scrolls to an anchor element.
 * @param anchor The ID of the anchor element.
 */
abstract scrollToAnchor(anchor: string): void;

setOffset

getScrollPosition

setHistoryScrollRestoration

For More Information

Abolfazl Roshanzamir
  • 12,730
  • 5
  • 63
  • 79
0

Add the below lines in style.css to get nicescroll in your angular application page.

::-webkit-scrollbar {
    width: 5px;
}


::-webkit-scrollbar-thumb {
    border-radius: 10px;
    -webkit-box-shadow: inset 0 0 6px rgba(0,0,0,0.5); 
    background: #c3c3c3 !important;
}
Rohinibabu
  • 660
  • 10
  • 16
0

You can use the native feature for anchor-based scrolling in angular. Please refer to this link for more info.

-1
constructor(private el: ElementRef)

ngAfterViewInit() {
  setTimeout(() => {
    this.el.nativeElement.scrollIntoView({
      behavior: 'smooth',
      block: 'center',
    });
  }, 0);
}
Yuriy Gyerts
  • 1,464
  • 18
  • 30