Показать выпадающее меню при наведении курсора и закрыть клик, используя только CSS

Может кто-нибудь помочь мне объяснить, почему ссылки из выпадающего меню не работают, когда я нажимаю на них? Может быть, из-за событий указателя? Я пытаюсь открыть выпадающее меню после закрытия ссылки или нажать кнопку закрытия. Я добавил некоторые интересные вещи, такие как скрытие родительского контейнера при нажатии ссылки.

Существует много вариантов:

  • используя :focus, но при использовании фокуса выпадающее меню не будет запускается при следующем наведении на раскрывающееся меню.

  • используя :active на контейнере и pointer-events, чтобы указать только активные ссылки, но события указателей являются ошибками

  • используя :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="#" onclick="location.href='http://www.google.com'; return false;">Go to link 1</a></li>
		<li class="link"><a href="#" onclick="location.href='https://www.google.co.uk'; return false;">Go to link 2</a></li>
		<li class="link"><a href="#" onclick="location.href='https://www.google.co.uk'; return false;">Go to link 3</a></li>
	</ul>

Ответ 1

Быстрая проверка: Рабочая JSFiddle

Может кто-нибудь помочь мне объяснить, почему ссылки из выпадающего меню не работают, когда я нажимаю на них? Может быть, из-за событий указателя?

Объяснение, почему это поведение: Да, вы правы, это из-за того, как вы используете логику селектора :active. Чтобы объяснить подробно, рассмотрите это правило CSS

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

У вас есть ссылки на меню под вашим основным li.test1, и любой щелчок по внутренним ссылкам также пузырится до этого элемента, поэтому его можно также щелкнуть по значку li. Итак, как только мышь удерживается (событие мыши вниз), оно вызывает событие :active, и вы скрываете links (т.е.: li.test1). Но событие click завершено только тогда, когда мышь как вниз, так и вверх. Итак, теперь li скрыт, а mouse up больше не находится в ссылке. Таким образом, вы видите, что нет возможности запуска события click. Это проблема.


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.


Решение: Вместо того, чтобы обертывать ваши внутренние ссылки меню внутри 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;
}

Ниже приведен рабочий фрагмент SO

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>

Ответ 2

Я бы сделал это обычно с помощью JS, но с CSS есть взломать:

Сначала создайте вход с 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>

Ответ 3

Кажется, что это не сработало, потому что на мыши вниз класс :hover для сохранения раскрывающегося меню исчез. Таким образом, событие mouse up не выполняется в ссылке, потому что выпадающее меню уже закрыто, так что клик не выполняется. Вы должны использовать javascript для открытия и закрытия раскрывающегося меню.

Ответ 4

Я бы предложил удалить

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

и найдите другой способ (несколько строк javascript будут делать), чтобы закрыть панель, когда вы нажимаете ссылку "X Закрыть". (Также исправлены некоторые html отсутствующие теги кстати). Теперь ссылки работают:

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>

Ответ 5

Вы можете использовать label и button на месте a для закрытия ссылки и сделать что-то вроде ниже -

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>

Ответ 6

Почему вы добавили "pointer-events: none;" в list-element.test1? Это перезаписывает ваш pointer-events: auto;.Try, чтобы удалить его, поскольку он связывает ваше событие click.

Ответ 7

Я предлагаю попробовать и использовать jQuery для обработки закрытия контейнера только при нажатии ссылки. pointer-events есть много проблем. Из-за этого они решили отложить эту функцию на CSS4.

Я также думаю, что pointer-events: none; предотвращает запуск любых событий щелчка, поэтому использование jQuery только для ссылки не работает. Я думаю, вам придется исправить открытие и закрытие контейнера с помощью jQuery.

Ответ 8

В 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>

Ответ 9

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

Измените это как на

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

Что происходит здесь, когда ваш div получает "активный" код psuedo из вашей ссылки, он скрывается перед тем, как DOM пузырится на вашу ссылку, чтобы дать перенаправление. Изменение его фокусировки может позволить щелчку на самом деле пройти?

Ответ 10

Один из вариантов - использовать animate. Я привел пример с вашим кодом с opacity. Использование visibility:hidden или overflow:hidden улучшит ваш код.

    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="#" onclick="location.href='http://www.google.com'; return false;">Go to link 1</a></li>
    		<li class="link"><a href="#" onclick="location.href='https://www.google.co.uk'; return false;">Go to link 2</a></li>
    		<li class="link"><a href="#" onclick="location.href='https://www.google.co.uk'; return false;">Go to link 3</a></li>
    	</ul>