Ion-picker not working properly and moving by its own

Hi guys! I’m having a problem with the component ion-picker when trying to use it so the user can set a timer choosing values from three columns. I created an issue in Github as this problem seems to be only happening when emulating in tablets. Am I missing something here? Is there any workaround for this kind of situation?

Current Behavior

When using ion-picker component to let the user choose how much time will a timer run, the ion-picker moves by its own and doesn’t stay in the column option that the user has set. This happens only in tablets simulators in the browser (I don’t have a tablet my own to test this).

This has been tested in Chrome and Mozilla. It doesn’t seem to be an Apple thing, as in the iPhone devices it works properly.

In Mobile - iPhone 12 pro (it works OK in other mobile devices too)

Image

In tablet - iPad Pro (it happens in all the tablets)

Image

Expected Behavior

Ion-picker column does not change its values by its own in tablets as it does in mobile devices.

Steps to Reproduce

  1. Create the next HTML and TS file:

This is my component HTML:

<ion-picker class="custom-picker">
  <ion-picker-column 
    [value]="selectedHour" 
    (ionChange)="hourChanged($event)">
    <ion-picker-column-option *ngFor="let num of hourOptions" [value]="num">{{ num }}</ion-picker-column-option>
  </ion-picker-column>
  <ion-picker-column 
    [value]="selectedMinute" 
    (ionChange)="minuteChanged($event)">
    <div class="two-dots" slot="prefix">:</div>
    <ion-picker-column-option *ngFor="let num of secMinOptions" [value]="num">{{ num }}</ion-picker-column-option>
    <div class="two-dots" slot="suffix">:</div>
  </ion-picker-column>
  <ion-picker-column 
    [value]="selectedSecond" 
    (ionChange)="secondChanged($event)">
    <ion-picker-column-option *ngFor="let num of secMinOptions" [value]="num">{{ num }}</ion-picker-column-option>
  </ion-picker-column>
</ion-picker>

This is my TS file:

import { CommonModule } from '@angular/common';
import { AfterViewInit, Component, ElementRef, EventEmitter, Output, ViewChild } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { IonicModule, IonPicker } from '@ionic/angular';

@Component({
  selector: 'app-custom-class-length',
  standalone: true,
  imports: [IonicModule, FormsModule, CommonModule],
  templateUrl: './custom-class-length.component.html',
  styleUrls: ['./custom-class-length.component.scss'],
})
export class CustomClassLengthComponent implements AfterViewInit {
  @Output() timeChanged = new EventEmitter<string>();
  selectedHour: string = '00';
  selectedMinute: string = '00';
  selectedSecond: string = '30';
  hourOptions = Array.from({ length: 24 }, (_, i) => i.toString().padStart(2, '0'));
  secMinOptions = Array.from({ length: 60 }, (_, i) => i.toString().padStart(2, '0'));

  constructor() {}

  ngAfterViewInit(): void {
    setTimeout(() => {
      const picker = document.querySelector('ion-picker.custom-picker');
      if (picker && picker.shadowRoot) {
        const beforeEl = picker.shadowRoot.querySelector('.picker-before') as HTMLElement;
        const afterEl = picker.shadowRoot.querySelector('.picker-after') as HTMLElement;
    
        if (beforeEl) beforeEl.style.background = 'transparent';
        if (afterEl) afterEl.style.background = 'transparent';
      }

      const pickerOptions = document.querySelectorAll('ion-picker-column-option');

      pickerOptions.forEach((option) => {
        const shadowButton = option.shadowRoot?.querySelector('button');
        
        if (shadowButton) {
          shadowButton.style.height = '100%';
          shadowButton.style.lineHeight = 'unset';
        }
      });
    }, 100);
  }

  getSelectedTime() {
    return 
  }

  hourChanged(event: CustomEvent) {
    this.selectedHour = event.detail.value;
    this.emitTime();
  }

  minuteChanged(event: CustomEvent) {
    this.selectedMinute = event.detail.value;
    this.emitTime();
  }

  secondChanged(event: CustomEvent) {
    this.selectedSecond = event.detail.value;
    this.emitTime();
  }

  private emitTime() {
    let timeValue = `${this.selectedHour}:${this.selectedMinute}:${this.selectedSecond}`
    console.log(timeValue)
    this.timeChanged.emit(timeValue);
  }
}
  1. Run Ionic serve in Mozilla or Chrome
  2. Select device view and choose iPad Pro or any tablet
  3. Change the selected option

Ionic Info

Versions:
Ionic:

Ionic CLI : 7.2.0
Ionic Framework : @ionic/angular 8.5.0
@angular-devkit/build-angular : 18.2.15
@angular-devkit/schematics : 18.2.15
@angular/cli : 18.2.15
@ionic/angular-toolkit : 11.0.1

Capacitor:

Capacitor CLI : 7.1.0
@capacitor/android : 7.0.1
@capacitor/core : 7.1.0
@capacitor/ios : 7.0.1

Utility:

cordova-res : 0.15.4
native-run : 2.0.1

System:

NodeJS : v22.12.0
npm : 10.9.0
OS : Linux 5.15

Additional Information

No response

This could be related to scaled fonts in this open issue - bug: ion-datetime wheel breaks in Android WebView with scaled fonts · Issue #29713 · ionic-team/ionic-framework · GitHub.

And in the future, please include the link to the issue you opened. Here it is for others - bug: ion-picker moving by its own when emulated in tablet · Issue #30299 · ionic-team/ionic-framework · GitHub