Custom select (Nice select) with custom scrollbar (mCustomScrollbar)

4.7k Views Asked by At

I'm new here and I'm facing an issue which I can't fix.

I have a custom select using nice select which is working perfectly, then I added mCustomScrollbar which is working fine too, the issue is when I want to use the keyboard only, I first focus using TAB and then pressing the down arrow (or spacebar, enter, up arrow) where it displays the options, once you keep using the arrow to move down the scrollbar is not moving with the cursor showing the rest of the options like if you use the mouse, I would like to find a way of fixing this so that when a user is using the keyboard it can see all the options.

Codepen: https://codepen.io/anon/pen/MPPybJ

HTML

<section class="form-container">
  <form action="" method="" class="tn-general" novalidate>
    <fieldset>
      <div class="row">
        <div class="col-md-5">
          <div class="form-group form-group-floating-label">
            <div class="custom-select">
              <select required>
                <option value="" disabled selected="selected" hidden>Seleccionar</option>
                <option value="1">Soltero</option>
                <option value="2">Casado</option>
                <option value="3">Divorciado</option>
                <option value="4">Viudo</option>
                <option value="5">Concubino</option>
                <option value="">Casado 1</option>
                <option value="">Casado 2</option>
                <option value="">Casado 3</option>
                <option value="">Casado 4</option>
                <option value="">Casado 5</option>
                <option value="">Casado 6</option>
                <option value="">Casado 7</option>
                <option value="">Casado 8</option>
                <option value="">Casado 9</option>
                <option value="">Casado 10</option>
                <option value="">Casado 11</option>
                <option value="">Casado 12</option>
                <option value="">Casado 13</option>
                <option value="">Casado 14</option>
                <option value="">Casado 15</option>
                <option value="">Casado 16</option>
                <option value="">Casado 17</option>
                <option value="">Casado 18</option>
                <option value="">Casado 19</option>
                <option value="">Casado 20</option>
              </select>
            </div>
          </div>
        </div>      
      </div>
    </fieldset>
  </form>
</section>

CSS

/* Font Size*/
$font-size-small: 0.8em; /*12px*/
$font-size-minismall: 0.813em; /*13px*/
$font-size-normal: 0.9em; /* 14px */
$font-size-main-mininormal: 0.938em; /* 15px */
$font-size-main-normal: 1em; /* 16px */
$font-size-smedium: 1.115em; /* 17px */
$font-size-medium: 1.125em; /* 18px */
$font-size-xmedium: 1.25em; /* 20px */
$font-size-xm-medium: 1.375em; /* 22px */
$font-size-big: 1.5em; /*24px*/
$font-size-xbig: 1.65em; /* 26px */
$font-size-mxlarge: 1.9em; /* 30px */
$font-size-mxxlarge: 2em; /* 32px */
$font-size-mxxxlarge: 2.125em; /* 34px */
$font-size-xlarge: 2.5em; /* 40px */
$font-size-large: 2.75em; /*44px*/
$font-size-xxlarge: 3em; /*48px*/
$font-size-xxxlarge: 50px; /* 50px */
$font-size-ultralarge: 3.75em; /* 60px */
/* Font Type*/
$font-type: "opensans-regular";
$font-type-light: "opensans-light";
$font-type-semibold: "opensans-semibold";
$font-type-bold: "opensans-bold";
$font-type-2: "urwgeometric-regular";
$font-type-2-light: "urwgeometric-light";
$font-type-2-thin: "urwgeometric-thin";
$font-type-2-semibold: "urwgeometric-semibold";
$font-type-2-bold: "urwgeometric-bold";

