#### Since 15.1.0

Scrollspy service and set of directives help to watch scroll position changes of the document or a specific container and get notified when a part of it is scrolled into or out of the viewport.

The core scrollspy implementation is a `NgbScrollSpyService` that is based on an `IntersectionObserver`. You can see the example of the service working on this very page to highlight which documentation section is currently active.

You should at least specify which container you'd like to spy on and which sections (fragments) inside this container should be watched. Fragments are identified by unique `id` attributes.

For example, if you want to watch for the document scroll changes, you need to do at least the following:

You can also pass multiple options when starting a service. For example, you can set a specific container element instead of the whole document, configure the intersection observer and change scrolling behavior.

You can use the service together with the `routerLink` directive and its `[fragment]` input, or you can force the scrollspy to get to a specific fragment via the `.scrollTo()` method.

The directive will help you to setup the scrollspy service instance on a specific container. It is merely a syntactic sugar around the service that will start and add fragments automatically, as well as clean everything up when host component is destroyed.

It will look something like this:

Please see and the demos and `NgbScrollSpy` API for all available inputs and outputs.

There are also two helper directives: `NgbScrollSpyMenu` and `NgbScrollSpyItem`. They will highlight the active item in a menu, nav or any custom list.

#### Individual items

`NgbScrollSpyItem` directive either gets the nearest scrollspy from the DI or uses the direct reference. It adds and removes `.active` class dynamically based on the current scrollspy state.

It has also several convenient ways of referencing related scrollspies and fragments:

For more details, please see the related remo

#### Hierarchical menus

In case of multiple nesting levels, you might want to highlight the whole branch of the menu and not only a single item. For this purpose, you can use the `NgbScrollSpyMenu` directive on a container with items.

It this case you might reference scrollspy only once at the menu level, or not reference at all if it is available via DI.

For more details, please see the related remo

If you want to customize the `IntersectionObserver` you can pass `rootMargin` and `threshold` options when starting the service.

If you don't like the default scrollspy behavior or would like to process intersection observer events on your own, you can completely override the algorithm by providing your own implementation function via the `[processChanges]="myCustomProcess"` input or set it directly via the service start options.

For example, default scrollspy implementation doesn't allow for gaps in-between items, ex. if you're in-between fragments 'one' and 'two' ('one' is not visible anymore and 'two' is not visible yet), we'll still mark item 'one' as active.

If you provide your own function, you'll get the list of the intersection observer entries and you can process them as you wish. You can use the current scrollspy state and it's up to you to call the provided `changeActive()` method when it's time to change the active fragment. You can also use the `context` that is persisted across the calls.