Grow your CSS skills. Land your dream job.

Pointer Events & Disabling Current Page Links

Published by Chris Coyier

It is a long-standing web design standard that the logo in the header area links to the homepage of the site. Another standard is that when displaying the navigation of a site, to highlight in some way the "current" page, if it is present in the navigation. I think those are great standards. The logo-link thing is so ubiquitous that your users will likely automatically try it if you've coded it that way or not. The current navigation thing is just good ol' horse-sense for grounding a users and making them feel good about their current location in a websites hierarchy.

But here is another good design standard: don't have links to the same page you are on, on that page.

The idea here is twofold:

  1. When you see a link, it looks like a link, it behaves like a link, that says "click this and be taken elsewhere." If the link takes you back to the same page you are on, that's kinda weird.
  2. It is a waste of server resources to reload a page for no reason.

How can you accomplish this without a bunch of development work and changing markup? CSS of course!


"Disabled" navigation from a quick demo.

The big idea here is that you can tell a link not to behave like a link (do nothing when clicked) using the pointer-events CSS property.

Body has a unique ID at the homepage:

<body id="home">

Navigation has a matching class name:

<nav>
    <ul>
       <li class="home"><a href="#">Home</a></li>
       <li class="about"><a href="#">About</a></li>
       <li class="clients"><a href="#">Clients</a></li>
       <li class="contact"><a href="#">Contact Us</a></li>
    </ul>
</nav>

Navigation for home is deactivated only on homepage:

#home nav .home > a {
       pointer-events: none;
       cursor: default;
}

Wow that was easy, eh? This works in Firefox 3.6+, Safari 3+, and the latest Chrome versions (v5+?). Nothing from Opera or IE yet. But hey, that's pretty sweet for such a little development investment.

Part of the trick to getting this to work is getting an ID or a class on the body you can work with. If that is a new idea to you, check out this article and this screencast for the basic idea. Also know that a CMS like WordPress has a body_class(); function which does a great job of providing all the class names you could ever want on the body.

Thanks to Ant Gray for the idea!

