仅使用 CSS 在悬停时显示下拉菜单并在单击时关闭

Show dropdown-menu on hover and close on click using only CSS

有人能帮我解释一下为什么当我点击下拉菜单中的 link 时它们不起作用吗?也许是因为指针事件?我试图让一个下拉菜单在单击 link 或单击关闭按钮后关闭。我添加了一些很酷的东西,比如在单击 link 时隐藏父容器。

这样做有很多选择:

  1. using :focus 但是当焦点被使用时下拉将不会 在下一次悬停在下拉菜单上时触发。

  2. 在容器上使用 :active 并且 pointer-events 仅指向 活动 links,但指针事件有问题

  3. 使用:target但是和:focus有同样的问题,不会触发 第二个胡佛。

body {
    padding: 20px;
}
.container {
    border: 1px solid lime;
    padding: 10px;
    width: 200px;
}
.test1 {
    display: none;
    border: 1px dashed orange;
    background: green;
    padding: 10px;
    pointer-events: none;
}
.container:hover .test1 {
    display: inline-block;
}
.container:hover .test1:active {
    display: none;
}
a {
    pointer-events: auto;
    color: lime;
    font-weight: bold;
}
<ul class="container">
  Drop down menu
 <li class="test1">
 <a class="dropdown" href="#">X Close</a>
 <ul class="content">
   CLOSE THIS CONTENT
  <li class="link"><a href="http://www.google.com">Go to link 1</a></li>
  <li class="link"><a href="https://www.google.co.uk">Go to link 2</a></li>
  <li class="link"><a href="https://www.google.co.uk">Go to link 3</a></li>
 </ul>

为什么要将 "pointer-events: none;" 添加到列表元素 .test1?这会覆盖您的 pointer-events: auto;。尝试删除它,因为它会绑定您的点击事件。

它似乎不起作用,因为在鼠标按下时,用于保持下拉菜单打开的 :hover-class 消失了。所以鼠标弹起事件不会在 link 上执行,因为下拉菜单已经再次关闭,所以没有执行点击。您应该使用 javascript 打开和关闭下拉菜单。

我建议删除

.container:hover .test1:active {
    display: none;
}

并找到另一种方法(几行 javascript 即可)在单击 "X Close" link 时关闭面板。 (顺便还修复了一些 html 缺失的标签)。现在 link 正在工作:

body {
    padding: 20px;
}
.container {
    border: 1px solid lime;
    padding: 10px;
    width: 200px;
}
.test1 {
    display: none;
    border: 1px dashed orange;
    background: green;
    padding: 10px;
    pointer-events: none;
}
.container:hover .test1 {
    display: inline-block;
}
a {
    pointer-events: auto;
    color: lime;
    font-weight: bold;
}
<ul class="container">
  Drop down menu
  <li class="test1">
    <a class="dropdown" href="#">X Close</a>
    <ul class="content">
      CLOSE THIS CONTENT
      <li class="link"><a href="http://www.google.com">Go to link 1</a></li>
      <li class="link"><a href="https://www.google.co.uk">Go to link 2</a></li>
      <li class="link"><a href="https://www.google.co.uk">Go to link 3</a></li>
    </ul>
  </li>
</ul>

我建议尝试使用 jQuery 仅在按下 link 时处理关闭容器。 pointer-events 有很多问题。因此,他们决定将该功能推迟到 CSS4。

我还认为 pointer-events: none; 会阻止触发任何点击事件,因此仅针对 link 使用 jQuery 是行不通的。我认为您必须使用 jQuery.

修复容器的打开和关闭

我通常会使用 JS 执行此操作 - 但是 CSS 一个 hack:

首先创建一个 ID 为 close 的输入和一个 label 来包装我们的关闭按钮:

  <input type="radio" id="close" />
  <li class="test1">
    <label for="close">
      <a class="dropdown" href="#">X Close</a>
    </label>

并添加这种样式而不是当前的 .test1:active:

.container:hover #close:active + .test1{
  display: none;
}
#close {
  display: none;
}

参见下面的演示:

body {
  padding: 20px;
}
.container {
  border: 1px solid lime;
  padding: 10px;
  width: 200px;
}
.test1 {
  display: none;
  border: 1px dashed orange;
  background: green;
  padding: 10px;
  pointer-events: none;
}
.container:hover .test1 {
  display: inline-block;
}
#close {
  display: none;
}
.container:hover #close:active + .test1 {
  display: none;
}
a {
  pointer-events: auto;
  color: lime;
  font-weight: bold;
}
<ul class="container">
  Drop down menu
  <input type="radio" id="close" />
  <li class="test1">
    <label for="close">
      <a class="dropdown" href="#">X Close</a>
    </label>
    <ul class="content">
      CLOSE THIS CONTENT
      <li class="link"><a href="http://www.google.com">Go to link 1</a>
      </li>
      <li class="link"><a href="https://www.google.co.uk">Go to link 2</a>
      </li>
      <li class="link"><a href="https://www.google.co.uk">Go to link 3</a>
      </li>
    </ul>
  </li>
