Digital Web Magazine

The web professional's online magazine of choice.

Separating Behavior and Presentation

Got something to say?

Share your comments on this topic with other web professionals

In: Columns > Keep It Simple

By Peter-Paul Koch

Published on May 19, 2004

The story so far:

This column deals with the third separation, that of behavior and presentation.

Modern Web development has recognized that CSS can take over many of JavaScript’s traditional functions. For instance, Eric Meyer’s ground-breaking research shows that foldout menus, long the exclusive domain of JavaScript bloatware libraries, can be created by just a few lines of CSS revolving around the li:hover selector.

If we ignore browser compatibility problems and assume that we can create flawless foldout menus both in CSS and in JavaScript, which should we use? Are foldout menus presentation or behavior?

Image replacement raises the same question. Although about twenty gazillion extensions, modifications and variations of this technique were published within a few months, they all rigidly stuck to CSS. Nobody seemed to be interested in porting it to JavaScript, so I did it myself.

If we compare my script to the best CSS variation (probably Pixy’s Cover-up method), which one is preferable? Is my script superior to a CSS solution? Or would CSS be the better way of implementing image replacement? In either case, why?

Personal preference

At the moment, most people seem to answer these questions from personal preference. In itself, that’s quite legitimate. If you work quickly and easily in CSS but find JavaScript scary and confusing, it’s only natural to stick to what you know.

Nonetheless personal preferences only go so far. If there are objective, compelling reasons to create a certain effect in JavaScript you should be able to do it, ignoring what your personal preferences happen to be.

Therefore, as a client-side programmer you should have some JavaScript knowledge. That doesn’t mean you should know the entire W3C DOM by heart, but it does mean you should roughly know what JavaScript can do for you and how to copy/tweak scripts written by others. If nothing else, this will allow you to make an informed decision not to use JavaScript.

Market share assumptions

An objective, compelling argument for—or against—JavaScript could be market share. If JavaScript is vastly better supported than CSS—or vice versa—it would make the choice between them rather easy.

It is generally assumed that noscript browser market share lies somewhere between 10 and 15%. These figures seem to be based on old theCounter stats. Interestingly, in recent months the reported noscript browser market share has dropped by 55%—from 13% in May 2003 to 6% in March 2004.

The sharp decline makes me distrust these figures. I do not believe that 5% of all WWW users turned on JavaScript in recent months, so I suspect theCounter has modified its detection method. However, the very fact that it needs substantial modification makes me distrust both results, the old 13% as well as the new 6%.

Nonetheless, let’s follow common opinion, assume these figures make sense and take their average. We therefore consider proven that noscript browsers have a market share of 10%.

Now we only have to compare this share to the nostyle browser market share to come to conclusions. Unfortunately this figure is unknown. I don’t know of a single stat farm that publishes CSS support figures. (It would be very easy to set up, though. Compare the amount of requests for a page with the amount of requests for its style sheet and you’ve got the necessary data.)

TheCounter reports a 98% market share for the modern browsers. We could assume this means that 98% of all browsers support CSS, but that’s dangerous. After all, we could with equal likelihood assume that 98% of all browsers support advanced JavaScript, but we know that’s not true.

If we make two assumptions from the same data using the same line of reasoning, and one of them turns out to be incorrect, what does that say about the other assumption? I am not prepared to assume that 98% of the browsers support CSS.

Therefore we have insufficient data for a market share comparision.

Rules?

Theory to the rescue. Can we define circumstances in which JavaScript would be preferable to CSS, or vice versa? In other words, can we clearly define the border between behavior and presentation? I found one rule, but it doesn’t work:

Any effect that takes place after a user action is behavior. Any other effect is presentation.

The advantage of this rule is that it highlights JavaScript’s great strength. It’s very hard to write useful scripts that aren’t triggered by user-generated events, so we might as well make a rule of it.

In practice we quickly encounter problems, though. According to this rule, image replacement is a CSS job since it doesn’t depend on user actions. So far so good. Foldout menus, though, are a JavaScript job, since they depend on mouseover and mouseout events.

This means abolishing the :hover selector. It is a pseudo-mouseover event handler and events should be handled in JavaScript, not in CSS. Since I don’t think this abolition would be greeted with glad cries all over Web development land, we must conclude that theory doesn’t (yet) offer any help.

Let’s see if a more practical rule works better.

Use the technology that requires the least amount of code.

This rule doesn’t say anything about the fundamental difference between behavior and presentation. In fact, we’ll see that it’s counter-intuitive from a theoretical perspective.

Nonetheless I like it a lot more than the previous rule. The best way to keep sites simple is to use the most efficient way of coding an effect, avoiding both CSS hacks and JavaScript objects.

Which technology requires the least amount of code? In general CSS is the better choice if you need the same effect on a group of elements. JavaScript, though, easily wins if you need a similar effect on a group of elements.

Inefficient CSS

