How To Generate CSS Click Events And Thoughts About Whether You Should

You are here:Home / Blog / CSS / How To Generate CSS Click Events And Thoughts About Whether You Should

When you want a click to change something on your page, you usually reach for Javascript. Adhering to principles of modularity and separating structure, presentation, and behavior we’re supposed to use Javascript for behavior layer. However, methods exist for generating click events using only html and css. What are they and should we use them?
I recently had opportunity to use a couple of these css click events in some demos I developed for a series of responsive navigation articles for Tuts+ and found them useful and simple to implement. Then a month ago I found an article with a roundup of most of the different css click event methods on the Codrops site.

I want to briefly walk through the different methods (I’ll provide links to more detailed explanations in and below each section) and also wonder aloud if we should be using them or in the interest of modular code we should stick to using Javascript for click events.

Structure, Presentation, and Behavior

I’m sure you’ve heard someone, maybe me, talk about writing more modular code by separating structure, presentation, and behavior. This separation of concerns generally leads to less code thats’s more maintainable and reusable. When working on the front end of a website we’re told to stick with 3 technologies.

html for structure

css for presentation

javascript for behavior

Over the years, things that are the domain of Javascript have found their way into CSS. Think transforms, transitions, and animations for example. These changes are certainly to an element’s state and we’ve been told they belong to Javascript. Yet we can and do create those state changes without a scripting language.

The real question is whether or not these methods are any less maintainable than Javascript.

Click events are similar. Without Javascript there are methods for simple things like showing and hiding content or changing the presentation of an element. We can trigger an animation or completely restyle the look and layout of a page all without ever turning to a Javascript onclick event.

These non-js click events are easy to use as I’ll show in a moment, but keep in mind the question of whether or not we should avoid using them in the name of modularity as you read through the rest of this post. If the point of separating structure, presentation, and behavior is more maintainable code, are we giving back some of that maintainability in using these html/css click events.

HTML and CSS Click Events

There are a handful of methods for generating a click event, however they all fall under two general categories.

All the methods below make use pseudo selectors. Some also use html form inputs and their associated labels to trigger the event.

Pseudo Selectos

CSS provides a number of ways to style elements based on their state. I’m sure you’ve been changing links based on :hover since not long after you discovered css. Of course :hover is a temporary change of state. Move your cursor off the element and everything reverts back to it’s original state.

Some pseudo selectors allow us to maintain state for a longer duration.

The :target hack — The idea behind this method is that the :target selector will match an element with an id that’s the same as the hash in the url. If you have a url like www.domain.com/my-web-page.html#alert and in your html have

And with that you have yourself a click event. A visitor clicks the link which points to the same page with the addition of the hashtag. Your #alert div changes from display: none to display: block. All without the use of Javascript.

One downside is that same link can’t be used to toggle things back to the initial state. It would require a different link that doesn’t include the hash in the url. However there are times when that’s what you want. Think of an accordion menu pattern. You could set up each of the top level items with a different hash that opens its particular submenu while all others close.

There are other downsides. It’s a new url which leads to a page refresh and can throw off browser history. You can only affect the one element, since an id is required. Again there are times when none of these will be an issue and this event is now finding its way into various responsive navigation patterns.

Here we aren’t navigating to another url, however we can only target one sibling element and anything inside it. We still can’t use the same element to click back to the initial state, but since clicking anywhere outside the now focused element removes focus, we can get back to the initial state without a new element.

The :active hack — Once again this is a similar method to the two above that uses the :active state of an element.

1
2
3

<div class="btn"><p class="alert">Some alarming information</p></div>

1
2
3
4
5
6
7

.alert {
display: none;
}
.btn:active .alert {
display: block;
}

Unfortunately the :active state only exists after you click an element and before you release the mouse button, so it’s very short lived. However, in combination with either the :hover pseudo selector or a css transition you can maintain the state longer and do some interesting things.

Form Elements

Form elements also give us a way to alter states. Forms even come with their own click event, the submit button, but we’re actually more interested in some form inputs here.

The checkbox hack — The idea here is to use a connected form label and checkbox input to toggle the checkbox on and off and once again use an adjacent sibling selector to change the state of another element. We can use :checked to trigger different styles depending on the state of the checkbox .

One advantage of the checkbox hack over the pseudo element selector hacks is we can use the same element to toggle something on and off. Click the label once to check the box. Click it again to uncheck it. This hack seems to be replacing the pseudo selector hacks for this very reason.

The radio input hack — This works much the same way as the checkbox hack, except we can now control more than a single on/off. We can use as many radio buttons as we want and change their state based on which is selected.

