Using Markup Based Javascript Effect Libraries to make dynamic sites in standards compliant HMTL
Summary
You can make websites effects with plenty of glitter using simple, standards compliant HTML through the use Javascript effect libraries which operate on CSS classes. I'll talk about why I think it's important, and if you stick with me, I'll point you to some of my favorite lightweight Javascript effect libraries.
The Conflict
Websites need eye-candy. Everyone loves rounded corners, fancy menus, animation, fades, effects... The problem is that the sparkly stuff often leads to unmaintainable code which is inaccessible and doesn't degrade gracefully. The usual solutions are all bad:
- Flash
Hard to maintain, requires proprietary software, doesn't degrade at all, not very accessible[1]. I'm not a big fan of Flash for most websites. I'm happy to see Flash use moving to complex client side web applications, which is about the only place it's justified (maybe, and hopefully not for much longer). - Javascript
This gets ugly fast. Even if you put your Javascript code in well structured JS files, you usually end up with a lot of javascript event code in HTML attributes. This completely fights the declarative nature of HTML, and leads to really ugly code. Javacript's a pain in the neck to debug, and ugly Javascript is just about impossible to debug. As I've said before, I'm concerned about the messy Javascript code that's being churned out because everybody loves AJAX but IE's Javascript isn't really ready for it. - Try to get out of it
That's not good either. Customers and end users have grown to expect a certain level of flashyness. Even if you succeed, they're not going to be happy about it.
Let's take a step back. Why do we need to write this Javascript? In many cases, we're adding behaviors and effects that browsers don't support (yet ). If they did support them, though, we'd invoke them declaratively in CSS, just as we do for all the behaviors and effects that CSS currently does support. Instead of directly manipulating the DOM in our HTML, we'd like to be defining content in our HTML and use CSS classes to map behaviors to the content.
Spoiler
We can do this today by writing Javascript effect libraries which operate on HTML elements with CSS specific classes.
The Gutless Disclaimer
I'm primarily talking about the mouseover / hover / onload stuff that makes the page move and shimmer, not AJAX code which calls back to the server. I think this approach could work pretty well for AJAX, but I'm focusing mostly on the simple sparkle stuff here.
But why, and why now?
This isn't a completely new idea. Peter-Paul Koch and Simon Willison were talking about this 2004 (PPK's writeup explains the philosophy behind this pretty well). This is important to consider now, though, as the AJAX movement is causing Javascript use to skyrocket. It's important that we get our Javascript approach right now more than ever. To quote Ben Nolan, author of the Behavior JS library:
< a class ="trashcan" href ="#" onclick ="if (confirm('Are you sure?')) { new Ajax.Updater('notes', '/page/2326/notes/destroy/128699', { ...
<script language="Javascript">
photo_hash['16209134'] = new Object();
photo_hash['16209134'].title = '2am on Saturday';
</script>
<h4 id="title_div16209134" style="margin-bottom: 0px; margin-top: 0px;">2am on Saturday</h4>
<script type="text/javascript">initPhotosUserPageTitle_div('16209134');</script>
The Payoff - Markup Based Effects
Note: Please click the links in this section! I'm including demos here since the pages have great demos. Check them out!
Lightbox JS
Lightbox JS is a great example of what I'm talking about. Reference a JS file, then add rel="lightbox" to any image tags on your page and they get a cool popup effect. If the image tag has a title, it's used in the display. If the browser doesn't support it or the page is being rendered in another format (screenreader, print, etc.), it's a standard image tag so it degrades gracefully.
Perfect.
FACE
FACE (Faruk's Animated CSS Enhancements) is a great example of how to do this right. You include a JS file, then define our behaviors by the CSS class as the library defines (see right). The CSS class syntax may look a little ugly, but if you think about this as virtual classes that define a particular behavior, it makes some sense. To use this, your CSS would include multiple classes that start with myclass - myclass1, myclass2, etc. FACE will automatically step through the classes using the parameters defined in the element's class, as on the right, so to have a div fade in on page load I'd simply define fader1 to have the div invisible and fader2 fully displayed, then set the div's class to S:fader:2:L:20.
See the site for some simple examples. This library really showcases the concept of markup driven behavior well.
Slideshows
There are a few slideshow systems that use this approach. Eric Meyer's S5 Simple Standards-Based Slide Show System (demo ) is my favorite, which uses CSS and Javascript for PowerPoint like slide shows that gracefully degrade since they're built with standards based HTML. View source on the demo - there's a single reference to a JS file, and the rest is clean, HTML.
The Couloir.org slideshow is nice for photo slideshows. It's really slick -there's even sound effects for mouseovers and image changes. Most people would assume it's Flash. There's a slight tradeoff in symantic purity and maintainability - the image references aren't in the HTML, so they aren't visible if you don't have Javascript enabled and maintainence is a little more complex - but the Javascript is all controlled by HTML element ID's, so the Javascript is simple.
Rounded Corners
There are a few systems which will round corners for you. Rounding corners looks cool, but it's a pain in the neck. Using fixed size background images isn't at all web friendly and doesn't work when the area needs to expand - more text or browser text size, for instance. You can make expanding boxes with rounded corners built from chopped up images , but that takes 8 or 9 images and 9 div's for each box, which is a lot of complication for a simple design feature. Doing this on the client side in Javascript can barely perceptible square moment as the page loads, but I think the simplicity is often worth the tradeoff. Nifty Corners (demo) is pretty cool and has a ton of options, but isn't completely pure from the CSS driven effects point of view. It operates on CSS ID's, but to invoke it you need to make an Javascript onload call:
Rounded("div#nifty","all","#FFF","#D4DDFF","smooth");
The Rounded() function accepts five parameters:
- A CSS selector that indicates on wich elements apply the function
- A string that indicates wich corners to round
- Outer color of the rounded corners
- Inner color of the rounded corners
- An optional fifth parameter, that will contain the options for Nifty Corners
Ilkka's Rounded Corners trades functionality for some simplicity and anti-aliasing, but still requires an onload function call. I'm still looking for a Rounded Corner implementation that's invoked via CSS, but I mention these solutions here because they do fulfil the general purpose of enhancing the user experience through the use of Javascript in a clean, unobtrusive manner that works with CSS rather than directly against the DOM.
Are there any Javascript libraries that make this kind of development easier?
Yes, I'm glad you asked!
Ben Nolan's Behavior library does exactly that. It really works, too - remember that amazing slideshow at Couloir.org? Built with Behavior. So is Foopad.com, a free hosted wiki service. Check out some simple Behavior demos here.
Of course, you can use any of the above libraries without writing any Javascript. That's the point. Behavior is for creating new affects like those I mentioned above.
Aren't you going to talk about dropdowns?
Dropdowns shouldn't really need Javascript at all. Son of Suckerfish is CSS based, and only used Javascript to work around IE bugs. Don't use mouseover Javascript code when CSS will do.
But what about AJAX?
The careful reader will note that I have avoided this issue through the the use of a Gutless Disclaimer, to which I now refer you.
If this careful reader happens to be familiar with Microsoft's Atlas project, though, the will note that this is the general direction that the Atlas team taken on the generated client side HTML. That "generated" is important - If you browse Live.com and view source, you won't see a scrap of semantic markup. Nothing but includes and javascript. Take a look at the generated source (Firefox WebDeveloper toolbar > View Source > View Generated Source; for IE use either FullSouce or a generated source viewer bookmarklet from here or here). The JS cruft is still there, but the actual HTML part of the page doesn't have a single javascript call despite a high amount of interactivity. That's because the CSS classes are defining the behaviors, and the javascript is acting on the behaviors. I think the feasibility of CSS driven AJAX is a separate discussion, but this shows it is at least a possibility.
Atlas is interesting in that it's Markup Based both in the original source code (on the server) and in the generated HTML on the browser. I'm not sure what this buys when the HTML is generated by a backend framework, but it's interesting.
I'm energized by this discussion and would like to read further. What to do?
Check out this huge CSS tools list. Read PPK's article. Take a look at the Behavior introduction page, which explains the reason the library was created in the first place.
Fin.
[1] Flash can be made accessible, but it's rarely done.