Ionic-framework: bug: ion-select cannot handle long lists with a visible scrollbar for web users (alert view, Ionic 4.4.2)

Created on 7 Jun 2019  路  7Comments  路  Source: ionic-team/ionic-framework

With Ionic 4.4.2, the ion-select component (with default alert interface) cannot be configured or styled to show a scrollbar for larger lists of more than 8 or so items. This makes the component unusable on larger lists where web-based users need scrollbars.

For lists of 10 to 20 items, there are temporary workarounds for changing the alert-wrapper max-height and adjusting the inner alert button height, but for larger 20+ lists, there doesn't seem to be any way to force a scrollbar on the inner content section of the alert (e.g. overflow-y: scroll on the alert-wrapper class).

After a lot of troubleshooting, it was easier to switch over to a plain select component for the larger. If this can't be easily fixed, then to support future CSS styling, it would be useful if there were an inner div inside of alert-wrapper, and if alert-wrapper could be set to overflow-y:scroll. There is something preventing overflow-y:scroll !important from taking effect on alert-wrapper, even in Chrome dev tools... maybe someone with more flex experience has a solution.

core bug

Most helpful comment

We are now using this workaround (in global.scss):

/*
 * This adds a scroll bar to ionic alerts
 */
.alert-radio-group::-webkit-scrollbar, .alert-checkbox-group::-webkit-scrollbar {
    width: 0.7em;
    display: block !important;
}

.alert-radio-group::-webkit-scrollbar-track, .alert-checkbox-group::-webkit-scrollbar-track {
    -webkit-box-shadow: inset 0 0 6px rgba(0,0,0,0.3);
    box-shadow: inset 0 0 6px rgba(0,0,0,0.3);
}

.alert-radio-group::-webkit-scrollbar-thumb, .alert-checkbox-group::-webkit-scrollbar-thumb {
    background-color: darkgrey;
    outline: 1px solid slategrey;
}

All 7 comments

We have the same issue and we are targeting desktop browsers as well, so users there think there are no more options available in the list, although there are, but they cannot scroll... (the could with two fingers on the touchscreen, or if they have a mouse wheel, but they simply don't hit on it).

@thmclellan By "plain select component" you mean a simple HTML <select>?

Yes, in our case we found a regular HTML select (with some modern styling) was an easier solution for all platforms.

We are now using this workaround (in global.scss):

/*
 * This adds a scroll bar to ionic alerts
 */
.alert-radio-group::-webkit-scrollbar, .alert-checkbox-group::-webkit-scrollbar {
    width: 0.7em;
    display: block !important;
}

.alert-radio-group::-webkit-scrollbar-track, .alert-checkbox-group::-webkit-scrollbar-track {
    -webkit-box-shadow: inset 0 0 6px rgba(0,0,0,0.3);
    box-shadow: inset 0 0 6px rgba(0,0,0,0.3);
}

.alert-radio-group::-webkit-scrollbar-thumb, .alert-checkbox-group::-webkit-scrollbar-thumb {
    background-color: darkgrey;
    outline: 1px solid slategrey;
}

Thanks @klemensz! Great workaround

thank you

We ran into this issue too. We found surprisingly little on the web about this disappearing scrollbar, apart from these two SO questions from 2014:
https://stackoverflow.com/questions/25685486/how-to-show-webkit-scrollbar-which-has-been-hidden-using-displaynone-css-proper
https://stackoverflow.com/questions/21985485/how-to-override-webkit-scrollbar-css-rule-and-make-scrollbar-visible-again

From our testing, it seems that at least Chrome removes the native scrollbar entirely as soon as some CSS rule is set on the ::-webkit-scrollbar pseudo-element, which explains why setting display: to unset or anything else doesn't restore the native scrollbar.

Although @klemensz workaround works great, we did prefer to have the native scrollbar back. For that, we had to actually patch the CSS rule using the document.styleSheets API, with the extra annoyance that the CSS is only injected in the document when the first alert is displayed (and even then, after the overlay opacity animation).

Here is the code we use. The public method below is called from a (ionFocus) handler on the <ion-select> . Please note that this only applies to md mode, but I'm sure there is a similar rule in ios mode.

  maybePatchAlertScrollbarCSS(alertClass) {
    if (!this.alreadyPatchedScrollbarCSS) {
      this.alreadyPatchedScrollbarCSS = true;
      setTimeout(() => this.patchAlertScrollbarCSS(alertClass), 200); // wait for backdrop opacity animation
    }
  }

  private patchAlertScrollbarCSS(alertClass) {
    const sheets = document.styleSheets;
    for (let i = 0; i < sheets.length; i++) {
      let rules:CSSRuleList|[] = [];
      try {
        rules = sheets[i].cssRules;
      } catch (e) {
        // style sheets from other domains are not accessible
      }
      for (let j = 0; j < rules.length; j++) {
        const rule = rules[j];
        if (this.isAlertScrollbarRule(rule)) {
          (rule as CSSStyleRule).selectorText = this.patchedAlertScrollbarSelector(alertClass);
        }
      }
    }
  }

  private isAlertScrollbarRule(rule: CSSRule) {
    if (rule.type === CSSRule.STYLE_RULE) {
      const selectorText = (rule as CSSStyleRule).selectorText;
      return /sc-ion-alert-md::-webkit-scrollbar/.test(selectorText)
    } else {
      return false;
    }
  }

  private patchedAlertScrollbarSelector(alertClass) {
    return `.alert-checkbox-group.sc-ion-alert-md::-webkit-scrollbar,
            ion-alert:not(.${alertClass}) .alert-radio-group.sc-ion-alert-md::-webkit-scrollbar,
            .alert-message.sc-ion-alert-md::-webkit-scrollbar`;
  }

@ionic-team it would be nice to have a parameter or a CSS class or something to prevent the ::-webkit-scrollbar rule from applying to a given <ion-select>

Thanks, @klemensz! This worked great!

Was this page helpful?
0 / 5 - 0 ratings