Extensible CSS Interface III: Adding Ajax Interactivity

~ 20 March 2008 ~

This series is sponsored by Authentic Jobs, a freelance and full-time job board for web professionals.

This is the third article in the four-part series, “The Highly Extensible CSS Interface”. Markup and images for this article:

Part III - Adding Ajax Interactivity

This third article documents the underlying components of Ajax, examines a few examples of Ajax in the demo, and wraps up with a shout-out to resolution dependence.

Before we begin…

I repeat the disclaimers from last time: One, this interface is optimized for any browser that supports standards exceptionally well. Sorry, no IE6 support. I’m relying on you to make concessions on your own for IE6, thereby allowing this series to focus on what’s possible with browsers that support standards exceptionally well without being bogged down in the mire of those that do not. (Again, consider conditional comments for IE6 concessions.)

Two, there are a few known “bugs” in the interface for which small inconsistencies will be seen from browser to browser. These will be documented as comments in the final markup (to be provided in Part IV). For this article, be aware that IE7 ignores the negative absolute positioning on the right corner image for the Latest Community Activity and Community Snapshot headings. I welcome any suggestions for fixing this.

Lastly, another hat tip to Aaron Barker who wrote a lot of custom jQuery and Ajax scripting for this demo.


What was penned a couple years ago as a preface to describing Ajax design terminology is still relevant today:

The line between “desktop UI” and “web UI” is gradually blurring. Love it or loathe it, “Ajax”, which originally referred to Asynchronous JavaScript + XML, has somehow become the catch-all term for describing “desktop-like” interaction on the web; more accurately, GUI interaction as seen previously only in native applications running in an operating system environment.

When I first spoke about Ajax in a workshop 18 months ago, few raised their hands when asked if they had experience developing sites and apps that employed Ajax. If asked that same question today, it’s likely half of that same audience would raise their hands. Indeed, love it or loathe it, Ajax has weaved its way into high-profile sites and weekend projects alike as the de facto standard for producing rich interactivity on the web. (It’s worth noting, however, Ajax’s position as king of the hill is increasingly challenged by emerging technologies such as Adobe Flex and Microsoft Silverlight.)

Ajax implementation typically includes at least three components: 1) asynchronous server communication, which is most commonly accomplished via XMLHttpRequest, 2) manipulation of the Document Object Model (DOM) for dynamic display and interaction, and 3) JavaScript to bind everything together. The ‘x’ in Ajax refers to XML, but Ajax can also also be accomplished with (X)HTML, the result of which is often termed AHAH.

Asynchronicity is the key component of Ajax — or any rich internet technology, for that matter — as it provides that “native app” feel within the web environment. Instead of the traditional request/response model that fetches an entire page with a full trip to the server, asynchronicity means we fetch data for only a select portion of the page, e.g. username availability when registering an account, “without interfering with the display and behavior of the existing page” (Wikipedia).

In the demo interface, we fake asynchronous server communication with a little JavaScript and by fetching data from a few static PHP pages:

  • activity.php for the Latest Community Activity section, which functions like Digg Spy with the help of jQuery Spy
  • ajaxStuff.php for mimicking the Ajax request for the bio’s edit-in-place feature in Part II (adds a spinner image and a one-second delay to mimic server retrieval)
  • search.php and jquery.autocomplete.js for the search field auto-complete (Part II)
  • project.js for the Community Snapshot and Latest Community Activity sections, edit in place, and overall scripting wizardry

Faking asynchronicity merely allows you to download the code samples and open the interface on any machine running PHP, without requiring true server communication.

As an example of how these components come together, let’s have a look at the Community Snapshot. For starters, we begin with markup: A div encloses the map as a background image, and styling sets the containing block to relative positioning:

<div id="map"></div>

#map {
  position: relative;
  margin: 0 auto;
  width: 277px;
  height: 155px;
  background: url(../img/map.gif) no-repeat center center;

It’s important that the positioning be set to relative as this will allow the “n members online” boxes that fade in and out to be positioned absolutely according to the map’s containing div. To accomplish this effect, we use a list item with several elements and CSS properties:

<li class="l1" id="map1">
  <p><strong>North America:</strong> <span>n</span> members online</p>

#map li p {
  padding: 5px 0;
  line-height: 100% important;
  font-weight: bold;
  background: url(../img/maploc-bg.png) no-repeat;
#map li strong {
  display: block;
  float: left;
  text-indent: -9999px;