A common use is a tab switcher. Louis Lazaris has created a nice example of a tab switcher on Adobe Developer Connection. I’ll send you there instead of reproducing his code here.

With a checkbox a single element is in an on/off state. With radio buttons many elements can be connected with one being on and the others being off. In Louis’ example the “on” tab takes on a different look and displays its content, while the content of the “off” tabs remain hidden.

His post also provides more in-depth examples of the checkbox hack and the focus hack so it’s worth having a look.

Should We Use These Hacks?

I asked above to keep in mind the question of whether or not these hacks make sense given our goal of modularity and separating structure, presentation, and behavior. What do you think? Should we use the non javascript hacks to change the state of elements? Isn’t that behavior? Doesn’t that mean we should use Javascript even if these hacks can be easier to use at times?

I’m not sure I have a good answer at the moment, though I do expect to use the hacks above more just because they do make for simple click events. Then again adding and removing a class on an element triggered by a Javascript click event is also pretty simple and allows us to change state just as all the methods above.

One con of all these hacks, which I haven’t yet mentioned is they don’t work in every version of every browser. For the most part that means older versions of IE as you probably expect. Fallbacks typically employ Javascript so….

About a year ago Kevin Dees argued in an article on the Treehouse blog that this whole separation of structure, presentation, and behavior is dead or dying. CSS is getting structure in the form of pseudo elements and it’s getting behavior in the form of pseudo selectors and animation. Let’s face it. If these things are in css, we’re going to use them.

The real question is whether or not these methods are any less maintainable than using Javascript. I can’t claim to have thought about it exhaustively, but they don’t seem to be any less maintainable on the surface. Perhaps it’s something worth a deeper look another time.

How about you? Have you been using any of these css click events and if so what do you think? Would you use them again?

24 comments

Had no idea these hacks existed! I came here because I´m currently studying your Responsive Navigation Off Canvas tut which by the way is awesome. Thanks to you I´m a 1 percent better front-end dev today (trying to reach 365 percent by the end of 2013)

Thanks Juanfe. These hacks are nice, aren’t they. I only recently discovered them myself and learned about them mainly by using them on the responsive navigation series. I’m glad you liked the off canvas article.

Thanks for the nice roundup. I figured I can use the target hack to switch a div on *and* off — sort off. I put the very same <a href="#thingOn" into the div switched on, just with <a href=”#thingOff” rel=”nofollow”> and place the switched on div exactly over the parent such that it looks like the link to switch is there all the same.

I do use the :target method quite a bit – especially for simple mobile menus but I’m not totally sure about the other methods mentioned in terms of semantic mark up and accessibility. Think you would need to think carefully about how overuse of tabindex might affect a keyboard only user or what a screen reader might make of random checkboxes. Any thoughts?

Thanks John. Good points about accessibility and semantics. I can accept a loss of semantics with these methods, because they are something of a hack and while semantics are important, I don’t think we should be slaves to it.

Accessibility on the other hand is something we do need to be concerned about. Too many checkboxes isn’t a good idea. One probably isn’t even the best idea, but I’m not sure how bad it is. I guess the tradeoff is how much Javascript can you eliminate by using one of these click events and is the tradeoff worthwhile.

The focus method: By placing a similar but invisible p (span or whatever works with tabindex) just after the p to click and then with focus make this p visible and the click p not visible (css sequence important!) you can get a text to click at the same location. As clicking at this point everywhere restores the initial state no focus and css is necessary for the “hide” p.
I think this would work for the target method as well, but haven’t tested this as I don’t like this method changes the url.
Example:

Thanks Bo. This is a new one to me. I’ll have to give it a try. Of all the methods listed, the one I’ve used the most is the checkbox hack. I’m with you on the :target hack. I don’t like that it changes the url even though it does work as advertised.

Thanks for making it right Steven. I tried with html entities like this line:
<tag>
But because they don’t show up as less than and greater than characters while entering I changed my mind as I thought I had done something wrong.

You may have already heard of it, but thought it was prudent to this article (I found it yesterday):http://labs.bigroomstudios.com/libraries/CuttySSark
Event Driven CSS! Still not 100% on what I think about it (and would like to do some performance tests) and definitely not sure about some of the more advanced examples (bringing too much behaviour into presentation) but still – for clicks, toggles onloads it’s pretty cool stuff.

Thank you, these are great. I do have a question, if you take a look at this gist, the label element is below, where you have to scroll the page down. Upon clicking it, it jumps to the top of the page. Is there a fix for this or will I have to invoke some js?

The label isn’t jumping for me. I’ve checked in both Safari and Firefox.

Did you find a fix? Nothing in your code is jumping out at me that would make the label jump to the top of the page. Just wanted to check to make sure you still have the issue before looking a little deeper.