Skip to content

bug: ion-segment scrollable IOS animation bug #29523

Closed
@rostislavcz

Description

@rostislavcz

Prerequisites

Ionic Framework Version

v7.x, v8.x

Current Behavior

When you use multiple segment items there is strange animation bug on ios devices when using scrollable option. (Android, Web - even Safari works fine)

<IonSegment scrollable={true} value="heart">
  <IonSegmentButton value="home">
    <IonIcon icon={home}></IonIcon>
  </IonSegmentButton>
  <IonSegmentButton value="heart">
    <IonIcon icon={heart}></IonIcon>
  </IonSegmentButton>
  <IonSegmentButton value="pin">
    <IonIcon icon={pin}></IonIcon>
  </IonSegmentButton>
  <IonSegmentButton value="star">
    <IonIcon icon={star}></IonIcon>
  </IonSegmentButton>
</IonSegment>

Here you can see the result on real device, i did a little CSS changes but tried also with original styles and there is the same result. I also did a little digging in your code and managed to solve the problem:

In Segment class there is method

private scrollActiveButtonIntoView(smoothScroll = true) {
  const { scrollable, value, el } = this;

  if (scrollable) {
    const buttons = this.getButtons();
    const activeButton = buttons.find((button) => button.value === value);
    if (activeButton !== undefined) {
      const scrollContainerBox = el.getBoundingClientRect();
      const activeButtonBox = activeButton.getBoundingClientRect();

      /**
        * Subtract the active button x position from the scroll
        * container x position. This will give us the x position
        * of the active button within the scroll container.
        */
      const activeButtonLeft = activeButtonBox.x - scrollContainerBox.x;

      /**
        * If we just used activeButtonLeft, then the active button
        * would be aligned with the left edge of the scroll container.
        * Instead, we want the segment button to be centered. As a result,
        * we subtract half of the scroll container width. This will position
        * the left edge of the active button at the midpoint of the scroll container.
        * We then add half of the active button width. This will position the active
        * button such that the midpoint of the active button is at the midpoint of the
        * scroll container.
        */
      const centeredX = activeButtonLeft - scrollContainerBox.width / 2 + activeButtonBox.width / 2;

      /**
        * We intentionally use scrollBy here instead of scrollIntoView
        * to avoid a WebKit bug where accelerated animations break
        * when using scrollIntoView. Using scrollIntoView will cause the
        * segment container to jump during the transition and then snap into place.
        * This is because scrollIntoView can potentially cause parent element
        * containers to also scroll. scrollBy does not have this same behavior, so
        * we use this API instead.
        *
        * Note that if there is not enough scrolling space to center the element
        * within the scroll container, the browser will attempt
        * to center by as much as it can.
        */
      el.scrollBy({
        top: 0,
        left: centeredX,
        behavior: smoothScroll ? 'smooth' : 'instant',
      });
    }
  }
}

Instead of el.scrollBy if I call el.scrollTo, the problem dissapears and it works as it should

Screen.Recording.2024-05-20.at.8.59.54.mov

Expected Behavior

The same result when you just change el.scrollBy to el.scrollTo

RPReplay_Final1716188775.mov

Steps to Reproduce

Run any basic Ionic/Capacitor project on ios device and use scrollable ion-segment with multiple items, that will has width more than 100% of device width

Code Reproduction URL

https://stackblitz.com/edit/dw3jre?file=package.json

Ionic Info

Ionic:

Ionic CLI : 7.0.1 (/usr/local/lib/node_modules/@ionic/cli)
Ionic Framework : @ionic/angular 8.0.0
@angular-devkit/build-angular : 17.3.5
@angular-devkit/schematics : 17.3.5
@angular/cli : 17.3.5
@ionic/angular-toolkit : 11.0.1

Capacitor:

Capacitor CLI : 6.0.0
@capacitor/android : 6.0.0
@capacitor/core : 6.0.0
@capacitor/ios : 6.0.0

Utility:

cordova-res : 0.15.4
native-run : 2.0.1

Additional Information

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    type: buga confirmed bug report

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions