带有自定义滚动条 (mCustomScrollbar) 的自定义选择 (Nice select)

Posted

技术标签:

【中文标题】带有自定义滚动条 (mCustomScrollbar) 的自定义选择 (Nice select)【英文标题】:Custom select (Nice select) with custom scrollbar (mCustomScrollbar) 【发布时间】:2019-03-28 02:49:19 【问题描述】:

我是新来的,遇到了一个我无法解决的问题。

我有一个使用nice select 的自定义选择,它运行良好,然后我添加了mCustomScrollbar,它也运行良好,问题是当我只想使用键盘时,我首先使用 TAB 然后按下显示选项的向下箭头(或空格键、回车键、向上箭头),一旦您继续使用箭头向下移动,滚动条不会随着光标移动而显示其余选项,例如如果您使用鼠标,我想找到一种解决此问题的方法,以便用户在使用键盘时可以看到所有选项。

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'
);

谢谢!

【问题讨论】:

【参考方案1】:

我有同样的任务。我就是这样做的

脚本:

$('.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);
 

...

【讨论】:

以上是关于带有自定义滚动条 (mCustomScrollbar) 的自定义选择 (Nice select)的主要内容,如果未能解决你的问题,请参考以下文章

带有自定义滚动条的 QML Listview

带有 css 或 jquery 的自定义滚动条 firefox

带有自定义刻度的滑块(标签和速度)

带有 knitr 幻灯片的长功能垂直滚动条

在 jQuery 自定义滚动条中使用鼠标滚动事件移动自定义滚动条

QGraphicsView 自定义滚动条