如何在纯CSS表单下拉元素中隐藏项目单击上的菜单

时间:2019-06-16 09:30:44

标签: jquery html css

对于CSS下拉列表,我有以下代码(从这里https://codepen.io/qwertie/pen/QBYMdZ获取):

HTML

  <div class="dropdown">
    <span tabindex="0"><span class="active_value">&nbsp;dropdown menu <i class='fas fa-caret-down fa-lg'></i></span></span>
    <div class="dropdownmenu">
        <ul>
      <li class="cb-item"><a href="http://test.net">home page</a></li>
      <li class="cb-item"><a href="http://test2.net">page</a></li>
      <li class="cb-item"><a href="#">Stay on this page</a></li>
      <li class="cb-item"><a href="#">Stay on this page</a></li>
      <li class="cb-item"><a href="#">Stay on this page</a></li>
      <li class="cb-item"><a href="#">Stay on this page</a></li>
      <li class="cb-item"><a href="#">Stay on this page</a></li>
      <li class="cb-item"><a href="#">Stay on this page</a></li>
      <li class="cb-item"><a href="#">fd gddsfgpage</a></li>
      <li class="cb-item"><a href="#">457567456756 757this page</a></li>
      <li class="cb-item"><a href="#">Stay on this page</a></li>
            </ul>
    </div>
  </div>

CSS

.dropdown {
    /* "relative" and "inline-block" (or just "block") are needed
     here so that "absolute" works correctly in children */
    position: relative;
    display: inline-block;
    width: 100%;
    height: 30px;
}

.dropdownmenu {
    background-color: #FFF !important;
    width: max-content;
    width: -moz-max-content;
    width: -webkit-max-content;
    width: -o-max-content;
    max-height: 200px;
    background-color: rgb(255, 255, 255);
    border-bottom-left-radius: 3px;
    border-bottom-right-radius: 3px;
    z-index: 10;
    overflow-y: scroll !important;
    overflow-x: hidden !important;
    border-width: 0px 1px 1px;
    border-style: solid solid solid;
    border-color: rgb(220, 220, 220) rgb(220, 220, 220) rgb(220, 220, 220);
}

span.active_value {
    padding: 6px 0px 6px 0px;
    width: 100%;
    position: absolute;
    background-color: #FFF;
    border: 1px solid #CECECE;
    cursor:pointer;
}

.dropdown i.fa-caret-down {
    position: absolute;
    right: 10px;
}

.dropdownmenu a {
    text-decoration: none;
    color: darkslategray;
}
.cb-item {
    display: block;
    margin: 0px;
    padding: 2px;
}

.cb-item:hover, .cb-item:hover > a {
    color: #fff !important;
    background-color: #006494;
    cursor: pointer;
}



    .dropdown > *:last-child {
        /* Using `display:block` here has two desirable effects:
     (1) Accessibility: it lets input widgets in the dropdown to
         be selected with the tab key when the dropdown is closed. 
     (2) It lets the opacity transition work.
     But it also makes the contents visible, which is undesirable 
     before the list drops down. To compensate, use `opacity: 0`
     and disable mouse pointer events. Another side effect is that
     the user can select and copy the contents of the hidden list,
     but don't worry, the selected content is invisible. */
        display: block;
        opacity: 0;
        pointer-events: none;
        transition: 0.4s; /* fade out */
        position: absolute;
        left: 0;
        top: 100%;
        border: 1px solid #888;
        background-color: #fff;
        box-shadow: 1px 2px 4px 1px #666;
        box-shadow: 1px 2px 4px 1px #4448;
        z-index: 9999;
        min-width: 100%;
        box-sizing: border-box;
    }
    /* List of situations in which to show the dropdown list.
   - Focus dropdown or non-last child of it => show last-child
   - Stay open for focus in last child, unless .dropdownmenu
   - .sticky last child stays open on hover
   - .dropdownmenu stays open on hover, ignores focus in last-child */
.dropdown:focus > *:last-child,
.dropdown > *:focus ~ *:last-child,
.dropdown > .dropdownmenu:last-child:hover {
    display: block;
    opacity: 1;
    transition: 0.15s;
    pointer-events: auto;
}
/* detect Edge/IE and behave if though dropdownmenu is on for all
   dropdowns (otherwise links won't be clickable) */
@supports (-ms-ime-align:auto) {
    .dropdown > *:last-child:hover {
        display: block;
        opacity: 1;
        pointer-events: auto;
    }
}
/* detect IE and do the same thing. */
@media all and (-ms-high-contrast: none), (-ms-high-contrast: active) {
    .dropdown > *:last-child:hover {
        display: block;
        opacity: 1;
        pointer-events: auto;
    }
}

.dropdown:not(.sticky) > *:not(:last-child):focus,
.dropdown:focus {
    pointer-events: none; /* Causes second click to close */
}

现在要做的是,当我单击下拉列表中的某个项目时,我会触发以下代码:

$(document).on('click', '.dropdown .dropdownmenu', function () {
    $(".dropdownmenu").hide("fast");
});
$(document).on('click', '.dropdown .dropdownmenu', function () {
    $(".dropdownmenu").show("fast");
});

但是此代码可能有点躲猫猫,因为有时隐藏菜单时,由于鼠标悬停在列表中的某个项目上,因此它会闪烁一点。我认为这是因为我的jQuery方法在隐藏菜单时以其他/其他方式隐藏菜单,这可能与CSS的隐藏/显示菜单方式冲突。

我认为现有的CSS代码正在使用opacity来显示/隐藏菜单,但据我所知,该值不会改变。

如何以基本功能保持正常运行的方式隐藏项目单击上的菜单?

1 个答案:

答案 0 :(得分:1)

说明

  

但是此代码可能有点躲猫猫,因为有时隐藏菜单时,由于鼠标悬停在列表中的某个项目上,因此它会闪烁一点。我认为这是因为我的jQuery方法在隐藏菜单时以其他/其他方式隐藏菜单,这可能与CSS的隐藏/显示菜单方式冲突。

不完全是。您因为告诉jQuery要做什么而发生冲突。查看您的代码:

$(document).on('click', '.dropdown .dropdownmenu', function () {
    $(".dropdownmenu").hide("fast");
});
$(document).on('click', '.dropdown .dropdownmenu', function () {
    $(".dropdownmenu").show("fast");
});

单击一次您有两件事:

  • $(".dropdownmenu").show("fast");
  • $(".dropdownmenu").hide("fast");

我们可以对此进行总结,以使问题更加明显:

$(document).on('click', '.dropdown .dropdownmenu', function () {
    $(".dropdownmenu").hide("fast");
    $(".dropdownmenu").show("fast");
});

您的代码要做的是每次执行这两个功能,无论下拉菜单的状态如何,以至于受到干扰。


解决方案

由于您的下拉菜单确实显示了没有JS的菜单,因此您不需要它,因此我们将其删除。

$(document).on('click', '.dropdown .dropdownmenu', function() {
  $(".dropdownmenu").hide("fast");
});

问题是:jQuery将通过在动画之后将display: none应用于style属性,来使用另一种隐藏方法(这不是闪烁的原因!),因此只能使用一次。 CSS用来隐藏/显示菜单的作用是使用opacity: 0使菜单不可见,这会使菜单更加复杂。为了解决这个问题,我删除了两个CSS小块,并将jQuery更改为:

$('.active_value').on('click', () => {
  $(".dropdownmenu").toggleClass('opened');
});

$(document).mouseup(function(e) {
  if (!$('.active_value').is(e.target)) {
    $(".dropdownmenu").removeClass('opened');
  }
});
.dropdown {
  /* "relative" and "inline-block" (or just "block") are needed
     here so that "absolute" works correctly in children */
  position: relative;
  display: inline-block;
  width: 100%;
  height: 30px;
}

.dropdownmenu {
  background-color: #FFF !important;
  width: max-content;
  width: -moz-max-content;
  width: -webkit-max-content;
  width: -o-max-content;
  max-height: 200px;
  background-color: rgb(255, 255, 255);
  border-bottom-left-radius: 3px;
  border-bottom-right-radius: 3px;
  z-index: 10;
  overflow-y: scroll !important;
  overflow-x: hidden !important;
  border-width: 0px 1px 1px;
  border-style: solid solid solid;
  border-color: rgb(220, 220, 220) rgb(220, 220, 220) rgb(220, 220, 220);
}

span.active_value {
  padding: 6px 0px 6px 0px;
  width: 100%;
  position: absolute;
  background-color: #FFF;
  border: 1px solid #CECECE;
  cursor: pointer;
}

.dropdown i.fa-caret-down {
  position: absolute;
  right: 10px;
}

.dropdownmenu a {
  text-decoration: none;
  color: darkslategray;
}

.cb-item {
  display: block;
  margin: 0px;
  padding: 2px;
}

.cb-item:hover,
.cb-item:hover>a {
  color: #fff !important;
  background-color: #006494;
  cursor: pointer;
}

.dropdown>*:last-child {
  /* Using `display:block` here has two desirable effects:
     (1) Accessibility: it lets input widgets in the dropdown to
         be selected with the tab key when the dropdown is closed. 
     (2) It lets the opacity transition work.
     But it also makes the contents visible, which is undesirable 
     before the list drops down. To compensate, use `opacity: 0`
     and disable mouse pointer events. Another side effect is that
     the user can select and copy the contents of the hidden list,
     but don't worry, the selected content is invisible. */
  display: block;
  opacity: 0;
  pointer-events: none;
  transition: 0.4s;
  /* fade out */
  position: absolute;
  left: 0;
  top: 100%;
  border: 1px solid #888;
  background-color: #fff;
  box-shadow: 1px 2px 4px 1px #666;
  box-shadow: 1px 2px 4px 1px #4448;
  z-index: 9999;
  min-width: 100%;
  box-sizing: border-box;
}


/* List of situations in which to show the dropdown list.
   - Focus dropdown or non-last child of it => show last-child
   - Stay open for focus in last child, unless .dropdownmenu
   - .sticky last child stays open on hover
   - .dropdownmenu stays open on hover, ignores focus in last-child */


/* detect Edge/IE and behave if though dropdownmenu is on for all
   dropdowns (otherwise links won't be clickable) */

@supports (-ms-ime-align:auto) {
  .dropdown>*:last-child:hover {
    display: block;
    opacity: 1;
    pointer-events: auto;
  }
}


/* detect IE and do the same thing. */

@media all and (-ms-high-contrast: none),
(-ms-high-contrast: active) {
  .dropdown>*:last-child:hover {
    display: block;
    opacity: 1;
    pointer-events: auto;
  }
}

.dropdownmenu.opened {
  display: block;
  opacity: 1;
  transition: 0.15s;
  pointer-events: auto;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<div class="dropdown">
  <span tabindex="0"><span class="active_value">&nbsp;dropdown menu <i class='fas fa-caret-down fa-lg'></i></span></span>
  <div class="dropdownmenu">
    <ul>
      <li class="cb-item"><a href="http://test.net">home page</a></li>
      <li class="cb-item"><a href="http://test2.net">page</a></li>
      <li class="cb-item"><a href="#">Stay on this page</a></li>
      <li class="cb-item"><a href="#">Stay on this page</a></li>
      <li class="cb-item"><a href="#">Stay on this page</a></li>
      <li class="cb-item"><a href="#">Stay on this page</a></li>
      <li class="cb-item"><a href="#">Stay on this page</a></li>
      <li class="cb-item"><a href="#">Stay on this page</a></li>
      <li class="cb-item"><a href="#">fd gddsfgpage</a></li>
      <li class="cb-item"><a href="#">457567456756 757this page</a></li>
      <li class="cb-item"><a href="#">Stay on this page</a></li>
    </ul>
  </div>
</div>

我使用了另一种方法,其中我完全删除了CSS :hover效果,以使用仅JS方法打开/关闭下拉菜单。如果将CSS和我的CSS进行比较,您会很快发现更改。我删除了一个类,并添加了opened类。

此外,请记住,这是许多方法中的一种,但我选择了。