13

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? I'm trying to have a dropdown menu that is closing after a link is clicked or the close button is clicked. I have added some cool stuff like hiding parent container when a link is clicked.

There are many options doing that:

  1. using :focus but when the focus is used the drop-down will not be triggered on the next hover over dropdown.

  2. using :active on container and pointer-events to point only the active links, but pointer events is buggy

  3. using :target but has the same problem as :focus, will not trigger the second hoover.

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>
BurebistaRuler
  • 6,209
  • 11
  • 48
  • 66
RulerNature
  • 693
  • 4
  • 13
  • 40
  • 1
    @hungerstar nope, not working on Chrome. The right behaviour should be to redirect you into google page while clicking on links. – RulerNature Dec 09 '16 at 14:16
  • 1
    You' re saying that "trying to have a dropdown menu that is closing after a link is clicked". Will the links have `target="blank"`? Otherwise how would you know if the menu got closed since you'll be redirected to the link? – Theodore K. Dec 14 '16 at 09:54
  • li and ul end tags are missing. – Imran Mohammed Dec 14 '16 at 08:19
  • 1
    do you need `X Close` or it can be optional ? actually its like either of close button or links will work as hover effect is conflicting them. – pradeep1991singh Dec 14 '16 at 15:05
  • 1
    @pradeep1991singh I need a close button because my original dropdown menu is actually very big so I need that there . – RulerNature Dec 14 '16 at 15:22
  • @RulerNature let me know if my answer suits your needs, Else if you want to achieve the functionality without changing your HTML even a bit.. let me know . – Rajshekar Reddy Dec 19 '16 at 07:43

10 Answers10

4

I would do this normally using JS - but with CSS there is a hack:

First create an input with id close and a label for this that wraps our close button:

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

and add in this style instead of the current .test1:active:

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

See demo below:

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>

But the above code has an invalid input element inside a ul - to prevent that you can edit the markup a bit to create one more wrapper for the ul (maybe you have to adjust the widths/padding a bit due to the markup change) - see code below:

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>
kukkuz
  • 41,512
  • 6
  • 59
  • 95
  • but the links are not redirecting you to the google page :| – RulerNature Dec 14 '16 at 10:24
  • that snippet won't worked but I have created a fiddle based on your code and yes, worked. Only one issue, the input is not allowed inside ul at that level :) – RulerNature Dec 14 '16 at 10:29
  • @RulerNature you are right, I totally missed that... See the edited answer with the corrected code using an extra wrapper in the markup... – kukkuz Dec 14 '16 at 12:36
  • 1
    The snippet can never work because redirects are blocked inside its iframe (not your fault, it's Stack overflow security) – vals Dec 14 '16 at 18:05
4

Quick Check : 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?

Explanation on why this behavior: Yes you are right, It is because of the way you are using the :active selector logic, To explain in detail, consider your this CSS rule

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

You have your menu links under your main li.test1 and any click on the inner links are also bubbled up to this element, so its as good as clicking the li. So as soon as the mouse is held down (mouse down event) it triggers the :active event and you are hiding the links (ie: li.test1), But a click event is complete only when mouse is both down and up. So by now the li is hidden and the mouse up is no longer on the link. So as you see there is no chance of the click event to be triggered. This is the issue.


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: Rather than wrapping up your inner menu links inside the li.test1 you can work with two different li , One for the X CLose and other for holding the menu links. With this in place we can make sure when ever the li.test1 is active (ie mouse is down) we can hide it and also the other new li which is adjacent to it. So this means when ever the user clicks on the X Close li we hide the menu, If he clicks on the other menu items you are redirected.

So the changes in your HTML structure should be like

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

And Main CSS rule is

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

Below is a SO working Snippet

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>

Note: The blank screen when you click on the links are due to the google's security Restrictions on cross origin policy which gives this error in console

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

However you can see the requests in the network tab when you click on the links.

Hope this helps!!

Rajshekar Reddy
  • 18,647
  • 3
  • 40
  • 59
  • @Rajshekar Reddy your answer is pretty good and keep the
    • structure which is very important, but when I click on links, nothing happen...should redirect to google page, I'm not sure why
    – RulerNature Dec 19 '16 at 09:18
  • 1
    @RulerNature see my reason on the *Note* section.. It is actually redirecting.. since the code is running in an iframe you see this error. Create your own HTML file and put this code.. You can see it redirecting to the specified link – Rajshekar Reddy Dec 19 '16 at 09:42
  • @RulerNature here I added all the above code into a html file and uploaded here https://www.sendspace.com/file/j1kss3 . You can download this and see the desired behavior. let me know if you need anything else – Rajshekar Reddy Dec 19 '16 at 09:50
  • @Rajshekar Reddy thank you very much man, let me test a little bit your work and I'll let you know :) – RulerNature Dec 19 '16 at 09:56
  • @Rajshekar Reddy can you help me please to integrate that into a bootstrap drop-down ? here is a small fiddle: https://jsfiddle.net/DTcHh/28011/ – RulerNature Dec 19 '16 at 13:37
  • 1
    @RulerNature here you go.. I changed the CSS selector to select all the siblings using `~` https://jsfiddle.net/RajReddy/DTcHh/28013/ – Rajshekar Reddy Dec 19 '16 at 13:42
  • @RulerNature another update to remove the small glitch during hiding the menu https://jsfiddle.net/RajReddy/DTcHh/28016/ – Rajshekar Reddy Dec 19 '16 at 14:18
1

It doesn't seem to work because on mouse down the :hover-class for keeping the dropdown menu open is vanished. So the mouse up event is not executed on the link because the dropdown is already closed again, so no click is performed. You should use javascript to open and close the dropdown menu.

Martin Cup
  • 2,399
  • 1
  • 21
  • 32
  • Yeah, I saw that but why ? it is that normal ? – RulerNature Dec 09 '16 at 14:19
  • If you take away `.container:hover .test1:active { display: none; }`it seems to work. – Martin Cup Dec 09 '16 at 14:30
  • doing that the container will not be closed when click on close top button or links ... – RulerNature Dec 09 '16 at 14:32
  • 2
    Yeah CSS is not very powerful when it comes to interactivity, that's why I suggested to use Javascript, because it is either a very complex thing to do in CSS or not possible, but I can't proof whether it is impossible. – Martin Cup Dec 09 '16 at 14:38
1

I would suggest removing

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

and find another way (a few lines of javascript will do) to close the panel when you click on the "X Close" link. (Also fixed some html missing tags by the way). Now the links are working:

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>
Theodore K.
  • 5,058
  • 4
  • 30
  • 46
  • not an option, I need that active in order to close the container after the links are accessed or when the "close" button on top is clicked. – RulerNature Dec 09 '16 at 14:31
1

You can use label and button in place on a for closing link and can do something like below -

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>

Hope this will help you in some way (y).

pradeep1991singh
  • 8,185
  • 4
  • 21
  • 31
0

Why did you add "pointer-events: none;" to the list-element .test1? This overwrites your pointer-events: auto;.Try to remove it, because it binds your click event.

realpenx
  • 113
  • 15
  • need that pointer events there in order to close container only on links and not when you click on whole container . So with pointer-events can indicate to do that only on links ;) – RulerNature Dec 09 '16 at 14:18
