简体   繁体   English

如何隐藏项目单击纯CSS窗体下拉菜单中的菜单

[英]How to hide menu on item click in pure CSS form dropdown element

I have the following code (which I got from here: https://codepen.io/qwertie/pen/QBYMdZ ) for a CSS dropdown: 我有以下用于CSS下拉列表的代码(从这里获得: https : //codepen.io/qwertie/pen/QBYMdZ ):

HTML 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 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 */
}

What I did now is when I click an item from the dropdownlist I fire this code: 现在要做的是,当我从下拉列表中单击一个项目时,我会触发以下代码:

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

But this code can be a bit dodgy since sometimes when it hides the menu, it flickers a bit as the mouse is over an item in the list. 但是此代码可能有点儿狡猾,因为有时隐藏菜单时,由于鼠标悬停在列表中的某个项目上,因此它会闪烁一下。 I think it's because my jQuery method hides the menu in a different/additional way in hiding the menu which may conflict with the CSS way of hiding/showing the menu. 我认为这是因为我的jQuery方法在隐藏菜单时以其他/其他方式隐藏菜单,这可能与CSS的隐藏/显示菜单方式冲突。

I thought that the existing CSS code was using opacity to show/hide the menu but that value does not change as far as I can see. 我以为现有的CSS代码正在使用opacity来显示/隐藏菜单,但据我所知,该值不会改变。

How can I hide the menu on item click in such a way that the basic functionality keeps working? 如何以基本功能正常运行的方式隐藏项目单击上的菜单?

Explanation 说明

But this code can be a bit dodgy since sometimes when it hides the menu, it flickers a bit as the mouse is over an item in the list. 但是此代码可能有点儿狡猾,因为有时隐藏菜单时,由于鼠标悬停在列表中的某个项目上,因此它会闪烁一下。 I think it's because my jQuery method hides the menu in a different/additional way in hiding the menu which may conflict with the CSS way of hiding/showing the menu. 我认为这是因为我的jQuery方法在隐藏菜单时以其他/其他方式隐藏菜单,这可能与CSS的隐藏/显示菜单方式冲突。

Not exactly. 不完全是。 You have a conflict because of what you told jQuery to do. 您因为告诉jQuery要做什么而发生冲突。 Take a look at your code: 看一下您的代码:

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

You have two things that should happen on a click: 单击时,有两件事应该发生:

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

We could summarize it to this to make the problem more obvious: 我们可以对此进行总结,以使问题更加明显:

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

What your code does is to execute those two functions each time no matter what the state of the dropdown is so it interferes. 您的代码要做的是无论下拉列表的状态如何, 每次执行时都要执行这两个功能。


Solution

Since your dropdown does show the menu without JS you don't need it so let's remove it. 由于您的下拉菜单确实显示了没有JS的菜单,因此您不需要它,因此让我们将其删除。

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

Problem is: jQuery will use a different hiding method (which is not the reason for the flickering!) by applying display: none to the style attribute after the animation so this only works one time. 问题是:jQuery通过在动画之后将display: none应用于style属性,jQuery将使用不同的隐藏方法(这不是闪烁的原因!),因此只能使用一次。 What your CSS does to hide/show the menu is to make it invisible by using opacity: 0 which makes it more complicated. CSS用来隐藏/显示菜单的作用是使用opacity: 0使菜单不可见,这会使菜单更加复杂。 To solve this problem I removed two small blocks of CSS and changed the jQuery to this: 为了解决这个问题,我删除了两个小的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> 

I used a different approach where I removed the CSS :hover effects completely to use a JS only approach to open/close the dropdown. 我使用了另一种方法,其中完全删除了CSS :hover效果,以使用仅JS方法打开/关闭下拉菜单。 If you compare your CSS and my CSS you will find the changes very quickly. 如果将CSS和我的CSS进行比较,您会很快发现更改。 I removed one class and added the opened class. 我删除了一个类,并添加了opened类。

Also, keep in mind that this is one of many approaches but the one I chose. 另外,请记住,这是许多方法之一,但我选择了一种。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM