Mouse wheel scrolling in Angular

October 22nd 2021 Angular

When you enable scrolling for an HTML element with content that overflows vertically, browsers automatically support scrolling with the mouse wheel when you hover over that element. This is not the case when the content overflows horizontally. To support this, some JavaScript code is required.

Here is a small example of content that can overflow horizontally:

<div class="container">
  <div class="items">
    <div class="item" *ngFor="let item of items">{{ item }}</div>
  </div>
</div>

There must be enough items for this to happen and the elements must be rendered in a single line, e.g. with flex layout:

.container {
  overflow-x: scroll;

  .items {
    display: flex;
    gap: 10px;

    .item {
      height: 100px;
      border: 1px solid;
      flex: 0 0 100px;
      display: flex;
      justify-content: center;
      align-items: center;
    }
  }
}

Mouse wheel scrolling can be added to the container element by handling its wheel event. In Angular, you can make this behavior reusable using attribute directives:

@Directive({
  selector: "[appHorizontalScroll]",
})
export class HorizontalScrollDirective {
  constructor(private element: ElementRef) {}

  @HostListener("wheel", ["$event"])
  public onScroll(event: WheelEvent) {
    this.element.nativeElement.scrollLeft += event.deltaY;
  }
}

The implementation is quite simple: it adds the vertical delta value to the horizontal position of the scrollbar. DOM ensures that the resulting value stays within the bounds.

To apply the behavior, add the directive to the HTML element:

<div class="container" appHorizontalScroll>
  <div class="items">
    <div class="item" *ngFor="let item of items">{{ item }}</div>
  </div>
</div>

That's all you need to do.

Since you no longer need the scrollbars for scrolling, you can now hide them. This can be done with CSS, but the details differ between Firefox and the other browsers:

.container {
  overflow-x: scroll;
  scrollbar-width: none; // hide scrollbar in Firefox

  &::-webkit-scrollbar {
    display: none; // hide scrollbar in Chromium
  }

  // ...
}

To see the approach in action, you can check out a sample application in my GitHub repository that demonstrates this.

To control the horizontal scrollbar of an HTML element with a mouse wheel, you need to handle its wheel event and adjust the position of the scrollbar in it accordingly. In an Angular application, the best way to do this is with an attribute directive.

Get notified when a new blog post is published (usually every Friday):

If you're looking for online one-on-one mentorship on a related topic, you can find me on Codementor.
If you need a team of experienced software engineers to help you with a project, contact us at Razum.
Copyright
Creative Commons License