Comments

  1. Hmmm… Interesting solution.
    Best regards!

  2. .home a:active {
    pointer-events: none;
    cursor: default;
    }

    • seelts

      “:active” not always means current page

    • This seems extremely dangerous to me. A link is active in the “:active” sense as it is being clicked. If you turn off pointer events at that time, you might effectively disable all links on the entire homepage.

    • If I want to add another 10 menu items, I’ll have to edit the CSS – it is bad practice.
      better to add the class .active for the current menu item

    • That’s a good point, it will require some upkeep, I don’t think that makes it bad practice though. And I want to make clear to anyone reading this that a CLASS of .active is a lot different than the PSEDUO-CLASS of :active

    • Which is exactly why I personally use “selected” instead of “active” for a current-page class name. Just to keep that differentiation clear.

    • I agree with banzalik since css is made to define a style which is independent of the content.
      Imagine you have a personal homepage with 5 links in the navigation. Now you want to add a new page about your dog or about your computer. Why should you change the css for doing this?

      The whole style of your page is already defined. All you want to do is adding some content.

  3. seelts

    Still can’t see the sense of using ID in body tag.

    This example, you’ve provided, means that you adding this ID on server-side. But. You can just make something like

    <li class="about nolink"><a href="#">About</a></li>

    in your server script. It seems to be nicer. In my opinion.

    • That’s fine too… but IDing the body has a ton of other uses whereas this is far more specific, (IMO) less semantic, and requires some programmer intervention to get it done.

    • to change the id in body require programmer :) or not?

    • It might. Probably not if #1) you are already doing it. #2) you are using a CMS like WordPress which has a simple function for it. #3) you are comfortable enough to add something like this:

      <body id="<?= basename($_SERVER['PHP_SELF'], ".php")?>">

    • This seems like the best way to go about it.

  4. Ah yes, horse logic. Nothing like good ‘ol fashioned web design and modern cursor events.

  5. Nice idea, I did not know about this property,but in my opinion this solution does not meet the standard you mentioned: “don’t have links to the same page you are on, on that page”

    If something is a link is defined by the markup and not by css. In your markup the “Home” link is still a link because the word “home” still has the meta information that links it to an URI.

    The mentioned standard is important from the postion of accessibility, when form example in a screenreader the style of the current active link can not be displayed. So if the loop through all the links on a page that you do not get the choice clicking the current visited link again.

    If you really want to meet the mentioned design standard you should change you markup. A well designed cms should do it for you.

    • Definitely a good point. If you have the ability to change the markup generated, that MAY be a good way to go.

      But another reason to use this, and in fact this is probably why it was added to CSS’ capabilities, is that removing the link around a navigation element may remove the only tag with the ability to target it. If you are using a standard “unordered list” navigation, you may be able to use the <li> element to style it the same way, but that’s not guaranteed. If you aren’t using a list item at all, the anchor tag may be all you got, and removing it could break the menu’s layout.

    • Two possibilities:

      - use a span tag instead of an anchor for the active “link” (this is what I do when caring about this standard). As I see you mentioned it yourself a few comments below.

      - use an anchor tag without the href attribute. I am not sure if this is a right way and if all browsers do not links the word if you do so, but it just came in my mind.
      Then you would have to change the css selector to a:link, the simple “a” selector would be for the current active link.

    • Removing the href attribute shouldn’t affect the styling, and you can always target <a> tags with the href attribute by adding :link to your CSS.

      I use the <a> tag without any href attribute a lot actually, especially when using JavaScript but that’s not to say that I don’t have fallbacks.

    • I made an example and I think it does very well:

      http://static.laszlokorte.de/html/active_link.html

    • sander

      You would probably want to override the default :active styling too… as clicking your active link still results in the default active link style (underline and blue)

  6. I think it’s clever that you can do this in CSS, but it doesn’t feel like it’s in CSS’s remit to disable links in this way – this is behaviour done in CSS (which is just as bad as appearance/layout done in JavaScript).

    • John

      Couldn’t agree more..
      Also seams odd to me that there is an “event” property for style sheets, when events are typically what defines scripting languages.

      Is this something we will see more of in future versions of CSS or is this an exception?

    • Even from someone like me who can’t write javascript and still struggles with jQuery I would have to agree. It is not CSS’s place to handle behavior. I am all for CSS handling animation because that is just how something is displayed, but for anything like this, that should remain javascript’s domain.

    • I think it’s an interesting thing to discuss, for sure. I think pointer-events is the closest intrusion on this territory to date. Some might argue even :hover is too behavior oriented (I’d disagree). Many more people are saying transitions/animations are behavior (I’d disagree). But this is almost unarguably behavior related.

  7. I am always cautious about putting IDs on body tags. They offer a lot of opportunity, but all too often, especially on teams, people end up using too specific rules relying on the body tag. Despite establishing proper coding patterns at the beginning of the project I constantly see:

    <pre><code>body#someid #main #content p {some rules}</code></pre>

    when all that was needed was:

    <pre><code>#content p {some rules}</code></pre>

    • Eddy

      If you use the same stylesheet for several pages (which is pretty common) #content p will not always be inside #main and #main will not always be inside body#someid which means you can target it on just the pages where it is. That is the point of giving the body tag an id or class.

    • or, if a certain page (e.g., the home page) has noticeably different styling, especially if it’s applied to elements/ids that also exist on other pages.

  8. bill

    Is pointer-events available to all major browsers?

    • Tommie Forssander

      Bill: Read the article again. Chris clearly states what browsers are supported.

  9. Cool idea. I was just thinking about this topic the other day. I think this will work in most cases, but in some situations where you have sub pages but no sub-navigation it may not work. You want to give the user the opportunity to go back to how the page/section was when they first visited (besides hitting the browser refresh button). Or if you have dynamic content (sliders, etc); you want to be able to reload the content. For example your snippets main page. I find that I use links like that to reload the page in the same way that I use a logo to take me back to the home page or many Google services (click Gmail logo to manually check for new mail). If dynamic content is going to be displayed by a page refresh, than you’d want to keep the button a link (like the Twitter sidebar links for mentions, etc).

  10. Eddy

    @Chris – Good standard, you should also implement it.

    • I just may. Like everything, much consideration needs to be made. For example on this site, you could be viewing the freebies area but specially the CSS-related freebies. The navigation will indicate that Snippets is current, but clicking it will take you back to the JavaScript stuff. So it’s a tough call but since it takes you to an actual different place it probably shouldn’t be deactivated.

    • Eddy

      On a related note, I always thought your home page is a bit confusing since the “Articles” tab is marked, but the home page has a bunch of other stuff, like screencasts and snippets. So if I click on Articles, I would expect to get to a page with just articles, not the home page. A simple solution would just be to change the “Articles” button to “Home”. Just my two cents.

    • Eddy

      Also, the heading of the article will take you to the same page..

  11. This reminds me of the screen cast you did a while back about nav highlighting for WordPress, but less complicated :)

  12. Hoteldebotel

    You actually did it your self here Chris, you linked the Title of the blog post on this page, to the same page (here)!

    • That goes along with my comment above. Makes sense to do that in blog posts because you may want to reload the page to see new updated comments. Or sometimes I will right click on the page title to get the link to post elsewhere.

  13. What happens if “About” has children, something like “our history”, “mission”, “board”, “in the community”, etc. Wouldn’t you be disabling the link to “About” from those children pages?

    • Ant

      If you use > selector, there are no problems.

      Try this:

       #nav > li > a {
      	pointer-events:none;
      }
    • Ant

      Oops.

      (Chris, please add comment preview).

  14. Tommie Forssander

    Thanks for the tip, Chris. Very nice indeed!

  15. While I agree with most of the comments here that this is a good idea, but not 10% practical in production code.

    There are lots of other power tools out there that developers would gravitate to. In Rails for instance, you can use link_to_unless_current.

    But if you are not in Rails and/or not executing production code, this is an AWESOME for “can’t make it — fake it prototypes”

    • Oh Rails, you’re so smart. What does it wrap the link in then if it IS current? Nothing, or does it use a <span> or something? What worries me about just removing links for current pages rather than use this CSS is it may remove the only tag you have to target the text.

    • You nailed it. The Ruby solution I offered will remove the <a> tag, so you would need to take that into consideration when engineering the UI.

      I was just using that as a single example. There are all kids of ways using JS (as I am sure you know) to manage this situation as well.

      But I still think that this is an awesome prototyping solution to fake a use case.

    • just for your interrest: In rails you can even give an additional parameter to specify what to do if the generated link is the active one.

    • While there are many way to get this same result, I think that js may be able to handle this best – just write a function that will compare the href in a link to the current url; and if it’s the same, remove it (the href, not the <a>), or just ass onclick=”return false;” or something. It’s more dynamic this way; you don’t have to hard-code the css for each page.

    • $#|+

      Chris, I typed ss instead of dd in my post above. You may want to fix that. Sorry!

      We should be able to edit our own comments (or at least delete them).

  16. Its pretty ironic that this page’s title links to the same page. Fix: remove the anchor link in single.php if your using WordPress.

    • I probably should. I usually do, but I think at one point or another I decided that I wanted a link there for some reason. I think for some reason I’ve developed the personal habit of right-clicking and copying URL’s of blog post titles when I want to do something like tweet it. And if that was gone it would bug me. But I should probably get over it and remove it as it’s clearly not needed.

    • Simon

      C’mon Chris you can use the address bar for that :)

    • It’s clearly needed if you use it.

  17. Thank’s Chris! this trick is simple but very usefull! I will use in my next website project.

  18. Wow, this is pretty cool. I’ve heard of more complicated ways of doing this but this is by far more straightforward.

    I’ll try this on my next project! :)

  19. Ben

    Nice post Chris, pointer-events is pretty interesting!

    In my experience you don’t always want that link to be inactive.

    On a fashion retail site I work on, the “Women Men Kids” links in the main nav are actually links to sections of the site, as opposed to unique individual pages. For example, clicking on Women will take you to the landing page of the women’s subsection and highlight Women in the main nav.

    From that page, you can drill down to individual product pages, but Women remains highlighted in the main nav to indicate which subsection you are in, even though it’s not a link to that individual product page.

    In this case, you want that link to be highlighted to indicate which subsection you’re in, but you also want it to be clickable to enable users to return to the main women’s page.

  20. I’ve changed my mind on this Web design maxim lately. For regular homepages, sure, but on sites like Reddit and Hacker News, I frequently click on the link that just reloads the current page, in case some new stories have come along. On the iPad this is particularly handy since the reload button is so tiny and you have no simple Cmd+R alternative :-)

    So.. I’m keeping links to the current page on all my sites from here on out. It hurts no-one, my visitors are smart enough to understand what a page reload is, and since most clients appreciate conditional GET, it barely uses any resources at all. Pragmatic vs dogmatic.

  21. This version will run faster and will be supported by all browsers, even Opera and IE.

    <nav>
        <ul>
           <li><a class="home"  href="#">Home</a></li>
           <li ><a class="about" href="#">About</a></li>
           <li><a class="clients" href="#">Clients</a></li>
           <li><a class="contact" href="#">Contact Us</a></li>
        </ul>
    </nav>
    a.home {
    pointer-events: none;
    cursor: default;
    }
    • That CSS selector will then match on all pages and disable the home link on all pages, not just the homepage, that’s the deal with the body ID, to limit it only to the current page.

      And the pointer-events property is what doesn’t work in Opera and IE, not the selector itself.

      Just trying to keep the message clear to anyone reading this.

    • I already posted a link above, but for the case you did not notice:

      <a href="#" rel="nofollow">Home</a>
      <a>Tutorials</a>
      <a href="#" rel="nofollow">About</a>
      <a href="" rel="nofollow">Contact</a>
      a:link {
      color: blue;
      text-decoration: underline;
      cursor: pointer;
      }
      			
      a {
      color: black;
      text-decoration: none;
      cursor: default;
      }
    • thx, of course, I had

      #home a.home {
      pointer-events: none;
      cursor: default;
      }

    • I just figured out that the code as I posted it, does not work in firefox. The simple solution for this is extending the a:link, selector with “, a:visited” because a vistited link in FF does not match a:link anymore

  22. Nice. Leave it to CSS to pick up the slack. CSS may just stand for Creative Stuff Solutions, just maybe…

  23. Amazing! I forget about doing that. That is simply brilliant.

  24. Whoah? I didn’t know you could do that. Thanks for sharing this.

  25. Chris, I understand the urge, but this is a really bad idea. For a few reasons, summed up as:

    1) Just because you can’t think of a reason people want to click on a link that leads to the same page doesn’t mean there isn’t one.

    2) A link doesn’t say ‘go somewhere else’–a link says, and has said since the internet began: go to wherever this points, which may be further down the page, in a modal window, or something else.

    Regarding 1, maybe the user wants to refresh the page without hitting ‘refresh’. Especially with article/blogpost titles and such, maybe they want to make sure they’re at the canonical/full address. Why frustrate that user? As in real life, what may seem like a trivial amount of effort to the designer can be annoying and even discouraging to users.

    Regarding 2, this may in fact come back to haunt one in terms of SEO. I believe Google already takes some Javascript behavior into account, and there’s no reason to think they won’t in the future. Webcrawlers, like web users, count on links just doing their thing. If that means linking to the same exact page, so be it.

    Moreover, this introduces what’s called a modal error into the core of your interface navigation. Modal errors are when the same thing acts two different ways in two different contexts, a big usability no-no.

    When I, as a normal web user, go to click on this link on your page and it does nothing, I’m at least momentarily confused, and start thinking about the technology instead of the content. Always a bad sign. (More of concern with people attempting to portray an image of competence, it may make me wonder if the site’s somehow ‘broken’. This may have some usability concerns, but is mostly a loss for the site instead of the user.)

  26. After reading all of the comments I have to agree with the one previous by DN, this is irregular behavior and changing the way people currently interact with navigational elements whether from a “design” perspective this makes perfect sense, from a UIX behavioral perspective this may be confusing and complicate the goal of the page which is the content and not swapping out functionality by changing how a typical viewer is use to interacting with a web page.

  27. Permalink to comment#

    Wow, very cool trick! I used this to disable a lightbox zoom action for images on small mobile screens. I thought I might have to find a way to disable the script. This is such a simple solution.

This comment thread is closed. If you have important information to share, you can always contact me.

*May or may not contain any actual "CSS" or "Tricks".