An image replacement example will help you understand this crucial difference. Suppose a page contains a few headers and a bunch of navigation links. We want them all to be replaced by images. Of course, every header and every navigation link needs its own specific image, since they all have different texts.

This leads to the following code:

<div class="nav">
	<a href="somewhere.html" class="imgreplacement"
		id="somewhere"><span></span
			>Somewhere</a>
	<a href="somewhere_else.html" class="imgreplacement"
		id="somewhere_else"><span></span
			>Somewhere else</a>
	[etc]
</div>

<div class="main">
	<h1 class="imgreplacement"
	id="welcome"><span></span>Welcome</h1>

	<p>Text</p>

	<h2 class="imgreplacement"
	id="possibilities"><span></span>Possibilities</h2>
	[etc]
</div>

.imgreplacement {
	// insert favorite image replacement technique here
}

.imgreplacement span {
	// insert favorite image replacement technique here
}

#somewhere span {
	background-image: url('pix/somewhere.gif');
}

#somewhere_else span {
	background-image: url('pix/somewhere_else.gif');
}

#welcome span {
	background-image: url('pix/welcome.gif');
}

#possibilities span {
	background-image: url('pix/possibilities.gif');
}
[etc]

Rather a lot of code, isn’t it? Adding more image replacements only increases the amount of CSS rules. When we need, say, 10 image replacements per page—3 headers and 7 navigation links, not an unreasonable amount—and when we want different headers on each page, CSS image replacement quickly becomes a maintenance nightmare.

As you see, CSS is a very inefficient tool for assigning a similar effect to a group of elements. All replaced elements need the same general rules, and that’s easy to set up. Every single element needs its own specific background image, though, and in CSS that means repeating similar code over and over again. (Incidentally, this problem is shared by all true CSS image replacement techniques. None of them can efficiently handle large numbers of image replacements.)

My JavaScript solution needs about 20 lines to handle an unlimited amount of image replacements without maintenance problems. Simply creating XHTML elements and assigning the correct id is enough to add new image replacements. The script automatically finds them and inserts the correct image.

In the case of image replacement, JavaScript is much, much more efficient than CSS.

Efficient CSS

The reverse goes for foldout menus, though. CSS only needs something like:

#navigation li ul {
	display: none;
}

#navigation li:hover ul {
	display: block;
}

A JavaScript solution would have to go through all navigation links, assign event handlers to them, open and close the correct submenus, and keep track of what it’s doing.

Here CSS is much more efficient than JavaScript, since we’re assigning the same effect to all lis in the navigation.

Unfortunately, browser compatibility interferes. Explorer on Windows only supports :hover on link elements, and not on any other. Therefore the pure CSS solution can’t be used yet. We’ll have to stick to JavaScript for the time being.

Separation

What we especially shouldn’t do is create complicated, cross-over methods à la Suckerfish Dropdowns. In my opinion the authors of this article make a mistake when they try to create dropdown menus in both JavaScript and CSS, the one for Explorer Windows and the other for all other browsers.

We have to separate behavior and presentation, so that in the end we can easily change either layer while leaving the other one intact. Spreading one effect over both layers is not the way to go. If an effect cannot fully work in CSS, don’t use CSS at all. The same goes for JavaScript, of course.

Besides, there is a psychological danger. The Suckerfish Dropdown menus are inaccessible in Explorer Windows without JavaScript, and I feel that this wouldn’t have happened if the authors had written a pure JavaScript version.

After years of careful indoctrination we’ve come to a point that the mere mention of JavaScript triggers accessibility alerts all over a Web developer’s brain. CSS is less of an accessibility threat, though, so it doesn’t have “Danger” signs plastered all over it.

In this particular case, the use of safe, accessible CSS seems to have lulled the authors into a false sense of security, to the point of forgetting the accessibility issues raised by the use of JavaScript.

As you see, mixing the behavior and presentation layers is a bad idea. (And before you counter that Explorer Windows users hardly ever disable JavaScript: remember that there are 10% noscript users and 5 to 8 % non-IE users. Therefore there must be a few percent IE-noscript users.)

Behavior and presentation

The conclusion must be that we cannot yet firmly separate behavior and presentation. We have insufficient data for a market share comparision. Defining a theoretical border between behavior and presentation calls for the abolition of the :hover pseudo-class.

Choosing the solution that requires the least code seems viable in practice, but it is counter-intuitive, assigning image replacement to JavaScript and foldout menus to CSS.

In practice, separating behavior and presentation today wholly depends on the personal preferences of individual Web developers. In itself there’s nothing wrong with that, since we haven’t found any objective, compelling reasons for using either the one or the other.

However, everyone’s personal preference seems to be CSS these days, and that’s what bothers me. The balance is lost. People seem to be afraid of JavaScript.

Got something to say?

Share your comments  with other professionals (33 comments)

Related Topics: DOM, CSS, XHTML

 

Peter-Paul Koch is a freelance web developer, writes and maintains the Quirksmode.org site. He is also an Administrator of the WDF and WDF-DOM mailing lists.

Media Temple

via Ad Packs