</ul>

但是上面的代码在 ul 中有一个无效的 input 元素 - 以防止您可以稍微编辑标记以为 ul 创建另一个包装器(也许由于标记更改,您必须稍微调整 widths/padding)- 请参阅下面的代码:

body {
  padding: 20px;
}
.container {
  border: 1px solid lime;
  padding: 10px;
}
ul {
  width: 200px;
}
.test1 {
  display: none;
  border: 1px dashed orange;
  background: green;
  padding: 10px;
  pointer-events: none;
}
.container:hover .test1 {
  display: inline-block;
}
#close {
  display: none;
}
.container:hover #close:active + ul > li.test1 {
  display: none;
}
a {
  pointer-events: auto;
  color: lime;
  font-weight: bold;
}
<div class="container">
  Drop down menu
  <input type="radio" id="close" />
  <ul>
    <li class="test1">
      <label for="close">
        <a class="dropdown" href="#">X Close</a>
      </label>
      <ul class="content">
        CLOSE THIS CONTENT
        <li class="link"><a href="http://www.google.com">Go to link 1</a>
        </li>
        <li class="link"><a href="https://www.google.co.uk">Go to link 2</a>
        </li>
        <li class="link"><a href="https://www.google.co.uk">Go to link 3</a>
        </li>
      </ul>
    </li>
  </ul>
</div>

您可以在 a 上使用 labelbutton 来关闭 link 并且可以执行如下操作 -

body {
  padding: 20px;
}

.container {
  border: 1px solid lime;
  padding: 10px;
  width: 200px;
}

.test1 {
  display: none;
  border: 1px dashed orange;
  background: green;
  padding: 10px;
  pointer-events: none;
}

.container:hover .test1 {
  display: inline-block;
}

a, label {
  pointer-events: auto;
  color: lime;
  font-weight: bold;
}

/* close button */
#xclose:active + .test1 {
  display:none;
}

#xclose {
  display: none;
}
<ul class="container">
  Drop down menu
  <button id="xclose">X close</button>
  <li class="test1">    
    <label class="dropdown" for="xclose">X Close</label>        
    <ul class="content">
      CLOSE THIS CONTENT
      <li class="link"><a href="http://www.google.com">Go to link 1</a></li>
      <li class="link"><a href="https://www.google.co.uk">Go to link 2</a></li>
      <li class="link"><a href="https://www.google.co.uk">Go to link 3</a></li>
    </ul>
  </li>
</ul>

希望这对您有所帮助 (y)。

在 CSS 中,您可以将 label 个元素绑定到 inputs。鉴于此,您可以将关闭按钮绑定到一个输入 - 当激活时 - 再次隐藏列表。

body{
  padding: 20px;
}

a, label{
  text-decoration: none;
  cursor: pointer;
  color: lime;
  font-weight: bold;
}

.container{
  border: 1px solid lime;
  padding: 10px;
  width: 200px;
}

.dropdown{
  display: none;
  border: 1px solid orange;
  background: green;
  margin-top: 10px;
  padding: 10px;
}

#close, #close:active + .dropdown{
  display: none;
}

.container:hover .dropdown{
  display: block;
}

.dropdown > ul{
  padding: 0;
  list-style: none;
}
<div class="container">
  Drop down menu
  <button id="close"></button>
  <div class="dropdown">
    <label for="close">X Close</label>
    <ul>
      <li class="link"><a href="http://www.google.com">Go to link 1</a></li>
      <li class="link"><a href="https://www.google.co.uk">Go to link 2</a></li>
      <li class="link"><a href="https://www.google.co.uk">Go to link 3</a></li>
    </ul>
  </div>
</div>

id="close"input插入列表前,由带for="close"
的标签触发 当它被触发时,以下规则将生效:

#close, #close:active + .dropdown{
  display: none;
}

隐藏列表。
但当您将鼠标悬停在 .container 上时,它会再次出现,让您重复该过程。 这里不需要不必要的JavaScript。输入即可。

您的代码也有一些问题。您的文本 Drop down menuCLOSE THIS CONTENT 直接位于 ul 中,这是无法完成的。 ul 只能包含 li,不能包含其他任何内容。

希望这对您有所帮助

.container:hover .test1:active {
display: none;
}

把这个赞改成

.container:hover .test1:focus{
    display: none;
    }

这里发生的事情是,当您的 div 从您的 link 点击中获取 "active" 伪代码时,它隐藏在 DOM 气泡之前到您的 link 给出重定向。将其更改为焦点可能会让点击实际通过?

快速检查:Working JSFiddle

Can someone help me with an explanation as to why the links from a dropdown menu are not working when I click on them? Maybe because of pointer events?

解释为什么会出现这种行为: 是的,你是对的,这是因为你使用 :active 选择器逻辑的方式,要详细解释,请考虑你的这个 CSS 规则

.container:hover .test1:active {
    display: none;
}