.l1 {
  background: url(../img/maploc-btm-left.png) no-repeat bottom;

Let’s break down each of these:

  • <p></p> - This is the wrapper for our content. While it’d be nice to keep our markup as lean as possible with just the li, in this instance we need to add an extra element to aid with extensibility (text resizing/translation) by breaking the box image into two, which I’ll describe in a minute. A paragraph seems the most semantic solution rather than a meaningless div.
  • <strong>North America:</strong> - Notice that for sighted users, the region text (“North America”) isn’t shown in the yellow boxes that fade in. In the spirit of extensibility, we’re considering sightless and alternate device users for whom the list item’s location relative to the map isn’t visible. Therefore, the idea here is that the location is provided in text rather than in geographical reference. So, we’re effectively “throwing” the text off the page using the text-indent property and a negative margin great enough to put the text outside the visible area of even the widest screen. display: none would accomplish the same, but some screen readers will ignore any text hidden with display: none. Of course, it’s questionable whether a screen reader would even pick up this text, as DOM refreshing isn’t always rendered properly by screen readers. (Note: The span element is a hook for jQuery to insert the number dynamically.)
  • class="l1" - We construct each yellow box with two images (top, bottom) specifically to allow for text resizing and translation. The top, maploc-bg.png, is much taller than needed for the default text. This is to accommodate a larger font size or an increased character count caused by translated text. The bottom, maploc-btm-left.png or maploc-btm-right.png, creates a nifty comment bubble thing and aligns to the bottom of the paragraph element. Depending on the box’s position on the map, class="l1" requests -left.png whereas class="l2" requests -right.png. Admittedly, class="l1", which is short for “location 1”, is not the most semantic selector declaration, but it’s arguably better than class="left" should the positioning be something other than left or right in the future. (Remember class="arial red 10" in Part I?)

Finally, markup that isn’t shown here but is shown in the demo, we set the absolute positioning of each list item:

<li class="l1" style="position: absolute; top: 10px; left: 20px;">

Recall that we set the position of #map to relative. Any element that is a child of #map, in this case li, will be positioned relative to the containing block of #map rather than the body or other parent element. Therefore, this list item is positioned 10px from the top and 20px from the left of #map. (Note: I’ve set this style inline for the sake of instruction. Ideally, you’d want to dynamically insert the positioning as each yellow box is generated.)

Once the markup is in place, we begin adding scripting that allows for Ajax magic to make a graceful entrance. Ironically, the Community Snapshot section isn’t a good demonstration of Ajax components because we’re totally faking things here by randomly creating “members online” numbers rather than pulling them from a database. Let’s shift our focus instead to the Latest Community Activity section to wrap up the discussion. But before we do, throw your mind back to Part II and take a look at the jQuery scripting we’ve added to fade the yellow boxes in/out:

function nextSnapshot(){

Look familiar?

So, the Latest Community Activity section is a better representation of Ajax as it fetches data asynchronously from a secondary source, activity.php, our pseudo database. As is the auto-complete for search (Part II), which fetches data asynchronously from search.php, another pseudo database. In both cases, we manipulate the DOM either by replacing elements in the document tree or by adding new ones. Finally, JavaScript in project.js and other files inside the /scripts directory bind everything together, rounding out the three components mentioned earlier.

I indicated in the series opener that a primary objective of this third article was the demonstration of judicious Ajax usage. While some of the interactivity demonstrated here could be discounted merely as eye candy, be aware the demo interface for this series was in fact derived from an actual project, the likes of which I’ll mention at the conclusion of the series. Some of the ideas shown here are based on actual prototype UI features, the sum of which aimed to improve the flow and speed of the interface, while others aimed to provide a very real glimpse into what was happening at that moment within a given community. Thankfully, my former client and good friend has been kind enough to allow me to repurpose certain elements for educational purposes, for which I’m appreciative and hope you are, too.

Additional Ajax reading:

Resolution Dependence & Miscellany

This third article is much lengthier than I anticipated, so I’ll try and wrap things up quickly. I can’t conclude without revisiting resolution dependence mentioned in Parts I and II, as the interface in this demo tricks out the content based on browser width. Resize your browser and watch how the arrangement of Latest Community Activity and Community Snapshot completely changes to adapt to the available screen real estate. Values that allow for this adaptation are contained in 1024.css, and re-read Part I to understand how resolution dependence works.

There’s also a couple child and adjacent selectors at play, and these are documented as comments in the HTML page and screen.css.

Finally, Mark James’ Silk Icon Set is used throughout the interface, but there are many other icon sets you should consider purchasing for your project.

Done. Please pick apart the markup, code, UI, my grammar, you name it. I’m all ears.



Veer Veer: Visual Elements for Creatives.
Stock photography, type, and killer tees. Genuinely recommended by Authentic Boredom.

1   Cory von Wallenstein ~ 20 March 2008

Gotta admit, I’m impressed. It’s a very effective demo.

2   David Bisset ~ 20 March 2008

Another home run Cameron. Thanks for twittering this out - what a great read for coders this morning. Can’t wait for the final part!

3   Vernon ~ 20 March 2008

I’m with Cory on this one… very impressed. Effective demo and a great write-up that will target a wide range of experience levels.

4   matthijs ~ 21 March 2008

Great article again. One question: you go to great lengths to make sure the layout is extensible, adapting to different screen resolutions and increasing text sizes.

That’s great, also or especially considering more and more people use mobile devices with small screen resolutions.

However, what are your thoughts on the use of and dependency on javascript? If you look at those same mobile devices, many of them won’t support javascript? Or do they? I know the iPhone/iPod touch have good js support in their safari browser, but many other phones/pda’s might not.

5   Divya ~ 23 March 2008

IE7 ignores the negative absolute positioning on the right corner image for the Latest Community Activity and Community Snapshot headings.

It seems to me the issue is with the negative margin (-2px) of the strong element. use position:relative to style it so that it shows up on IE 7 (applies for IE 6 as well).

6   Obieg Dokumentow ~ 24 March 2008

Thanks for a very useful article!

7   Cameron Moll ~ 24 March 2008

However, what are your thoughts on the use of and dependency on javascript? If you look at those same mobile devices, many of them won’t support javascript? Or do they?

If you’re asking specific to mobile devices, no, most devices will not support the scripting used in this interface. If you’re asking generally, unobtrusive scripting should be used whenever possible, as pointed out by Dan Mall in Part II.

It seems to me the issue is with the negative margin (-2px) of the strong element. use position:relative to style it so that it shows up on IE 7 (applies for IE 6 as well).

Great. I’m not in front of a machine w/Parallels at the moment, but I’ll give this a try as soon as I am.

8   Adam Kirkwood ~ 25 March 2008

Thank you Cameron for an amazing article, yet again! It’s definitely bringing many ideas to surface which I hope to include in future projects!

Can’t wait for the next part of this series!

9   Aleksei Rastimrshin ~ 25 March 2008

Hi Cameron!
jquery - it’s good!

10   Aleksei Rastimeshin ~ 25 March 2008

Hi! Cameron.
the speed of loading of my site hardly more than 2.5 seconds - jquery is perfectly ( is present video)
On Russian forum of 2007 soft application js also was discussed.
You could explain or specify as the calculation or should work where it is possible to read
At me does not function

11   apotheken ~ 26 March 2008

this is very brilliant and helpfull! AJAX and CSS at it`s best - we are planning some community activieties in our project…

12   Daniel Hillesheim ~ 26 March 2008

Great article Cameron, as always. Thanks for spending the time to articulate and demonstrate these methods. It’s very helpful to say the least. Can’t wait for the next one.

13   John Faulds ~ 28 March 2008

Comments have all gone a bit spammy. :/

Please pick apart the markup, code, UI, my grammar, you name it. I’m all ears.

I’d use a list to present the items under ‘Latest Community Activity’ and I’d use heading tags for each of the links to articles and rather than divs.

Also, you’ve skipped a heading level from h1 to h3 - I’d make the two h3s h2s and use h3s for all the ‘Latest Community Activity’ links.

14   Cameron Moll ~ 28 March 2008

Comment spam deleted.

I’d use a list to present the items under ‘Latest Community Activity’ and I’d use heading tags for each of the links to articles and rather than divs.

Actually, if this were ideal markup, I’d use a table rather than a list, as the content is organized in a tabular set. However, neither a list nor a table was used only because we ran into implementation issues with the jQuery Spy plugin which controls the Latest Community Activity.

So in short, if this were an actual project we probably would have spent more time reworking the plugin to use a table (or list) rather than divs.

Good call on the h2 skip, btw.

15   greg ~ 30 March 2008

Fantastic work Cameron. You ought to consider republishing the whole tutorial as a mini site.

16   Cameron Moll ~ 31 March 2008

Fantastic work Cameron. You ought to consider republishing the whole tutorial as a mini site.

Absolutely. Part of the reason it’s taking me so long to get Part IV up, in fact.

17   Bryan ~ 01 April 2008

Cameron, props for the well written and very educational article. What a great read!


18   Adrian ~ 03 April 2008

Bookmarked for sure. Thanks for taking the time to create and share this demo.


Authentic Boredom is the platitudinous web home of Cameron Moll, designer, author, and speaker. More…

Come in, we're hiring

Full-time and freelance job opportunities. Post a job...

...view all jobs »


A selection of fine reading, available for a limited time only:

In Print

CSS Mastery CSS Mastery: Advanced Web Standard Solutions A solid round-up of indispensable CSS design techniques by Andy Budd, Simon Collison, and Cameron Moll.

Mobile Web Design Mobile Web Design A guide to publishing web content beyond the desktop. Tips, methodology, and resources. Now available.


Letterpress Posters Letterpress Posters The unassuming beauty of a freshly letterpressed print.

Wicked Worn That Wicked Worn Look. Techniques for that worn, aged, distressed look.

Mister Retro Mister Retro Machine Wash Filters Turn the dial to “Instaworn” with these filters.

Blinksale Blinksale Dive in and enjoy shamelessly easy invoicing from Firewheel Design.

Basecamp Basecamp My preferred web app for internal and client project collaboration.


HOW Conference HOW Conference Austin, June 24–27. Pentagram, Adobe, P&G, et al.

Web Design World Web Design World Seattle, July 20–22. Practical sessions on web design.

An Event Apart Stimulate Salt Lake City, September 2009. Entrepreneurship and design conference.

Feed Me
Articles: RSS
Linkage: RSS

Follow me: Twitter