- A: The CSS revolution
- B: Separation of presentation and structure
- C: Separation of behavior and structure
- D: Separation of behavior and presentation
- E: Accessibility overview
- F: Rules of accessibility
- G: The example scripts
D: Separation of behavior and presentation
The third separation, that of behavior and presentation, is unfortunately much more complex than the previous two. Don’t expect clear answers in this section; this separation is one of the areas of modern JavaScripting that has not yet crystallized into a set of easily learned and understood rules. Right now we have more questions than answers.
The basic question is: which effects should you define in CSS and which ones in JavaScript? Although the answer might seem obvious—presentation goes in the CSS and behavior in the JavaScript—there are gray areas where CSS and JavaScript overlap, and where it’s unclear if a certain effect is presentation or behavior.
Dropdown Menu—:hover or mouseover/out?
Dropdown Menu’s purpose is to show submenus when the user mouses over a main menu item and hide them when the user mouses out again, and since time immemorial (1997, to be exact) we’ve used JavaScript to obtain this effect. Back then there were no other options; if you wanted a dropdown menu you needed JavaScript.
Figure 2.3 Dropdown Menu. When the user mouses over the News link, the submenu becomes visible. Do we code this in JavaScript or in CSS?
However, you can now create this effect in CSS, without any need for JavaScript:
<li><a href=”#”>News</a> <ul> <li><a href=”#”>Press Releases</a></li> <li><a href=”#”>News Articles</a> </li> <li><a href=”#”>Photo Gallery</a></li> <li><a href=”#”>Official Blog</a></li> </ul> </li> // in .css file li ul {display: none;} li:hover ul {display: block}
Any <ul> inside an <li>—in other words, any submenu—is initially hidden (display: none). When the user mouses over the <li>, though (li:hover), the submenu becomes visible (display: block).
Which solution is preferable? Most people will opt for JavaScript over CSS because Explorer 6 and earlier do not support li:hover.
Nonetheless, this eminently practical consideration does not answer the fundamental question. Let’s for a moment suppose that all browsers support :hover perfectly in all circumstances, and that the CSS and JavaScript solutions are therefore equal in terms of browser compatibility. Which do we use?
The CSS code is a lot simpler than the JavaScript code, and that’s of course an advantage. As we’ll see in 7H, the JavaScript mouseout event, especially, is very obnoxious and needs a firm and masterful hand to keep it from playing up. In contrast, the CSS :hover selector just...works.
In addition, the CSS code continues to work when JavaScript is disabled. Unfortunately, this does not necessarily mean that the CSS variant is more accessible than the JavaScript one.
Some people use a keyboard instead of a mouse. They use keystrokes (usually Tab) to put the focus on HTML elements (usually links), and then press Enter to activate the focused element. These keyboard users will not be able to use a CSS dropdown menu, since li:hover is a pure mouse selector that does not react to the keyboard focus. Besides, it’s impossible to focus on <li>s—keyboard focus works only on links, buttons, and form fields.
In contrast, the JavaScript can be made to accommodate keyboard users, as we’ll see in 7G. Therefore a CSS dropdown menu isn’t inherently more accessible than the JavaScript version. Keyboard users will vastly prefer the JavaScript version.
In fact, both variants have their own unique problems, and from an accessibility standpoint neither is clearly superior. Accessibility alone doesn’t help us to choose between CSS and JavaScript.
Let’s take a more high-level theoretical perspective. Are dropdown menus presentation or behavior? The effect takes place only after a user action, which would argue for it being a behavior. On the other hand, the effect is about presenting the submenus, which argues for it being presentational.
Although personally I tend to lean towards the behavioral answer, the problem allows for more than one interpretation, and every Web developer should find his or her own solution to this theoretical conundrum—or just ignore it.
In conclusion, the single point on which a CSS :hover solution scores distinctly better than a JavaScript mouseover/out solution is the amount of code you need to write and maintain. Is this enough to say that the CSS solution is always better than the JavaScript one? It still boils down to a personal decision.
The same effect vs. a similar effect
In a dropdown menu, you want to deploy the same effect on any <li> that’s eligible for it. “If this <li> has a nested <ul> (i.e., a submenu), show it when the user has his mouse over the <li>.” As we saw, this rule is easy to summarize in two lines of CSS:
li ul {display: none} li:hover ul {display: block}
The CSS is so simple because all <li>s are treated the same. Keep that in mind.
Now let’s take a different example: a mouseover. When the user mouses over an image, the image changes, and when she mouses out, the image changes back to its original state.
Until today, all mouseover effects have been written in JavaScript, which is largely a matter of tradition. A JavaScript mouseover effect has been an all-time favorite since its inception in 1996, and it’s one of the most copied scripts on the HTTP://WWW. Since there are already a gazillion example scripts, nobody has ever ported it to CSS.
Nonetheless, in theory it’s possible to create a CSS mouseover effect:
<a href=”somewhere.html” id=”somewhere”>Somewhere</a> <a href=”somewhere_else.html” id=”somewhere_else”>Somewhere else</a> a#somewhere { background-image: url(pix/somewhere.gif); } a#somewhere_else { background-image: url(pix/somewhere_else.gif); } a:hover#somewhere, a:focus#somewhere, a:active#somewhere { background-image: url(pix/somewhere_hover.gif); } a:hover#somewhere_else, a:focus#somewhere_else, a:active#somewhere_else { background-image: url(pix/somewhere_else_hover.gif); }
You’ll notice that every mouseover effect needs two CSS declarations—one for the normal state and one for the mouseover state. The reason is simple: every link has its unique normal and mouseover image, and these unique images need to be defined in the CSS.
In this case we’re not deploying the same effect on all links, but a similar one. All links change images when the user mouses over them, but every link needs its own set of images. For every link we add to the document we have to create two new CSS declarations, and we have to do that manually. In fact, a pure CSS mouseover quickly becomes a maintenance hell, especially when you use dozens of links on your site.
This is, in fact, a general rule. CSS is extremely efficient when you want to deploy exactly the same effect on a number of elements, as in the dropdown example, but extremely inefficient when you want to deploy a similar effect on a number of elements, as in the mouseover example.
JavaScript allows you to write a script that can manage mouseover on an unlimited amount of links:
<a href=”somewhere.html” id=”somewhere”><img src=”pix/somewhere.gif” /></a> <a href=”somewhere_else.html” id=”somewhere_else”><img src=”pix/somewhere_else.gif” /> </a> function initMouseOvers() { var links = document.getElementsByTagName(‘img’); for (var i=0;i<links.length;i++) { var moSrc = links[i].src.substring(0,
links[i].src.lastIndexOf(‘.’)); moSrc += ‘_hover.gif’; links[i].moSrc = moSrc; links[i].origSrc = links[i].src; links[i].onmouseover = function () { this.src = this.moSrc; } links[i].onmouseout = function () { this.src = this.origSrc; } } }
Initially this solution requires more lines than a CSS solution, but this is more than offset by its versatility. If you need another mouseover, you simply add a link to the document, and it works.
Therefore, when creating similar-but-not-quite-the-same effects such as mouseovers, JavaScript is the most efficient solution. This is something to keep in mind when you’re forced to choose between CSS and JavaScript.
Right now it’s not possible to reach a definite conclusion about the separation of behavior and presentation. More research is necessary, and for now I’d like to ask you to spend a few minutes of thought on this problem whenever you encounter it—and if you find a good general rule, publish it! Maybe you’ll lead the way in discovering the principles of the third separation.