您的菜单 link 在您的主菜单 li.test1 下,并且对内部 link 的任何点击也会冒泡到此元素,因此它与点击li。因此,只要按住鼠标(鼠标按下事件),它就会触发 :active 事件,并且您隐藏了 links(即:li.test1),但是 只有当鼠标同时按下和向上时,点击事件才完成。所以现在 li 已隐藏,mouse up 不再位于 link 上。因此,如您所见,没有机会触发点击事件。就是这个问题。


I saw other answers which you seem to be interested in and this really doesn't need any kind of hack, It can be done by just formatting your HTML and with some CSS changes.


解决方案: 与其将内部菜单 link 包裹在 li.test1 中,不如 使用两个不同的 li,一个用于X CLose,另一个用于容纳menu links。有了这个,我们可以确保 每当 li.test1 处于活动状态时 (即鼠标按下)我们可以 隐藏它以及其他新的 li 与它相邻。所以这意味着每当用户点击 X Close li 我们隐藏菜单,如果他点击其他菜单项,你将被重定向。

所以你的 HTML 结构的变化应该像

<ul class="container">
  Drop down menu
  <li class="test1">
    <a class="dropdown" href="#">X Close</a>
  </li>
  <li class="MenuLinks">
    <ul class="content">
      <!-- all your links go here-->
    </ul>
  </li>
</ul>

而主要 CSS 规则是

.container:hover .test1:active,
.container:hover .test1:active + .MenuLinks {
  display: none;
}

下面是一个有效的片段

body {
  padding: 20px;
}
.container {
  border: 1px solid lime;
  padding: 10px;
  width: 200px;
  list-style-type: none;
}
.test1,
.MenuLinks {  
  display: none;
  border-color: orange;
  border-style: dashed;
  background: green;
  pointer-events: none;
}
.test1 {
  padding: 10px;
  border-width: 1px 1px 0px 1px;
}
.MenuLinks {
  border-width: 0px 1px 1px 1px;
}
.container:hover li {
  display: block;
}

/*Rule to hide both test1 and MenuLinks when X Close is clicked*/
.container:hover .test1:active,
.container:hover .test1:active + .MenuLinks {
  display: none;
}


a {
  pointer-events: auto;
  color: lime;
  font-weight: bold;
}
<ul class="container">
  Drop down menu
  <li class="test1">
    <a class="dropdown" href="#">X Close</a>
  </li>
  <!--seperate li for close-->

  <li class="MenuLinks">
    <!--wrap all your menu items here-->
    <ul class="content">
      CLOSE THIS CONTENT
      <li class="link"><a href="http://www.google.com">Go to link 1</a>
      </li>
      <li class="link"><a href="https://www.google.co.uk">Go to link 2</a>
      </li>
      <li class="link"><a href="https://www.google.co.uk">Go to link 3</a>
      </li>
    </ul>
    <li>
</ul>


注意: 当您点击 link 时出现黑屏是由于 google 的跨源策略安全限制控制台中出现此错误

Refused to display 'https://www.google.co.in/?gfe_rd=cr&ei=x2VWWLL2Ae-K8Qfwx4ngDQ' in a frame because it set 'X-Frame-Options' to 'SAMEORIGIN'.

但是,当您单击 link 时,您可以在网络选项卡中看到请求。

希望对您有所帮助!!

其中一个选项是使用 animate。我已经用 opacity 给出了您的代码示例。使用 visibility:hiddenoverflow:hidden 将增强您的代码。

<div class="snippet" data-lang="js" data-hide="false" data-console="true" data-babel="false">
<div class="snippet-code">
<pre><code>    body {
        padding: 20px;
    }
    .container {
        border: 1px solid lime;
        padding: 10px;
        width: 200px;
    }
    .test1 {
        display: none;
        border: 1px dashed orange;
        background: green;
        padding: 10px;
        pointer-events: none;
    }
    .container:hover .test1 {
        display: inline-block;
    }
    
    a {
        pointer-events: auto;
        color: lime;
        font-weight: bold;
    }


.container .test1 {
  -webkit-animation: seconds 1.0s forwards;
  -webkit-animation-iteration-count: 1;
  -webkit-animation-delay: 2s;
  animation: seconds 1.0s forwards;
  animation-iteration-count: 1;
  animation-delay: 2s;
  position: relative;
}
@-webkit-keyframes seconds {
  0% {
    opacity: 1;
  }
  100% {
    opacity: 0;

  }

@keyframes seconds {
  0% {
    opacity: 1;
  }

  100% {
    opacity: 0;

  }
}
    <ul class="container">
      Drop down menu
     <li class="test1">
     <a class="dropdown" href="#">X Close</a>
     <ul class="content">
       CLOSE THIS CONTENT
      <li class="link"><a href="http://www.google.com">Go to link 1</a></li>
      <li class="link"><a href="https://www.google.co.uk">Go to link 2</a></li>
      <li class="link"><a href="https://www.google.co.uk">Go to link 3</a></li>
     </ul>