0

I would suggest to try and use jQuery to handle closing the container only when a link is pressed. pointer-events have many issues. Because of this they have decided to postpone the feature to CSS4.

I also think pointer-events: none; prevents any click events to be fired, so using jQuery just for the link wont work. I think you'll have to fix the opening and closing of the container with jQuery.

Kevinvhengst
  • 1,672
  • 4
  • 27
  • 40
  • with javascript that can be done in a minute but I don't want to use js, it's possible doing that only with css, I saw something similar done with :target and :active but in my case I need to apply that behaviour to those links. – RulerNature Dec 14 '16 at 09:35
  • @RulerNature But what is the reason you don't want to use JS? Why spend so much time on trying to implement a CSS feature that they said will not be supported well till CSS4. – Kevinvhengst Dec 14 '16 at 09:37
0

In CSS, you can bind label elements to inputs. Given this, you can bind the close button to an input that - when active - hides the list again.

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>

The input with id="close" is inserted before the list, and will be triggered by the label with for="close"
When it is triggered, the following rule will take effect:

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

Which hides the list.
But when you hover over the .container, it will show up again, allowing you to repeat the process. There is no need for unnecessary JavaScript here. An input will do.

There were also some things wrong with your code. You had the text Drop down menu and CLOSE THIS CONTENT directly inside an ul, which can not be done. An ul can only contain li's, and nothing else.

Hope this helps

Gust van de Wal
  • 5,211
  • 1
  • 24
  • 48
0
.container:hover .test1:active {
display: none;
}

Change this like to

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

What's happening here is that when your div is getting the "active" psuedo code from your link click, it's hiding before the DOM bubbles to your link to give the redirect. Changing it to focus might allow the click to actually go through?

jjeining
  • 61
  • 1
  • 8
0

One of the option is to use animate.I have given a example with your code with opacity. Using visibility:hidden or overflow:hidden will enhance your 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>
shubham agrawal
  • 3,435
  • 6
  • 20
  • 31