10

I am adapting a website in order to make it feel native on the iPad.

This website has navigation that shows a drop-down with the sub-navigation on hover. This works like a charm on the iPad. When you touch it the subnav, it opens and closes again when you click/touch somewhere else.

Now i have the requirement to make it close again when the navigation point is touched again.

I was thinking, i could just set the pointer-events:none on hover & active for the iPad, but this makes the sub-navigation flicker and it does not work...

i have also tried to cover the navigation point with element set with the before selector and setting its pointer events to none, but this does not work...

Any idea, how i could solve this problem using CSS only. (I can not modify the HTML nor the JS)

PS: you can reproduce this on www.macprime.ch for example... (click the main navigation on the top, and try to close the dropdown again)

edit ok i tried almost everything that was possible with CSS only. I don't think its possible. If anyone can tell me why, he/she will get the bounty reward.

meo
  • 30,872
  • 17
  • 87
  • 123

3 Answers3

2

You could have a second transparent element that appears above the one you tapped. That way, when the user taps again, they will be selecting the other element and the first will lose its hover status:

<div class="blocker" onclick="void()"></div>
<div class="menuItem" onclick="void()"></div>

<style>
    .blocker, .menuItem {
        /* use the same position, width, height, etc */
    }
    .menuItem {
        /* make it look pretty */
        z-index: 100;
    }
    .blocker {
        z-index: 99;
    }
    .menuItem:hover {
        z-index: 98;
    }
</style>

Of course, this will have a negative effect on the desktop, so you will want to do something like:

<style>
    .blocker { display: none; }
    .touchevents .blocker { display: block; }
</style>
<script>
    if('ontouchstart' in document)
        document.body.className += ' touchevents';
</script>

UPDATE Added onclick events to make them clickable.

You can see a working demo here: http://fiddle.jshell.net/vfkqS/6/

Unfortunately, I could not find a solution that does not require HTML or JavaScript changes, but I was able to keep them to a minimum.

You would need to make two non-CSS changes total:

  1. Add a JavaScript mechanism for identifying if touch events are supported. See two line example above.
  2. Add one div per menu which is clickable (onclick="void()") and has a unique identifier that can link it to the menu.

You may be able to do those two things with CSS but I'm not sure. Tablet detection would be a little sketchy in CSS and I don't think you can make something that sophisticated with a :before or :after pseudo-selector.

Brian Nickel
  • 26,890
  • 5
  • 80
  • 110
  • i was afraid i had to do something like this... I already tried a lot of things with :before elements, pointer-events etc... Thank you. If i don't get a better answer in the next hours you get the bounty. PS: I don't think you need those onclick events... Simple use `a` tags. And you can do a pseudo iPad detection with css only: http://stackoverflow.com/questions/3839809/detect-iphone-ipad-purely-by-css – meo Oct 15 '11 at 10:11
  • Either should work, `onclick` or `a`. The tablet just needs to register that the element is touchable. I opted for `onclick` because it has no side effects and makes the whole element clickable. When testing it out, I had to do a lot of work with a link to make it work perfectly (display block, size to 100%, update the appearance, etc). – Brian Nickel Oct 15 '11 at 14:48
0

This is an interesting question and similar to one I've had come up recently. How do you marry a standard navigation dropdown that displays on hover with a touch event interface. Using the hover event as a trigger works really well on a desktop. In a world without hover events (tablets and smart phones), not so much.

In my case I landed on the idea of defining the behaviors: click/touch event would do the triggering, hover event would do subtle indications. For more details on this line of thinking see: http://www.markdotto.com/2012/02/27/bootstrap-explained-dropdowns/

For the issue you're trying to overcome I'm wondering if using @media queries in your CSS is a better solution...

@media (max-width: 979px) {

    /*
        New CSS declarations to show the sub navigation lists
        in a more compact way that fits nicely on the iPad.

        Something like...
    */

    section.nav-overlay {

        display: block;
        height: 60px;
        visibility: visible;
        width: 979px; /* Or the max container width */

    }

        section.nav-overlay ul li {

            float: left;

        }

        /*

            Etc. etc. with the additional exceptions.
            You get the idea.

        */

}

By doing this you would create more of a native interface on the iPad. However, if going this route is off the table, something like what Brian has above is better. Just wanted to give you an alternative.

jstam
  • 561
  • 3
  • 3
  • sorry, but i dont understand how this could help me solve this problem. – meo May 11 '12 at 21:53
  • As you said, doing this in CSS only would be difficult. If you used @media queries you could change the way the dropdown menu appeared on the iPad altogether (having it appear on screen rather than dropdown from a hover event). Furthermore, your issue may go away entirely if the dropdown menu weren't displayed on a hover event, but on a click event. Click events translate much more nicely to touch events. Both of these options would come with significant UI behavior changes which may be outside of the scope of what you're trying to do. – jstam May 14 '12 at 13:33
  • Thank you, but its not like i have a choice to make it different. It has to work this way. But i think i will need to use the JS variant.. :/ – meo May 14 '12 at 20:16
-3

Set pointer-events: none on the active state:

nav#mainnavi > ul > li > a:active {
  pointer-events: none
}
methodofaction
  • 70,885
  • 21
  • 151
  • 164
  • pointer-events does not 'close' the overlay - only prevents the href to be executed … so sadly thats no solution for this problem – albuvee Oct 11 '11 at 12:37