it-swarm.com.ru

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

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

Есть много вариантов сделать это:

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

  2. использование :active для контейнера и pointer-events для указания только active ссылок, но события указателя содержат ошибки

  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>

12
RulerNature

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

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

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

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

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


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.


Solution: Вместо того, чтобы заключать ссылки внутреннего меню в li.test1, вы можете работать с двумя разными li, одним для X CLose и другим для хранения menu links. Имея это в виду, мы можем быть уверены, что когда li.test1 активен (т. Е. Мышь не работает), мы можем скрыть его, а также другую новую li, которая прилегает к нему. Таким образом, это означает, что когда пользователь нажимает на X Closeli, мы скрываем меню. Если он нажимает на другие пункты меню, вы перенаправлены.

Таким образом, изменения в вашей структуре 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>


Примечание: Пустой экран, когда вы нажимаете на ссылки, связан с безопасностью 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'.

Однако вы можете увидеть запросы на вкладке сети, когда вы нажимаете на ссылки.

Надеюсь это поможет!!

3
Rajshekar Reddy

Я бы сделал это, как правило, используя JS - но с CSS есть есть взломать:

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

Но в приведенном выше коде есть недопустимый элемент input внутри ul - чтобы не допустить, что вы можете немного отредактировать разметку, чтобы создать еще одну обертку для ul (возможно, вам придется немного отрегулировать ширину/отступ из-за изменения разметки) - см. код ниже:

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>

4
kukkuz

Вы можете использовать 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>

Надеюсь, это поможет вам в некотором роде (у).

1
pradeep1991singh

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

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

1
Theodore K.

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

1
Martin Cup

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

input с id="close" вставляется перед списком и будет вызываться меткой с for="close"
Когда оно сработает, вступит в силу следующее правило:

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

Который скрывает список.
Но когда вы наводите курсор мыши на .container, он снова появится, что позволит вам повторить процесс . Здесь нет необходимости в ненужном JavaScript. Вход будет делать.

Также были некоторые проблемы с вашим кодом. У вас был текст Drop down menu и CLOSE THIS CONTENT непосредственно внутри ul, что невозможно сделать. ul может содержать только li и ничего больше.

Надеюсь это поможет

0
Gust van de Wal

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

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

0
Kevinvhengst

Одним из вариантов является использование 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="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>
0
shubham agrawal
.container:hover .test1:active {
display: none;
}

Правка это как

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

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

0
jjeining

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

0
ReAlPeNx