$color-white: #ffffff;
$color-black: #000000;
/* Gray Color*/
$color-gray: #eeeeee;
$color-gray-1:#C8C8C8;
$color-message-gray: #999fa5;
$color-soft-gray: #aeaeae;
$color-soft-gray-2: #f3f3f3;
$color-soft-gray-3: #c1c1c1;
$color-soft-gray-4: #aaa;
$color-soft-gray-5: #777777;
$color-soft-gray-6: #969696;
$color-soft-gray-7: #f9f9f9;
$color-soft-gray-8: #dddddd;
$color-soft-gray-9: #f0f0f0;
$color-soft-gray-10: #e3e3e3;
$color-dark-gray: #666666;
$color-dark-gray-0: #333333;
$color-dark-gray-2: #434343;
$color-dark-gray-3: #535353;
$color-dark-gray-4: #626262;
$color-dark-gray-5: #d4d4d4;
$color-dark-gray-5: #c9c9c9;
$color-dark-gray-6: #a6a6a6;
$color-dark-gray-7: #555555;
$color-dark-gray-8: #303030;
$color-dark-gray-9:#d8d8d8;
/* Orange Color*/
$color-soft-orange: #f9a885;
$color-super-soft-orange: #FFF8E4;
$color-ui-orange: #ff6600;
$color-ui-orange-2: #ff5a00;
$color-ui-orange-3: #FF6800;
$color-orange: #f56122;
$color-orange-2:#ef5816;
$color-orange-3:#ed5927;
$color-orange-3: #ff7022;
$color-orange-4: #ff5d00;
$color-orange-5: #ef5411;
$color-orange-6:#ff8b1d;
$color-orange-7:#ff8400;
$color-orange-8: #FFA500;
$color-dark-orange: #da480a;
/* Red Color*/
$color-red: #e14421;
$color-red-2: #de0000;
$color-red-3 :#ff6464;
/* Blue Color*/
$color-blue: #3F525F;
$color-dark-blue: #2c4854;
/* Green Color*/
$color-green: #009a63;
$color-green-2: #009900;
$color-green-3: #00d095;
/*Yellow Colors*/
$color-soft-yellow: #fcf8e3;
$color-soft-yellow-2: #fff5d8;
$color-yellow-1: #ffbf00;
$color-yellow-2: #fad054;
/*Gradient Class Colors*/
.tn-gradient-1 {
    background-image: linear-gradient(119deg, #ff6600,#ffcb00);
}

.tn-general {
  .custom-checkbox {
    .custom-control-indicator {
      border-radius: 50%;
      border: 0.15rem solid $color-soft-gray-3;
      background-color: white;
      width: 1.5rem;
      height: 1.5rem;
    }
    .custom-control-description {
      padding-top: 5px;
      padding-left: 10px;
    }
    .custom-control-input:checked~.custom-control-indicator {
      color: white;
      background-color: $color-ui-orange;
      border-color: $color-ui-orange;
      background-size: 10px;
    }
    .custom-control-input:focus ~ .custom-control-indicator {
      box-shadow: 0 0 0 1px #fff, 0 0 0 3px #fff;
    }
  }
  .custom-checkbox-nobg {
    .custom-control-indicator {
      border-radius: 25%;
      border: 0.05rem solid $color-soft-gray;
      background-color: white;
      width: 1.5rem;
      height: 1.5rem;
    }
    .custom-control-description {
      padding-top: 5px;
      padding-left: 10px;
    }
    .custom-control-input:checked ~ .custom-control-indicator {
      color: $color-dark-gray;
      background-color: white;
      border-color: $color-dark-gray;
      background-size: 10px;
      background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23666' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E");
    }
    .custom-control-input:focus ~ .custom-control-indicator {
      box-shadow: 0 0 0 1px #fff, 0 0 0 3px #fff;
    }
  }
  .tn-btn-main {
    -webkit-appearance: none;
    -moz-appearance: none;
    appearance: none;
    cursor: pointer;
    background-color: $color-orange-3;
    border-radius: 50px;
    border: 0;
    color: white;
    font-family: $font-type-semibold;
    font-size: $font-size-main-normal;
    line-height: 1;
    text-align: center;
    width: 200px;
    height: 42px;
    padding: 0;
    margin: 20px 0;
    display: inline-block;
    vertical-align: middle;
    transform: perspective(1px) translateZ(0);
    box-shadow: 0 0 1px transparent;
    overflow: hidden;
    transition-duration: 0.3s;
    transition-property: color, background-color;
    &.tn-mt-3 {
      margin-top: 30px;
    }
    &:hover {
      background-color: $color-orange-7;
    }
    &:focus {
      outline: 0;
    }
    &.disabled {
      opacity: 0.6;
      color: $color-dark-gray-7;
      cursor: default;
      font-family: "opensans-regular";
    }
  }
  .tn-btn-msg {
    -webkit-appearance: none;
    -moz-appearance: none;
    appearance: none;
    cursor: pointer;
    background-color: $color-ui-orange-3;
    border-radius: 5px;
    border: 0;
    color: white;
    font-family: $font-type-semibold;
    font-size: $font-size-medium;
    line-height: 1;
    padding: 10px 15px;
    margin: 5px 0;
    display: inline-block;
    vertical-align: middle;
    transform: perspective(1px) translateZ(0);
    box-shadow: 0 0 1px transparent;
    overflow: hidden;
    transition-duration: 0.3s;
    transition-property: color, background-color;
    &.tn-mt-3 {
      margin-top: 30px;
    }
    &:hover {
      background-color: $color-orange-7;
    }
    &:focus {
      outline: 0;
    }
    &.disabled {
      opacity: 0.6;
      color: $color-dark-gray-7;
      cursor: default;
      font-family: "opensans-regular";
    }
  }
  .tn-btn-second {
    -webkit-appearance: none;
    -moz-appearance: none;
    appearance: none;
    cursor: pointer;
    background-color: $color-white;
    border: 2px solid $color-ui-orange;
    border-radius: 50px;
    color: $color-ui-orange;
    font-family: $font-type-semibold;
    font-size: $font-size-main-normal;
    line-height: 1;
    width: 200px;
    height: 42px;
    padding: 0;
    text-align: center;
    margin: 20px 0;
    display: inline-block;
    vertical-align: middle;
    transform: perspective(1px) translateZ(0);
    box-shadow: 0 0 1px transparent;
    overflow: hidden;
    transition-duration: 0.3s;
    transition-property: color, background-color;
    &.tn-mt-3 {
      margin-top: 30px;
    }
    &:hover {
      border: 2px solid $color-orange-7;
      background-color: $color-white;
      color: $color-orange-7;
    }
    &:focus {
      outline: 0;
    }
    &.disabled {
      opacity: 0.6;
      color: $color-dark-gray-7;
      cursor: default;
      font-family: "opensans-regular";
    }
  }
  .tn-btn-collapse {
    -webkit-appearance: none;
    -moz-appearance: none;
    appearance: none;
    color: $color-orange-5;
    font-size: $font-size-normal;
    font-family: $font-type-semibold;
    background-color: $color-soft-gray-9;
    width: 100%;
    border: 0 none;
    padding: 0.8rem;
    position: relative;
    &:before {
      outline: 0;
      display: inline-block;
      content: "";
      background: url("../images/buttons/tn-arrow-collapse.png") center center no-repeat;
      height: 12px;
      width: 12px;
      position: relative;
      top: 2px;
      right: 5px;
    }
    &:focus {
      outline: 0;
      box-shadow: none;
    }
  }
  .tn-btn-collapse[aria-expanded="true"] {
    &:before {
      background: url("../images/buttons/tn-arrow-collapsed.png") no-repeat;
    }
  }
  /* Black Check */
  .check-icon {
    list-style-type: none;
    li {
      background: url("../images/icons/check-small-2.png") no-repeat 0 4px;
      padding-left: 20px;
      margin: 5px 0;
      font-family: $font-type;
      line-height: 1;
      color: $color-dark-gray;
    }
  }
  .tn-form-wrapper {
    p {
      margin-bottom: 0;
    }
  }
  .tn-form-title {
    h1 {
      color: $color-dark-gray-8;
      font-family: $font-type;
      font-weight: bold;
      font-size: $font-size-mxxxlarge;
      padding-bottom: 15px;
    }
  }
  // Floating labels
  .form-group.form-group-floating-label {
    position: relative;
    &:not(:first-child) {
      margin-top: 40px;
    }
    label {
      font-size: 15px;
      font-weight: 600;
      color: $color-soft-gray-4;
      display: block;
    }
    .form-control {
      font-family: 'urwgeometric-regular';
      font-size: $font-size-xmedium;
      font-weight: 600;
      color: $color-dark-gray-0;
      width: 100%;
      border: 0;
      border-bottom: 1px solid #CCC;
      border-radius: 0;
      padding-top: 0;
      padding-left: 0;
      outline: 0;
      &.invalid {
        border-color: $color-red-2;
      }
      &:focus {
        border-color: $color-ui-orange;
      }
      &:focus + .form-control-placeholder,
      &:valid + .form-control-placeholder {
        font-size: $font-size-main-normal;
        transform: translate3d(0, -100%, 0);
      }
      &:disabled + .form-control-placeholder {
        font-size: $font-size-main-normal;
        transform: translate3d(0, -100%, 0);
      }
      &:disabled + .form-control-placeholder.form-control-placeholder-no-input {
        transform: none;
      }
      &:disabled {
        background-color: transparent;
        cursor: not-allowed;
        border-color: $color-soft-gray-10;
      }
    }
    .form-control-placeholder {
      font-size: $font-size-xmedium;
      font-weight: 600;
      color: $color-soft-gray-4;
      position: absolute;
      top: 0;
      left: 0;
      padding-top: 5px;
      transition: all 200ms;
      cursor: text;
    }
    .form-invalid-message {
      font-size: $font-size-normal;
      font-weight: 600;
      color: $color-red-2;
      max-width: 100%;
      margin-top: 4px;
      margin-bottom: 0;
      position: absolute;

      &.position-relative {
        position: relative;
      }
    }
    &.form-group-single-inputs {
      input {
        display: inline-block;
        height: 24px;
        font-size: $font-size-xbig;
        text-align: center;
        max-width: 20px;
        padding: 0;
        margin-top: 17px;
        margin-right: 7px;
        vertical-align: bottom;
        &:valid {
          border-color: transparent;
        }
        &:invalid {
          border-color: #CCC;
        }
        &:focus {
          border-color: $color-ui-orange;
        }
        &.invalid {
          border-color: $color-red-2;
        }
      }
    }
    // custom select dropdown
    select {
      display: none;
    }
    .custom-select {
      display: block;
      background: transparent;
      border: 0;
      padding: 6px 0;
      position: relative;
        .nice-select {
          font-family: 'urwgeometric-regular';
          font-size: $font-size-xmedium;
          font-weight: 600;
          color: $color-dark-gray-0;
          background: url('../../Content/images/buttons/chevron-down-arrow-light-gray.png') no-repeat right;
          background-size: 15px;
          border-bottom: 1px solid #CCC;
          padding-bottom: 7px;
          cursor: pointer;
          &:focus {
            outline-width: 2px;
            outline-style: solid;
            outline-color: Highlight;
          }
          &:active,
          &:hover,
          &.removeFocus {
            outline: none;
          }
          & span.current {
            color: $color-soft-gray-4;
          }
          &.open {
            border-color: $color-ui-orange;
            .list {
              opacity: 1;
              pointer-events: auto;
              transform: scale(1) translateY(0);
            }
          }
          &.invalid {
            border-color: $color-red-2;
          }
          &.disabled {
            border-color: $color-soft-gray-10;
            pointer-events: none;
            & span {
              color: $color-soft-gray-10;
            }
          }
          &.optionSelected {
            background: url('../../Content/images/buttons/chevron-down-arrow-dark-gray.png') no-repeat right;
            background-size: 15px;
            & span.current {
              color: $color-dark-gray-0;
            }
          }
          // List and options
          .list {
            max-height: 400px;
            font-size: $font-size-medium;
            font-weight: 600;
            background-color: white;
            color: $color-dark-gray-0;
            position: absolute;
            top: 100%;
            left: 0;
            right: 0;
            z-index: 1;
            margin-top: 8px;
            border: 1px solid #e5e5e5;
            border-radius: 6px;
            box-shadow: 0 5px 10px 0 rgba(0, 0, 0, 0.1);
            opacity: 0;
            pointer-events: none;
            overflow: hidden;

            transition: all .2s cubic-bezier(0.5, 0, 0, 1.25), opacity .15s ease-out;
            &:hover .option:not(:hover):not(.selected) {
              background-color: transparent;
            }
          }
          .option {
            font-weight: bold;
            font-size: 18px;
            height: 70px;
            padding: 0 20px;
            display: flex;
            align-items: center;
            cursor: pointer;
            outline: none;
            transition: all 0.2s;
            &:hover,
            &.focus,
            &.selected.focus {
              background-color: $color-gray;
            }
            &.selected {
              background-color: $color-gray;
            }
            &.disabled {
              display: none;
            }
          }
        }
      }
    // Input checkbox
    .form-input-checkbox {
      // Remove the original ones
      .styled-checkbox {
        position: absolute;
        opacity: 0;
        // Checbox label
        & + label {
          display: inline;
          position: relative;
          padding: 0;
          cursor: pointer;
          // Add styled chexbox
          &:before {
            content: '';
            display: inline-block;
            width: 22px;
            height: 22px;
            background: white;
            vertical-align: text-bottom;
            margin-right: 18px;
            border: 2px solid $color-dark-gray-0;
            border-radius: 4px;
          }
        }
        // Box checked
        &:checked + label:before {
          content: '';
          background: url('../../Content/images/icons/select-checkbox-checked.png') no-repeat right;
          background-size: contain;
          border: 0;
          border-radius: 0;
        }
      }
    }
    .custom-radio {
      & .custom-control-label {
        cursor: pointer;
        margin-bottom: 0;
        &::before {
          content: '';
          border-radius: 50%;
          display: inline-block;
          width: 24px;
          height: 24px;
          pointer-events: none;
          -webkit-user-select: none;
          -moz-user-select: none;
          -ms-user-select: none;
          user-select: none;
          background: url('../../Content/images/icons/radio-button-unselected.svg') center center no-repeat;
          vertical-align: top;
          cursor: pointer;
          margin-right: 10px;
        }
        &::after {
          content: '';
          display: block;
          width: 24px;
          height: 24px;
          background-repeat: no-repeat;
          background-position: center center;
          background-size: 50% 50%;
          position: absolute;
          top: 0;
        }
      }
      & .custom-control-input:not(:checked):focus ~ .custom-control-label::before {
        outline-width: 2px;
        outline-style: solid;
        outline-color: Highlight;
      }
      & .custom-control-input:checked ~ .custom-control-label::before {
        background: url('../../Content/images/icons/radio-button-selected.svg') center center no-repeat;
      }
      & .custom-control-input:checked ~ .custom-control-label::after {
        background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%23fff'/%3E%3C/svg%3E");
      }
    }
    // input[type="radio"] {
    //   & + label span {
    //     display: inline-block;
    //     width: 24px;
    //     height: 24px;
    //     vertical-align: top;
    //     background: url('../../Content/images/icons/radio-button-unselected.svg') center center no-repeat;
    //     cursor: pointer;
    //     margin-right: 10px;
    //   }
    //
    //   &:checked + label span {
    //     background: url('../../Content/images/icons/radio-button-selected.svg') center center no-repeat;
    //   }
    // }
  }
  // General errors
  .general-invalid-data {
    font-size: 15px;
    font-weight: 600;
    line-height: 1;
    color: $color-red-2;
  }
  // Remove box-shadow from inputs with type text
  input[type="text"] {
    box-shadow: none;
  }
}

JS

// initialize custom select

$('select').niceSelect();

// add outline only when using TAB
let niceSelect = $('.nice-select');

niceSelect.on('click', function()
{
    $(this).addClass('removeFocus');
});

niceSelect.on('blur', function()
{
    if($(this).hasClass('removeFocus'))
    {
        $(this).removeClass('removeFocus');
    }
});

// add class when choosing an option

$('.list .option:not(.disabled)').on('click keypress', function()
{
    $(this).closest('.nice-select').addClass('optionSelected');
});

// remove mCustomScrollbar tabindex

setTimeout(() => {
    $('.mCustomScrollBox').prop('tabindex', '-1');
}, 1000);

$('.nice-select .list').mCustomScrollbar({
    theme: 'minimal-dark'
});

Thank you!

1

There are 1 best solutions below

0
Дмитрий Исаенко On

I had same task. And I did it like this

script:

$('.jsNiceSelect').niceSelect();

$(document).on('mouseenter', '.nice-select .mCSB_scrollTools', function(event) {
  var $dropdown = $(this).parents('.nice-select');
  $dropdown.addClass('open_scroll');
});
$(document).on('click.nice_select', function(event) {
  if ($(event.target).closest('.nice-select').length === 0) {
    $('.nice-select').removeClass('open_scroll');
    setTimeout(function() { $('.nice-select').removeClass('open'); }, 50);
  }
});
$(document).on('click.nice_select', '.nice-select .option:not(.disabled)', function(event) {
  $('.nice-select').removeClass('open_scroll open');
  setTimeout(function() { $('.nice-select').removeClass('open'); }, 50);
});

css:

...
&.open {
 here standard styles nice select
}

here add this:

&.open_scroll{
z-index: 4;
&:after {
  -webkit-transform: rotate(180deg);
  -ms-transform: rotate(180deg);
  transform: rotate(180deg);
}
.list {
  opacity: 1;
  pointer-events: auto;
  -webkit-transform: scale(1) translateY(0);
  -ms-transform: scale(1) translateY(0);
  transform: scale(1) translateY(0);
 }
}
...