# articles

title: How To Create Rockband'ism
year: 2008
author: Henriette Weber
author_slug: henrietteweber
published: 2008-12-07T00:00:00+00:00
url: https://24ways.org/2008/how-to-create-rockbandism/
topic: business
contents:
There are mysteries happening in the world of business these days. We want something else by now. The business of business has to become more than business. We want to be able to identify ourselves with the brands we purchase and we want them to do good things. We want to feel cool because we buy stuff, and we don’t just want a shopping experience – we want an engagement with a company we can relate to.

Let me get back to “feeling cool” – if we want to feel cool, we might get the companies we buy from to support that. That’s why I am on a mission to make companies into rockbands.

Now when I say rockbands – I don’t mean the puke-y, drunky, nasty stuff that some people would highlight is also a part of rockbands. Therefore I have created my own word “rockband’ism”. This word is the definition of a childhood dream version of being in a rockband – the feeling of being more respected and loved and cool, than a cockroach or a suit on the floor of a company.

Rockband’ism

Rockband’ism is what we aspire to, to feel cool and happy.

So basically what I am arguing is that companies should look upon themselves as rockbands. Because the world has changed, so business needs to change as well.

I have listed a couple of things you could do today to become a rockband, as a person or as a company.

1 – Give your support to companies that make a difference to their surroundings – if you are buying electronics look up what the electronic producers are doing of good in the world (check out the Greenpeace Guide to Greener Electronics).

2 – Implement good karma in your everyday life (and do well by doing good). What you give out you get back at some point in some shape – this can also be implemented for business.

3 – WWRD? – “what would a rockband do”? or if you are into Kenny Rogers – what would he do in any given situation? This will also show yourself where your business or personal integrity lies because you actually act as a person or a rockband you admire.

4 – Start leading instead of managing – If we can measure stuff why should we manage it? Leadership is key here instead of management. When you lead you tell people how to reach the stars, when you manage you keep them on the ground.

5 – Respect and confide in, that people are the best at what they do. If they aren’t, they won’t be around for long. If they are and you keep on buggin’ them, they won’t be around for long either.

6 – Don’t be arrogant – Because audiences can’t stand it – talk to people as a person not as a company.

7 – Focus on your return on involvement – know that you get a return on, what you involve yourself in. No matter if it’s bingo, communities, talks, ornithology or un-conferences.

8 – Find out where you can make a difference and do it. Don’t leave it up to everybody else to save the world.

9 – Find out what you can do to become an authentic, trustworthy and remarkable company. Maybe you could even think about this a lot and make these thoughts into an actionplan.

10 – Last but not least – if you’re not happy – do something else, become another type of rockband, maybe a soloist of a sort, or an orchestra.

No more business as usual

This really isn’t time for more business as usual, our environment (digital, natural, work or any other kind of environment) is changing. You are going to have to change too.

This article actually sprang from a talk I did at the Shift08 conference in Lisbon in October. In addition to this article for 24 ways I have turned the talk into an eBook that you can get on Toothless Tiger Press for free.

May you all have a sustainable and great Christmas full of great moments with your loved ones. December is a month for gratitude, enjoyment and love.


title: Charm Clients, Win Pitches
year: 2008
author: Marcus Lillington
author_slug: marcuslillington
published: 2008-12-09T00:00:00+00:00
url: https://24ways.org/2008/charm-clients-win-pitches/
topic: business
contents:
Over the years I have picked up a number of sales techniques that have lead to us doing pretty well in the pitches we go for. Of course, up until now, these top secret practices have remained firmly locked in the company vault but now I am going to share them with you. They are cunningly hidden within the following paragraphs so I’m afraid you’re going to have to read the whole thing.

Ok, so where to start? I guess a good place would be getting invited to pitch for work in the first place.

Shameless self promotion

What not to do

You’re as keen as mustard to ‘sell’ what you do, but you have no idea as to the right approach. From personal experience (sometimes bitter!), the following methods are as useful as the proverbial chocolate teapot:


	Cold calling
	Advertising
	Bidding websites
	Sales people
	Networking events


Ok, I’m exaggerating; sometimes these things work. For example, cold calling can work if you have a story – a reason to call and introduce yourself other than “we do web design and you have a website”. “We do web design and we’ve just moved in next door to you” would be fine. 

Advertising can work if your offering is highly specialist. However, paying oodles of dollars a day to Google Ads to appear under the search term ‘web design’ is probably not the best use of your budget. 

Specialising is, in fact, probably a good way to go. Though it can feel counter intuitive in that you are not spreading yourself as widely as you might, you will eventually become an expert and therefore gain a reputation in your field. Specialism doesn’t necessarily have to be in a particular skillset or technology, it could just as easily be in a particular supply chain or across a market.

Target audience

‘Who to target?’ is the next question. If you’re starting out then do tap-up your family and friends. Anything that comes your way from them will almost certainly come with a strong recommendation. Also, there’s nothing wrong with calling clients you had dealings with in previous employment (though beware of any contractual terms that may prevent this). You are informing your previous clients that your situation has changed; leave it up to them to make any move towards working with you. After all, you’re simply asking to be included on the list of agencies invited to tender for any new work.

Look to target clients similar to those you have worked with previously. Again, you have a story – hopefully a good one!

So how do you reach these people?


	Mailing lists
	Forums
	Writing articles
	Conferences / Meetups
	Speaking opportunities
	Sharing Expertise


In essence: blog, chat, talk, enthuse, show off (a little)… share.

There are many ways you can do this. There’s the traditional portfolio, almost obligatory blog (regularly updated of course), podcast, ‘giveaways’ like Wordpress templates, CSS galleries and testimonials. Testimonials are your greatest friend. Always ask clients for quotes (write them and ask for their permission to use) and even better, film them talking about how great you are.

Finally, social networking sites can offer a way to reach your target audiences. You do have to be careful here though. You are looking to build a reputation by contributing value. Do not self promote or spam!

Writing proposals

Is it worth it?

Ok, so you have been invited to respond to a tender or brief in the form of a proposal. Good proposals take time to put together so you need to be sure that you are not wasting your time. There are two fundamental questions that you need to ask prior to getting started on your proposal:


	Can I deliver within the client’s timescales?
	Does the client’s budget match my price?


The timescales that clients set are often plucked from the air and a little explanation about how long projects usually take can be enough to change expectations with regard to delivery. However, if a deadline is set in stone ask yourself if you can realistically meet it. Agreeing to a deadline that you know you cannot meet just to win a project is a recipe for an unhappy client, no chance of repeat business and no chance of any recommendations to other potential clients.

Price is another thing altogether. So why do we need to know?

The first reason, and most honest reason, is that we don’t want to do a lot of unpaid pitch work when there is no chance that our price will be accepted. Who would? But this goes both ways – the client’s time is also being wasted. It may only be the time to read the proposal and reject it, but what if all the bids are too expensive? Then the client needs to go through the whole process again.

The second reason why we need to know budgets relates to what we would like to include in a proposal over what we need to include. For example, take usability testing. We always highly recommend that a client pays for at least one round of usability testing because it will definitely improve their new site – no question. But, not doing it doesn’t mean they’ll end up with an unusable turkey. It’s just more likely that any usability issues will crop up after launch.

I have found that the best way to discover a budget is to simply provide a ballpark total, usually accompanied by a list of ‘likely tasks for this type of project’, in an initial email or telephone response. Expect a lot of people to dismiss you out of hand. This is good. Don’t be tempted to ‘just go for it’ anyway because you like the client or work is short – you will regret it.

Others will say that the ballpark is ok. This is not as good as getting into a proper discussion about what priorities they might have but it does mean that you are not wasting your time and you do have a chance of winning the work. The only real risk with this approach is that you misinterpret the requirements and produce an inaccurate ballpark.

Finally, there is a less confrontational approach that I sometimes use that involves modular pricing. We break down our pricing into quite detailed tasks for all proposals but when I really do not have a clue about a client’s budget, I will often separate pricing into ‘core’ items and ‘optional’ items. This has proved to be a very effective method of presenting price.

What to include

So, what should go into a proposal? It does depend on the size of the piece of work. If it’s a quick update for an existing client then they don’t want to read through all your blurb about why they should choose to work with you – a simple email will suffice.

But, for a potential new client I would look to include the following:


	Your suitability
	Summary of tasks
	Timescales
	Project management methodology
	Pricing
	Testing methodology
	Hosting options
	Technologies
	Imagery
	References
	Financial information
	Biographies


However, probably the most important aspect of any proposal is that you respond fully to the brief. In other words, don’t ignore the bits that either don’t make sense to you or you think irrelevant. If something is questionable, cover it and explain why you don’t think it is something that warrants inclusion in the project.

Should you provide speculative designs? If the brief doesn’t ask for any, then certainly not. If it does, then speak to the client about why you don’t like to do speculative designs. Explain that any designs included as part of a proposal are created to impress the client and not the website’s target audience. Producing good web design is a partnership between client and agency. This can often impress and promote you as a professional. However, if they insist then you need to make a decision because not delivering any mock-ups will mean that all your other work will be a waste of time.

Walking away

As I have already mentioned, all of this takes a lot of work. So, when should you be prepared to walk away from a potential job? I have already covered unrealistic deadlines and insufficient budget but there are a couple of other reasons. Firstly, would this new client damage your reputation, particularly within current sectors you are working in? Secondly, can you work with this client? A difficult client will almost certainly lead to a loss-making project.

Perfect pitch

Requirements

If the original brief didn’t spell out what is expected of you at a presentation then make sure you ask beforehand. The critical element is how much time you have. It seems that panels are providing less and less time these days.

The usual formula is that you get an hour; half of which should be a presentation of your ideas followed by 30 minutes of questions. This isn’t that much time, particularly for a big project that covers all aspect of web design and production. Don’t be afraid to ask for more time, though it is very rare that you will be granted any.

Ask if there any areas that a) they particularly want you to cover and b) if there are any areas of your proposal that were weak.

Ask who will be attending. The main reason for this is to see if the decision maker(s) will be present but it’s also good to know if you’re presenting to 3 or 30 people.

Who should be there

Generally speaking, I think two is the ideal number. Though I have done many presentations on my own, I always feel having two people to bounce ideas around with and have a bit of banter with, works well. You are not only trying to sell your ideas and expertise but also yourselves. One of the main things in the panels minds will be – “can I work with these people?”

Having more than two people at a presentation often looks like you’re wheeling people out just to demonstrate that they exist.

What makes a client want to hire you?

In a nutshell: Confidence, Personality, Enthusiasm.

You can impart confidence by being well prepared and professional, providing examples and demonstrations and talking about your processes. You may find project management boring but pretty much every potential client will want to feel reassured that you manage your projects effectively.

As well as demonstrating that you know what you’re talking about, it is important to encourage, and be part of, discussion about the project. Be prepared to suggest and challenge and be willing to say “I don’t know”.

Also, no-one likes a show-off so don’t over promote yourself; encourage them to contact your existing clients.

What makes a client like you?

Engaging with a potential client is tricky and it’s probably the area where you need to be most on your toes and try to gauge the reaction of the client. We recommend the following:


	Encourage questions throughout
	Ask if you make sense – which encourages questions if you’re not getting any
	Humour – though don’t keep trying to be funny if you’re not getting any laughs!
	Be willing to go off track
	Read your audience
	Empathise with the process – chances are, most of the people in front of you would rather be doing something else
	Think about what you wear – this sounds daft but do you want to be seen as either the ‘stiff in the suit’ or the ‘scruffy art student’? Chances are neither character would get hired.


Differentiation

Sometimes, especially if you think you are an outsider, it’s worth taking a few risks. I remember my colleague Paul starting off a presentation once with the line (backed up on screen) – “Headscape is not a usability consultancy”. This was in response to the clients request to engage a usability consultancy. The thrust of Paul’s argument was that we are a lot more than that.

This really worked. We were the outside choice but they ended up hiring us. Basically, this differentiated us from the crowd. It showed that we are prepared to take risks and think, dare I say it, outside of the box.

Dealing with difficult characters 

How you react to tricky questioning is likely to be what determines whether you have a good or bad presentation. Here are a few of those characters that so often turn up in panels:

The techie – this is likely to be the situation where you need to say “I don’t know”. Don’t bluff as you are likely to dig yourself a great big embarrassment-filled hole. Promise to follow up with more information and make sure that you do so as quickly as possible after the pitch. 

The ‘hard man’ MD – this the guy who thinks it is his duty to throw ‘curve ball’ questions to see how you react. Focus on your track record (big name clients will impress this guy) and emphasise your processes.

The ‘no clue’ client – you need to take control and be the expert though you do need to explain the reasoning behind any suggestions you make. This person will be judging you on how much you are prepared to help them deliver the project.

The price negotiator – be prepared to discuss price but do not reduce your rate or the effort associated with your proposal. Fall back on modular pricing and try to reduce scope to come within budget. You may wish to offer a one-off discount to win a new piece of work but don’t get into detail at the pitch.

Don’t panic…

If you go into a presentation thinking ‘we must win this’ then, chances are, you won’t. Relax and be yourself. If you’re not hitting it off with the panel then so be it. You have to remember that quite often you will be making up the numbers in a tendering process. This is massively frustrating but, unfortunately, part of it. If it’s not going well, concentrate on what you are offering and try to demonstrate your professionalism rather than your personality. Finally, be on your toes, watch people’s reactions and pay attention to what they say and try to react accordingly.

So where are the secret techniques I hear you ask? Well, using the words ‘secret’ and ‘technique’ was probably a bit naughty. Most of this stuff is about being keen, using your brain and believing in yourself and what you are selling rather than following a strict set of rules.


title: The IE6 Equation
year: 2008
author: Jeremy Keith
author_slug: jeremykeith
published: 2008-12-08T00:00:00+00:00
url: https://24ways.org/2008/the-ie6-equation/
topic: code
contents:
It is the destiny of one browser to serve as the nemesis of web developers everywhere. At the birth of the Web Standards movement, that role was played by Netscape Navigator 4; an outdated browser that refused to die. Its tenacious existence hampered the adoption of modern standards. Today that role is played by Internet Explorer 6.

There’s a sensation that I’m sure you’re familiar with. It’s a horrible mixture of dread and nervousness. It’s the feeling you get when—after working on a design for a while in a standards-compliant browser like Firefox, Safari or Opera—you decide that you can no longer put off the inevitable moment when you must check the site in IE6. Fingers are crossed, prayers are muttered, but alas, to no avail. The nemesis browser invariably screws something up.

What do you do next? If the differences in IE6 are minor, you could just leave it be. After all, websites don’t need to look exactly the same in all browsers. But if there are major layout issues and a significant portion of your audience is still using IE6, you’ll probably need to roll up your sleeves and start fixing the problems.

A common approach is to quarantine IE6-specific CSS in a separate stylesheet. This stylesheet can then be referenced from the HTML document using conditional comments like this:

<!--[if lt IE 7]>
<link rel="stylesheet" href="ie6.css" type="text/css" media="screen" />
<![endif]-->

That stylesheet will only be served up to Internet Explorer where the version number is less than 7.

You can put anything inside a conditional comment. You could put a script element in there. So as well as serving up browser-specific CSS, it’s possible to serve up browser-specific JavaScript.

A few years back, before Microsoft released Internet Explorer 7, JavaScript genius Dean Edwards wrote a script called IE7. This amazing piece of code uses JavaScript to make Internet Explorer 5 and 6 behave like a standards-compliant browser. Dean used JavaScript to bootstrap IE’s CSS support.

Because the script is specifically targeted at Internet Explorer, there’s no point in serving it up to other browsers. Conditional comments to the rescue:

<!--[if lt IE 7]>
<script src="http://ie7-js.googlecode.com/svn/version/2.0(beta3)/IE7.js" type="text/javascript"></script>
<![endif]-->

Standards-compliant browsers won’t fetch the script. Users of IE6, on the hand, will pay a kind of bad browser tax by having to download the JavaScript file.

So when should you develop an IE6-specific stylesheet and when should you just use Dean’s JavaScript code? This is the question that myself and my co-worker Natalie Downe set out to answer one morning at Clearleft. We realised that in order to answer that question you need to first answer two other questions, how much time does it take to develop for IE6? and how much of your audience is using IE6?

Let’s say that t represents the total development time. Let t6 represent the portion of that time you spend developing for IE6. If your total audience is a, then a6 is the portion of your audience using IE6. With some algebraic help from our mathematically minded co-worker Cennydd Bowles, Natalie and I came up with the following equation to calculate the percentage likelihood that you should be using Dean’s IE7 script:



p = 50 [ log ( at6 / ta6 ) + 1 ]

Try plugging in your own numbers. If you spend a lot of time developing for IE6 and only a small portion of your audience is using that browser, you’ll get a very high number out of the equation; you should probably use the IE7 script. But if you only spend a little time developing for IE6 and a significant portion of you audience are still using that browser, you’ll get a very small value for p; you might as well write an IE6-specific stylesheet.

Of course this equation is somewhat disingenuous. While it’s entirely possible to research the percentage of your audience still using IE6, it’s not so easy to figure out how much of your development time will be spent developing for that one browser. You can’t really know until you’ve already done the development, by which time the equation is irrelevant.

Instead of using the equation, you could try imposing a limit on how long you will spend developing for IE6. Get your site working in standards-compliant browsers first, then give yourself a time limit to get it working in IE6. If you can’t solve all the issues in that time limit, switch over to using Dean’s script. You could even make the time limit directly proportional to the percentage of your audience using IE6. If 20% of your audience is still using IE6 and you’ve just spent five days getting the site working in standards-compliant browsers, give yourself one day to get it working in IE6. But if 50% of your audience is still using IE6, be prepared to spend 2.5 days wrestling with your nemesis.

All of these different methods for dealing with IE6 demonstrate that there’s no one single answer that works for everyone. They also highlight a problem with the current debate around dealing with IE6. There’s no shortage of blog posts, articles and even entire websites discussing when to drop support for IE6. But very few of them take the time to define what they mean by “support.” This isn’t a binary issue. There is no Boolean answer. Instead, there’s a sliding scale of support:


	Block IE6 users from your site.
	Develop with web standards and don’t spend any development time testing in IE6.
	Use the Dean Edwards IE7 script to bootstrap CSS support in IE6.
	Write an IE6 stylesheet to address layout issues.
	Make your site look exactly the same in IE6 as in any other browser.


Each end of that scale is extreme. I don’t think that anybody should be actively blocking any browser but neither do I think that users of an outdated browser should get exactly the same experience as users of a more modern browser. The real meanings of “supporting” or “not supporting” IE6 lie somewhere in-between those extremes.

Just as I think that semantics are important in markup, they are equally important in our discussion of web development. So let’s try to come up with some better terms than using the catch-all verb “support.” If you say in your client contract that you “support” IE6, define exactly what that means. If you find yourself in a discussion about “dropping support” for IE6, take the time to explain what you think that entails.

The web developers at Yahoo! are on the right track with their concept of graded browser support. I’m interested in hearing more ideas of how to frame this discussion. If we can all agree to use clear and precise language, we stand a better chance of defeating our nemesis.


title: The First Tool You Reach For
year: 2008
author: Kevin Yank
author_slug: kevinyank
published: 2008-12-13T00:00:00+00:00
url: https://24ways.org/2008/the-first-tool-you-reach-for/
topic: code
contents:
Microsoft recently announced that Internet Explorer 8 will be released in the first half of 2009. Compared to the standards support of other major browsers, IE8 will not be especially great, but it will finally catch up with the state of the art in one specific area: support for CSS tables. This milestone has the potential to trigger an important change in the way you approach web design.

To show you just how big a difference CSS tables can make, think about how you might code a fluid, three-column layout from scratch. Just to make your life more difficult, give it one fixed-width column, with a background colour that differs from the rest of the page. Ready? Go!

Okay, since you’re the sort of discerning web designer who reads 24ways, I’m going to assume you at least considered doing this without using HTML tables for the layout. If you’re especially hardcore, I imagine you began thinking of CSS floats, negative margins, and faux columns. If you did, colour me impressed!

Now admit it: you probably also gave an inward sigh about the time it would take to figure out the math on the negative margin overlaps, check for dropped floats in Internet Explorer and generally wrestle each of the major browsers into giving you what you want. If after all that you simply gave up and used HTML tables, I can’t say I blame you.

There are plenty of professional web designers out there who still choose to use HTML tables as their main layout tool. Sure, they may know that users with screen readers get confused by inappropriate use of tables, but they have a job to do, and they want tools that will make that job easy, not difficult.

Now let me show you how to do it with CSS tables. First, we have a div element for each of our columns, and we wrap them all in another two divs:

<div class="container">
	<div>
		<div id="menu">
		⋮
		</div>
		<div id="content">
		⋮
		</div>
		<div id="sidebar">
		⋮
		</div>
	</div>
</div>

Don’t sweat the “div clutter” in this code. Unlike tables, divs have no semantic meaning, and can therefore be used liberally (within reason) to provide hooks for the styles you want to apply to your page.

Using CSS, we can set the outer div to display as a table with collapsed borders (i.e. adjacent cells share a border) and a fixed layout (i.e. cell widths unaffected by their contents):

.container {
	display: table;
	border-collapse: collapse;
	table-layout: fixed;
}

With another two rules, we set the middle div to display as a table row, and each of the inner divs to display as table cells:

.container > div {
	display: table-row;
}
.container > div > div {
	display: table-cell;
}

Finally, we can set the widths of the cells (and of the table itself) directly:

.container {
	width: 100%;
}
#menu {
	width: 200px;
}
#content {
	width: auto;
}
#sidebar {
	width: 25%;
}

And, just like that, we have a rock solid three-column layout, ready to be styled to your own taste, like in this example:



This example will render perfectly in reasonably up-to-date versions of Firefox, Safari and Opera, as well as the current beta release of Internet Explorer 8.

CSS tables aren’t only useful for multi-column page layout; they can come in handy in most any situation that calls for elements to be displayed side-by-side on the page. Consider this simple login form layout:



The incantation required to achieve this layout using CSS floats may be old hat to you by now, but try to teach it to a beginner, and watch his eyes widen in horror at the hoops you have to jump through (not to mention the assumptions you have to build into your design about the length of the form labels).

Here’s how to do it with CSS tables:

<form action="/login" method="post">
	<div>
		<div>
			<label for="username">Username:</label>
			<span class="input"><input type="text" name="username" id="username"/></span>
		</div>
		<div>
			<label for="userpass">Password:</label>
			<span class="input"><input type="password" name="userpass" id="userpass"/></span>
		</div>
		<div class="submit">
			<label for="login"></label>
			<span class="input"><input type="submit" name="login" id="login" value="Login"/></span>
		</div>
	</div>
</form>

This time, we’re using a mixture of divs and spans as semantically transparent styling hooks. Let’s look at the CSS code.

First, we set up the outer div to display as a table, the inner divs to display as table rows, and the labels and spans as table cells (with right-aligned text):

form > div {
	display: table;
}
form > div > div {
	display: table-row;
}
form label,
form span {
	display: table-cell;
	text-align: right;
}

We want the first column of the table to be wide enough to accommodate our labels, but no wider. With CSS float techniques, we had to guess at what that width was likely to be, and adjust it whenever we changed our form labels. With CSS tables, we can simply set the width of the first column to something very small (1em), and then use the white-space property to force the column to the required width:

form label {
	white-space: nowrap;
	width: 1em;
}

To polish off the layout, we’ll make our text and password fields occupy the full width of the table cells that contain them:

input[type=text],
input[type=password] {
	width: 100%;
}

The rest is margins, padding and borders to get the desired look. Check out the finished example.

As the first tool you reach for when approaching any layout task, CSS tables make a lot more sense to your average designer than the cryptic incantations called for by CSS floats. When IE8 is released and all major browsers support CSS tables, we can begin to gradually deploy CSS table-based layouts on sites that are more and more mainstream.

In our new book, Everything You Know About CSS Is Wrong!, Rachel Andrew and I explore in much greater detail how CSS tables work as a page layout tool in the real world. CSS tables have their quirks just like floats do, but they don’t tend to affect common layout tasks, and the workarounds tend to be less fiddly too. Check it out, and get ready for the next big step forward in web design with CSS.


title: Ghosts On The Internet
year: 2008
author: Gavin Bell
author_slug: gavinbell
published: 2008-12-20T00:00:00+00:00
url: https://24ways.org/2008/ghosts-on-the-internet/
topic: ux
contents:
By rights the internet should be full of poltergeists, poor rootless things looking for their real homes. Many events on the internet are not properly associated with their correct timeframe. I don’t mean a server set to the wrong time, though that happens too. Much of the content published on the internet is separated from any proper reference to its publication time. What does publication even mean? Let me tell you a story…


	“It is 2019 and this is Kathy Clees reporting on the story of the moment, the shock purchase of Microsoft by Apple Inc. A Internet Explorer security scare story from 2008 was responsible, yes from 11 years ago, accidently promoted by an analyst, who neglected to check the date of their sources.”


If you think this is fanciful nonsense, then cast your mind back to September 2008, this story in Wired or The Times (UK) about a huge United Airlines stock tumble. A Florida newspaper had a automated popular story section. A random reader looking at a story about United’s 2002 Bankruptcy proceedings caused this story to get picked up by Google’s later visit to the South Florida Sun Sentinel’s news home page. 

The story was undated, Google’s news engine apparently gave it a 2008 date, an analyst picked it up and pushed it to Bloomberg and within minutes the United stock was tumbling. Their stock price dropped from $12 to $3, then recovered to $11 over the day. An eight percent fall in share price over a mis-configured date

Completing this out of order Christmas Carol, lets look at what is current practice and how dates are managed, we might even get to clank some chains. Publication date used to be inseparable from publication, the two things where stamped on the same piece of paper. How can we determine when things have been published, now?

Determining publication dates

Time as defined by http://www.w3.org/TR/NOTE-datetime extends ISO 8601, mandating the use of a year value. This is pretty well defined, we can even get very accurate timings down to milliseconds, Ruby and other languages can even handle Calendar reformation. So accuracy is not the issue.

One problem is that there are many dates which could be interpreted as the publication date. Publication can mean any of date written or created; date placed on server; last modified date; or the current date from the web server. Created and modified have parallels with file systems, but the large number of database driven websites means that this no longer holds much meaning, as there are no longer any files. 

Checking web server HEAD may also not correspond, it might give the creation time for the HTML file you are viewing or it might give the last modified time for a file from disk. It is too unreliable and lacking in context to be of real value. So if the web server will not help, then how can we get the right timeframe for our content? 

We are left with URLs and the actual page content.



Looking at Flickr, this picture (by Douglas County History Research Center) has four date values which can be associated with it. It was taken around 1900, scanned in 1992 and placed on Flickr on July 29th, 2008 and replaced later that day. Which dates should be represented here? 

This is hard question to answer, but currently the date of upload to Flickr is the best represented in terms of the date URL, /photos/douglascountyhistory/archives/date-posted/2008/07/29/, plus some Dublin Core RDF for the year. Flickr uses 2008 as the value for this image. Not accurate, but a reasonable compromise for the millions of other images on their site.

Flickr represents location much better than it represents time. For the most part this is fine, but once you go back in time to the 1800s then the maps of the world start to change a lot and you need to reference both time and place.

The Google timeline search offers another interesting window on the world, showing results organised by decade for any search term. Being able to jump to a specific occurrence of a term makes it easier to get primary results rather than later reporting. 

The 1918 “Spanish flu” results jump out in this timeline. 



Any major news event will have multiple analysis articles after the event, finding the original reporting of hurricane Katrina is harder now. Many publishers are putting older content online, e.g. Harpers or Nature or The Times, often these use good date based URLs, sometimes they are unhelpful database references. If this content is available for free, then how much better would it be to provide good metadata on date of publication.

Date based URLs

A quick word on date based URLs, they can be brilliant at capturing first published date. However they can be hard to interpret. Is /03/04 a date in March or April, what about 08/03/04? Obviously 2008/03/04 is easier to understand, it is probably March 4th. Including a proper timestamp in the page content avoid this kind of guesswork. 

Many sites represent the date as a plain text string; a few hook an HTML class of date around it, a very few provide an actual timestamp. Associating the date with the individual content makes it harder to get the date wrong.

Movable Type and TypePad are a notable exceptions, they will embed Dublin Core RDF to represent each posting e.g. dc:date="2008-12-18T02:57:28-08:00". WordPress doesn’t support date markup out of the box, though there is a patch and a howto for hAtom available.

In terms of newspapers, the BBC use <meta name="OriginalPublicationDate" content="2008/12/18 18:52:05" /> along with opaque URLs such as http://news.bbc.co.uk/1/hi/technology/7787335.stm. 

The Guardian use nice clear URLs http://www.guardian.co.uk/business/2008/dec/18/car-industry-recession but have no marked up date on the page. 

The New York Times are similar to the Guardian with nice URLs, http://www.nytimes.com/2008/12/19/business/19markets.html, but again no timestamps. All of these papers have all the data available, but it is not marked up in a useful manner.

Syndication formats

Syndication formats are better at supporting dates, RSS uses RFC 822 for dates, just like email so dates such as Wed, 17 Dec 2008 12:52:40 GMT are valid, with all the white space issues that entails. 

The Atom syndication format uses the much clearer http://tools.ietf.org/html/rfc3339 with timestamps of the form 1996-12-19T16:39:57-08:00. Both syndication formats encourage the use of last modified. This is understandable, but a pity as published date is a very useful value. The Atom syndication format supports “published” and mandates “updated” as timestamps, see the Atom RFC 4287 for more detail.

Marking up dates

However the aim of this short article is to encourage you to use microformats or RDF to encode dates. A good example of this is Twitter, they use hAtom for each individual entry, http://twitter.com/zzgavin/status/1065835819 contains the following markup, which represents a human and a machine readable version of the time of that tweet.

<span class="published" title="2008-12-18T22:01:27+00:00">about 3 hours ago</span> 

The spec for datetime is still draft at the minute and there is still ongoing conversation around the right format and semantics for representing date and time in microformats, see the datetime design pattern for details. 

The hAtom example page shows the minimal changes required to implement hAtom on well formed blog post content and for other less well behaved content. You have the information already in your content publication systems, this is not some additional onerous content entry task, simply some template formatting.

I started to see this as a serious issue after reading Stewart Brand’s Clock of the Long Now about five years ago. Brand’s book explores the issues of short term thinking that permeate our society, thinking beyond the end of the financial year is a stretch for many people. The Long Now has a world view of a 10,000 year timeframe, see http://longnow.org/ for much more information. Freebase from Long Now Board member Danny Hillis, supports dates quite well – see the entry for A Christmas Carol.

In conclusion

I feel we should be making it easier for people searching for our content in the future. We’ve moved through tagging content and on to geo-tagging content. Now it is time to get the timestamps right on our content. How do I know when something happened and how can I find other things that happened at the same time is a fair question. This should be something I can satisfy simply and easily. There are a range of tools available to us in either hAtom or RDF to specify time accurately alongside the content, so what is stopping you?

Thinking of the long term it is hard for us to know now what will be of relevance for future generations, so we should aim to raise the floor for publishing tools so that all content has the right timeframe associated with it. We are moving from publishing words and pictures on the internet to being able to associate publication with an individual via XFN and OpenID. We can associate place quite well too, the last piece of useful metadata is timeframe.


title: Rocking Restrictions
year: 2008
author: Tim Van Damme
author_slug: timvandamme
published: 2008-12-14T00:00:00+00:00
url: https://24ways.org/2008/rocking-restrictions/
topic: process
contents:
I love my job. I live my job. For every project I do, I try to make it look special. I’ll be honest: I have a fetish for comments like “I never saw anything like that!” or, “I wish I thought of that!”. I know, I have an ego-problem. (Eleven I’s already)

But sometimes, you run out of inspiration. Happens to everybody, and everybody hates it. “I’m the worst designer in the world.” “Everything I designed before this was just pure luck!” No it wasn’t.

Countless articles about finding inspiration have already been written. Great, but they’re not the magic potion you’d expect them to be when you need it. Here’s a list of small tips that can have immediate effect when applying them/using them. Main theme: Liberate yourself from the designers’ block by restricting yourself.

Do’s

Grids

If you aren’t already using grids, you’re doing something wrong. Not only are they a great help for aligning your design, they also restrict you to certain widths and heights. (For more information about grids, I suggest you read Mark Boulton’s series on designing grid systems. Oh, he’s also publishing a book I think.)

So what’s the link between grids and restrictions? Instead of having the option to style a piece of layout with a width of 1 to 960 pixels, you have to choose from values like 60 pixels, 140, 220, 300, …

Start small

Having a hard time finding a style for the layout, why don’t you start with one small object? No, not that small object, I meant a piece of a form, or a link, or try styling your headers (h1 – h6).

Let’s take a submit button of a form: it’s small, but needs much attention. People will click it. People will hover it. Maybe sometimes it’s disabled? Also: a button needs to look like a button, so typically it requires more styling then a regular link. Once you’ve got the button, move on, following the button’s style.

Color palettes

There are lots of resources on the web for finding inspiration for color palettes. Some of the most famous are COLOURlovers, wear palettes and Adobe’s Kuler. Browse through them (or create your own from a picture), pick a color palette you like and which works with the subject you’re handling, and stick with it. 4-5 colors, maybe with some tonal variations, but that’s it.

Fonts

There aren’t many fonts available for the web (Richard Rutter has a great article on this subject), but you’d be surprised how long they go. A simple text-transform: uppercase; or font-style: italic; can change a dull looking font into something entirely fresh.

Play around with the fonts you want to use and the variations you’ll be using, and make a list. Pick five combinations of fonts and their variations, and stick with them throughout the layout.

Single-task

Most of us use multiple monitors. They’re great to increase productivity, but make it harder to focus on a single task. Here’s what you do: try using only your smallest monitor. Maybe it’s the one from your laptop, maybe it’s an old 1024×768 you found in the attic. Having Photoshop (or Fireworks or…) taking over your entire workspace blocks out all the other distractions on your screen, and works quite liberating.

Mute everything…

…but not entirely. I noticed I was way more focused when I set NetNewsWire to refresh it’s feeds only once every two hours. After two hours, I need a break anyway. Turning off Twitterrific was a mistake, as it’s my window to the world, and it’s the place where the people I like to call colleagues live. You can’t exactly ask them to bring you a cup of coffee when they go to the vending machine, but they do keep you fresh, and it stops you from going human-shy. Instead I changed the settings to not play a notification sound when new Tweets arrive so it doesn’t disturb me when I’m zoning.

Don’ts

CSS galleries

Don’t start browsing all kinds of CSS galleries. Either you’ll feel bad, or you just start using elements in a way you can’t call “inspired” anymore. Instead gather your own collection of inspiration. Example: I use LittleSnapper in which I dump everything I find inspiring. This goes from a smart layout idea, to a failed picture someone posted on Flickr. Everything is inspiring.

Panicking

Don’t panic. It’s the worst thing you could do. Instead, get away from the computer, and go to bed early. A good night of sleep combined with a hot/cold shower can give you a totally new perspective on a design. Got a deadline by tomorrow? Well, you should’ve started earlier. Got a good excuse to start on this design this late? Tell your client it was either that or a bad design.

120-hour work-week

Don’t work all day long, including evenings and early mornings. Write off that first hour, you don’t really think you’ll get anything productive done before 9AM?! I don’t even think you should work on one and the same design all day long. If you’re stuck, try working in blocks of 1 or 2 hours on a certain design. Mixing projects isn’t for everyone, but it might just do the trick for you.

Summary


	Use grids, not only for layout purposes.
	Pick a specific element to start with.
	Use a colour palette.
	Limit the amount of fonts and variations you’ll use.
	Search for the smallest monitor around, and restrict yourself to that one.
	Reduce the amount of noise.
	Don’t start looking on the internet for inspiration. Build your own little inspirarchive.
	Work in blocks.


title: Easier Page States for Wireframes
year: 2008
author: Richard Rutter
author_slug: richardrutter
published: 2008-12-11T00:00:00+00:00
url: https://24ways.org/2008/easier-page-states-for-wireframes/
topic: process
contents:
When designing wireframes for web sites and web apps, it is often overlooked that the same ‘page’ can look wildly different depending on its context. A logged-in page will look different from a logged-out page; an administrator’s view may have different buttons than a regular user’s view; a power user’s profile will be more extensive than a new user’s.

These different page states need designing at some point, especially if the wireframes are to form a useful communication medium between designer and developer. Documenting the different permutations can be a time consuming exercise involving either multiple pages in one’s preferred box-and-arrow software, or a fully fledged drawing containing all the possible combinations annotated accordingly.

Enter interactive wireframes and Polypage

Interactive wireframes built in HTML are a great design and communication tool. They provide a clickable prototype, running in the browser as would the final site. As such they give a great feel for how the site will be to use. Once you add in the possibilities of JavaScript and a library such as jQuery, they become even more flexible and powerful.

Polypage is a jQuery plugin which makes it really easy to design multiple page states in HTML wireframes. There’s no JavaScript knowledge required (other than cutting and pasting in a few lines). The page views are created by simply writing all the alternatives into your HTML page and adding special class names to apply state and conditional view logic to the various options. 

When the page is loaded Polypage automatically detects the page states defined by the class names and creates a control bar enabling the user to toggle page states with the click of a mouse or the clack of a keyboard.



Using cookies by way of the jQuery cookie plugin, Polypage retains the view state throughout your prototype. This means you could navigate through your wireframes as if you were logged out; as if you were logged in as an administrator; with notes on or off; or with any other view or state you might require. The possibilities are entirely up to you.

How does it work?

Firstly you need to link to jQuery, the jQuery cookie plugin and to Polypage. Something like this:

<script src="javascripts/jquery-1.2.6.min.js" type="text/javascript"></script>
<script src="javascripts/cookie.jquery.js" type="text/javascript"></script>
<script src="javascripts/polypage.jquery.js" type="text/javascript"></script>

Then you need to initialise Polypage on page load using something along these lines:

<script type="text/javascript">
	$(document).ready(function() {
		$.polypage.init();
	});
</script>

Next you need to define the areas of your wireframe which are particular to a given state or view. Do this by applying classes beginning with pp_. Polypage will ignore all other classes in the document.

The pp_ prefix should be followed by a state name. This can be any text string you like, bearing in mind it will appear in the control bar. Typical page states might include ‘logged_in’, ‘administrator’ or ‘group_owner’. A complete class name would therefore look something like pp_logged_in.

Examples

If a user is logged in, you might want to specify an option for him or her to sign out. Using Polypage, this could be put in the wireframe as follows:

<a href="logout" class="pp_logged_in"> Sign out </a>

Polypage will identify the pp_logged_in class on the link and hide it (as the ‘Sign out’ link should only be shown when the page is in the ‘logged in’ view). Polypage will then automatically write a ‘logged in’ toggle to the control bar, enabling you to show or hide the ‘Sign out’ link by toggling the ‘logged in’ view. The same will apply to all content marked with a pp_logged_in class.

States can also be negated by adding a not keyword to the class name. For example you might want to provide a log in link for users who are not signed in. Using Polypage, you would insert the not keyword after the pp prefix as follows:

<a href="login" class="pp_not_logged_in"> Login </a>

Again Polypage identifies the pp prefix but this time sees that the ‘Login’ link should not be shown when the ‘logged in’ state is selected.

States can also be joined together to add some basic logic to pages. The syntax follows natural language and uses the or and and keywords in addition to the afore-mentioned not. Some examples would be pp_logged_in_and_admin, pp_admin_or_group_owner and pp_logged_in_and_not_admin.

Finally, you can set default states for a page by passing an array to the polypage.init() function like this:

$.polypage.init(['logged_in', 'admin']);

You can see a fully fledged example in this fictional social network group page. The example page defaults to a logged in state. You can see the logged out state by toggling ‘logged in’ off in the Polypage control bar. There are also views specified for a group member, a group admin, a new group and notes. 

Where can I get hold of it?

You can download the current version from GitHub.

Polypage was originally developed by Clearleft and New Bamboo, with particular contributions from Andy Kent and Natalie Downe. It has been used in numerous real projects, but it is still an early release so there is bound to be room for improvement. We’re pleased to say that Polypage is now an open source project so any feedback, particularly by way of actual improvements, is extremely welcome.


title: Hide And Seek in The Head
year: 2006
author: Peter-Paul Koch
author_slug: ppk
published: 2006-12-06T00:00:00+00:00
url: https://24ways.org/2006/hide-and-seek-in-the-head/
topic: code
contents:
If you want your JavaScript-enhanced pages to remain accessible and understandable to scripted and noscript users alike, you have to think before you code. Which functionalities are required (ie. should work without JavaScript)? Which ones are merely nice-to-have (ie. can be scripted)? You should only start creating the site when you’ve taken these decisions.

Special HTML elements

Once you have a clear idea of what will work with and without JavaScript, you’ll likely find that you need a few HTML elements for the noscript version only.

Take this example: A form has a nifty bit of Ajax that automatically and silently sends a request once the user enters something in a form field. However, in order to preserve accessibility, the user should also be able to submit the form normally. So the form should have a submit button in noscript browsers, but not when the browser supports sufficient JavaScript.

Since the button is meant for noscript browsers, it must be hard-coded in the HTML:

<input type="submit" value="Submit form" id="noScriptButton" />

When JavaScript is supported, it should be removed:

var checkJS = [check JavaScript support];
window.onload = function () {
	if (!checkJS) return;
	document.getElementById('noScriptButton').style.display = 'none';
}

Problem: the load event

Although this will likely work fine in your testing environment, it’s not completely correct. What if a user with a modern, JavaScript-capable browser visits your page, but has to wait for a huge graphic to load? The load event fires only after all assets, including images, have been loaded. So this user will first see a submit button, but then all of a sudden it’s removed. That’s potentially confusing.

Fortunately there’s a simple solution: play a bit of hide and seek in the <head>:

var checkJS = [check JavaScript support];
if (checkJS) {
	document.write('<style>#noScriptButton{display: none}</style>');
}

First, check if the browser supports enough JavaScript. If it does, document.write an extra <style> element that hides the button.

The difference with the previous technique is that the document.write command is outside any function, and is therefore executed while the JavaScript is being parsed. Thus, the #noScriptButton{display: none} rule is written into the document before the actual HTML is received.

That’s exactly what we want. If the rule is already present at the moment the HTML for the submit button is received and parsed, the button is hidden immediately. Even if the user (and the load event) have to wait for a huge image, the button is already hidden, and both scripted and noscript users see the interface they need, without any potentially confusing flashes of useless content.

In general, if you want to hide content that’s not relevant to scripted users, give the hide command in CSS, and make sure it’s given before the HTML element is loaded and parsed.

Alternative

Some people won’t like to use document.write. They could also add an empty <link /> element to the <head> and give it an href attribute once the browser’s JavaScript capabilities have been evaluated. The <link /> element is made to refer to a style sheet that contains the crucial #noScriptButton{display: none}, and everything works fine.

Important note: The script needs access to the <link />, and the only way to ensure that access is to include the empty <link /> element before your <script> tag.


title: A Message To You, Rudy - CSS Production Notes
year: 2006
author: Andy Clarke
author_slug: andyclarke
published: 2006-12-15T00:00:00+00:00
url: https://24ways.org/2006/css-production-notes/
topic: process
contents:
When more than one designer or developer work together on coding an XHTML/CSS template, there are several ways to make collaboration effective. Some prefer to comment their code, leaving a trail of bread-crumbs for their co-workers to follow. Others use accompanying files that contain their working notes or communicate via Basecamp.

For this year’s 24ways I wanted to share a technique that I has been effective at Stuff and Nonsense; one that unfortunately did not make it into the final draft of Transcending CSS. This technique, CSS production notes, places your page production notes in one convenient place within an XHTML document and uses nothing more than meaningful markup and CSS.

Let’s start with the basics; a conversation between a group of people. In the absence of notes or conversation elements in XHTML you need to make an XHTML compound that will effectively add meaning to the conversation between designers and developers. As each person speaks, you have two elements right there to describe what has been said and who has spoken: <blockquote> and its cite attribute. 

<blockquote cite="andy"> 
	<p>This project will use XHTML1.0 Strict, CSS2.1 and all that malarkey.</p>
</blockquote>

With more than one person speaking, you need to establish a temporal order for the conversation. Once again, the element to do just that is already there in XHTML; the humble ordered list.

<ol id="notes">
	<li>
		<blockquote cite="andy"> 
			<p>This project will use XHTML1.0 Strict, CSS2.1 and all that malarkey.</p>
		</blockquote> 
	</li>
	<li>
		<blockquote cite="dan"> 
			<p>Those bits are simple and bulletproof.</p>
		</blockquote> 
	</li>
</ol>

Adding a new note is as simple as adding a new item to list, and if you prefer to add more information to each note, such as the date or time that the note was written, go right ahead. Place your note list at the bottom of the source order of your document, right before the closing <body> tag. One advantage of this approach over using conventional comments in your code is that all the notes are unobtrusive and are grouped together in one place, rather than being spread throughout your document.

Basic CSS styling

For the first stage you are going to add some basic styling to the notes area, starting with the ordered list. For this design I am basing the look and feel on an instant messenger window.



ol#notes {
	width : 300px; 
	height : 320px; 
	padding : .5em 0; 
	background : url(im.png) repeat; 
	border : 1px solid #333; 
	border-bottom-width : 2px; 
	-moz-border-radius : 6px; /* Will not validate */
	color : #000; 
	overflow : auto; 
}
ol#notes li { 
	margin : .5em; 
	padding : 10px 0 5px; 
	background-color : #fff; 
	border : 1px solid #666; 
	-moz-border-radius : 6px; /* Will not validate */ 
}
ol#notes blockquote { 
	margin : 0; 
	padding : 0; 
}
ol#notes p { 
	margin : 0 20px .75em;
	padding : 0; 
}
ol#notes p.date { 
	font-size : 92%;
	color : #666; 
	text-transform : uppercase; 
}

Take a gander at the first example.

You could stop right there, but without seeing who has left the note, there is little context. So next, extract the name of the commenter from the <blockquote>’s cite attribute and display it before each note by using generated content.

ol#notes blockquote:before { 
	content : " "attr(cite)" said: "; 
	margin-left : 20px; 
	font-weight : bold; 
}

Fun with more detailed styling

Now, with all of the information and basic styling in place, it’s time to have some fun with some more detailed styling to spruce up your notes. Let’s start by adding an icon for each person, once again based on their cite. First, all of the first paragraphs of a <blockquote>’s that includes a cite attribute are given common styles.

ol#notes blockquote[cite] p:first-child {
	min-height : 34px;
	padding-left : 40px; 
}

Followed by an individual background-image.

ol#notes blockquote[cite="Andy"] p:first-child { 
	background : url(malarkey.png) no-repeat 5px 5px; 
} 

If you prefer a little more interactivity, add a :hover state to each <blockquote> and perhaps highlight the most recent comment.

ol#notes blockquote:hover { 
	background-color : #faf8eb; 
	border-top : 1px solid #fff; 
	border-bottom : 1px solid #333; 
}
ol#notes li:last-child blockquote { 
	background-color : #f1efe2; 
}



You could also adjust the style for each comment based on the department that the person works in, for example:

<li>
	<blockquote cite="andy" class="designer"> 
		<p>This project will use XHTML1.0 Strict, CSS2.1 and all that malarkey.</p>
	</blockquote> 
</li>
<li>
	<blockquote cite="dan"> 
		<p>Those bits are simple and bulletproof.</p>
	</blockquote> 
</li>
ol#notes blockquote.designer { border-color : #600; }

Take a look at the results of the second stage.

Show and hide the notes using CSS positioning

With your notes now dressed in their finest, it is time to tuck them away above the top of your working XHTML/CSS prototype so that you can reveal them when you need them, no JavaScript required. Start by moving the ordered list of notes off the top of the viewport leaving only a few pixels in view. It is also a good idea to make them semi-transparent by using the opacity property for browsers that have implemented it.

ol#notes { 
	position : absolute; 
	opacity : .25;
	z-index : 2000;  
	top : -305px; 
	left : 20px; 
}

Your last step is to add :hover and :focus dynamic pseudo-classes to reposition the list at the top of the viewport and restore full opacity to display them in their full glory when needed.

ol#notes:hover, ol#notes:focus {
	top : 0; 
	opacity : 1; 
}



Now it’s time to sit back, pour yourself a long drink and bask in the glory of the final result. Your notes are all stored in one handy place at the bottom of your document rather than being spread around your code. When your templates are complete, simply dive straight to the bottom and pull out the notes.

A Message To You, Rudy

Thank-you to everybody for making this a really great year for web standards. Have a wonderful holiday season.

Buy Andy Clarke’s book Transcending CSS from Amazon.com


title: Fast and Simple Usability Testing
year: 2006
author: Natalie Downe
author_slug: nataliedowne
published: 2006-12-16T00:00:00+00:00
url: https://24ways.org/2006/fast-and-simple-usability-testing/
topic: process
contents:
Everyone knows by now that they should test the usability of their applications, but still hardly anybody actually does it. In this article I’ll share some tips I’ve picked up for doing usability tests quickly and effectively.

Relatively recent tools like Django and Ruby on Rails allow us to develop projects faster and to make significant changes later in the project timeline. Usability testing methods should now be adapted to fit this modern approach to development.

When to test

In an ideal world usability tests would be carried out frequently from an early stage of the project. Time and budget constraints lead this to be impractical; usability is often the first thing to get dropped from the project plan.

If you can only test at one stage in the project, whatever the size, the most valuable time is before your first public beta — leaving long enough to fix issues and not so late that you can’t rethink your scope.

There are three main categories of usability test:


	Testing design mockups
	Testing a new working application
	Testing established applications


Each category requires a slightly different approach. For small modern web projects you are most likely to be testing a new working application. You will of course have already done functional tests so you won’t be worried about the user breaking things. The main differences between the categories apply in how you word The Script.

Testing an established application is the most fun in my opinion. Humans are remarkably adaptable and rapidly develop coping strategies to work around usability issues in software they are forced to use. Uncovering these strategies may lead you to understand previously unspoken needs of your users. Often small changes to the application will have a dramatic affect on their everyday lives.

Who to test

When you have built a project to scratch your own itch, your intended audience will be people just like you. Test subjects in this case should be easy to find – friends, co-workers etc.

This is not always the case; your users may not be like you at all. When they are not, it’s all the more important to run usability tests. Testing on friends, family and co-workers is better than not doing usability tests at all, but it can’t be compared to testing on actual samples of your intended audience. People who would use the system will provide more genuine feedback and deeper insight.

Never let your test subjects put themselves in the shoes of your ‘actual’ users. For example, you should discourage comments like “Well, I would do this BUT if I was a bus driver I’d do that”. Users are not qualified to put themselves in the position of others. Inaccurate data is often worse than no data.

Aim for five or six test subjects: any more and you probably won’t learn anything new; any less and you’re likely to be overwhelmed by issues stemming from people’s individual personalities.

The Script

The Script is a single side of A4 (or letter) paper, consisting of questions for your testers and reminders for yourself. Have a balance of task-based questions and expectation analysis. This helps maintain consistency across tests. Expectation analysis is more important for testing designs and new applications: “Where would you find X?”, “What would you expect to happen if you clicked on Y?”. In an established system users will probably know where these things are though it can still be illuminating to ask these questions though phrased slightly differently.

Task-based questions involve providing a task for the user to complete. If you are testing an established system it is a good idea to ask users to bring in tasks that they would normally perform. This is because the user will be more invested in the outcome of the task and will behave in a more realistic fashion. When designing tasks for new systems and designs ensure you only provide loose task details for the same reason. Don’t tell testers to enter “Chantelle”; have them use their own name instead. Avoid introducing bias with the way questions are phrased.

It’s a good idea to ask for users’ first impressions at the beginning of the test, especially when testing design mockups. “What are the main elements on the page?” or “What strikes you first?”.

You script should run for a maximum of 45 minutes. 30-35 minutes is better; after this you are likely to lose their attention. Tests on established systems can take longer as there is more to learn from them. When scheduling the test you will need to leave yourself 5 minutes between each one to collate your notes and prepare for the next. Be sure to run through the script beforehand.

Your script should be flexible. It is possible that during the test a trend will come to light that opens up whole new avenues of possible questioning. For example, during one initial test of an established system I noticed that the test subject had been printing off items from the application and placing them in a folder in date order (the system ordered alphabetically). I changed the script to ask future participants in that run, if they ever used external tools to help them with tasks within the system. This revealed a number of interesting issues that otherwise would not have been found.

Running the tests

Treat your test subjects like hedgehogs. Depending on your target audience they probably feel a little nervous and perhaps even scared of you. So make them a little nest out of straw, stroke their prickles and give them some cat food. Alternatively, reassure them that you are testing the system and that they can’t give a wrong answer. Reward them with a doughnut or jam tart at the end. Try to ensure the test environment is relaxed and quiet, but also as close as possible to the situation where they would actually use the system.

Have your subjects talk out loud is very important as you can’t read their minds, but it is a very unnatural process. To loosen up your subjects and get them talking in the way you want them to, try the Stapler Trick. Give them a stapler or similar item and ask them to open it, take the staples out, replace them, shut the stapler and staple some paper – talking all the time about what they see, what they expect to happen, what actually happens and how that matches up. Make them laugh at you.

Say how long the test will take up front, and tell your subject why you are doing it. After the test has been completed, conclude by thanking them for their time and assuring them that they were very useful. Then give them the sugary treat.

What to look for

Primarily, you should look out for incidents where the user stops concentrating on her tasks and starts thinking about the tool and how she is going to use it. For example, when you are hammering in a nail you don’t think about how to use a hammer; good software should be the same. Words like ‘it’ and ‘the system’ and are good indications that the test subject has stopped thinking about the task in hand. Note questioning words, especially where testers question their own judgement, “why can’t I find …”, “I expected to see …” etc. as this indicates that the work flow for the task may have broken down.

Also keep an eye on occasions where the user completely fails to do a task. They may need some prompting to unstick them, but you should be careful not to bias the test. These should be the highest priority issues for you to fix. If users recover from getting stuck, make a note of how they recovered. Prolonged periods of silence from the test subject may also require prompting as they should be talking all the time. Ask them what they are thinking or looking for but avoid words like ‘try’ (e.g. ‘what are you trying to do?’) as this implies that they are currently failing.

Be wary of users’ opinions on aesthetics and be prepared to bring them back to the script if they get side-tracked.

Writing it up

Even if you are the only developer it’s important to summarise the key issues that emerged during testing: your notes won’t make much sense to you a week or so after the test.

If you are writing for other people, include a summary no longer than two pages; this can consist of a list or table of the issues including recommendations and their priorities. Remember to anonymise the users in the report. In team situations, you may be surprised at how many people are interested in the results of the usability test even if it doesn’t relate directly to something that they can fix.

To conclude…

Some usability testing is better than none at all, even for small projects or those with strict deadlines. Make the most of the time and resources available. Choose your users carefully, make them comfortable, summarise your report and don’t forget to leave a doughnut for yourself!


title: Writing Responsible JavaScript
year: 2006
author: Drew McLellan
author_slug: drewmclellan
published: 2006-12-10T00:00:00+00:00
url: https://24ways.org/2006/writing-responsible-javascript/
topic: code
contents:
Without a doubt, JavaScript has been making something of a comeback in the last year. If you’re involved in client-side development in any way at all, chances are that you’re finding yourself writing more JavaScript now than you have in a long time.

If you learned most of your JavaScript back when DHTML was all the rage and before DOM Scripting was in vogue, there have been some big shifts in the way scripts are written. Most of these are in the way event handlers are assigned and functions declared. Both of these changes are driven by the desire to write scripts that are responsible page citizens, both in not tying behaviour to content and in taking care not to conflict with other scripts. I thought it may be useful to look at some of these more responsible approaches to learn how to best write scripts that are independent of the page content and are safely portable between different applications.

Event Handling

Back in the heady days of Web 1.0, if you wanted to have an object on the page react to something like a click, you would simply go ahead and attach an onclick attribute. This was easy and understandable, but much like the font tag or the style attribute, it has the downside of mixing behaviour or presentation in with our content. As we’re learned with CSS, there are big benefits in keeping those layers separate. Hey, if it works for CSS, it should work for JavaScript too.

Just like with CSS, instead of adding an attribute to our element within the document, the more responsible way to do that is to look for the item from your script (like CSS does with a selector) and then assign the behaviour to it. To give an example, take this oldskool onclick use case:

<a id="anim-link" href="#" onclick="playAnimation()">Play the animation</a>

This could be rewritten by removing the onclick attribute, and instead doing the following from within your JavaScript.

document.getElementById('anim-link').onclick = playAnimation;

It’s all in the timing

Of course, it’s never quite that easy. To be able to attach that onclick, the element you’re targeting has to exist in the page, and the page has to have finished loading for the DOM to be available. This is where the onload event is handy, as it fires once everything has finished loading. Common practise is to have a function called something like init() (short for initialise) that sets up all these event handlers as soon as the page is ready.

Back in the day we would have used the onload attibute on the <body> element to do this, but of course what we really want is:

window.onload = init;

As an interesting side note, we’re using init here rather than init() so that the function is assigned to the event. If we used the parentheses, the init function would have been run at that moment, and the result of running the function (rather than the function itself) would be assigned to the event. Subtle, but important.

As is becoming apparent, nothing is ever simple, and we can’t just go around assigning our initialisation function to window.onload. What if we’re using other scripts in the page that might also want to listen out for that event? Whichever script got there last would overwrite everything that came before it. To manage this, we need a script that checks for any existing event handlers, and adds the new handler to it. Most of the JavaScript libraries have their own systems for doing this. If you’re not using a library, Simon Willison has a good stand-alone example

function addLoadEvent(func) {
	var oldonload = window.onload;
	if (typeof window.onload != 'function') {
		window.onload = func;
	} else {
		window.onload = function() {
			if (oldonload) {
				oldonload();
			}
			func();
		}
	}
}

Obviously this is just a toe in the events model’s complex waters. Some good further reading is PPK’s Introduction to Events.

Carving out your own space

Another problem that rears its ugly head when combining multiple scripts on a single page is that of making sure that the scripts don’t conflict. One big part of that is ensuring that no two scripts are trying to create functions or variables with the same names. Reusing a name in JavaScript just over-writes whatever was there before it.

When you create a function in JavaScript, you’ll be familiar with doing something like this.

function foo() {
	... goodness ...
}

This is actually just creating a variable called foo and assigning a function to it. It’s essentially the same as the following.

var foo = function() {
	... goodness ...
}

This name foo is by default created in what’s known as the ‘global namespace’ – the general pool of variables within the page. You can quickly see that if two scripts use foo as a name, they will conflict because they’re both creating those variables in the global namespace.

A good solution to this problem is to add just one name into the global namespace, make that one item either a function or an object, and then add everything else you need inside that. This takes advantage of JavaScript’s variable scoping to contain you mess and stop it interfering with anyone else.

Creating An Object

Say I was wanting to write a bunch of functions specifically for using on a site called ‘Foo Online’. I’d want to create my own object with a name I think is likely to be unique to me.

var FOOONLINE = {};

We can then start assigning functions are variables to it like so:

FOOONLINE.message = 'Merry Christmas!';
FOOONLINE.showMessage = function() {
	alert(this.message);
};

Calling FOOONLINE.showMessage() in this example would alert out our seasonal greeting. The exact same thing could also be expressed in the following way, using the object literal syntax.

var FOOONLINE = {
	message: 'Merry Christmas!',
	showMessage: function() {
		alert(this.message);
	}
};

Creating A Function to Create An Object

We can extend this idea bit further by using a function that we run in place to return an object. The end result is the same, but this time we can use closures to give us something like private methods and properties of our object.

var FOOONLINE = function(){
	var message = 'Merry Christmas!';
	return {
		showMessage: function(){
			alert(message);
		}
	}
}();

There are two important things to note here. The first is the parentheses at the end of line 10. Just as we saw earlier, this runs the function in place and causes its result to be assigned. In this case the result of our function is the object that is returned at line 4.

The second important thing to note is the use of the var keyword on line 2. This ensures that the message variable is created inside the scope of the function and not in the global namespace. Because of the way closure works (which if you’re not familiar with, just suspend your disbelief for a moment) that message variable is visible to everything inside the function but not outside. Trying to read FOOONLINE.message from the page would return undefined.

This is useful for simulating the concept of private class methods and properties that exist in other programming languages. I like to take the approach of making everything private unless I know it’s going to be needed from outside, as it makes the interface into your code a lot clearer for someone else to read. 

All Change, Please

So that was just a whistle-stop tour of a couple of the bigger changes that can help to make your scripts better page citizens. I hope it makes useful Sunday reading, but obviously this is only the tip of the iceberg when it comes to designing modular, reusable code.

For some, this is all familiar ground already. If that’s the case, I encourage you to perhaps submit a comment with any useful resources you’ve found that might help others get up to speed. Ultimately it’s in all of our interests to make sure that all our JavaScript interoperates well – share your tips.


title: Accessible Dynamic Links
year: 2006
author: Mike Davies
author_slug: mikedavies
published: 2006-12-05T00:00:00+00:00
url: https://24ways.org/2006/accessible-dynamic-links/
topic: ux
contents:
Although hyperlinks are the soul of the World Wide Web, it’s worth using them in moderation. Too many links becomes a barrier for visitors navigating their way through a page. This difficulty is multiplied when the visitor is using assistive technology, or is using a keyboard; being able to skip over a block of links doesn’t make the task of finding a specific link any easier.

In an effort to make sites easier to use, various user interfaces based on the hiding and showing of links have been crafted. From drop-down menus to expose the deeper structure of a website, to a decluttering of skip links so as not to impact design considerations. Both are well intentioned with the aim of preserving a good usability experience for the majority of a website’s audience; hiding the real complexity of a page until the visitor interacts with the element.

When JavaScript is not available

The modern dynamic link techniques rely on JavaScript and CSS, but regardless of whether scripting and styles are enabled or not, we should consider the accessibility implications, particularly for screen-reader users, and people who rely on keyboard access.

In typical web standards-based drop-down navigation implementations, the rough consensus is that the navigation should be structured as nested lists so when JavaScript is not available the entire navigation map is available to the visitor. This creates a situation where a visitor is faced with potentially well over 50 links on every page of the website. Keyboard access to such structures is frustrating, there’s far too many options, and the method of serially tabbing through each link looking for a specific one is tedious.

Instead of offering the visitor an indigestible chunk of links when JavaScript is not available, consider instead having the minimum number of links on a page, and when JavaScript is available bringing in the extra links dynamically. Santa Chris Heilmann offers an excellent proof of concept in making Ajax navigation optional.

When JavaScript is enabled, we need to decide how to hide links. One technique offers a means of comprehensively hiding links from keyboard users and assistive technology users. Another technique allows keyboard and screen-reader users to access links while they are hidden, and making them visible when reached.

Hiding the links

In JavaScript enhanced pages whether a link displays on screen depends on a certain event happening first. For example, a visitor needs to click a top-level navigation link that makes a set of sub-navigation links appear. In these cases, we need to ensure that these links are not available to any user until that event has happened.

The typical way of hiding links is to style the anchor elements, or its parent nodes with display: none. This has the advantage of taking the links out of the tab order, so they are not focusable. It’s useful in reducing the number of links presented to a screen-reader or keyboard user to a minimum. Although the links are still in the document (they can be referenced and manipulated using DOM Scripting), they are not directly triggerable by a visitor.

Once the necessary event has happened, like our visitor has clicked on a top-level navigation link which shows our hidden set of links, then we can display the links to the visitor and make them triggerable. This is done simply by undoing the display: none, perhaps by setting the display back to block for block level elements, or inline for inline elements. For as long as this display style remains, the links are in the tab order, focusable by keyboard, and triggerable.

A common mistake in this situation is to use visibility: hidden, text-indent: -999em, or position: absolute with left: -999em to position these links off-screen. But all of these links remain accessible via keyboard tabbing even though the links remain hidden from screen view. In some ways this is a good idea, but for hiding sub-navigation links, it presents the screen-reader user and keyboard user with too many links to be of practical use.

Moving the links out of sight

If you want a set of text links accessible to screen-readers and keyboard users, but don’t want them cluttering up space on the screen, then style the links with position: absolute; left: -999em. Links styled this way remain in the tab order, and are accessible via keyboard. (The position: absolute is added as a style to the link, not to a parent node of the link – this will give us a useful hook to solve the next problem).

a.helper {
	position: absolute;
	left: -999em;
}

One important requirement when displaying links off-screen is that they are visible to a keyboard user when they receive focus. Tabbing on a link that is not visible is a usability mudpit, since the visitor has no visible cue as to what a focused link will do, or where it will go.

The simple answer is to restyle the link so that it appears on the screen when the hidden link receives focus. The anchor’s :focus pseudo-class is a logical hook to use, and with the following style repositions the link onscreen when it receives the focus:

a.helper:focus, a.helper.focus {
	top: 0;
	left: 0;
}

This technique is useful for hiding skip links, and options you want screen-reader and keyboard users to use, but don’t want cluttering up the page. Unfortunately Internet Explorer 6 and 7 don’t support the focus pseudo-class, which is why there’s a second CSS selector a.helper.focus so we can use some JavaScript to help out. When the page loads, we look for all links that have a class of helper and add in onfocus and onblur event handlers:

if (anchor.className == "helper") {
	anchor.onfocus = function() {
		this.className = 'helper focus';
	}
	anchor.onblur = function() {
		this.className = 'helper';
	}
}

Since we are using JavaScript to cover up for deficiencies in Internet Explorer, it makes sense to use JavaScript initially to place the links off-screen. That way an Internet Explorer user with JavaScript disabled can still use the skip link functionality.

It is vital that the number of links rendered in this way is kept to a minimum. Every link you offer needs to be tabbed through, and gets read out in a screen reader. Offer these off-screen links that directly benefit these types of visitor.

Andy Clarke and Kimberly Blessing use a similar technique in the Web Standards Project‘s latest design, but their technique involves hiding the skip link in plain sight and making it visible when it receives focus. Navigate the page using just the tab key to see the accessibility-related links appear when they receive focus.

This technique is also a good way of hiding image replaced text. That way the screen-readers still get the actual text, and the website still gets its designed look.

Which way?

If the links are not meant to be reachable until a certain event has occurred, then the display: none technique is the preferred approach. If you want the links accessible but out of the way until they receive focus, then the off-screen positioning (or Andy’s hiding in plain sight technique) is the way to go.


title: Intricate Fluid Layouts in Three Easy Steps
year: 2006
author: Nate Koechley
author_slug: natekoechley
published: 2006-12-20T00:00:00+00:00
url: https://24ways.org/2006/intricate-fluid-layouts/
topic: code
contents:
The Year of the Script may have drawn attention away from CSS but building fluid, multi-column, cross-browser CSS layouts can still be as unpleasant as a lump of coal. Read on for a worry-free approach in three quick steps.

The layout system I developed, YUI Grids CSS, has three components. They can be used together as we’ll see, or independently.

The Three Easy Steps


	Choose fluid or fixed layout, and choose the width (in percents or pixels) of the page.
	Choose the size, orientation, and source-order of the main and secondary blocks of content.
	Choose the number of columns and how they distribute (for example 50%-50% or 25%-75%), using stackable and nestable grid structures.


The Setup

There are two prerequisites: We need to normalize the size of an em and opt into the browser rendering engine’s Strict Mode.

Ems are a superior unit of measure for our case because they represent the current font size and grow as the user increases their font size setting. This flexibility—the container growing with the user’s wishes—means larger text doesn’t get crammed into an unresponsive container. We’ll use YUI Fonts CSS to set the base size because it provides consistent-yet-adaptive font-sizes while preserving user control.

The second prerequisite is to opt into Strict Mode (more info on rendering modes) by declaring a Doctype complete with URI. You can choose XHTML or HTML, and Transitional or Strict. I prefer HTML 4.01 Strict, which looks like this:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">

Including the CSS

A single small CSS file powers a nearly-infinite number of layouts thanks to a recursive system and the interplay between the three distinct components. You could prune to a particular layout’s specific needs, but why bother when the complete file weighs scarcely 1.8kb uncompressed? Compressed, YUI Fonts and YUI Grids combine for a miniscule 0.9kb over the wire.

You could save an HTTP request by concatenating the two CSS files, or by adding their contents to your own CSS, but I’ll keep them separate for now:

<link href="fonts.css" rel="stylesheet" type="text/css">
<link href="grids.css" rel="stylesheet" type="text/css">

Example: The Setup

Now we’re ready to build some layouts.

Step 1: Choose Fluid or Fixed Layout

Choose between preset widths of 750px, 950px, and 100% by giving a document-wrapping div an ID of doc, doc2, or doc3. These options cover most use cases, but it’s easy to define a custom fixed width.

The fluid 100% grid (doc3) is what I’ve been using almost exclusively since it was introduced in the last YUI released.

<body>
	<div id="doc3"></div>
</body>

All pages are centered within the viewport, and grow with font size. The 100% width page (doc3) preserves 10px of breathing room via left and right margins. If you prefer your content flush to the viewport, just add doc3 {margin:auto} to your CSS.

Regardless of what you choose in the other two steps, you can always toggle between these widths and behaviors by simply swapping the ID value. It’s really that simple.

Example: 100% fluid layout

Step 2: Choose a Template Preset

This is perhaps the most frequently omitted step (they’re all optional), but I use it nearly every time. In a source-order-independent way (good for accessibility and SEO), “Template Presets” provide commonly used template widths compatible with ad-unit dimension standards defined by the Interactive Advertising Bureau, an industry association.

Choose between the six Template Presets (.yui-t1 through .yui-t6) by setting the class value on the document-wrapping div established in Step 1. Most frequently I use yui-t3, which puts the narrow secondary block on the left and makes it 300px wide. 

<body>
	<div id="doc3" class="yui-t3"></div>
</body>

The Template Presets control two “blocks” of content, which are defined by two divs, each with yui-b (“b” for “block”) class values. Template Presets describe the width and orientation of the secondary block; the main block will take up the rest of the space.

<body>
	<div id="doc3" class="yui-t3">
	  <div class="yui-b"></div>
	  <div class="yui-b"></div>
	</div>
</body>

Use a wrapping div with an ID of yui-main to structurally indicate which block is the main block. This wrapper—not the source order—identifies the main block.

<body>
	<div id="doc3" class="yui-t3">
	  <div id="yui-main">
	    <div class="yui-b"></div>
	  </div>
	  <div class="yui-b"></div>
	</div>
</body>

Example: Main and secondary blocks sized and oriented with .yui-t3 Template Preset

Again, regardless of what values you choose in the other steps, you can always toggle between these Template Presets by toggling the class value of your document-wrapping div. It’s really that simple.

Step 3: Nest and Stack Grid Structures.

The bulk of the power of the system is in this third step. The key is that columns are built by parents telling children how to behave. By default, two children each consume half of their parent’s area. Put two units inside a grid structure, and they will sit side-by-side, and they will each take up half the space. Nest this structure and two columns become four. Stack them for rows of columns.

An Even Number of Columns

The default behavior creates two evenly-distributed columns. It’s easy. Define one parent grid with .yui-g (“g” for grid) and two child units with .yui-u (“u” for unit). The code looks like this:

<div class="yui-g">
	<div class="yui-u first"></div>
	<div class="yui-u"></div>
</div>

Be sure to indicate the “first“ unit because the :first-child pseudo-class selector isn’t supported across all A-grade browsers. It’s unfortunate we need to add this, but luckily it’s not out of place in the markup layer since it is structural information.

Example: Two evenly-distributed columns in the main content block

An Odd Number of Columns

The default system does not work for an odd number of columns without using the included “Special Grids” classes. To create three evenly distributed columns, use the “yui-gb“ Special Grid:

<div class="yui-gb">
	<div class="yui-u first"></div>
	<div class="yui-u"></div>
	<div class="yui-u"></div>
</div>

Example: Three evenly distributed columns in the main content block

Uneven Column Distribution

Special Grids are also used for unevenly distributed column widths. For example, .yui-ge tells the first unit (column) to take up 75% of the parent’s space and the other unit to take just 25%.

<div class="yui-ge">
	<div class="yui-u first"></div>
	<div class="yui-u"></div>
</div>

Example: Two columns in the main content block split 75%-25%

Putting It All Together

Start with a full-width fluid page (div#doc3). Make the secondary block 180px wide on the right (div.yui-t4). Create three rows of columns: Three evenly distributed columns in the first row (div.yui-gb), two uneven columns (66%-33%) in the second row (div.yui-gc), and two evenly distributed columns in the thrid row.

<body>
	<!-- choose fluid page and Template Preset -->
	<div id="doc3" class="yui-t4">
		<!-- main content block -->
		<div id="yui-main">
			<div class="yui-b">
				<!-- stacked grid structure, Special Grid "b" -->
				<div class="yui-gb">
					<div class="yui-u first"></div>
					<div class="yui-u"></div>
					<div class="yui-u"></div>
				</div>
				<!-- stacked grid structure, Special Grid "c" -->
				<div class="yui-gc">
					<div class="yui-u first"></div>
					<div class="yui-u"></div>
				</div>
				<!-- stacked grid structure -->
				<div class="yui-g">
					<div class="yui-u first"></div>
					<div class="yui-u"></div>
				</div>
			</div>
		</div>
		<!-- secondary content block -->
		<div class="yui-b"></div>
	</div>
</body>

Example: A complex layout.

Wasn’t that easy? Now that you know the three “levers” of YUI Grids CSS, you’ll be creating headache-free fluid layouts faster than you can say “Peace on Earth”.


title: Showing Good Form
year: 2006
author: James Edwards
author_slug: jamesedwards
published: 2006-12-11T00:00:00+00:00
url: https://24ways.org/2006/showing-good-form/
topic: ux
contents:
Earlier this year, I forget exactly when (it’s been a good year), I was building a client site that needed widgets which look like this (designed, incidentally, by my erstwhile writing partner, Cameron Adams):



Building this was a challenge not just in CSS, but in choosing the proper markup – how should such a widget be constructed?

Mmm … markup

It seemed to me there were two key issues to deal with:


	The function of the interface is to input information, so semantically this is a form, therefore we have to find a way of building it using form elements: fieldset, legend, label and input
	We can’t use a table for layout, even though that would clearly be the easiest solution!


Abusing tables for layout is never good – physical layout is not what table semantics mean. But even if this data can be described as a table, we shouldn’t mix forms markup with non-forms markup, because of the behavioral impact this can have on a screen reader:

To take a prominent example, the screen reader JAWS has a mode specifically for interacting with forms (cunningly known as “forms mode”). When running in this mode its output only includes relevant elements – legends, labels and form controls themselves. Any other kind of markup – like text in a previous table cell, a paragraph or list in between – is simply ignored. The user in this situation would have to switch continually in and out of forms mode to hear all the content. (For more about this issue and some test examples, there’s a  thread at accessify forum which wanders in that direction.)

One further issue for screen reader users is implied by the design: the input fields are associated together in rows and columns, and a sighted user can visually scan across and down to make those associations; but a blind user can’t do that. For such a user the row and column header data will need to be there at every axis; in other words, the layout should be more like this:



And constructed with appropriate semantic markup to convey those relationships. By this point the selection of elements seems pretty clear: each row is a fieldset, the row header is a legend, and each column header is a label, associated with an input.

Here’s what that form looks like with no CSS:



And here’s some markup for the first row (with most of the attributes removed just to keep this example succinct):

<fieldset>
	<legend>
		<span>Match points</span>
	</legend>
	<label>
		<span>Win</span>
		<input value="3" />
	</label>
	<label>
		<span>Draw</span>
		<input value="1" />
	</label>
	<label>
		<span>Lose</span>
		<input value="0" />
	</label>
	<label>
		<span>Played</span>
		<input value="0" />
	</label>
</fieldset>

The span inside each legend is because legend elements are highly resistant to styling! Indeed they’re one of the most stubborn elements in the browsers’ vocabulary. Oh man … how I wrestled with the buggers … until this obvious alternative occurred to me! So the legend element itself is just a container, while all the styling is on the inner span.

Oh yeah, there was some CSS too

I’m not gonna dwell too much on the CSS it took to make this work – this is a short article, and it’s all there in the demo [demo page, style sheet]

But I do want to touch on the most interesting bit – where we get from a layout with headers on every row, to one where only the top row has headers – or at least, so it appears to graphical browsers. For screen readers, as we noted, we need those headers on every row, so we should employ some cunning CSS to partly negate their visual presence, without removing them from the output.

The core styling for each label span is like this:

label span
{
	display:block;
	padding:5px;
	line-height:1em;
	background:#423221;
	color:#fff;
	font-weight:bold;
}

But in the rows below the header they have these additional rules:

fieldset.body label span
{
	padding:0 5px;
	line-height:0;
	position:relative;
	top:-10000em;
}

The rendered width of the element is preserved, ensuring that the surrounding label is still the same width as the one in the header row above, and hence a unified column width is preserved all the way down. But the element effectively has no height, and so it’s effectively invisible. The styling is done this way, rather than just setting the height to zero and using overflow:hidden, because to do that would expose an unrelated quirk with another popular screen reader! (It would hide the output from Window Eyes, as shown in this  test example at access matters.)

The finished widget

It’s an intricate beast allright! But after all that we do indeed get the widget we want:


	Demo page
	Style sheet


It’s not perfect, most notably because the legends have to have a fixed width; this can be in em to allow for text scaling, but it still doesn’t allow the content to break into multiple lines. It also doesn’t look quite right in Safari; and some CSS hacking was needed to make it look right in IE6 and IE7.

Still it worked well enough for the purpose, and satisfied the client completely. And most of all it re-assured me in my faith – that there’s never any need to abuse tables for layout. (Unless of course you think this content is a table anyway, but that’s another story!)


title: Boost Your Hyperlink Power
year: 2006
author: Jeremy Keith
author_slug: jeremykeith
published: 2006-12-18T00:00:00+00:00
url: https://24ways.org/2006/boost-your-hyperlink-power/
topic: code
contents:
There are HTML elements and attributes that we use every day. Headings, paragraphs, lists and images are the mainstay of every Web developer’s toolbox. Perhaps the most common tool of all is the anchor. The humble a element is what joins documents together to create the gloriously chaotic collection we call the World Wide Web.

Anatomy of an Anchor

The power of the anchor element lies in the href attribute, short for hypertext reference. This creates a one-way link to another resource, usually another page on the Web:

<a href="http://allinthehead.com/">

The href attribute sits in the opening a tag and some descriptive text sits between the opening and closing tags:

<a href="http://allinthehead.com/">Drew McLellan</a>

“Whoop-dee-freakin’-doo,” I hear you say, “this is pretty basic stuff” – and you’re quite right. But there’s more to the anchor element than just the href attribute.

The Theory of relativity

You might be familiar with the rel attribute from the link element. I bet you’ve got something like this in the head of your documents:

<link rel="stylesheet" type="text/css" media="screen" href="styles.css" />

The rel attribute describes the relationship  between the linked document and the current document. In this case, the value of rel is “stylesheet”. This means that the linked document is the stylesheet for the current document: that’s its relationship.

Here’s another common use of rel:

<link rel="alternate" type="application/rss+xml" title="my RSS feed" href="index.xml" />

This describes the relationship of the linked file – an RSS feed – as “alternate”: an alternate view of the current document.

Both of those examples use the link element but you are free to use the rel attribute in regular hyperlinks. Suppose you’re linking to your RSS feed in the body of your page:

Subscribe to <a href="index.xml">my RSS feed</a>.

You can add extra information to this anchor using the rel attribute:

Subscribe to <a href="index.xml" rel="alternate" type="application/rss+xml">my RSS feed</a>.

There’s no prescribed list of values for the rel attribute so you can use whatever you decide is semantically meaningful. Let’s say you’ve got a complex e-commerce application that includes a link to a help file. You can explicitly declare the relationship of the linked file as being “help”:

<a href="help.html" rel="help">need help?</a>

Elemental Microformats

Although it’s completely up to you what values you use for the rel attribute, some consensus is emerging in the form of microformats. Some of the simplest microformats make good use of rel. For example, if you are linking to a license that covers the current document, use the rel-license microformat:

Licensed under a <a href="http://creativecommons.org/licenses/by/2.0/" rel="license">Creative Commons attribution license</a>

That describes the relationship of the linked document as “license.”

The rel-tag microformat goes a little further. It uses rel to describe the final part of the URL of the linked file as a “tag” for the current document:

Learn more about <a href="http://en.wikipedia.org/wiki/Microformats" rel="tag">semantic markup</a>

This states that the current document is being tagged with the value “Microformats.”

XFN, which stands for XHTML Friends Network, is a way of describing relationships between people:

<a href="http://allinthehead.com/" rel="friend">Drew McLellan</a>

This microformat makes use of a very powerful property of the rel attribute. Like the class attribute, rel can take multiple values, separated by spaces:

<a href="http://allinthehead.com/" rel="friend met colleague">Drew McLellan</a>

Here I’m describing Drew as being a friend, someone I’ve met, and a colleague (because we’re both Web monkies).

You Say You Want a revolution

While rel describes the relationship of the linked resource to the current document, the rev attribute describes the reverse relationship: it describes the relationship of the current document to the linked resource. Here’s an example of a link that might appear on help.html:

<a href="shoppingcart.html" rev="help">continue shopping</a>

The rev attribute declares that the current document is “help” for the linked file.

The vote-links microformat makes use of the rev attribute to allow you to qualify your links. By using the value “vote-for” you can describe your document as being an endorsement of the linked resource:

I agree with <a href="http://richarddawkins.net/home" rev="vote-for">Richard Dawkins</a>.

There’s a corresponding vote-against value. This means that you can link to a document but explicitly state that you don’t agree with it.

I agree with <a href="http://richarddawkins.net/home" rev="vote-for">Richard Dawkins</a>
about those <a href="http://www.icr.org/" rev="vote-against">creationists</a>. 

Of course there’s nothing to stop you using both rel and rev on the same hyperlink:

<a href="http://richarddawkins.net/home" rev="vote-for" rel="muse">Richard Dawkins</a>

The Wisdom of Crowds

The simplicity of rel and rev belies their power. They allow you to easily add extra semantic richness to your hyperlinks. This creates a bounty that can be harvested by search engines, aggregators and browsers. Make it your New Year’s resolution to make friends with these attributes and extend the power of hypertext.


title: Knockout Type - Thin Is Always In
year: 2006
author: Shaun Inman
author_slug: shauninman
published: 2006-12-17T00:00:00+00:00
url: https://24ways.org/2006/knockout-type/
topic: code
contents:
OS X has gorgeous native anti-aliasing (although I will admit to missing 10px aliased Geneva — *sigh*). This is especially true for dark text on a light background. However, things can go awry when you start using light text on a dark background. Strokes thicken. Counters constrict. Letterforms fill out like seasonal snackers.

 

So how do we combat the fat? In Safari and other Webkit-based browsers we can use the CSS ‘text-shadow’ property. While trying to add a touch more contrast to the navigation on haveamint.com I noticed an interesting side-effect on the weight of the type. 



The second line in the example image above has the following style applied to it:

  

This creates an invisible drop-shadow. (Why is it invisible? The shadow is positioned directly behind the type (the first two zeros) and has no spread (the third zero). So the color, black, is completely eclipsed by the type it is supposed to be shadowing.)

 

Why applying an invisible drop-shadow effectively lightens the weight of the type is unclear. What is clear is that our light-on-dark text is now of a comparable weight to its dark-on-light counterpart.

 

You can see this trick in effect all over ShaunInman.com and in the navigation on haveamint.com and Subtraction.com. The HTML and CSS source code used to create the example images used in this article can be found here.


title: Faster Development with CSS Constants
year: 2006
author: Rachel Andrew
author_slug: rachelandrew
published: 2006-12-02T00:00:00+00:00
url: https://24ways.org/2006/faster-development-with-css-constants/
topic: process
contents:
Anyone even slightly familiar with a programming language will have come across the concept of constants – a fixed value that can be used through your code. For example, in a PHP script I might have a constant which is the email address that all emails generated by my application get sent to. 

$adminEmail = 'info@example.com';

I could then use $adminEmail in my script whenever I wanted an email to go to that address. The benefit of this is that when the client decides they want the email to go to a different address, I only need change it in one place – the place where I initially set the constant. I could also quite easily make this value user defined and enable the administrator to update the email address.

Unfortunately CSS doesn’t support constants. It would be really useful to be able to define certain values initially and then use them throughout a CSS file, so in this article I’m going to take a look at some of the methods we do have available and provide pointers to more in depth commentary on each. If you have a different method, or tip to share please add it to the comments.

So what options do we have?

One way to get round the lack of constants is to create some definitions at the top of your CSS file in comments, to define ‘constants’. A common use for this is to create a ‘color glossary’. This means that you have a quick reference to the colors used in the site to avoid using alternates by mistake and, if you need to change the colors, you have a quick list to go down and do a search and replace. 

In the below example, if I decide I want to change the mid grey to #999999, all I need to do is search and replace #666666 with #999999 – assuming I’ve remember to always use that value for things which are mid grey.

/*
Dark grey (text): #333333
Dark Blue (headings, links) #000066
Mid Blue (header) #333399
Light blue (top navigation) #CCCCFF
Mid grey: #666666
*/

This is a fairly low-tech method, but if used throughout the development of the CSS files can make changes far simpler and help to ensure consistency in your color scheme.

I’ve seen this method used by many designers however Garrett Dimon documents the method, with more ideas in the comments.

Going server-side

To truly achieve constants you will need to use something other than CSS to process the file before it is sent to the browser. You can use any scripting language – PHP, ASP, ColdFusion etc. to parse a CSS file in which you have entered constants. So that in a constants section of the CSS file you would have:

$darkgrey = '#333333';
$darkblue = '#000066';

The rest of the CSS file is as normal except that when you come to use the constant value you would use the constant name instead of adding the color:

p {
	color: $darkgrey;
}

Your server-side script could then parse the CSS file, replace the constant names with the constant values and serve a valid CSS file to the browser. Christian Heilmann has done just this for PHP however this could be adapted for any language you might have available on your server.

Shaun Inman came up with another way 
 of doing this that removes the need to link to a PHP script and also enables the adding of constants using the syntax of at-rules . This method is again using PHP and will require you to edit an .htaccess file. 

A further method is to generate static CSS files either using a script locally – if the constants are just to enable speed of development – or as part of the web application itself. Storing a template stylesheet with constant names in place of the values you will want to update means that your script can simply open the template, replace the variables and save the result as a new stylesheet file.

While CSS constants are a real help to developers, they can also be used to add new functionality to your applications. As with the email address example that I used at the beginning of this article, using a combination of CSS and server-side scripting you could enable a site administrator to select the colours for a new theme to be used on a page of a content managed site. By using constants you need only give them the option to change certain parts of the CSS and not upload a whole different CSS file, which could lead to some interesting results!

As we are unlikely to find real CSS constants under the tree this Christmas the above methods are some possibilities for better management of your stylesheets. However if you have better methods, CSS Constant horror stories or any other suggestions, add your comments below.


title: Random Lines Made With Mesh
year: 2006
author: Veerle Pieters
author_slug: veerlepieters
published: 2006-12-08T00:00:00+00:00
url: https://24ways.org/2006/random-lines-made-with-mesh/
topic: design
contents:
I know that Adobe Illustrator can be a bit daunting for people who aren’t really advanced users of the program, but you would be amazed by how easy you can create cool effects or backgrounds. In this short tutorial I show you how to create a cool looking background only in 5 steps. 

Step 1 – Create Lines



Create lines using random widths and harmonious suitable colors. If you get stuck on finding the right colors, check out Adobe’s Kuler and start experimenting.

Step 2 – Convert Strokes to Fills



Select all lines and convert them to fills. Go to the Object menu, select Path > Outline Stroke. Select the Rectangle tool and draw 1 big rectangle on top the lines. Give the rectangle a suitable color. With the rectangle still selected, go to the Object menu, select Arrange > Send to Back.

Step 3 – Convert to Mesh



Select all objects by pressing the command key (for Mac users), control key (for Windows users) + the “a” key. Go to the Object menu and select the Envelope Distort > Make with Mesh option. Enter 2 rows and 2 columns. Check the preview box to see what happens and click the OK button.

Step 4 – Play Around with The Mesh Points 



Play around with the points of the mesh using the Direct Selection tool (the white arrow in the Toolbox). Click on the top right point of the mesh. Once you’re starting to drag hold down the shift key and move the point upwards. 



Now start dragging the bezier handles on the mesh to achieve the effect as shown in the above picture. Of course you can try out all kind of different effects here. 

The Final Result



This is an example of how the final result can look. You can try out all kinds of different shapes dragging the handles of the mesh points. This is just one of the many results you can get. So next time you haven’t got inspiration for a background of a header, a banner or whatever, just experiment with a few basic shapes such as lines and try out the ‘Envelope Distort’ options in Illustrator or the ‘Make with Mesh’ option and experiment, you’ll be amazed by the unexpected creative results.


title: Tasty Text Trimmer
year: 2006
author: Drew McLellan
author_slug: drewmclellan
published: 2006-12-01T00:00:00+00:00
url: https://24ways.org/2006/tasty-text-trimmer/
topic: code
contents:
In most cases, when designing a user interface it’s best to make a decision about how data is best displayed and stick with it. Failing to make a decision ultimately leads to too many user options, which in turn can be taxing on the poor old user. 

Under some circumstances, however, it’s good to give the user freedom in customising their workspace. One good example of this is the ‘Article Length’ tool in Apple’s Safari RSS reader. Sliding a slider left of right dynamically changes the length of each article shown. It’s that kind of awesomey magic stuff that’s enough to keep you from sleeping. Let’s build one.

The Setup

Let’s take a page that has lots of long text items, a bit like a news page or like Safari’s RSS items view. If we were to attach a class name to each element we wanted to resize, that would give us something to hook onto from the JavaScript. 

Example 1: The basic page.

As you can see, I’ve wrapped my items in a DIV and added a class name of chunk to them. It’s these chunks that we’ll be finding with the JavaScript. Speaking of which …

Our Core Functions

There are two main tasks that need performing in our script. The first is to find the chunks we’re going to be resizing and store their original contents away somewhere safe. We’ll need this so that if we trim the text down we’ll know what it was if the user decides they want it back again. We’ll call this loadChunks. 

var loadChunks = function(){
	var everything = document.getElementsByTagName('*');
	var i, l;
	chunks	= [];
	for (i=0, l=everything.length; i<l; i++){
		if (everything[i].className.indexOf(chunkClass) > -1){
			chunks.push({
				ref: everything[i],
				original: everything[i].innerHTML
			});
		}
	}
};

The variable chunks is stored outside of this function so that we can access it from our next core function, which is doTrim.

var doTrim = function(interval) {
	if (!chunks) loadChunks();
	var i, l;
	for (i=0, l=chunks.length; i<l; i++){
		var a = chunks[i].original.split(' ');
		a = a.slice(0, interval);
		chunks[i].ref.innerHTML	= a.join(' ');
	}
};

The first thing that needs to be done is to call loadChunks if the chunks variable isn’t set. This should only happen the first time doTrim is called, as from that point the chunks will be loaded.

Then all we do is loop through the chunks and trim them. The trimming itself (lines 6-8) is very simple. We split the text into an array of words (line 6), then select only a portion from the beginning of the array up until the number we want (line 7). Finally the words are glued back together (line 8).

In essense, that’s it, but it leaves us needing to know how to get the number into this function in the first place, and how that number is generated by the user. Let’s look at the latter case first.

The YUI Slider Widget

There are lots of JavaScript libraries available at the moment. A fair few of those are really good. I use the Yahoo! User Interface Library professionally, but have only recently played with their pre-build slider widget. Turns out, it’s pretty good and perfect for this task. 

Once you have the library files linked in (check the docs linked above) it’s fairly straightforward to create yourself a slider.

slider = YAHOO.widget.Slider.getHorizSlider("sliderbg", "sliderthumb", 0, 100, 5); 
slider.setValue(50);
slider.subscribe("change", doTrim);

All that’s needed then is some CSS to make the slider look like a slider, and of course a few bits of HTML. We’ll see those later.

See It Working!

Rather than spell out all the nuts and bolts of implementing this fairly simple script, let’s just look at in it action and then pick on some interesting bits I’ve added.

Example 2: Try the Tasty Text Trimmer.

At the top of the JavaScript file I’ve added a small number of settings.

var chunkClass	= 'chunk';
var minValue	= 10;
var maxValue	= 100;
var multiplier	= 5;

Obvious candidates for configuration are the class name used to find the chunks, and also the some minimum and maximum values. The minValue is the fewest number of words we wish to display when the slider is all the way down. The maxValue is the length of the slider, in this case 100.

Moving the slider makes a call to our doTrim function with the current value of the slider. For a slider 100 pixels long, this is going to be in the range of 0-100. That might be okay for some things, but for longer items of text you’ll want to allow for displaying more than 100 words. I’ve accounted for this by adding in a multiplier – in my code I’m multiplying the value by 5, so a slider value of 50 shows 250 words. You’ll probably want to tailor the multiplier to the type of content you’re using.

Keeping it Accessible 

This effect isn’t something we can really achieve without JavaScript, but even so we must make sure that this functionality has no adverse impact on the page when JavaScript isn’t available. This is achieved by adding the slider markup to the page from within the insertSliderHTML function.

var insertSliderHTML = function(){
	var s = '<a id="slider-less" href="#less"><img src="icon_min.gif" width="10" height="10" alt="Less text" class="first" /></a>';
	s +=' <div id="sliderbg"><div id="sliderthumb"><img src="sliderthumbimg.gif" /></div></div>';
	s +=' <a id="slider-more" href="#more"><img src="icon_max.gif" width="10" height="10" alt="More text" /></a>';
	document.getElementById('slider').innerHTML = s;
}

The other important factor to consider is that a slider can be tricky to use unless you have good eyesight and pretty well controlled motor skills. Therefore we should provide a method of changing the value by the keyboard.

I’ve done this by making the icons at either end of the slider links so they can be tabbed to. Clicking on either icon fires the appropriate JavaScript function to show more or less of the text.

In Conclusion

The upshot of all this is that without JavaScript the page just shows all the text as it normally would. With JavaScript we have a slider for trimming the text excepts that can be controlled with the mouse or with a keyboard.

If you’re like me and have just scrolled to the bottom to find the working demo, here it is again:

Try the Tasty Text Trimmer

Trimmer for Christmas? Don’t say I never give you anything!


title: Gravity-Defying Page Corners
year: 2006
author: Dan Cederholm
author_slug: dancederholm
published: 2006-12-24T00:00:00+00:00
url: https://24ways.org/2006/gravity-defying-page-corners/
topic: design
contents:
While working on Stikkit, a “page curl” came to be.
Not being as crafty as Veerle, you see.
I fired up Photoshop to see what could be.
“Another copy is running on the network“ … oopsie.

With license issues sorted out and a concept in mind
I set out to create something flexible and refined.
One background image and code that is sure to be lean.
A simple solution for lazy people like me.

The curl I’ll be showing isn’t a curl at all.
It’s simply a gradient that’s 18 pixels tall.
With a fade to the left that’s diagonally aligned
and a small fade on the right that keeps the illusion defined.



Create a selection with the marquee tool (keeping in mind a reasonable minimum width) and drag a gradient (black to transparent) from top to bottom.



Now drag a gradient (the background color of the page to transparent) from the bottom left corner to the top right corner.



Finally, drag another gradient from the right edge towards the center, about 20 pixels or so.

But the top is flat and can be positioned precisely
just under the bottom right edge very nicely.
And there it will sit, never ever to be busted
by varying sizes of text when adjusted.

<div id="page">
	<div id="page-contents">
		<h2>Gravity-Defying!</h2>
		<p>Lorem ipsum dolor ...</p>
	</div>
</div>

Let’s dive into code and in the markup you’ll see
“is that an extra div?” … please don’t kill me?
The #page div sets the width and bottom padding
whose height is equal to the shadow we’re adding.



The #page-contents div will set padding in ems
to scale with the text size the user intends.
The background color will be added here too
but not overlapping the shadow where #page’s padding makes room.

A simple technique that you may find amusing
is to substitute a PNG for the GIF I was using.
For that would be crafty and future-proof, too.
The page curl could sit on any background hue.

I hope you’ve enjoyed this easy little trick.
It’s hardly earth-shattering, and arguably slick.
But it could come in handy, you just never know.
Happy Holidays! And pleasant dreams of web three point oh.


title: Photographic Palettes
year: 2006
author: Dave Shea
author_slug: daveshea
published: 2006-12-22T00:00:00+00:00
url: https://24ways.org/2006/photographic-palettes/
topic: design
contents:
How many times have you seen a colour combination that just worked, a match so perfect that it just seems obvious? 

Now, how many times do you come up with those in your own work? A perfect palette looks easy when it’s done right, but it’s often maddeningly difficult and time-consuming to accomplish.

Choosing effective colour schemes will always be more art than science, but there are things you can do that will make coming up with that oh-so-smooth palette just a little a bit easier. A simple trick that can lead to incredibly gratifying results lies in finding a strong photograph and sampling out particularly harmonious colours.

Photo Selection

Not all photos are created equal. You certainly want to start with imagery that fits the eventual tone you’re attempting to create. A well-lit photo of flowers might lead to a poor colour scheme for a funeral parlour’s web site, for example. It’s worth thinking about what you’re trying to say in advance, and finding a photo that lends itself to your message.

As a general rule of thumb, photos that have a lot of neutral or de-saturated tones with one or two strong colours make for the best palette; bright and multi-coloured photos are harder to derive pleasing results from. Let’s start with a relatively neutral image.

Sampling



In the above example, I’ve surrounded the photo with three different background colours directly sampled from the photo itself. Moving from left to right, you can see how each of the sampled colours is from an area of increasingly smaller coverage within the photo, and yet there’s still a strong harmony between the photo and the background image. I don’t really need to pick the big obvious colours from the photo to create that match, I can easily concentrate on more interesting colours that might work better for what I intend.

Using a similar palette, let’s apply those colour choices to a more interesting layout:



In this mini-layout, I’ve re-used the same tan colour from the previous middle image as a background, and sampled out a nicely matching colour for the top and bottom overlays, as well as the two different text colours. Because these colours all fall within a narrow range, the overall balance is harmonious.

What if I want to try something a little more daring? I have a photo of stacked chairs of all different colours, and I’d like to use a few more of those. No problem, provided I watch my colour contrast:



Though it uses varying shades of red, green, and yellow, this palette actually works because the values are even, and the colours muted. Placing red on top of green is usually a hideous combination of death, but if the green is drab enough and the red contrasts well enough, the result can actually be quite pleasing. I’ve chosen red as my loudest colour in this palette, and left green and yellow to play the quiet supporting roles.

Obviously, there are no hard and fast rules here. You might not want to sample absolutely every colour in your scheme from a photo. There are times where you’ll need a variation that’s just a little bit lighter, or a blue that’s not in the photo. You might decide to start from a photo base and tweak, or add in colours of your own. That’s okay too.

Tonal Variations

I’ll leave you with a final trick I’ve been using lately, a way to bring a bit more of a formula into the equation and save some steps.



Starting with the same base palette I sampled from the chairs, in the above image I’ve added a pair of overlaying squares that produce tonal variations of each primary. The lighter variation is simply a solid white square set to 40% opacity, the darker one is a black square at 20%. That gives me a highlight and shadow for each colour, which would prove handy if I had to adapt this colour scheme to a larger layout.

I could add a few more squares of varying opacities, or adjust the layer blending modes for different effects, but as this looks like a great place to end, I’ll leave that up to your experimental whims. Happy colouring!


title: A Scripting Carol
year: 2006
author: Derek Featherstone
author_slug: derekfeatherstone
published: 2006-12-21T00:00:00+00:00
url: https://24ways.org/2006/a-scripting-carol/
topic: code
contents:
We all know the stories of the Ghost of Scripting Past – a time when the web was young and littered with nefarious scripting, designed to bestow ultimate control upon the developer, to pollute markup with event handler after event handler, and to entrench advertising in the minds of all that gazed upon her.

And so it came to be that JavaScript became a dirty word, thrown out of solutions by many a Scrooge without regard to the enhancements that JavaScript could bring to any web page. JavaScript, as it was, was dead as a door-nail.

With the arrival of our core philosophy that all standardistas hold to be true: “separate your concerns – content, presentation and behaviour,” we are in a new era of responsible development the Web Standards Way™. Or are we? Have we learned from the Ghosts of Scripting Past? Or are we now faced with new problems that come with new ways of implementing our solutions?

The Ghost of Scripting Past

If the Ghost of Scripting Past were with us it would probably say: 


	You must remember your roots and where you came from, and realize the misguided nature of your early attempts for control. That person you see down there, is real and they are the reason you exist in the first place… without them, you are nothing.


In many ways we’ve moved beyond the era of control and we do take into account the user, or at least much more so than we used to. Sadly – there is one advantage that old school inline event handlers had where we assigned and reassigned CSS style property values on the fly – we knew that if JavaScript wasn’t supported, the styles wouldn’t be added because we ended up doing them at the same time.

If anything, we need to have learned from the past that just because it works for us doesn’t mean it is going to work for anyone else – we need to test more scenarios than ever to observe the multitude of browsing arrangements we’ll observe: CSS on with JavaScript off, CSS off/overridden with JavaScript on, both on, both off/not supported. It is a situation that is ripe for conflict.

This may shock some of you, but there was a time when testing was actually easier: back in the day when Netscape 4 was king. Yes, that’s right. I actually kind of enjoyed Netscape 4 (hear me out, please). With NS4’s CSS implementation known as JavaScript Style Sheets, you knew that if JavaScript was off the styles were off too.

The Ghost of Scripting Present

With current best practice – we keep our CSS and JavaScript separate from each other. So what happens when some of our fancy, unobtrusive DOM Scripting doesn’t play nicely with our wonderfully defined style rules?

Lets look at one example of a collapsing and expanding menu to illustrate where we are now:

Simple Collapsing/Expanding Menu Example

We’re using some simple JavaScript (I’m using jquery in this case) to toggle between a CSS state for expanded and not expanded:

JavaScript

$(document).ready(function(){
	TWOFOURWAYS.enableTree();
});
var TWOFOURWAYS = new Object();
TWOFOURWAYS.enableTree = function ()
{
	$("ul li a").toggle(function(){
		$(this.parentNode).addClass("expanded");
	}, function() {
		$(this.parentNode).removeClass("expanded");
	});
	return false;	
}

CSS

ul li ul {
	display: none;
}
ul li.expanded ul {
	display: block;
}

At this point we’ve separated our presentation from our content and behaviour, and all is well, right?

Not quite.

Here’s where I typically see failures in the assessment work that I do on web sites and applications (Yes, call me Scrooge – I don’t care!). We know our page needs to work with or without scripting, and we know it needs to work with or without CSS. All too often the testing scenarios don’t take into account combinations.

Testing it out

So what happens when we test this? Make sure you test with:


	CSS off
	JavaScript off


Use the simple example again.

With CSS off, we revert to a simple nested list of links and all functionality is maintained. With JavaScript off, however, we run into a problem – we have now removed the ability to expand the menu using the JavaScript triggered CSS change.

Hopefully you see the problem – we have a JavaScript and CSS dependency that is critical to the functionality of the page. Unobtrusive scripting and binary on/off tests aren’t enough. We need more.

This Ghost of Scripting Present sighting is seen all too often.

Lets examine the JavaScript off scenario a bit further – if we require JavaScript to expand/show the branch of the tree we should use JavaScript to hide them in the first place. That way we guarantee functionality in all scenarios, and have achieved our baseline level of interoperability. 

To revise this then, we’ll start with the sub items expanded, use JavaScript to collapse them, and then use the same JavaScript to expand them.

HTML

<ul>
	<li><a href="#">Main Item</a>
		<ul class="collapseme">
			<li><a href="#">Sub item 1</a></li>
			<li><a href="#">Sub item 2</a></li>
			<li><a href="#">Sub item 3</a></li>
		</ul>
	</li>
</ul>

CSS

/* initial style is expanded */
ul li ul.collapseme {
	display: block;
}

JavaScript

// remove the class collapseme after the page loads
$("ul ul.collapseme").removeClass("collapseme");

And there you have it – a revised example with better interoperability.

This isn’t rocket surgery by any means. It is a simple solution to a ghostly problem that is too easily overlooked (and often is).

The Ghost of Scripting Future

Well, I’m not so sure about this one, but I’m guessing that in a few years’ time, we’ll all have seen a few more apparitions and have a few more tales to tell. And hopefully we’ll be able to share them on 24 ways.

Thanks to Drew for the invitation to contribute and thanks to everyone else out there for making this a great (and haunting) year on the web!


title: Making XML Beautiful Again: Introducing Client-Side XSL
year: 2006
author: Ian Forrester
author_slug: ianforrester
published: 2006-12-07T00:00:00+00:00
url: https://24ways.org/2006/beautiful-xml-with-xsl/
topic: code
contents:
Remember that first time you saw XML and got it? When you really understood what was possible and the deep meaning each element could carry? Now when you see XML, it looks ugly, especially when you navigate to a page of XML in a browser. Well, with every modern browser now supporting XSL 1.0, I’m going to show you how you can turn something as simple as an ATOM feed into a customised page using a browser, Notepad and some XSL.

What on earth is this XSL?

XSL is a family of recommendations for defining XML document transformation and presentation. It consists of three parts:


	XSLT 1.0 – Extensible Stylesheet Language Transformation, a language for transforming XML
	XPath 1.0 – XML Path Language, an expression language used by XSLT to access or refer to parts of an XML document. (XPath is also used by the XML Linking specification)
	XSL-FO 1.0 – Extensible Stylesheet Language Formatting Objects, an XML vocabulary for specifying formatting semantics


XSL transformations are usually a one-to-one transformation, but with newer versions (XSL 1.1 and XSL 2.0) its possible to create many-to-many transformations too. So now you have an overview of XSL, on with the show…

So what do I need?

So to get going you need a browser an supports client-side XSL transformations such as Firefox, Safari, Opera or Internet Explorer. Second, you need a source XML file – for this we’re going to use an ATOM feed from Flickr.com. And lastly, you need an editor of some kind. I find Notepad++ quick for short XSLs, while I tend to use XMLSpy or Oxygen for complex XSL work. 

Because we’re doing a client-side transformation, we need to modify the XML file to tell it where to find our yet-to-be-written XSL file. Take a look at the source XML file, which originates from my Flickr photos tagged sky, in ATOM format.

The top of the ATOM file now has an additional <?xml-stylesheet /> instruction, as can been seen on Line 2 below. This instructs the browser to use the XSL file to transform the document.

<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<?xml-stylesheet type="text/xsl" href="flickr_transform.xsl"?>
<feed xmlns="http://www.w3.org/2005/Atom"
	xmlns:dc="http://purl.org/dc/elements/1.1/">

Your first transformation

Your first XSL will look something like this:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0"
	xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:dc="http://purl.org/dc/elements/1.1/">
	<xsl:output method="html" encoding="utf-8"/>
</xsl:stylesheet>

This is pretty much the starting point for most XSL files. You will notice the standard XML processing instruction at the top of the file (line 1). We then switch into XSL mode using the XSL namespace on all XSL elements (line 2). In this case, we have added namespaces for ATOM (line 4) and Dublin Core (line 5). This means the XSL can now read and understand those elements from the source XML. 

After we define all the namespaces, we then move onto the xsl:output element (line 6). This enables you to define the final method of output. Here we’re specifying html, but you could equally use XML or Text, for example. The encoding attributes on each element do what they say on the tin. As with all XML, of course, we close every element including the root.

The next stage is to add a template, in this case an <xsl:template /> as can be seen below:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0"
	xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:dc="http://purl.org/dc/elements/1.1/">
	<xsl:output method="html" encoding="utf-8"/>
	<xsl:template match="/">
		<html>
			<head>
				<title>Making XML beautiful again : Transforming ATOM</title>
			</head>
			<body>
				<xsl:apply-templates select="/atom:feed"/>
			</body>
		</html>
	</xsl:template>
</xsl:stylesheet>

The beautiful thing about XSL is its English syntax, if you say it out loud it tends to make sense. 

The / value for the match attribute on line 8 is our first example of XPath syntax. The expression / matches any element – so this <xsl:template/> will match against any element in the document. As the first element in any XML document is the root element, this will be the one matched and processed first.

Once we get past our standard start of a HTML document, the only instruction remaining in this <xsl:template/> is to look for and match all <atom:feed/> elements using the <xsl:apply-templates/> in line 14, above.

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0"
	xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:dc="http://purl.org/dc/elements/1.1/">
	<xsl:output method="html" encoding="utf-8"/>
	<xsl:template match="/">
		<xsl:apply-templates select="/atom:feed"/>
	</xsl:template>
	<xsl:template match="/atom:feed">
		<div id="content">
			<h1>
				<xsl:value-of select="atom:title"/>
			</h1>
			<p>
				<xsl:value-of select="atom:subtitle"/>
			</p>
			<ul id="entries">
				<xsl:apply-templates select="atom:entry"/>
			</ul>
		</div>
	</xsl:template>
</xsl:stylesheet>

This new template (line 12, above) matches <feed/> and starts to write the new HTML elements out to the output stream. The <xsl:value-of/> does exactly what you’d expect – it finds the value of the item specifed in its select attribute. With XPath you can select any element or attribute from the source XML. 

The last part is a repeat of the now familiar <xsl:apply-templates/> from before, but this time we’re using it inside of a called template. Yep, XSL is full of recursion…

<xsl:template match="atom:entry">
	<li class="entry">
		<h2>
			<a href="{atom:link/@href}">
				<xsl:value-of select="atom:title"/>
			</a>
		</h2>
		<p class="date">
			(<xsl:value-of select="substring-before(atom:updated,'T')"/>)
		</p>
		<p class="content">
			<xsl:value-of select="atom:content" disable-output-escaping="yes"/>
		</p>
		<xsl:apply-templates select="atom:category"/>
	</li>
</xsl:template>

The <xsl:template/> which matches atom:entry (line 1) occurs every time there is a <entry/> element in the source XML file. So in total that is 20 times, this is naturally why XSLT is full of recursion. This <xsl:template/> has been matched and therefore called higher up in the document, so we can start writing list elements directly to the output stream. The first part is simply a <h2/> with a link wrapped within it (lines 3-7). We can select attributes using XPath using @. 

The second part of this template selects the date, but performs a XPath string function on it. This means that we only get the date and not the time from the string (line 9). This is achieved by getting only the part of the string that exists before the T. 

Regular Expressions are not part of the XPath 1.0 string functions, although XPath 2.0 does include them. Because of this, in XSL we tend to rely heavily on the available XML output. 

The third part of the template (line 12) is a <xsl:value-of/> again, but this time we use an attribute of <xsl:value-of/> called disable output escaping to turn escaped characters back into XML. 

The very last section is another <xsl:apply-template/> call, taking us three templates deep. Do not worry, it is not uncommon to write XSL which go 20 or more templates deep!

<xsl:template match="atom:category">
	<xsl:for-each select=".">
		<xsl:element name="a">
			<xsl:attribute name="rel">
				<xsl:text>tag</xsl:text>
			</xsl:attribute>
			<xsl:attribute name="href">
				<xsl:value-of select="concat(@scheme, @term)"/>
			</xsl:attribute>
			<xsl:value-of select="@term"/>
		</xsl:element>
		<xsl:text> </xsl:text>
	</xsl:for-each>
</xsl:template>

In our final <xsl:template/>, we see a combination of what we have done before with a couple of twists. Once we match atom:category we then count how many elements there are at that same level (line 2). The XPath . means ‘self’, so we count how many category elements are within the <entry/> element. 

Following that, we start to output a link with a rel attribute of the predefined text, tag (lines 4-6). In XSL you can just type text, but results can end up with strange whitespace if you do (although there are ways to simply remove all whitespace). 

The only new XPath function in this example is concat(), which simply combines what XPaths or text there might be in the brackets. We end the output for this tag with an actual tag name (line 10) and we add a space afterwards (line 12) so it won’t touch the next tag. (There are better ways to do this in XSL using the last() XPath function). 

After that, we go back to the <xsl:for-each/> element again if there is another category element, otherwise we end the <xsl:for-each/> loop and end this <xsl:template/>.

A touch of style

Because we’re using recursion through our templates, you will find this is the end of the templates and the rest of the XML will be ignored by the parser. Finally, we can add our CSS to finish up. (I have created one for Flickr and another for News feeds)

<style type="text/css" media="screen">@import "flickr_overview.css?v=001";</style>

So we end up with a nice simple to understand but also quick to write XSL which can be used on ATOM Flickr feeds and ATOM News feeds. With a little playing around with XSL, you can make XML beautiful again.

All the files can be found in the zip file (14k)


title: Cheating Color
year: 2006
author: Jason Santa Maria
author_slug: jasonsantamaria
published: 2006-12-23T00:00:00+00:00
url: https://24ways.org/2006/cheating-color/
topic: design
contents:
Have you ever been strapped to use specific colors outlined in a branding guide? Felt restricted because those colors ended up being too light or dark for the way you want to use them?

Here’s the solution: throw out your brand guide.

gasp!

OK, don’t throw it out. Just put it in a drawer for a few minutes.

Branding Guides be Damned

When dealing with color on screen, it’s easy to get caught up in literal values from hex colors, you can cheat colors ever so slightly to achieve the right optical value. This is especially prevalent when trying to bring a company’s identity colors to a screen design. Because the most important idea behind a brand guide is to help a company maintain the visual integrity of their business, consider hex numbers to be guidelines rather than law. Once you are familiar enough with the colors your company uses, you can start to flex them a bit, and take a few liberties.

This is a quick method for cheating to get the color you really want. With a little sleight of design, we can swap a color that might be part of your identity guidelines, with one that works better optically, and no one will be the wiser!

Color is a Wily Beast

This might be hard: You might have to break out of the idea that a color can only be made using one method. Color is fluid. It interacts and changes based on its surroundings. Some colors can appear lighter or darker based on what color they appear on or next to. The RGB gamut is additive color, and as such, has a tendency to push contrast in the direction that objects may already be leaning—increasing the contrast of light colors on dark colors and decreasing the contrast of light on light. Obviously, because we are talking about monitors here, these aren’t hard and fast rules.

Cheat and Feel Good About It

On a light background, when you have a large element of a light color, a small element of the same color will appear lighter.

Enter our fake company: Double Dagger. They manufacture footnotes. Take a look at Fig. 1 below. The logo (Double Dagger), rule, and small text are all #6699CC. Because the logo so large, we get a good sense of the light blue color. Unfortunately, the rule and small text beneath it feel much lighter because we can’t create enough contrast with such small shapes in that color.

Now take a look at Fig. 2. Our logo is still #6699CC, but now the rule and smaller text have been cheated to #4477BB, effectively giving us the same optical color that we used in the logo. You will find that we get a better sense of the light blue, and the added benefit of more contrast for our text. Doesn’t that feel good?



Conversely, when you have a large element of a dark color, a small element of the same color will appear darker.

Let’s look at Fig. 3 below. Double Dagger has decided to change its identity colors from blue to red. In Fig. 3, our logo, rule, and small text are all #330000, a very dark red. If you look at the rule and small text below the logo, you will notice that they seem dark enough to be confused with black. The dark red can’t be sustained by the smaller shapes. Now let’s look at Fig. 4. The logo is still #33000, but we’ve now cheated the rule and smaller text to #550000. This gives us a better sense of a red, but preserves the dark and moody direction the company has taken.



But we’ve only touched on color against a white background. For colors against a darker background, you may find lighter colors work fine, but darker colors need to be cheated a bit to the lighter side in order to reach a good optical equivalent. Take a look below at Fig. 5 and Fig. 6. Both use the same exact corresponding colors as Fig. 1 and Fig. 2 above, but now they are set against a dark background. Where the blue used in Fig. 1 above was too light for the smaller elements, we find it is just right for them in Fig. 5, and the darker blue we used in Fig. 2 has now proven too dark for a dark background, as evidenced in Fig. 6.



Your mileage may vary, and this may not be applicable in all situations, but consider it to be just another tool on your utility belt for dealing with color problems.


title: Rounded Corner Boxes the CSS3 Way
year: 2006
author: Andy Budd
author_slug: andybudd
published: 2006-12-04T00:00:00+00:00
url: https://24ways.org/2006/rounded-corner-boxes-the-css3-way/
topic: code
contents:
If you’ve been doing CSS for a while you’ll know that there are approximately 3,762 ways to create a rounded corner box. The simplest techniques rely on the addition of extra mark-up directly to your page, while the more complicated ones add the mark-up though DOM manipulation. While these techniques are all very interesting, they do seem somewhat of a kludge. The goal of CSS is to separate structure from presentation, yet here we are adding superfluous mark-up to our code in order to create a visual effect. The reason we are doing this is simple. CSS2.1 only allows a single background image per element.

Thankfully this looks set to change with the addition of multiple background images into the CSS3 specification. With CSS3 you’ll be able to add not one, not four, but eight background images to a single element. This means you’ll be able to create all kinds of interesting effects without the need of those additional elements.

While the CSS working group still seem to be arguing over the exact syntax, Dave Hyatt went ahead and implemented the currently suggested mechanism into Safari. The technique is fiendishly simple, and I think we’ll all be a lot better off once the W3C stop arguing over the details and allow browser vendors to get on and provide the tools we need to build better websites.

To create a CSS3 rounded corner box, simply start with your box element and apply your 4 corner images, separated by commas.

.box {
	background-image: url(top-left.gif), url(top-right.gif), url(bottom-left.gif), url(bottom-right.gif);
}

We don’t want these background images to repeat, which is the normal behaviour, so lets set all their background-repeat properties to no-repeat.

.box {
	background-image: url(top-left.gif), url(top-right.gif), url(bottom-left.gif), url(bottom-right.gif);
	background-repeat: no-repeat, no-repeat, no-repeat, no-repeat;
}

Lastly, we need to define the positioning of each corner image.

.box {
	background-image: url(top-left.gif), url(top-right.gif), url(bottom-left.gif), url(bottom-right.gif);
	background-repeat: no-repeat, no-repeat, no-repeat, no-repeat;
	background-position: top left, top right, bottom left, bottom right;
}

And there we have it, a simple rounded corner box with no additional mark-up.

As well as using multiple background images, CSS3 also has the ability to create rounded corners without the need of any images at all. You can do this by setting the border-radius property to your desired value as seen in the next example.

.box {
	border-radius: 1.6em;
}

This technique currently works in Firefox/Camino and creates a nice, if somewhat jagged rounded corner. If you want to create a box that works in both Mozilla and WebKit based browsers, why not combine both techniques and see what happens.


title: Flickr Photos On Demand with getFlickr
year: 2006
author: Christian Heilmann
author_slug: chrisheilmann
published: 2006-12-03T00:00:00+00:00
url: https://24ways.org/2006/flickr-photos-on-demand/
topic: code
contents:
In case you don’t know it yet, Flickr is great. It is a lot of fun to upload, tag and caption photos and it is really handy to get a vast network of contacts through it. 

Using Flickr photos outside of it is a bit of a problem though. There is a Flickr API, and you can get almost every page as an RSS feed, but in general it is a bit tricky to use Flickr photos inside your blog posts or web sites. You might not want to get into the whole API game or use a server side proxy script as you cannot retrieve RSS with Ajax because of the cross-domain security settings.

However, Flickr also provides an undocumented JSON  output, that can be used to hack your own solutions in JavaScript without having to use a server side script.


	If you enter the URL http://flickr.com/photos/tags/panda you get to the flickr page with photos tagged “panda”.
	If you enter the URL http://api.flickr.com/services/feeds/photos_public.gne?tags=panda&format=rss_200 you get the same page as an RSS feed.
	If you enter the URL http://api.flickr.com/services/feeds/photos_public.gne?tags=panda&format=json you get a JavaScript function called jsonFlickrFeed with a parameter that contains the same data in JSON format


You can use this to easily hack together your own output by just providing a function with the same name. I wanted to make it easier for you, which is why I created the helper getFlickr for you to download and use.

getFlickr for Non-Scripters

Simply include the javascript file getflickr.js and the style getflickr.css in the head of your document:

<script type="text/javascript" src="getflickr.js"></script>
<link rel="stylesheet" href="getflickr.css" type="text/css">

Once this is done you can add links to Flickr pages anywhere in your document, and when you give them the CSS class getflickrphotos they get turned into gallery links. When a visitor clicks these links they turn into loading messages and show a “popup” gallery with the connected photos once they were loaded. As the JSON returned is very small it won’t take long. You can close the gallery, or click any of the thumbnails to view a photo. Clicking the photo makes it disappear and go back to the thumbnails.

Check out the example page and click the different gallery links to see the results.

Notice that getFlickr works with Unobtrusive JavaScript as when scripting is disabled the links still get to the photos on Flickr.

getFlickr for JavaScript Hackers

If you want to use getFlickr with your own JavaScripts you can use its main method leech():

getFlickr.leech(sTag, sCallback);

 
	sTag
	the tag you are looking for
	sCallback
	an optional function to call when the data was retrieved.
 

After you called the leech() method you have two strings to use:

 
	getFlickr.html[sTag]
	contains an HTML list (without the outer UL element) of all the images linked to the correct pages at flickr. The images are the medium size, you can easily change that by replacing _m.jpg with _s.jpg for thumbnails.
	getFlickr.tags[sTag]
	contains a string of all the other tags flickr users added with the tag you searched for(space separated)
 

You can call getFlickr.leech() several times when the page has loaded to cache several result feeds before the page gets loaded. This’ll make the photos quicker for the end user to show up. If you want to offer a form for people to search for flickr photos and display them immediately you can use the following HTML:

<form onsubmit="getFlickr.leech(document.getElementById('tag').value, 'populate');return false">
  <label for="tag">Enter Tag</label>
  <input type="text" id="tag" name="tag" />
  <input type="submit" value="energize" />
  <h3>Tags:</h3><div id="tags"></div>
  <h3>Photos:</h3><ul id="photos"></ul>
</form>

All the JavaScript you’ll need (for a basic display) is this:

function populate(){
  var tag = document.getElementById('tag').value;
  document.getElementById('photos').innerHTML = getFlickr.html[tag].replace(/_m\.jpg/g,'_s.jpg');
  document.getElementById('tags').innerHTML = getFlickr.tags[tag];
  return false;
}

Easy as pie, enjoy!

Check out the example page and try the form to see the results.


title: Styling hCards with CSS
year: 2006
author: John Allsopp
author_slug: johnallsopp
published: 2006-12-14T00:00:00+00:00
url: https://24ways.org/2006/styling-hcards-with-css/
topic: design
contents:
There are plenty of places online where you can learn about using the hCard microformat to mark up contact details at your site (there are some resources at the end of the article). But there’s not yet been a lot of focus on using microformats with CSS. So in this installment of 24 ways, we’re going to look at just that – how microformats help make CSS based styling simpler and more logical.

Being rich, quite complex structures, hCards provide designers with a sophisticated scaffolding for styling them. A recent example of styling hCards I saw, playing on the business card metaphor, was by Andy Hume, at http://thedredge.org/2005/06/using-hcards-in-your-blog/. While his approach uses fixed width cards, let’s take a look at how we might style a variable width business card style for our hCards.

Let’s take a common hCard, which includes address, telephone and email details

<div class="vcard">
	<p class="fn org">Web Directions North
		<a href="http://suda.co.uk/projects/X2V/get-vcard.php?uri=http://north.webdirections.org/contact/">
			<img src="images/vcard-add.png" alt="download vcard icon"></a>
	</p>

	
		 1485 Laperrière Avenue 
		 Ottawa  ON  K1Z 7S8 
		Canada
	

	
		Phone/Fax: Work: 61 2 9365 5007
		Email: info@webdirections.org
	


We’ll be using a variation on the now well established “sliding doors” technique (if you create a CSS technique, remember it’s very important to give it a memorable name or acronym, and bonus points if you get your name in there!) by Douglas Bowman, enhanced by Scott Schiller (see http://www.schillmania.com/projects/dialog/,) which will give us a design which looks like this



The technique, in a nutshell, uses background images on four elements, two at the top, and two at the bottom, to add each rounded corner.

We are going to make this design “fluid” in the sense that it grows and shrinks in proportion with the size of the font that the text of the element is displayed with. This is sometimes referred to as an “em driven design” (we’ll see why in a moment).

To see how this works in practice, here’s the same design with the text “zoomed” up in size



and the same design again, when we zoom the text size down



By the way, the hCard image comes from Chris Messina, and you can download it and other microformat icons from the microformats wiki.

Now, with CSS3, this whole task would be considerably easier, because we can add multiple background images to an element, and border images for each edge of an element. Safari, version 1.3 up, actually supports multiple background images, but sadly, it’s not supported in Firefox 1.5, or even Firefox 2.0 (let’s not mention IE7 eh?). So it’s probably too little supported to use now. So instead we’ll use a technique that only involves CSS2, and works in pretty much any browser.

Very often, developers add div or span elements as containers for these background images, and in fact, if you visit Scott Shiller’s site, that’s what he has done there. But if at all possible we shouldn’t be adding any HTML simply for presentational purposes, even if the presentation is done via CSS. What we can do is to use the HTML we have already, as much as is possible, to add the style we want. This can take some creative thinking, but once you get the hang of this approach it becomes a more natural way of using HTML compared with simply adding divs and spans at will as hooks for style. Of course, this technique isn’t always simple, and in fact sometimes simply not possible, requiring us to add just a little HTML to provide the “hooks” for CSS.

Let’s go to work

The first step is to add a background image to the whole vCard element.



We make this wide enough (for example 1000 or more pixels) and tall enough that no matter how large the content of the vCard grows, it will never overflow this area. We can’t simply repeat the image, because the top left corner will show when the image repeats.

We add this as the background image of the vCard element using CSS.

While we are at it, let’s give the text a sans-serif font, some color so that it will be visible, and stop the image repeating.

.vcard {
	background-image: url(images/vcardfill.png);
	background-repeat: no-repeat;
	color: #666;
	font-family: "Lucida Grande", Verdana, Helvetica, Arial, sans-serif;
}

Which in a browser, will look something like this.



Next step we need to add the top right hand corner of the hCard. In keeping with our aim of not adding HTML simply for styling purposes, we want to use the existing structure of the page where possible. Here, we’ll use the paragraph of class fn and org, which is the first child element of the vcard element.

<p class="fn org">Web Directions Conference Pty Ltd <img src="images/vcard-add.png" alt="download vcard icon"></p>

Here’s our CSS for this element

.fn {
	background-image: url(images/topright.png);
	background-repeat: no-repeat;
	background-position: top right;
	padding-top: 2em;
	font-weight: bold;
	font-size: 1.1em;
}

Again, we don’t want it to repeat, but this time, we’ve specified a background position for the image. This will make the background image start from the top, but its right edge will be located at the right edge of the element. I also made the font size a little bigger, and the weight bold, to differentiate it from the rest of the text in the hCard.

Here’s the image we are adding as the background to this element.



So, putting these two CSS statements together we get



We specified a padding-top of 2em to give some space between the content of the fn element and the edge of the fn element. Otherwise the top of the hCard image would be hard against the border. To see this in action, just remove the padding-top: 2em; declaration and preview in a browser.

So, with just two statements, we are well under way. We’ve not even had to add any HTML so far. Let’s turn to the bottom of the element, and add the bottom border (well, the background image which will serve as that border).

Now, which element are we going to use to add this background image to?

OK, here I have to admit to a little, teensie bit of cheating. If you look at the HTML of the hCard, I’ve grouped the email and telephone properties into a div, with a class of telecommunications. This grouping is not strictly requred for our hCard.

<div class="telecommunications">
	<p class="tel">Phone/Fax: <span class="tel"><span class="type">Work</span>:
		<span class="value">61 2 9365 5007</span></p>
	<p class="email">Email: <a class="value" href="mailto:info@webdirections.org">info@webdirections.org</a></p>
</div>

Now, I chose that class name because that is what the vCard specification calls this group of properties. And typically, I do tend to group together related elements using divs when I  mark up content. I find it makes the page structure more logical and readable. But strictly speaking, this isn’t necessary, so you may consider it cheating. But my lesson in this would be, if you are going to add markup, try to make it as meaningful as possible.

As you have probably guessed by now, we are going to add one part of the bottom border image to this element. We’re going to add this image as the background-image.



Again, it will be a very wide image, like the top left one, so that no matter how wide the element might get, the background image will still be wide enough. Now, we’ll need to make this image sit in the bottom left of the element we attach it to, so we use a backgound position of left bottom (we put the horizontal position before the vertical). Here’s our CSS statement for this

.telecommunications {
	background-image: url(images/bottom-left.png);
	background-repeat: no-repeat;
	background-position: left bottom;
	margin-bottom: 2em;
}

And that will look like this



Not quite there, but well on the way. Time for the final piece in the puzzle.

OK, I admit, I might have cheated just a little bit more in this step. But like the previous step, all valid, and (hopefully) quite justifiable markup. If we look at the HTML again, you’ll find that our email address is marked up like this

<p class="email">Email: <a class="value" href="mailto:info@webdirections.org">info@webdirections.org</a></p>

Typically, in hCard, the value part of this property isn’t required, and we could get away with

<a class="email" href="mailto:info@webdirections.org">info@webdirections.org</a>

The form I’ve used, with the span of class value is however, perfectly valid hCard markup (hard allows for multiple email addresses of different types, which is where this typically comes in handy). Why have I gone to all this trouble? Well, when it came to styling the hCard, I realized I needed a block element to attach the background image for the bottom right hand corner to. Typically the last block element in the containing element is the ideal choice (and sometimes it’s possible to take an inline element, for example the link here, and use CSS to make it a block element, and attach it to that, but that really doesn’t work with this design).

So, if we are going to use the paragraph which contains the email link, we need a way to select it exclusively, which means that with CSS2 at least, we need a class or id as a hook for our CSS selector (in CSS3 we could use the last-child selector, which selects the last child element of a specified element, but again, as last child is not widely supported, we won’t rely on it here.)

So, the least worst thing we could do is take an existing element, and add some reasonably meaningful markup to it. That’s why we gave the paragraph a class of email, and the email address a class of value. Which reminds me a little of a moment in Hamlet


	The lady doth protest too much, methinks


OK, let’s get back to the CSS.

We add the bottom right corner image, positioning it in the bottom right of the element, and making sure it doesn’t repeat. We also add some padding to the bottom, to balance out the padding we added to the top of the hCard.

p.email {
	background-image: url(images/bottom-right.png);
	background-position: right bottom;
	background-repeat: no-repeat;
	padding-bottom: 2em;
}

Which all goes to make our hCard look like this



It just remains for us to clean up a little.

Let’s start from the top. We’ll float the download image to the right like this

.vcard img {
	float: right;
	padding-right: 1em;
	margin-top: -1em
}

See how we didn’t have to add a class to style the image, we used the  fact that the image is a descendent of the vcard element, and a descendent selector. In my experience, the very widely supported, powerful descendent selector is one of the most underused aspects of CSS. So if you don’t use it frequently, look into it in more detail.

We added some space to the right of the image, and pulled it up a bit closer to the top of the hCard, like this



We also want to add some whitespace between the edge of the hCard and the text. We would typically add padding to the left of the containing element, (in this case the vcard element) but this would break our bottom left hand corner, like this



That’s because the div element we added this bottom left background image to would be moved in by the padding on its containing element.

So instead, we add left margin to all the paragraphs in the hCard

.vcard p {
	margin-left: 1em;
}

(there is the descendent selector again – it is the swiss army knife of CSS)

Now, we’ve not yet made the width of the hCard a function of the size of the text inside it (or “em driven” as we described it earlier). We do this by giving the hCard a width that is specified in em units. Here we’ll set a width of say 28em, which makes the hCard always roughly as wide as 28 characters (strictly speaking 28 times the width of the letter capital M). 

So the statement for our containing vcard element becomes

.vcard {
	background-image: url(images/vcardfill.png);
	background-repeat: no-repeat;
	color: #666;
	font-family: "Lucida Grande", Verdana, Helvetica, Arial, sans-serif;
	width: 28em;
}

and now our element will look like this



We’ve used almost entirely the existing HTML from our original hCard (adding just a little, and trying as much as possible to keep that additional markup meaningful), and just 6 CSS statements.

Holiday Bonus – a downloadable vCard

Did you notice this part of the HTML

<a href="http://suda.co.uk/projects/X2V/get-vcard.php?uri=http://north.webdirections.org/contact/">
        <img src="images/vcard-add.png" alt="download vcard icon"></a>

What’s with the odd looking url

<a href="http://suda.co.uk/projects/X2V/get-vcard.php?uri=http://north.webdirections.org/contact/"

If you click the link, X2V, a nifty web service from Brian Suda, grabs the page at the URL, and if it finds a hCard, converts it to a vCard, and depending on how your system is setup, automatically downloads it and adds it to your address book (Mac OS X) or prompts you whether you’d like to save the vCard and add it to whatever application is the default vCard handler on your system. 

What X2V does is take the actual HTML of your hCard, and with the magic of XSLT, converts it to a vCard. So, by simply marking up contact details using hCard, and adding a link like this, you automatically get downloadable vCard – and if you change your contact details, and update the hCard, there’s no vCard file to update as well.

Technorati also have a similar service at http://technorati.com/contact so you might want to use that if you expect any kind of load, as they can probably afford the bandwidth more than Brian!

If you want to play with the HTML and CSS for this design, the code and images can be downloaded.

Hope you enjoyed this, and found it useful. If so, you might like to check out my microformats focussed blog, or get along to Web Directions North, where I’ll be speaking along with Dan Cederholmn and Tantek Çelik in a 2 hour session focussed solely on microformats. And keep an eye out for my microformats book, from which this article has been adapted, coming in the spring of 2007.

A happy festive season, and all the best for 2007

John

Some hCard links


	The hCard entry at microformats.org
	The hCard Creator
	The hCard cheatsheet
	The hCard FAQ
	Ideas for authoring hCards



	Microfomatique – a blog about microformats
	Web Directions North – featuring a full 2 hour focussed microformats session


title: Compose to a Vertical Rhythm
year: 2006
author: Richard Rutter
author_slug: richardrutter
published: 2006-12-12T00:00:00+00:00
url: https://24ways.org/2006/compose-to-a-vertical-rhythm/
topic: design
contents:
“Space in typography is like time in music. It is infinitely divisible, but a few proportional intervals can be much more useful than a limitless choice of arbitrary quantities.” So says the typographer Robert Bringhurst, and just as regular use of time provides rhythm in music, so regular use of space provides rhythm in typography, and without rhythm the listener, or the reader, becomes disorientated and lost.

On the Web, vertical rhythm – the spacing and arrangement of text as the reader descends the page – is contributed to by three factors: font size, line height and margin or padding. All of these factors must calculated with care in order that the rhythm is maintained. 

The basic unit of vertical space is line height. Establishing a suitable line height that can be applied to all text on the page, be it heading, body copy or sidenote, is the key to a solid dependable vertical rhythm, which will engage and guide the reader down the page. To see this in action, I’ve created an example with headings, footnotes and sidenotes. 

Establishing a suitable line height

The easiest place to begin determining a basic line height unit is with the font size of the body copy. For the example I’ve chosen 12px. To ensure readability the body text will almost certainly need some leading, that is to say spacing between the lines. A line-height of 1.5em would give 6px spacing between the lines of body copy. This will create a total line height of 18px, which becomes our basic unit. Here’s the CSS to get us to this point:

body {
	font-size: 75%; 
}
html>body {
	font-size: 12px; 
}
p {
	line-height 1.5em; 
}

There are many ways to size text in CSS and the above approach provides and accessible method of achieving the pixel-precision solid typography requires. By way of explanation, the first font-size reduces the body text from the 16px default (common to most browsers and OS set-ups) down to the 12px we require. This rule is primarily there for Internet Explorer 6 and below on Windows: the percentage value means that the text will scale predictably should a user bump the text size up or down. The second font-size sets the text size specifically and is ignored by IE6, but used by Firefox, Safari, IE7, Opera and other modern browsers which allow users to resize text sized in pixels.

Spacing between paragraphs

With our rhythmic unit set at 18px we need to ensure that it is maintained throughout the body copy. A common place to lose the rhythm is the gaps set between margins. The default treatment by web browsers of paragraphs is to insert a top- and bottom-margin of 1em. In our case this would give a spacing between the paragraphs of 12px and hence throw the text out of rhythm. If the rhythm of the page is to be maintained, the spacing of paragraphs should be related to the basic line height unit. This is achieved simply by setting top- and bottom-margins equal to the line height.

In order that typographic integrity is maintained when text is resized by the user we must use ems for all our vertical measurements, including line-height, padding and margins.

p {
	font-size:1em;
	margin-top: 1.5em;
	margin-bottom: 1.5em; 
}

Browsers set margins on all block-level elements (such as headings, lists and blockquotes) so a way of ensuring that typographic attention is paid to all such elements is to reset the margins at the beginning of your style sheet. You could use a rule such as:

body,div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,pre,form,fieldset,p,blockquote,th,td {  
	margin:0; 
	padding:0; 
}

Alternatively you could look into using the Yahoo! UI Reset style sheet which removes most default styling, so providing a solid foundation upon which you can explicitly declare your design intentions.

Variations in text size

When there is a change in text size, perhaps with a heading or sidenotes, the differing text should also take up a multiple of the basic leading. This means that, in our example, every diversion from the basic text size should take up multiples of 18px. This can be accomplished by adjusting the line-height and margin accordingly, as described following.

Headings

Subheadings in the example page are set to 14px. In order that the height of each line is 18px, the line-height should be set to 18 ÷ 14 = 1.286. Similarly the margins above and below the heading must be adjusted to fit. The temptation is to set heading margins to a simple 1em, but in order to maintain the rhythm, the top and bottom margins should be set at 1.286em so that the spacing is equal to the full 18px unit.

h2 {
	font-size:1.1667em;
	line-height: 1.286em;
	margin-top: 1.286em;
	margin-bottom: 1.286em; 
}

One can also set asymmetrical margins for headings, provided the margins combine to be multiples of the basic line height. In our example, a top margin of 1½ lines is combined with a bottom margin of half a line as follows:

h2 {
	font-size:1.1667em;
	line-height: 1.286em;
	margin-top: 1.929em;
	margin-bottom: 0.643em; 
}

Also in our example, the main heading is given a text size of 18px, therefore the line-height has been set to 1em, as has the margin:

h1 {
	font-size:1.5em;
	line-height: 1em;
	margin-top: 0;
	margin-bottom: 1em; 
}

Sidenotes

Sidenotes (and other supplementary material) are often set at a smaller size to the basic text. To keep the rhythm, this smaller text should still line up with body copy, so a calculation similar to that for headings is required. In our example, the sidenotes are set at 10px and so their line-height must be increased to 18 ÷ 10 = 1.8.

.sidenote {
	font-size:0.8333em;
	line-height:1.8em; 
}

Borders

One additional point where vertical rhythm is often lost is with the introduction of horizontal borders. These effectively act as shims pushing the subsequent text downwards, so a two pixel horizontal border will throw out the vertical rhythm by two pixels. A way around this is to specify horizontal lines using background images or, as in our example, specify the width of the border in ems and adjust the padding to take up the slack. 

The design of the footnote in our example requires a 1px horizontal border. The footnote contains 12px text, so 1px in ems is 1 ÷ 12 = 0.0833. I have added a margin of 1½ lines above the border (1.5 × 18 ÷ 12 = 2.5ems), so to maintain the rhythm the border + padding must equal a ½ (9px). We know the border is set to 1px, so the padding must be set to 8px. To specify this in ems we use the familiar calculation: 8 ÷ 12 = 0.667.

Hit me with your rhythm stick

Composing to a vertical rhythm helps engage and guide the reader down the page, but it takes typographic discipline to do so. It may seem like a lot of fiddly maths is involved (a few divisions and multiplications never hurt anyone) but good type setting is all about numbers, and it is this attention to detail which is the key to success.


title: Revealing Relationships Can Be Good Form
year: 2006
author: Ian Lloyd
author_slug: ianlloyd
published: 2006-12-13T00:00:00+00:00
url: https://24ways.org/2006/revealing-relationships-can-be-good-form/
topic: ux
contents:
A few days ago, a colleague of mine – someone I have known for several years, who has been doing web design for several years and harks back from the early days of ZDNet – was running through a prototype I had put together for some user testing. As with a lot of prototypes, there was an element of ‘smoke and mirrors’ to make things look like they were working. 

One part of the form included a yes/no radio button, and selecting the Yes option would, in the real and final version of the form, reveal some extra content. Rather than put too much JavaScript in the prototype, I took a preverbial shortcut and created a link which I wrapped around the text next to the radio button – clicking on that link would cause the form to mimic a change event on the radio button. But it wasn’t working for him. 

Why was that? Because whereas I created the form using a <label> tag for each <input> and naturally went to click on the text rather than the form control itself, he was going straight for the control (and missing the sneaky little <a href> I’d placed around the text). Bah! There goes my time-saver.

So, what did I learn? That a web professional who has used the Internet for years had neither heard of the <label> tag, nor had he ever tried clicking on the text. It just goes to show that despite its obvious uses, the label element is not as well known as it rightfully deserves to be. So, what’s a web-standards-loving guy to do? Make a bit more bleedin’ obvious, that’s what! 

The Mouse Pointer Trick

OK, this is the kind of thing that causes some people outrage. A dead simple way of indicating that the label does something is to use a snippet of CSS to change the default mouse cursor to a hand. It’s derided because the hand icon is usually used for links, and some would argue that using this technique is misleading:

label {
	cursor: pointer;
}

This is not a new idea, though, and you didn’t come here for this. The point is that with something very simple, you’ve made the label element discoverable. But there are other ways that you can do this that are web standards friendly and won’t upset the purists quite so much as the hand/pointer trick. Time to wheel in the JavaScript trolley jack …

Our Old Friend AddEvent

First things, first, you’ll need to use the addEvent function (or your favourite variation thereof) that Scott Andrew devised and make that available to the document containing the form:

function addEvent(elm, evType, fn, useCapture)
{
	if(elm.addEventListener)
	{
		elm.addEventListener(evType, fn, useCapture);
		return true;
	}
	else if (elm.attachEvent)
	{
		var r = elm.attachEvent('on' + evType, fn);
		return r;
	}
	else
	{
		elm['on' + evType] = fn;
	}
}

Finding All Your Labels

Once you’ve linked to the addEvent function (or embedded it on the page), you can start to get your JavaScripting fingers a-flexing. Now, what I’m suggesting you do here is:


	Identify all the label elements on the page by working your way through the DOM
	Find out the value of the for attribute for each label that you uncover
	Attach a behaviour or two to each of those label elements – and to the input that the label relates to (identified with the for attribute)


Here’s the technobabble version of the steps above:

function findLabels()
{
	var el = document.getElementsByTagName("label");
	for (i=0;i<el.length;i++)
	{
		var thisId = el[i].getAttribute("for");
		if ((thisId)==null)
		{
			thisId = el[i].htmlFor;
		}
		if(thisId!="")
		{
			//apply these behaviours to the label
			el[i].onmouseover = highlightRelationship;
			el[i].onmouseout = hideRelationship;
		}
	}
}
function highlightRelationship()
{
	var thisId = this.getAttribute("for");
	if ((thisId)==null)
	{
		thisId = this.htmlFor;
	}	
	this.className="showRel";
	document.getElementById(thisId).className="showRel";
	//if (document.getElementById(thisId).type=="text") document.getElementById(thisId).select();
}
function hideRelationship()
{
	var thisId = this.getAttribute("for");
	if ((thisId)==null)
	{
		thisId = this.htmlFor;
	}	
	this.className="";
	document.getElementById(thisId).className="";
}
addEvent(window, 'load', findLabels, false);

Using the above script, you can apply a CSS class (I’ve called it showRel) to the elements when you hover over them. How you want it to look is up to you, of course. Here are a few examples of the idea. Note: the design is not exactly what you’d call ‘fancy’, and in the examples there is one input that looks broken but it is deliberately moved away from the label it relates to, just to demonstrate that you can show the relationship even from afar. 



	Background colour changes on hover
	Background colour change + mouse pointer trick
	Background colour change + mouse pointer trick + text selection


Hopefully you’ll agree that using an unobtrusive piece of JavaScript you can make otherwise ‘shy’ elements like the label reveal their true colours. Although you might want to tone down the colours from the ones I’ve used in this demo!


title: Marking Up a Tag Cloud
year: 2006
author: Mark Norman Francis
author_slug: marknormanfrancis
published: 2006-12-09T00:00:00+00:00
url: https://24ways.org/2006/marking-up-a-tag-cloud/
topic: code
contents:
Everyone’s doing it. 

The problem is, everyone’s doing it wrong. 

Harsh words, you might think. But the crimes against decent markup are legion in this area. You see, I’m something of a markup and semantics junkie. So I’m going to analyse some of the more well-known tag clouds on the internet, explain what’s wrong, and then show you one way to do it better. 

del.icio.us 

I think the first ever tag cloud I saw was on del.icio.us. Here’s how they mark it up. 

<div class="alphacloud">
	<a href="/tag/.net" class="lb s2">.net</a>
	<a href="/tag/advertising" class=" s3">advertising</a>
	<a href="/tag/ajax" class=" s5">ajax</a>
	...
</div>

Unfortunately, that is one of the worst examples of tag cloud markup I have ever seen. The page states that a tag cloud is a list of tags where size reflects popularity. However, despite describing it in this way to the human readers, the page’s author hasn’t described it that way in the markup. It isn’t a list of tags, just a bunch of anchors in a <div>. This is also inaccessible because a screenreader will not pause between adjacent links, and in some configurations will not announce the individual links, but rather all of the tags will be read as just one link containing a whole bunch of words. Markup crime number one. 

Flickr 

Ah, Flickr. The darling photo sharing site of the internet, and the biggest blind spot in every standardista’s vision. Forgive it for having atrocious markup and sometimes confusing UI because it’s just so much damn fun to use. Let’s see what they do. 

<p id="TagCloud">
	 <a href="/photos/tags/06/" style="font-size: 14px;">06</a> 
	 <a href="/photos/tags/africa/" style="font-size: 12px;">africa</a> 
	 <a href="/photos/tags/amsterdam/" style="font-size: 14px;">amsterdam</a> 
	...
</p>

Again we have a simple collection of anchors like del.icio.us, only this time in a paragraph. But rather than using a class to represent the size of the tag they use an inline style. An inline style using a pixel-based font size. That’s so far away from the goal of separating style from content, they might as well use a <font> tag. You could theoretically parse that to extract the information, but you have more work to guess what the pixel sizes represent. Markup crime number two (and extra jail time for using non-breaking spaces purely for visual spacing purposes.)

Technorati 

Ah, now. Here, you’d expect something decent. After all, the Overlord of microformats and King of Semantics Tantek Çelik works there. Surely we’ll see something decent here? 

<ol class="heatmap">
	<li><em><em><em><em><a href="/tag/Britney+Spears">Britney Spears</a></em></em></em></em></li>
	<li><em><em><em><em><em><em><em><em><em><a href="/tag/Bush">Bush</a></em></em></em></em></em></em></em></em></em></li>
	<li><em><em><em><em><em><em><em><em><em><em><em><em><em><a href="/tag/Christmas">Christmas</a></em></em></em></em></em></em></em></em></em></em></em></em></em></li>
	...
	<li><em><em><em><em><em><em><a href="/tag/SEO">SEO</a></em></em></em></em></em></em></li>
	<li><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><a href="/tag/Shopping">Shopping</a></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></li>
	...
</ol>

Unfortunately it turns out not to be that decent, and stop calling me Shirley. It’s not exactly terrible code. It does recognise that a tag cloud is a list of links. And, since they’re in alphabetical order, that it’s an ordered list of links. That’s nice. However … fifteen nested <em> tags? FIFTEEN? That’s emphasis for you. Yes, it is parse-able, but it’s also something of a strange way of looking at emphasis. The HTML spec states that <em> is emphasis, and <strong> is for stronger emphasis. Nesting <em> tags seems counter to the idea that different tags are used for different levels of emphasis. Plus, if you had a screen reader that stressed the voice for emphasis, what would it do? Shout at you? Markup crime number three. 

So what should it be? 

As del.icio.us tells us, a tag cloud is a list of tags where the size that they are rendered at contains extra information. However, by hiding the extra context purely within the CSS or the HTML tags used, you are denying that context to some users. The basic assumption being made is that all users will be able to see the difference between font sizes, and this is demonstrably false. 

A better way to code a tag cloud is to put the context of the cloud within the content, not the markup or CSS alone. As an example, I’m going to take some of my favourite flickr tags and put them into a cloud which communicates the relative frequency of each tag. 

To start with a tag cloud in its most basic form is just a list of links. I am going to present them in alphabetical order, so I’ll use an ordered list. Into each list item I add the number of photos I have with that particular tag. The tag itself is linked to the page on flickr which contains those photos. So we end up with this first example. To display this as a traditional tag cloud, we need to alter it in a few ways: 


	The items need to be displayed next to each other, rather than one-per-line
	The context information should be hidden from display (but not from screen readers)
	The tag should link to the page of items with that tag


Displaying the items next to each other simply means setting the display of the list elements to inline. The context can be hidden by wrapping it in a <span> and then using the off-left method to hide it. And the link just means adding an anchor (with rel="tag" for some extra microformats bonus points). So, now we have a simple collection of links in our second example. 

The last stage is to add the sizes. Since we already have context in our content, the size is purely for visual rendering, so we can just use classes to define the different sizes. For my example, I’ll use a range of class names from not-popular through ultra-popular, in order of smallest to largest, and then use CSS to define different font sizes. If you preferred, you could always use less verbose class names such as  size1 through size6. Anyway, adding some classes and CSS gives us our final example, a semantic and more accessible tag cloud.


title: The Mobile Web, Simplified
year: 2006
author: Cameron Moll
author_slug: cameronmoll
published: 2006-12-19T00:00:00+00:00
url: https://24ways.org/2006/the-mobile-web-simplified/
topic: ux
contents:
A note from the editors:  although eye-opening in 2006, this article is no longer relevant to today’s mobile web.
                
                
                      
                Considering a foray into mobile web development? Following are four things you need to know before making the leap.

1. 4 billion mobile subscribers expected by 2010

Fancy that. Coupled with the UN prediction of 6.8 billion humans by 2010, 4 billion mobile subscribers (source) is an astounding 59% of the planet. Just how many of those subscribers will have data plans and web-enabled phones is still in question, but inevitably this all means one thing for you and me: A ton of potential eyes to view our web content on a mobile device.

2. Context is king

Your content is of little value to users if it ignores the context in which it is viewed. Consider how you access data on your mobile device.  You might be holding a bottle of water or gripping a handle on the subway/tube. You’re probably seeking specific data such as directions or show times, rather than the plethora of data at your disposal via a desktop PC.

The mobile web, a phrase often used to indicate “accessing the web on a mobile device”,  is very much a context-, content-, and component-specific environment. Expressed in terms of your potential target audience, access to web content on a mobile device is largely influenced by surrounding circumstances and conditions, information relevant to being mobile, and the feature set of the device being used. Ask yourself, What is relevant to my users and the tasks, problems, and needs they may encounter while being mobile? Answer that question and you’ll be off to a great start.

3. WAP 2.0 is an XHTML environment

In a nutshell, here are a few fundamental tenets of mobile internet technology:


	Wireless Application Protocol (WAP) is the protocol for enabling mobile access to internet content.
	Wireless Markup Language (WML) was the language of choice for WAP 1.0.
	Nearly all devices sold today are WAP 2.0 devices.
	With the introduction of WAP 2.0, XHTML Mobile Profile (XHTML-MP) became the preferred markup language.
	XHTML-MP will be familiar to anyone experienced with XHTML Transitional or Strict.


Summary? The mobile web is rapidly becoming an XHTML environment, and thus you and I can apply our existing “desktop web” skills to understand how to develop content for it. With WML on the decline, the learning curve is much smaller today than it was several years ago. I’m generalizing things gratuitously, but the point remains: Get off yo’ lazy butt and begin to take mobile seriously.

I’ll even pass you a few tips for getting started. First, the DOCTYPE for XHTML-MP is as follows:

<!DOCTYPE html PUBLIC "-//WAPFORUM//DTD XHTML Mobile 1.0//EN"
"http://www.openmobilealliance.org/tech/DTD/xhtml-mobile10.dtd">

As for MIME type, Open Mobile Alliance (OMA) specifies using the MIME type application/vnd.wap.xhtml+xml, but ultimately you need to ensure the server delivering your mobile content is configured properly for the MIME type you choose to use, as there are other options (see Setting up WAP Servers).

Once you’ve made it to the body, the XHTML-MP markup is not unlike what you’re already used to. A few resources worth skimming:


	Developers Home XHTML-MP Tutorial – An impressively replete resource for all things XHTML-MP
	XHTML-MP Tags List – A complete list of XHTML-MP elements and accompanying attributes


And last but certainly not least, CSS. There exists WAP CSS, which is essentially a subset of CSS2 with WAP-specific extensions. For all intents and purposes, much of the CSS you’re already comfortable using will be transferrable to mobile. As for including CSS in your pages, your options are the same as for desktop sites: external, embedded, and inline. Some experts will argue embedded or inline over external in favor of reducing the number of HTTP connections per page request, yet many popular mobilized sites and apps employ external linking without issue.

Stocking stuffers: Flickr Mobile, Fandango Mobile, and Popurls Mobile. A few sites with whom you can do the View Source song and dance for further study.

4. “Cell phone” is so DynaTAC

If you’re a U.S. resident, listen up: You must rid your vocabulary of the term “cell phone”. We’re one of the few economies on the planet to refer to a mobile phone accordingly. If you care to find yourself in any of the worthwhile mobile development circles, begin using terms more widely accepted: “mobile” or “mobile phone” or “handset” or “handy”. If you’re not sure which, go for “mobile”. Such as, “Yo dog, check out my new mobile.”

More importantly, however, is overcoming the mentality that access to the mobile web can be done only with a phone. Instead, “device” encourages us to think phone, handheld computer, watch, Nintendo DS, car, you name it.

Simple enough?


title: The Neverending (Background Image) Story
year: 2007
author: Elliot Jay Stocks
author_slug: elliotjaystocks
published: 2007-12-03T00:00:00+00:00
url: https://24ways.org/2007/the-neverending-background-image-story/
topic: code
contents:
Everyone likes candy for Christmas, and there’s none better than eye candy. Well, that, and just more of the stuff. Today we’re going to combine both of those good points and look at how to create a beautiful background image that goes on and on… forever!

Of course, each background image is different, so instead of agonising over each and every pixel, I’m going to concentrate on five key steps that you can apply to any of your own repeating background images. In this example, we’ll look at the Miami Beach background image used on the new FOWA site, which I’m afraid is about as un-festive as you can get.

1. Choose your image wisely

I find there are three main criteria when judging photos you’re considering for repetition manipulation (or ‘repetulation’, as I like to say)…


	simplicity (beware of complex patterns)
	angle and perspective (watch out for shadows and obvious vanishing points)
	consistent elements (for easy cloning)


You might want to check out this annotated version of the image, where I’ve highlighted elements of the photo that led me to choose it as the right one.

The original image purchased from iStockPhoto.

The Photoshopped version used on the FOWA site.

2. The power of horizontal lines

With the image chosen and your cursor poised for some Photoshop magic, the most useful thing you can do is drag out the edge pixels from one side of the image to create a kind of rough colour ‘template’ on which to work over. It doesn’t matter which side you choose, although you might find it beneficial to use the one with the simplest spread of colour and complex elements.

Click and hold on the marquee tool in the toolbar and select the ‘single column marquee tool’, which will span the full height of your document but will only be one pixel wide. Make the selection right at the edge of your document, press ctrl-c / cmd-c to copy the selection you made, create a new layer, and hit ctrl-v / cmd-v to paste the selection onto your new layer. using free transform (ctrl-t / cmd-t), drag out your selection so that it becomes as wide as your entire canvas. 

A one-pixel-wide selection stretched out to the entire width of the canvas.

3. Cloning

It goes without saying that the trusty clone tool is one of the most important in the process of creating a seamlessly repeating background image, but I think it’s important to be fairly loose with it. Always clone on to a new layer so that you’ve got the freedom to move it around, but above all else, use the eraser tool to tweak your cloned areas: let that handle the precision stuff and you won’t have to worry about getting your clones right first time.

In the example below, you can see how I overcame the problem of the far-left tree shadow being chopped off by cloning the shadow from the tree on its right. 

The edge of the shadow is cut off and needs to be ‘made’ from a pre-existing element.

The successful clone completes the missing shadow.

The two elements are obviously very similar but it doesn’t look like a clone because the majority of the shape is ‘genuine’ and only a small part is a duplicate. Also, after cloning I transformed the duplicate, erased parts of it, used gradients, and — ooh, did someone mention gradients?

4. Never underestimate a gradient

For this image, I used gradients in a similar way to a brush: covering large parts of the canvas with a colour that faded out to a desired point, before erasing certain parts for accuracy.

Several of the gradients and brushes that make up the ‘customised’ part of the image, visible when the main photograph layer is hidden.

The full composite.

Gradients are also a bit of an easy fix: you can use a gradient on one side of the image, flip it horizontally, and then use it again on the opposite side to make a more seamless join.

Speaking of which…

5. Sewing the seams

No matter what kind of magic Photoshop dust you sprinkle over your image, there will still always be the area where the two edges meet: that scary ‘loop’ point. Fret ye not, however, for there’s help at hand in the form of a nice little cheat. Even though the loop point might still be apparent, we can help hide it by doing something to throw viewers off the scent.

The seam is usually easy to spot because it’s a blank area with not much detail or colour variation, so in order to disguise it, go against the rule: put something across it!

This isn’t quite as challenging as it may sound, because if we intentionally make our own ‘object’ to span the join, we can accurately measure the exact halfway point where we need to split it across the two sides of the image. This is exactly what I did with the FOWA background image: I made some clouds!

A sky with no clouds in an unhappy one.

A simple soft white brush creates a cloud-like formation in the sky.

After taking the cloud’s opacity down to 20%, I used free transform to highlight the boundaries of the layer. I then moved it over to the right, so that the middle of the layer perfectly aligned with the right side of the canvas.

Finally, I duplicated the layer and did the same in reverse: dragging the layer over to the left and making sure that the middle of the duplicate layer perfectly aligned with the left side of the canvas.

And there you have it! Boom! Ta-da! Et Voila! To see the repeating background image in action, visit futureofwebapps.com on a large widescreen monitor or see a simulation of the effect.

Thanks for reading, folks. Have a great Christmas!


title: Increase Your Font Stacks With Font Matrix
year: 2007
author: Richard Rutter
author_slug: richardrutter
published: 2007-12-17T00:00:00+00:00
url: https://24ways.org/2007/increase-your-font-stacks-with-font-matrix/
topic: design
contents:
Web pages built in plain old HTML and CSS are displayed using only the fonts installed on users’ computers (@font-face implementations excepted). To enable this, CSS provides the font-family property for specifying fonts in order of preference (often known as a font stack). For example:

h1 {font-family: 'Egyptienne F', Cambria, Georgia, serif}

So in the above rule, headings will be displayed in Egyptienne F. If Egyptienne F is not available then Cambria will be used, failing that Georgia or the final fallback default serif font. This everyday bit of CSS will be common knowledge among all 24 ways readers.

It is also a commonly held belief that the only fonts we can rely on being installed on users’ computers are the core web fonts of Arial, Times New Roman, Verdana, Georgia and friends. But is that really true?

If you look in the fonts folder of your computer, or even your Mum’s computer, then you are likely to find a whole load of fonts besides the core ones. This is because many software packages automatically install extra typefaces. For example, Office 2003 installs over 100 additional fonts. Admittedly not all of these fonts are particularly refined, and not all are suitable for the Web. However they still do increase your options. 

The Matrix

I have put together a matrix of (western) fonts showing which are installed with Mac and Windows operating systems, which are installed with various versions of Microsoft Office, and which are installed with Adobe Creative Suite.



The matrix is available for download as an Excel file and as a CSV.  There are no readily available statistics regarding the penetration of Office or Creative Suite, but you can probably take an educated guess based on your knowledge of your readers.

The idea of the matrix is that use can use it to help construct your font stack. First of all pick the font you’d really like for your text – this doesn’t have to be in the matrix. Then pick the generic family (serif, sans-serif, cursive, fantasy or monospace) and a font from each of the operating systems. Then pick any suitable fonts from the Office and Creative Suite lists.

For example, you may decide your headings should be in the increasingly ubiquitous Clarendon. This is a serif type face. At OS-level the most similar is arguably Georgia. Adobe CS2 comes with Century Old Style which has a similar feel. Century Schoolbook is similar too, and is installed with all versions of Office. Based on this your font stack becomes:

font-family: 'Clarendon Std', 'Century Old Style Std', 'Century Schoolbook', Georgia, serif






Note the ‘Std’ suffix indicating a ‘standard’ OpenType file, which will normally be your best bet for more esoteric fonts.

I’m not suggesting the process of choosing suitable fonts is an easy one. Firstly there are nearly two hundred fonts in the matrix, so learning what each font looks like is tricky and potentially time consuming (if you haven’t got all the fonts installed on a machine to hand you’ll be doing a lot of Googling for previews). And it’s not just as simple as choosing fonts that look similar or have related typographic backgrounds, they need to have similar metrics as well, This is especially true in terms of x-height which gives an indication of how big or small a font looks.

Over to You

The main point of all this is that there are potentially more fonts to consider than is generally accepted, so branch out a little (carefully and tastefully) and bring a little variety to sites out there. If you come up with any novel font stacks based on this approach, please do blog them (tagged as per the footer) and at some point they could all be combined in one place for everyone to consider.

Appendix

What about Linux?

The only operating systems in the matrix are those from Microsoft and Apple. For completeness, Linux operating systems should be included too, although these are many and varied and very much in a minority, so I omitted them for time being. For the record, some Linux distributions come packaged with Microsoft’s core fonts. Others use the Vera family, and others use the Liberation family which comprises fonts metrically identical to Times New Roman and Arial.

Sources

The sources of font information for the matrix are as follows:


	Windows XP SP2
	Windows Vista
	Office 2003
	Office 2007
	Mac OSX Tiger
	Mac OSX Leopard (scroll down two thirds)
	Office 2004 (Mac) by inspecting my Microsoft Office 2004/Office/Fonts folder
	Office 2008 (Mac) is expected to be as Office 2004 with the addition of the Vista ClearType fonts
	Creative Suite 2 (see pdf link in first comment)
	Creative Suite 3


title: Christmas Is In The AIR
year: 2007
author: Jonathan Snook
author_slug: jonathansnook
published: 2007-12-19T00:00:00+00:00
url: https://24ways.org/2007/christmas-is-in-the-air/
topic: code
contents:
That’s right, Christmas is coming up fast and there’s plenty of things to do. Get the tree and lights up, get the turkey, buy presents and who know what else. And what about Santa? He’s got a list. I’m pretty sure he’s checking it twice.

Sure, we could use an existing list making web site or even a desktop widget. But we’re geeks! What’s the fun in that? Let’s build our own to-do list application and do it with Adobe AIR!

What’s Adobe AIR?

Adobe AIR, formerly codenamed Apollo, is a runtime environment that runs on both Windows and OSX (with Linux support to follow). This runtime environment lets you build desktop applications using Adobe technologies like Flash and Flex. Oh, and HTML. That’s right, you web standards lovin’ maniac. You can build desktop applications that can run cross-platform using the trio of technologies, HTML, CSS and JavaScript.

If you’ve tried developing with AIR before, you’ll need to get re-familiarized with the latest beta release as many things have changed since the last one (such as the API and restrictions within the sandbox.)

To get started

To get started in building an AIR application, you’ll need two basic things:


	The AIR runtime. The runtime is needed to run any AIR-based application.
	The SDK. The software development kit gives you all the pieces to test your application. Unzip the SDK into any folder you wish.


You’ll also want to get your hands on the JavaScript API documentation which you’ll no doubt find yourself getting into before too long. (You can download it, too.)

Also of interest, some development environments have support for AIR built right in. Aptana doesn’t have support for beta 3 yet but I suspect it’ll be available shortly.

Within the SDK, there are two main tools that we’ll use: one to test the application (ADL) and another to build a distributable package of our application (ADT). I’ll get into this some more when we get to that stage of development.

Building our To-do list application

The first step to building an application within AIR is to create an XML file that defines our default application settings. I call mine application.xml, mostly because Aptana does that by default when creating a new AIR project. It makes sense though and I’ve stuck with it. Included in the templates folder of the SDK is an example XML file that you can use.

The first key part to this after specifying things like the application ID, version, and filename, is to specify what the default content should be within the content tags. Enter in the name of the HTML file you wish to load. Within this HTML file will be our application.

<content>ui.html</content>

Create a new HTML document and name it ui.html and place it in the same directory as the application.xml file. The first thing you’ll want to do is copy over the AIRAliases.js file from the frameworks folder of the SDK and add a link to it within your HTML document.

<script type="text/javascript" src="AIRAliases.js"></script>

The aliases create shorthand links to all of the Flash-based APIs.

Now is probably a good time to explain how to debug your application.

Debugging our application

So, with our XML file created and HTML file started, let’s try testing our ‘application’. We’ll need the ADL application located in BIN folder of the SDK and tell it to run the application.xml file.

/path/to/adl /path/to/application.xml

You can also just drag the XML file onto ADL and it’ll accomplish the same thing. If you just did that and noticed that your blank application didn’t load, you’d be correct. It’s running but isn’t visible. Which at this point means you’ll have to shut down the ADL process. Sorry about that!

Changing the visibility

You have two ways to make your application visible. You can do it automatically by setting the placing true in the visible tag within the application.xml file.

<visible>true</visible>

The other way is to do it programmatically from within your application. You’d want to do it this way if you had other startup tasks to perform before showing the interface. To turn the UI on programmatically, simple set the visible property of nativeWindow to true.

<script type="text/javascript">
	nativeWindow.visible = true;
</script>

Sandbox Security

Now that we have an application that we can see when we start it, it’s time to build the to-do list application. In doing so, you’d probably think that using a JavaScript library is a really good idea — and it can be but there are some limitations within AIR that have to be considered.

An HTML document, by default, runs within the application sandbox. You have full access to the AIR APIs but once the onload event of the window has fired, you’ll have a limited ability to make use of eval and other dynamic script injection approaches. This limits the ability of external sources from gaining access to everything the AIR API offers, such as database and local file system access. You’ll still be able to make use of eval for evaluating JSON responses, which is probably the most important if you wish to consume JSON-based services.

If you wish to create a greater wall of security between AIR and your HTML document loading in external resources, you can create a child sandbox. We won’t need to worry about it for our application so I won’t go any further into it but definitely keep this in mind.

Finally, our application

Getting tired of all this preamble? Let’s actually build our to-do list application. I’ll use jQuery because it’s small and should suit our needs nicely. Let’s begin with some structure:

<body>
	<input type="text" id="text" value="">
	<input type="button" id="add" value="Add">
	<ul id="list"></ul>
</body>

Now we need to wire up that button to actually add a new item to our to-do list.

<script type="text/javascript">
$(document).ready(function(){
	// make sure the application is visible
	nativeWindow.visible = true;
	$('#add').click(function(){
		var t = $('#text').val();
		if(t)
		{
			// use DOM methods to create the new list item
			var li = document.createElement('li');
			// the extra space at the end creates a buffer between the text
			// and the delete link we're about to add
			li.appendChild(document.createTextNode(t + ' '));
			// create the delete link
			var del = document.createElement('a');
			// this makes it a true link. I feel dirty doing this.
			del.setAttribute('href', '#');
			del.addEventListener('click', function(evt){
				this.parentNode.parentNode.removeChild(this.parentNode);
			});
			del.appendChild(document.createTextNode('[del]'));
			li.appendChild(del);
			// append everything to the list
			$('#list').append(li);
			//reset the text box
			$('#text').val('');
		}
	})
});
</script>

And just like that, we’ve got a to-do list! That’s it! Just never close your application and you’ll remember everything. Okay, that’s not very practical. You need to have some way of storing your to-do items until the next time you open up the application.

Storing Data

You’ve essentially got 4 different ways that you can store data:


	Using the local database. AIR comes with SQLLite built in. That means you can create tables and insert, update and select data from that database just like on a web server.
	Using the file system. You can also create files on the local machine. You have access to a few folders on the local system such as the documents folder and the desktop.
	Using EcryptedLocalStore. I like using the EcryptedLocalStore because it allows you to easily save key/value pairs and have that information encrypted. All this within just a couple lines of code.
	Sending the data to a remote API. Our to-do list could sync up with Remember the Milk, for example.


To demonstrate some persistence, we’ll use the file system to store our files. In addition, we’ll let the user specify where the file should be saved. This way, we can create multiple to-do lists, keeping them separate and organized.

The application is now broken down into 4 basic tasks:


	Load data from the file system.
	Perform any interface bindings.
	Manage creating and deleting items from the list.
	Save any changes to the list back to the file system.


Loading in data from the file system

When the application starts up, we’ll prompt the user to select a file or specify a new to-do list. Within AIR, there are 3 main file objects: File, FileMode, and FileStream. File handles file and path names, FileMode is used as a parameter for the FileStream to specify whether the file should be read-only or for write access. The FileStream object handles all the read/write activity.

The File object has a number of shortcuts to default paths like the documents folder, the desktop, or even the application store. In this case, we’ll specify the documents folder as the default location and then use the browseForSave method to prompt the user to specify a new or existing file. If the user specifies an existing file, they’ll be asked whether they want to overwrite it.

var store = air.File.documentsDirectory;
var fileStream = new air.FileStream();
store.browseForSave("Choose To-do List");

Then we add an event listener for when the user has selected a file. When the file is selected, we check to see if the file exists and if it does, read in the contents, splitting the file on new lines and creating our list items within the interface.

store.addEventListener(air.Event.SELECT, fileSelected);
function fileSelected()
{
	air.trace(store.nativePath);
	// load in any stored data
	var byteData = new air.ByteArray();
	if(store.exists)
	{
		fileStream.open(store, air.FileMode.READ);
		fileStream.readBytes(byteData, 0, store.size);
		fileStream.close();

		if(byteData.length > 0)
		{
			var s = byteData.readUTFBytes(byteData.length);
			oldlist = s.split(“\r\n”);

			// create todolist items
			for(var i=0; i < oldlist.length; i++)
			{
				createItem(oldlist[i], (new Date()).getTime() + i );
			}
		}
	}
}

Perform Interface Bindings

This is similar to before where we set the click event on the Add button but we’ve moved the code to save the list into a separate function.

$('#add').click(function(){
		var t = $('#text').val();
		if(t){
			// create an ID using the time
			createItem(t, (new Date()).getTime() );
		}
})

Manage creating and deleting items from the list

The list management is now in its own function, similar to before but with some extra information to identify list items and with calls to save our list after each change.

function createItem(t, id)
{
	if(t.length == 0) return;
	// add it to the todo list
	todolist[id] = t;
	// use DOM methods to create the new list item
	var li = document.createElement('li');
	// the extra space at the end creates a buffer between the text
	// and the delete link we're about to add
	li.appendChild(document.createTextNode(t + ' '));
	// create the delete link
	var del = document.createElement('a');
	// this makes it a true link. I feel dirty doing this.
	del.setAttribute('href', '#');
	del.addEventListener('click', function(evt){
		var id = this.id.substr(1);
		delete todolist[id]; // remove the item from the list
		this.parentNode.parentNode.removeChild(this.parentNode);
		saveList();
	});
	del.appendChild(document.createTextNode('[del]'));
	del.id = 'd' + id;
	li.appendChild(del);
	// append everything to the list
	$('#list').append(li);
	//reset the text box
	$('#text').val('');
	saveList();
}

Save changes to the file system

Any time a change is made to the list, we update the file. The file will always reflect the current state of the list and we’ll never have to click a save button. It just iterates through the list, adding a new line to each one.

function saveList(){
	if(store.isDirectory) return;
	var packet = '';
	for(var i in todolist)
	{
		packet += todolist[i] + '\r\n';
	}
	var bytes = new air.ByteArray();
	bytes.writeUTFBytes(packet);
	fileStream.open(store, air.FileMode.WRITE);
	fileStream.writeBytes(bytes, 0, bytes.length);
	fileStream.close();
}

One important thing to mention here is that we check if the store is a directory first. The reason we do this goes back to our browseForSave call. If the user cancels the dialog without selecting a file first, then the store points to the documentsDirectory that we set it to initially. Since we haven’t specified a file, there’s no place to save the list.

Hopefully by this point, you’ve been thinking of some cool ways to pimp out your list. Now we need to package this up so that we can let other people use it, too.

Creating a Package

Now that we’ve created our application, we need to package it up so that we can distribute it. This is a two step process. The first step is to create a code signing certificate (or you can pay for one from Thawte which will help authenticate you as an AIR application developer).

To create a self-signed certificate, run the following command. This will create a PFX file that you’ll use to sign your application.

adt -certificate -cn todo24ways 1024-RSA todo24ways.pfx mypassword

After you’ve done that, you’ll need to create the package with the certificate

adt -package -storetype pkcs12 -keystore todo24ways.pfx todo24ways.air application.xml .

The important part to mention here is the period at the end of the command. We’re telling it to package up all files in the current directory.

After that, just run the AIR file, which will install your application and run it.

Important things to remember about AIR

When developing an HTML application, the rendering engine is Webkit. You’ll thank your lucky stars that you aren’t struggling with cross-browser issues. (My personal favourites are multiple backgrounds and border radius!)

Be mindful of memory leaks. Things like Ajax calls and event binding can cause applications to slowly leak memory over time. Web pages are normally short lived but desktop applications are often open for hours, if not days, and you may find your little desktop application taking up more memory than anything else on your machine!

The WebKit runtime itself can also be a memory hog, usually taking about 15MB just for itself. If you create multiple HTML windows, it’ll add another 15MB to your memory footprint. Our little to-do list application shouldn’t be much of a concern, though.

The other important thing to remember is that you’re still essentially running within a Flash environment. While you probably won’t notice this working in small applications, the moment you need to move to multiple windows or need to accomplish stuff beyond what HTML and JavaScript can give you, the need to understand some of the Flash-based elements will become more important.

Lastly, the other thing to remember is that HTML links will load within the AIR application. If you want a link to open in the users web browser, you’ll need to capture that event and handle it on your own. The following code takes the HREF from a clicked link and opens it in the default web browser.

air.navigateToURL(new air.URLRequest(this.href));

Only the beginning

Of course, this is only the beginning of what you can do with Adobe AIR. You don’t have the same level of control as building a native desktop application, such as being able to launch other applications, but you do have more control than what you could have within a web application. Check out the Adobe AIR Developer Center for HTML and Ajax for tutorials and other resources.

Now, go forth and create your desktop applications and hopefully you finish all your shopping before Christmas!

Download the example files.


title: Typesetting Tables
year: 2007
author: Mark Boulton
author_slug: markboulton
published: 2007-12-07T00:00:00+00:00
url: https://24ways.org/2007/typesetting-tables/
topic: design
contents:
Tables have suffered in recent years on the web. They were used for laying out web pages. Then, following the Web Standards movement, they’ve been renamed by the populous as `data tables’ to ensure that we all know what they’re for. There have been some great tutorials for the designing tables using CSS for presentation and focussing on the semantics in the displaying of data in the correct way. However, typesetting tables is a subtle craft that has hardly had a mention.

Table design can often end up being a technical exercise. What data do we need to display? Where is the data coming from and what form will it take? When was the last time your heard someone talk about lining numerals? Or designing to the reading direction?

Tables are not read like sentences

When a reader looks at, and tries to understand, tabular data, they’re doing a bunch of things at the same time.


	Generally, they’re task based; they’re looking for something.
	They are reading horizontally AND vertically


Reading a table is not like reading a paragraph in a novel, and therefore shouldn’t be typeset in the same way. Designing tables is information design, it’s functional typography—it’s not a time for eye candy.

Typesetting tables

Typesetting great looking tables is largely an exercise in restraint. Minimal interference with the legibility of the table should be in the forefront of any designers mind.

When I’m designing tables I apply some simple rules:


	Plenty of negative space
	Use the right typeface
	Go easy on the background tones, unless you’re giving reading direction visual emphasis
	Design to the reading direction


By way of explanation, here are those rules as applied to the following badly typeset table.

Your default table

This table is a mess. There is no consideration for the person trying to read it. Everything is too tight. The typeface is wrong. It’s flat. A grim table indeed.



Let’s see what we can do about that.

Plenty of negative space

The badly typeset table has been set with default padding. There has been little consideration for the ascenders and descenders in the type interfering with the many horizontal rules.

The first thing we do is remove most of the lines, or rules. You don’t need them – the data in the rows forms its own visual rules. Now, with most of the rules removed, the ones that remain mean something; they are indicating some kind of hierarchy to the help the reader understand what the different table elements mean – in this case the column headings.



Now we need to give the columns and rows more negative space. Note the framing of the column headings. I’m giving them more room at the bottom. This negative space is active—it’s empty for a reason. The extra air in here also gives more hierarchy to the column headings.



Use the right typeface

The default table is set in a serif typeface. This isn’t ideal for a couple of reasons. This serif typeface has a standard set of text numerals. These dip below the baseline and are designed for using figures within text, not on their own. What you need to use is a typeface with lining numerals. These align to the baseline and are more legible when used for tables.



Sans serif typefaces generally have lining numerals. They are also arguably more legible when used in tables.

Go easy on the background tones, unless you’re giving reading direction visual emphasis 

We’ve all seen background tones on tables. They have their use, but my feeling is that use should be functional and not decorative.

If you have a table that is long, but only a few columns wide, then alternate row shading isn’t that useful for showing the different lines of data. It’s a common misconception that alternate row shading is to increase legibility on long tables. That’s not the case. Shaded rows are to aid horizontal reading across multiple table columns. On wide tables they are incredibly useful for helping the reader find what they want.



Background tone can also be used to give emphasis to the reading direction. If we want to emphasis a column, that can be given a background tone.



Hierarchy

As I said earlier, people may be reading a table vertically, and horizontally in order to find what they want. Sometimes, especially if the table is complex, we need to give them a helping hand.

Visually emphasising the hierarchy in tables can help the reader scan the data. Column headings are particularly important. Column headings are often what a reader will go to first, so we need to help them understand that the column headings are different to the stuff beneath them, and we also need to give them more visual importance. We can do this by making them bold, giving them ample negative space, or by including a thick rule above them. We can also give the row titles the same level of emphasis.



In addition to background tones, you can give emphasis to reading direction by typesetting those elements in bold. You shouldn’t use italics—with sans serif typefaces the difference is too subtle.

So, there you have it. A couple of simple guidelines to make your tables cleaner and more readable.


title: Underpants Over My Trousers
year: 2007
author: Andy Clarke
author_slug: andyclarke
published: 2007-12-14T00:00:00+00:00
url: https://24ways.org/2007/underpants-over-my-trousers/
topic: design
contents:
With Christmas approaching faster than a speeding bullet, this is the perfect time for you to think about that last minute present to buy for the web geek in your life. If you’re stuck for ideas for that special someone, forget about that svelte iPhone case carved from solid mahogany and head instead to your nearest comic-book shop and pick up a selection of comics or graphic novels. (I’ll be using some of my personal favourite comic books as examples throughout). 

Trust me, whether your nearest and dearest has been reading comics for a while or has never peered inside this four-colour world, they’ll thank-you for it.

Aside from indulging their superhero fantasies, comic books can provide web designers with a rich vein of inspiring ideas and material to help them create shirt button popping, trouser bursting work for the web. I know from my own personal experience, that looking at aspects of comic book design, layout and conventions and thinking about the ways that they can inform web design has taken my design work in often-unexpected directions. 

There are far too many fascinating facets of comic book design that provide web designers with inspiration to cover in the time that it takes to pull your underpants over your trousers. So I’m going to concentrate on one muscle bound aspect of comic design, one that will make you think differently about how you lay out the content of your pages in panels. 

A suitcase full of Kryptonite

Now, to the uninitiated onlooker, the panels of a comic book may appear to perform a similar function to still frames from a movie. But inside the pages of a comic, panels must work harder to help the reader understand the timing of a story. It is this method for conveying narrative timing to a reader that I believe can be highly useful to designers who work on the web as timing, drama and suspense are as important in the web world as they are in worlds occupied by costumed crime fighters and superheroes.

I’d like you to start by closing your eyes and thinking about your own process for laying out panels of content on a page. OK, you’ll actually be better off with your eyes open if you’re going to carry on reading.

I’ll bet you a suitcase full of Kryptonite that you often, if not always, structure your page layouts, and decide on the dimensions of those panels according to either:


	The base grid that you are working to
	The Golden Ratio or another mathematical schema


More likely, I bet that you decide on the size and the number of your panels based on the amount of content that will be going into them. From today, I’d like you to think about taking a different approach. This approach not only addresses horizontal and vertical space, but also adds the dimension of time to your designs.

Slowing down the action

A comic book panel not only acts as a container for its content but also indicates to a reader how much time passes within the panel and as a result, how much time the reader should focus their attention on that one panel. 

Smaller panels create swift eye movement and shorter bursts of attention. Larger panels give the perception of more time elapsing in the story and subconsciously demands that a reader devotes more time to focus on it. 

Concrete by Paul Chadwick (Dark Horse Comics)

This use of panel dimensions to control timing can also be useful for web designers in designing the reading/user experience. Imagine a page full of information about a product or service. You’ll naturally want the reader to focus for longer on the key benefits of your offering rather than perhaps its technical specifications.

Now take a look at this spread of pages from Watchmen by Alan Moore and Dave Gibbons.

Watchmen by Alan Moore and Dave Gibbons (Diamond Comic Distributors 2004)

Throughout this series of (originally) twelve editions, artist Dave Gibbons stuck rigidly to his 3×3 panels per page design and deviated from it only for dramatic moments within the narrative. 

In particular during the last few pages of chapter eleven, Gibbons adds weight to the impending doom by slowing down the action by using larger panels and forces the reader to think longer about what was coming next. The action then speeds up through twelve smaller panels until the final panel: nothing more than white space and yet one of the most iconic and thought provoking in the entire twelve book series.

Watchmen by Alan Moore and Dave Gibbons (Diamond Comic Distributors 2004)

On the web it is common for clients to ask designers to fill every pixel of screen space with content, perhaps not understanding the drama that can be added by nothing more than white space.

In the final chapter, Gibbons emphasises the carnage that has taken place (unseen between chapters eleven and twelve) by presenting the reader with six full pages containing only single, large panels. 

Watchmen by Alan Moore and Dave Gibbons (Diamond Comic Distributors 2004)

This drama, created by the artist’s use of panel dimensions to control timing, is a technique that web designers can also usefully employ when emphasising important areas of content.

Think back for a moment to the home page of Apple Inc., during the launch of their iconic iPhone, where the page contained nothing more than a large image and the phrase “Say hello to iPhone”. Rather than fill the page with sales messages, Apple’s designers allowed the space itself to tell the story and created a real sense of suspense and expectation among their readers.

Borders

Whereas on the web, panel borders are commonly used to add emphasis to particular areas of content, in comic books they take on a different and sometimes opposite role. 

In the examples so far, borders have contained all of the action. Removing a border can have the opposite effect to what you might at first think. Rather than taking emphasis away from their content, in comics, borderless panels allow the reader’s eyes to linger for longer on the content adding even stronger emphasis.

Concrete by Paul Chadwick (Dark Horse Comics)

This effect is amplified when the borderless content is allowed to bleed to the edges of a page. Because the content is no longer confined, except by the edges of the page (both comic and web) the reader’s eye is left to wander out into open space. 

Concrete by Paul Chadwick (Dark Horse Comics)

This type of open, borderless content panel can be highly useful in placing emphasis on the most important content on a page in exactly the very opposite way that we commonly employ on the web today. 

So why is time an important dimension to think about when designing your web pages? On one level, we are often already concerned with the short attention spans of visitors to our pages and should work hard to allow them to quickly and easily find and read the content that both they and we think is important. Learning lessons from comic book timing can only help us improve that experience.

On another: timing, suspense and drama are already everyday parts of the web browsing experience. Will a reader see what they expect when they click from one page to the next? Or are they in for a surprise? 

Most importantly, I believe that the web, like comics, is about story telling: often the story of the experiences that a customer will have when they use our product or service or interact with our organisation. It is this element of story telling than can be greatly improved by learning from comics.

It is exactly this kind of learning and adapting from older, more established and at first glance unrelated media that you will find can make a real distinctive difference to the design work that you create.

Fill your stockings

If you’re a visual designer or developer and are not a regular reader of comics, from the moment that you pick up your first title, I know that you will find them inspiring. 

I will be writing more, and speaking about comic design applied to the web at several (to be announced) events this coming year. I hope you’ll be slipping your underpants over your trousers and joining me then. In the meantime, here is some further reading to pick up on your next visit to a comic book or regular bookshop and slip into your stockings:


	Comics and Sequential Art by Will Eisner (Northern Light Books 2001)
	Understanding Comics: The Invisible Art by Scott McCloud (Harper Collins 1994)


Have a happy superhero season.

(I would like to thank all of the talented artists, writers and publishers whose work I have used as examples in this article and the hundreds more who inspire me every day with their tall tales and talent.)


title: A Gift Idea For Your Users: Respect, Yo
year: 2007
author: Brian Oberkirch
author_slug: brianoberkirch
published: 2007-12-23T00:00:00+00:00
url: https://24ways.org/2007/a-gift-idea-for-your-users-respect-yo/
topic: ux
contents:
If, indeed, it is the thought that counts, maybe we should pledge to make more thoughtful design decisions.  In addition to wowing people who use the Web sites we build with novel features, nuanced aesthetics and the new new thing, maybe we should also thread some subtle things throughout our work that let folks know:  hey, I’m feeling ya.  We’re simpatico.  I hear you loud and clear.

It’s not just holiday spirit that moves me to talk this way.  As good as people are, we need more than the horizon of karma to overcome that invisible demon, inertia.  Makers of the Web, respectful design practices aren’t just the right thing, they are good for business.  Even if your site is the one and only place to get experience x, y or zed, you don’t rub someone’s face in it.  You keep it free flowing, you honor the possible back and forth of a healthy transaction, you are Johnny Appleseed with the humane design cues.  You make it clear that you are in it for the long haul.

A peek back:



Think back to what search (and  strategy) was like before Google launched a super clean page with “I’m Feeling Lucky” button.  Aggregation was the order of the day (just go back and review all the ‘strategic alliances’ that were announced daily.)  Yet the GOOG comes along with this zen layout (nope, we’re not going to try to make you look at one of our media properties) and a bold, brash, teleport-me-straight-to-the-first-search-result button.  It could have been titled “We’re Feeling Cocky”.  These were radical design decisions that reset how people thought about search services.  Oh, you mean I can just find what I want and get on with it?

It’s maybe even more impressive today, after the GOOG has figured out how to monetize attention better than anyone.  “I’m Feeling Lucky” is still there.  No doubt, it costs the company millions.  But by leaving a little money on the table, they keep the basic bargain they started to strike in 1997.  We’re going to get you where you want to go as quickly as possible.

Where are the places we might make the same kind of impact in our work?  Here are a few ideas:

Respect People’s Time

As more services become more integrated with our lives, this will only become more important.  How can you make it clear that you respect the time a user has granted you?

User-Oriented Defaults

Default design may be the psionic tool in your belt.  Unseen, yet pow-er-ful.  Look at your defaults.  Who are they set up to benefit?  Are you depending on users not checking off boxes so you can feel ok about sending them email they really don’t want?  Are you depending on users not checking off boxes so you tilt privacy values in ways most beneficial for your SERPs?  Are you making it a little too easy for 3rd party applications to run buckwild through your system?

There’s being right and then there’s being awesome.  Design to the spirit of the agreement and not the letter.

See this?



Make sure that’s really the experience you think people want.  Whenever I see a service that defaults to not opting me in their newsletter just because I bought a t shirt from them, you can be sure that I trust them that much more.  And they are likely to see me again.

Reduce, Reuse

It’s likely that people using your service will have data and profile credentials elsewhere.  You should really think hard about how you can let them repurpose some of that work within your system.  Can you let them reduce the number of logins/passwords they have to manage by supporting OpenID?  Can you let them reuse profile information from another service by slurping in (or even subscribing) to hCards?  Can you give them a leg up by reusing a friends list they make available to you?  (Note:  please avoid the anti-pattern of inviting your user to upload all her credential data from 3rd party sites into your system.)

This is a much larger issue, and if you’d like to get involved, have a look at the wiki, and dive in.

Make it simple to leave

Oh, this drives me bonkers.  Again, the more simple you make it to increase or decrease involvement in your site, or to just opt-out altogether, the better.  This example from Basecamp is instructive:



At a glance, I can see what the implications are of choosing a different type of account.  I can also move between account levels with one click.  Finally, I can cancel the service easily.  No hoop jumping.  Also, it should be simple for users to take data with them or delete it.

Let Them Have Fun

Don’t overlook opportunities for pleasure.  Even the most mundane tasks can be made more enjoyable.  Check out one of my favorite pieces of interaction design from this past year:



Holy knob fiddling, Batman!  What a great way to get people to play with preference settings:  an equalizer metaphor.  Those of a certain age will recall how fun it was to make patterns with your uncle’s stereo EQ.  I think this is a delightful way to encourage people to optimize their own experience of the news feed feature.  Given the killer nature of this feature, it was important for Facebook to make it easy to fine tune.

I’d also point you to Flickr’s Talk Like A Pirate Day Easter egg as another example of design that delights.  What a huge amount of work for a one-off, totally optional way to experience the site.  And what fun.  And how true to its brand persona.  Brill.

Anti-hype

Don’t talk so much.  Rather, ship and sample.  Release code, tell the right users.  See what happens.   Make changes.  Extend the circle a bit by showing some other folks.  Repeat.

The more you hype coming features, the more you talk about what isn’t yet, the more you build unrealistic expectations.  Your genius can’t possibly match our collective dreaming.  Disappointment is inevitable.  Yet, if you craft the right melody and make it simple for people to hum your tune, it will spread.  Give it time.  Listen.

Speak the Language of the Tribe

It’s respectful to speak in a human way.  Not that you have to get all zOMGWTFBBQ!!1 in your messaging.  People respond when you speak to them in a way that sounds natural.  Natural will, of course, vary according to context.  Again, listen in and people will signal the speech that works in that group for those tasks.  Reveal those cues in your interface work and you’ll have powerful proof that actual people are working on your Web site.

This example of Pownce‘s gender selector is the kind of thing I’m talking about:



Now, this doesn’t mean you should mimic the lingo on some cool kidz site.  Your service doesn’t need to have a massage when it’s down.  Think about what works for you and your tribe.  Excellent advice here from Feedburner’s Dick Costolo on finding a voice for your service.  Also, Mule Design’s Erika Hall has an excellent talk on improving your word fu.

Pass the mic, yo

Here is a crazy idea:  you could ask your users what they want.  Maybe you could even use this input to figure out what they really want.  Tools abound.  Comments, wikis, forums, surveys.  Embed the sexy new Get Satisfaction widget and have a dynamic FAQ running.

The point is that you make it clear to people that they have a means of shaping the service with you.  And you must showcase in some way that you are listening, evaluating and taking action against some of that user input.

You get my drift.  There are any number of ways we can show respect to those who gift us with their time, data, feedback, attention, evangelism, money.  Big things are in the offing.  I can feel the love already.


title: Get In Shape
year: 2007
author: Dave Shea
author_slug: daveshea
published: 2007-12-16T00:00:00+00:00
url: https://24ways.org/2007/get-in-shape/
topic: design
contents:
Pop quiz: what’s wrong with the following navigation?



Maybe nothing. But then again, maybe there’s something bugging you about the way it comes together, something you can’t quite put your finger on. It seems well-designed, but it also seems a little… off.

The design decisions that led to this eventual form were no doubt well-considered:


	Client: The top level needs to have a “current page” status indicator of some sort.
	Designer: How about a white tab?
	Client: Great! The second level needs to show up underneath the first level though…
	Designer: Okay, but that white tab I just added makes it hard to visually connect the bottom nav to the top.
	Client: Too late, we’ve seen the white tab and we love it. Try and make it work.
	Designer: Right. So I placed the second level in its own box.
	Client: Hmm. They seem too separated. I can’t tell that the yellow nav is the second level of the first.
	Designer: How about an indicator arrow?
	Client: Brilliant!


The problem is that the end result feels awkward and forced. During the design process, little decisions were made that ultimately affect the overall shape of the navigation. What started out as a neatly contained rounded rectangle ended up as an ambiguous double shape that looks funny, though it’s often hard to pinpoint precisely why.

The Shape of Things

Well the why in this case is because seemingly unrelated elements in a design still end up visually interacting. Adding a new item to a page impacts everything surrounding it. In this navigation example, we’re looking at two individual objects that are close enough to each other that they form a relationship; if we reduce them to strictly their outlines, it’s a little easier to see that this particular combination registers oddly.



The two shapes float with nothing really grounding them. If they were connected, perhaps it would be a different story. The white tab divides the top shape in half, leaving a gap in the middle of it. There’s very little balance in this pairing because the overall shape of the navigation wasn’t considered during the design process.

Here’s another example: Gmail. Great email client, but did you ever closely look at what’s going on in that left hand navigation? The continuous blue bar around the message area spills out into the navigation. If we remove all text, we’re left with this odd configuration:



Though the reasoning for anchoring the navigation highlight against the message area might be sound, the result is an irregular shape that doesn’t correspond with anything in reality. You may never consciously notice it, but once you do it’s hard to miss. One other example courtesy of last.fm:



The two header areas are the same shade of pink so they appear to be closely connected. When reduced to their outlines it’s easy to see that this combination is off-balance: the edges don’t align, the sharp corners of the top shape aren’t consistent with the rounded corners of the bottom, and the part jutting out on the right of the bottom one seems fairly random. The result is a duo of oddly mis-matched shapes.

Design Strategies

Our minds tend to pick out familiar patterns. A clever designer can exploit this by creating references in his or her work to shapes and combinations with which viewers are already familiar. There are a few simple ideas that can be employed to help you achieve this: consistency, balance, and completion.

Consistency

A fairly simple way to unify the various disparate shapes on a page is by designing them with a certain amount of internal consistency. You don’t need to apply an identical size, colour, border, or corner treatment to every single shape; devolving a design into boring repetition isn’t what we’re after here. But it certainly doesn’t hurt to apply a set of common rules to most shapes within your work.



Consider purevolume and its multiple rounded-corner panels. From the bottom of the site’s main navigation to the grey “Extras” panels halfway down the page (shown above), multiple shapes use a common border radius for unity. Different colours, different sizes, different content, but the consistent outlines create a strong sense of similarity. Not that every shape on the site follows this rule; they break the pattern right at the top with a darker sharp-cornered header, and again with the thumbnails below. But the design remains unified, nonetheless.

Balance

Arguably the biggest problem with the last.fm example earlier is one of balance. The area poking out of the bottom shape created a fairly obvious imbalance for no apparent reason. The right hand side is visually emphasized due to the greater area of pink coverage, but with the white gap left beside it, the emphasis seems unwarranted. It’s possible to create tension in your design by mismatching shapes and throwing off the balance, but when that happens unintentionally it can look like a mistake.



Above are a few examples of design elements in balanced and unbalanced configurations. The examples in the top row are undeniably more pleasing to the eye than those in the bottom row. If these were fleshed out into full designs, those derived from the templates in the top row would naturally result in stronger work.

Take a look at the header on 9Rules for a study in well-considered balance. On the left you’ll see a couple of paragraphs of text, on the right you have floating navigational items, and both flank the site’s logo. This unusual layout combines multiple design elements that look nothing alike, and places them together in a way that anchors each so that no one weighs down the header.

Completion

And finally we come to the idea of completion. Shapes don’t necessarily need hard outlines to be read visually as shapes, which can be exploited for various purposes. Notice how Zend’s mid-page “Business Topics” and “News” items (below) fade out to the right and bottom, but the placement of two of these side-by-side creates an impression of two panels rather than three disparate floating columns. By allowing the viewer’s eye to complete the shapes, they’ve lightened up the design of the page and removed inessential lines. In a busy design this technique could prove quite handy.



Along the same lines, the individual shapes within your design may also be combined visually to form outlines of larger shapes. The differently-coloured header and main content/sidebar shapes on Veerle’s blog come together to form a single central panel, further emphasized by the slight drop shadow to the right.

Implementation

Studying how shape can be used effectively in design is simply a starting point. As with all things design-related, there are no hard and fast rules here; ultimately you may choose to bring these principles into your work more often, or break them for effect. But understanding how shapes interact within a page, and how that effect is ultimately perceived by viewers, is a key design principle you can use to impress your friends.


title: CSS for Accessibility
year: 2007
author: Ann McMeekin
author_slug: annmcmeekin
published: 2007-12-13T00:00:00+00:00
url: https://24ways.org/2007/css-for-accessibility/
topic: design
contents:
CSS is magical stuff. In the right hands, it can transform the plainest of (well-structured) documents into a visual feast. But it’s not all fur coat and nae knickers (as my granny used to say). Here are some simple ways you can use CSS to improve the usability and accessibility of your site. 

Even better, no sexy visuals will be harmed by the use of these techniques. Promise.

Nae knickers

This is less of an accessibility tip, and more of a reminder to check that you’ve got your body background colour specified.

If you’re sitting there wondering why I’m mentioning this, because it’s a really basic thing, then you might be as surprised as I was to discover that from a sample of over 200 sites checked last year, 35% of UK local authority websites were missing their body background colour.

Forgetting to specify your body background colour can lead to embarrassing gaps in coverage, which are not only unsightly, but can prevent your users reading the text on your site if they use a different operating system colour scheme.

All it needs is the following line to be added to your CSS file:

body {background-color: #fff;}

If you pair it with 

color: #000;

… you’ll be assured of maintaining contrast for any areas you inadvertently forget to specify, no matter what colour scheme your user needs or prefers.

Even better, if you’ve got standard reset CSS you use, make sure that default colours for background and text are specified in it, so you’ll never be caught with your pants down. At the very least, you’ll have a white background and black text that’ll prompt you to change them to your chosen colours.

Elbow room

Paying attention to your typography is important, but it’s not just about making it look nice. 

Careful use of the line-height property can make your text more readable, which helps everyone, but is particularly helpful for those with dyslexia, who use screen magnification or simply find it uncomfortable to read lots of text online. 

When lines of text are too close together, it can cause the eye to skip down lines when reading, making it difficult to keep track of what you’re reading across. 

So, a bit of room is good.

That said, when lines of text are too far apart, it can be just as bad, because the eye has to jump to find the next line. That not only breaks up the reading rhythm, but can make it much more difficult for those using Screen Magnification (especially at high levels of magnification) to find the beginning of the next line which follows on from the end of the line they’ve just read.

Using a line height of between 1.2 and 1.6 times normal can improve readability, and using unit-less line heights help take care of any pesky browser calculation problems.

For example: 

p {
	font-family: "Lucida Grande", Lucida, Verdana, Helvetica, sans-serif;
	font-size: 1em;
	line-height: 1.3;
}

or if you want to use the shorthand version:

p {
	font: 1em/1.3 "Lucida Grande", Lucida, Verdana, Helvetica, sans-serif;
}

View some examples of different line-heights, based on default text size of 100%/1em.

Further reading on Unitless line-heights from Eric Meyer.

Transformers: Initial case in disguise

Nobody wants to shout at their users, but there are some occasions when you might legitimately want to use uppercase on your site.

Avoid screen-reader pronunciation weirdness (where, for example, CONTACT US would be read out as Contact U S, which is not the same thing – unless you really are offering your users the chance to contact the United States) caused by using uppercase by using title case for your text and using the often neglected text-transform property to fake uppercase.

For example:

.uppercase {
	text-transform: uppercase
}    

Don’t overdo it though, as uppercase text is harder to read than normal text, not to mention the whole SHOUTING thing.

Linky love

When it comes to accessibility, keyboard only users (which includes those who use voice recognition software) who can see just fine are often forgotten about in favour of screen reader users.

This Christmas, share the accessibility love and light up those links so all of your users can easily find their way around your site.

The link outline

AKA: the focus ring, or that dotted box that goes around links to show users where they are on the site.

The techniques below are intended to supplement this, not take the place of it. You may think it’s ugly and want to get rid of it, especially since you’re going to the effort of tarting up your links.

Don’t. 

Just don’t.

The non-underlined underline

If you listen to Jacob Nielsen, every link on your site should be underlined so users know it’s a link.

You might disagree with him on this (I know I do), but if you are choosing to go with underlined links, in whatever state, then remove the default underline and replacing it with a border that’s a couple of pixels away from the text. 

The underline is still there, but it’s no longer cutting off the bottom of letters with descenders (e.g., g and y) which makes it easier to read.

This is illustrated in Examples 1 and 2.

You can modify the three lines of code below to suit your own colour and border style preferences, and add it to whichever link state you like.

text-decoration: none;
border-bottom: 1px #000 solid;
padding-bottom: 2px;

Standing out from the crowd

Whatever way you choose to do it, you should be making sure your links stand out from the crowd of normal text which surrounds them when in their default state, and especially in their hover or focus states.

A good way of doing this is to reverse the colours when on hover or focus.

Well-focused

Everyone knows that you can use the :hover pseudo class to change the look of a link when you mouse over it, but, somewhat ironically, people who can see and use a mouse are the group who least need this extra visual clue, since the cursor handily (sorry) changes from an arrow to a hand.

So spare a thought for the non-pointing device users that visit your site and take the time to duplicate that hover look by using the :focus pseudo class.

Of course, the internets being what they are, it’s not quite that simple, and predictably, Internet Explorer is the culprit once more with it’s frustrating lack of support for :focus. Instead it applies the :active pseudo class whenever an anchor has focus.

What this means in practice is that if you want to make your links change on focus as well as on hover, you need to specify focus, hover and active.

Even better, since the look and feel necessarily has to be the same for the last three states, you can combine them into one rule.

So if you wanted to do a simple reverse of colours for a link, and put it together with the non-underline underlines from before, the code might look like this:

a:link {
	background: #fff;
	color: #000;
	font-weight: bold;
	text-decoration: none; 
	border-bottom: 1px #000 solid; 
	padding-bottom: 2px;
}
a:visited {
	background: #fff;
	color: #800080;
	font-weight: bold;
	text-decoration: none; 
	border-bottom: 1px #000 solid; 
	padding-bottom: 2px;
}
a:focus, a:hover, a:active {
	background: #000;
	color: #fff;
	font-weight: bold;
	text-decoration: none; 
	border-bottom: 1px #000 solid; 
	padding-bottom: 2px;
}

Example 3 shows what this looks like in practice.

Location, Location, Location

To take this example to it’s natural conclusion, you can add an id of current (or something similar) in appropriate places in your navigation, specify a full set of link styles for current, and have a navigation which, at a glance, lets users know which page or section they’re currently in.

Example navigation using location indicators.

and the source code

Conclusion

All the examples here are intended to illustrate the concepts, and should not be taken as the absolute best way to format links or style navigation bars – that’s up to you and whatever visual design you’re using at the time.

They’re also not the only things you should be doing to make your site accessible. 

Above all, remember that accessibility is for life, not just for Christmas.


title: JavaScript Internationalisation
year: 2007
author: Matthew Somerville
author_slug: matthewsomerville
published: 2007-12-08T00:00:00+00:00
url: https://24ways.org/2007/javascript-internationalisation/
topic: code
contents:
or:  Why Rudolph Is More Than Just a Shiny Nose

Dunder sat, glumly staring at the computer screen.

“What’s up, Dunder?” asked Rudolph, entering the stable and shaking off the snow from his antlers.

“Well,” Dunder replied, “I’ve just finished coding the new reindeer intranet Santa Claus asked me to do. You know how he likes to appear to be at the cutting edge, talking incessantly about Web 2.0, AJAX, rounded corners; he even spooked Comet recently by talking about him as if he were some pushy web server.

“I’ve managed to keep him happy, whilst also keeping it usable, accessible, and gleaming — and I’m still on the back row of the sleigh! But anyway, given the elves will be the ones using the site, and they come from all over the world, the site is in multiple languages. Which is great, except when it comes to the preview JavaScript I’ve written for the reindeer order form. Here, have a look…”

As he said that, he brought up the textileRef:8234272265470b85d91702:linkStartMarker:“order
    form in French”:/examples/javascript-internationalisation/initial.fr.html on the screen. (Same in English).

“Looks good,” said Rudolph.

“But if I add some items,” said Dunder, “the preview appears in English, as it’s hard-coded in the JavaScript. I don’t want separate code for each language, as that’s just silly — I thought about just having if statements, but that doesn’t scale at all…”

“And there’s more, you aren’t displaying large numbers in French properly, either,” added Rudolph, who had been playing and looking at part of the source code:

function update_text() {
	var hay = getValue('hay');
	var carrots = getValue('carrots');
	var bells = getValue('bells');
	var total = 50 * bells + 30 * hay + 10 * carrots;
	var out = 'You are ordering '
		+ pretty_num(hay) + ' bushel' + pluralise(hay) + ' of hay, '
		+ pretty_num(carrots) + ' carrot' + pluralise(carrots)
		+ ', and ' + pretty_num(bells) + ' shiny bell' + pluralise(bells)
		+ ', at a total cost of <strong>' + pretty_num(total)
		+ '</strong> gold pieces. Thank you.';
	document.getElementById('preview').innerHTML = out;
}
function pretty_num(n) {
	n += '';
	var o = '';
	for (i=n.length; i>3; i-=3) {
		o = ',' + n.slice(i-3, i) + o;
	}
	o = n.slice(0, i) + o;
	return o;
}
function pluralise(n) {
	if (n!=1) return 's';
	return '';
}

“Oh, botheration!” cried Dunder. “This is just so complicated.”

“It doesn’t have to be,” said Rudolph, “you just have to think about things in a slightly different way from what you’re used to. As we’re only a simple example, we won’t be able to cover all possibilities, but for starters, we need some way of providing different information to the script dependent on the language. We’ll create a global i18n object, say, and fill it with the correct language information. The first variable we’ll need will be a thousands separator, and then we can change the pretty_num function to use that instead:

function pretty_num(n) {
	n += '';
	var o = '';
	for (i=n.length; i>3; i-=3) {
		o = i18n.thousands_sep + n.slice(i-3, i) + o;
	}
	o = n.slice(0, i) + o;
	return o;
}

“The i18n object will also contain our translations, which we will access through a function called _() — that’s just an underscore. Other languages have a function of the same name doing the same thing. It’s very simple:

function _(s) {
	if (typeof(i18n)!='undefined' && i18n[s]) {
		return i18n[s];
	}
	return s;
}

“So if a translation is available and provided, we’ll use that; otherwise we’ll default to the string provided — which is helpful if the translation begins to lag behind the site’s text at all, as at least something will be output.”

“Got it,” said Dunder. “ _('Hello Dunder') will print the translation of that string, if one exists, ‘Hello Dunder’ if not.”

“Exactly. Moving on, your plural function breaks even in English if we have a word where the plural doesn’t add an s — like ‘children’.”

“You’re right,” said Dunder. “How did I miss that?”

“No harm done. Better to provide both singular and plural words to the function and let it decide which to use, performing any translation as well:

function pluralise(s, p, n) {
	if (n != 1) return _(p);
	return _(s);
}

“We’d have to provide different functions for different languages as we employed more elves and got more complicated — for example, in Polish, the word ‘file’ pluralises like this: 1 plik, 2-4 pliki, 5-21 plików, 22-24 pliki, 25-31 plików, and so on.” (More information on plural forms)

“Gosh!”

“Next, as different languages have different word orders, we must stop using concatenation to construct sentences, as it would be impossible for other languages to fit in; we have to keep coherent strings together. Let’s rewrite your update function, and then go through it:

function update_text() {
	var hay = getValue('hay');
	var carrots = getValue('carrots');
	var bells = getValue('bells');
	var total = 50 * bells + 30 * hay + 10 * carrots;
	hay = sprintf(pluralise('%s bushel of hay', '%s bushels of hay', hay), pretty_num(hay));
	carrots = sprintf(pluralise('%s carrot', '%s carrots', carrots), pretty_num(carrots));
	bells = sprintf(pluralise('%s shiny bell', '%s shiny bells', bells), pretty_num(bells));
	var list = sprintf(_('%s, %s, and %s'), hay, carrots, bells);
	var out = sprintf(_('You are ordering %s, at a total cost of <strong>%s</strong> gold pieces.'),
		list, pretty_num(total));
	out += ' ';
	out += _('Thank you.');
	document.getElementById('preview').innerHTML = out;
}

“ sprintf is a function in many other languages that, given a format string and some variables, slots the variables into place within the string. JavaScript doesn’t have such a function, so we’ll write our own. Again, keep it simple for now, only integers and strings; I’m sure more complete ones can be found on the internet.

function sprintf(s) {
	var bits = s.split('%');
	var out = bits[0];
	var re = /^([ds])(.*)$/;
	for (var i=1; i<bits.length; i++) {
		p = re.exec(bits[i]);
		if (!p || arguments[i]==null) continue;
		if (p[1] == 'd') {
			out += parseInt(arguments[i], 10);
		} else if (p[1] == 's') {
			out += arguments[i];
		}
		out += p[2];
	}
	return out;
}

“Lastly, we need to create one file for each language, containing our i18n object, and then include that from the relevant HTML. Here’s what a blank translation file would look like for your order form:

var i18n = {
	thousands_sep: ',',
	"%s bushel of hay": '',
	"%s bushels of hay": '',
	"%s carrot": '',
	"%s carrots": '',
	"%s shiny bell": '',
	"%s shiny bells": '',
	"%s, %s, and %s": '',
	"You are ordering %s, at a total cost of <strong>%s</strong> gold pieces.": '',
	"Thank you.": ''
};

“If you implement this across the intranet, you’ll want to investigate the xgettext program, which can automatically extract all strings that need translating from all sorts of code files into a standard .po file (I think Python mode works best for JavaScript). You can then use a different program to take the translated .po file and automatically create the language-specific JavaScript files for us.” (e.g. German .po file for PledgeBank, mySociety’s .po-.js script, example output)

With a flourish, Rudolph finished editing. “And there we go, localised JavaScript in English, French, or German, all using the same main code.”

“Thanks so much, Rudolph!” said Dunder.

“I’m not just a pretty nose!” Rudolph quipped. “Oh, and one last thing — please comment liberally explaining the context of strings you use. Your translator will thank you, probably at the same time as they point out the four hundred places you’ve done something in code that only works in your language and no-one else’s…”

Thanks to Tim Morley and Edmund Grimley Evans for the French and German translations respectively.


title: Diagnostic Styling
year: 2007
author: Eric Meyer
author_slug: ericmeyer
published: 2007-12-20T00:00:00+00:00
url: https://24ways.org/2007/diagnostic-styling/
topic: process
contents:
We’re all used to using CSS to make our designs live and breathe, but there’s another way to use CSS: to find out where our markup might be choking on missing accessibility features, targetless links, and just plain missing content.  

Note: the techniques discussed here mostly work in Firefox, Safari, and Opera, but not Internet Explorer.  I’ll explain why that’s not really a problem near the end of the article — and no, the reason is not “everyone should just ignore IE anyway”.

Basic Diagnostics

To pick a simple example, suppose you want to call out all holdover font and center elements in a site.  Simple: you just add the following to your styles.

font, center {outline: 5px solid red;}

You could take it further and add in a nice lime background or some such, but big thick red outlines should suffice.  Now you’ll be able to see the offenders wherever as you move through the site.  (Of course, if you do this on your public server, everyone else will see the outlines too.  So this is probably best done on a development server or local copy of the site.)

Not everyone may be familiar with outlines, which were introduced in CSS2, so a word on those before we move on.  Outlines are much like borders, except outlines don’t affect layout.  Eh?  Here’s a comparison.



On the left, you have a border.  On the right, an outline.  The border takes up layout space, pushing other content around and generally being a nuisance.  The outline, on the other hand, just draws into quietly into place.  In most current browsers, it will overdraw any content already onscreen, and will be overdrawn by any content placed later — which is why it overlaps the images above it, and is overlapped by those below it.

Okay, so we can outline deprecated elements like font and center.  Is that all?  Oh no.

Attribution

Let’s suppose you also want to find any instances of inline style — that is, use of the style attribute on elements in the markup.  This is generally discouraged (outside of HTML e-mails, which I’m not going to get anywhere near), as it’s just another side of the same coin of using font: baking the presentation into the document structure instead of putting it somewhere more manageable.  So:

*[style], font, center {outline: 5px solid red;}

Adding that attribute selector to the rule’s grouped selector means that we’ll now be outlining any element with a style attribute.

There’s a lot more that attribute selectors will let use diagnose.  For example, we can highlight any images that have empty alt or title text.

img[alt=""] {border: 3px dotted red;}
img[title=""] {outline: 3px dotted fuchsia;}

Now, you may wonder why one of these rules calls for a border, and the other for an outline.  That’s because I want them to “add together” — that is, if I have an image which possesses both alt and title, and the values of both are empty, then I want it to be doubly marked.



See how the middle image there has both red and fuchsia dots running around it?  (And am I the only one who sorely misses the actual circular dots drawn by IE5/Mac?)  That’s due to its markup, which we can see here in a fragment showing the whole table row.

<tr>
<th scope="row">empty title</th>
<td><img src="comic.gif" title="" /></td>
<td><img src="comic.gif" title="" alt="" /></td>
<td><img src="comic.gif" title="" alt="comical" /></td>
</tr>

Right, that’s all well and good, but it misses a rather more serious situation: the selector img[alt=""] won’t match an img element that doesn’t even have an alt attribute.  How to tackle this problem?

Not a Problem

Well, if you want to select something based on a negative, you need a negative selector.

img:not([alt]) {border: 5px solid red;}

This is really quite a break from the rest of CSS selection, which is all positive: “select anything that has these characteristics”.  With :not(), we have the ability to say (in supporting browsers) “select anything that hasn’t these characteristics”.  In the above example, only img elements that do not have an alt attribute will be selected.  So we expand our list of image-related rules to read:

img[alt=""] {border: 3px dotted red;}
img[title=""] {outline: 3px dotted fuchsia;}
img:not([alt]) {border: 5px solid red;}
img:not([title]) {outline: 5px solid fuchsia;}

With the following results:



We could expand this general idea to pick up tables who lack a summary, or have an empty summary attribute.

table[summary=""] {outline: 3px dotted red;}
table:not([summary]) {outline: 5px solid red;}

When it comes to selecting header cells that lack the proper scope, however, we have a trickier situation.  Finding headers with no scope attribute is easy enough, but what about those that have a scope attribute with an incorrect value?

In this case, we actually need to pull an on-off maneuver.  This has us setting all th elements to have a highlight style, and then turn it off for the elements that meet our criteria.

th {border: 2px solid red;}
th[scope="col"], th[scope="row"] {border: none;}

This was necessary because of the way CSS selectors work.  For example, consider this:

th:not([scope="col"]), th:not([scope="row"]) {border: 2px solid red;}

That would select…all th elements, regardless of their attrributes.  That’s because every th element doesn’t have a scope of col, doesn’t have a scope of row, or doesn’t have either.  There’s no escaping this selector o’ doom!

This limitation arises because :not() is limited to containing a single “thing” within its parentheses.  You can’t, for example, say “select all elements except those that are images which descend from list items”.  Reportedly, this limitation was imposed to make browser implementation of :not() easier.

Still, we can make good use of :not() in the service of further diagnosing.  Calling out links in trouble is a breeze:

a[href]:not([title]) {border: 5px solid red;}
a[title=""] {outline: 3px dotted red;}
a[href="#"] {background: lime;}
a[href=""] {background: fuchsia;}



Here we have a set that will call our attention to links missing title information, as well as links that have no valid target, whether through a missing URL or a JavaScript-driven page where there are no link fallbacks in the case of missing or disabled JavaScript (href="#").

And What About IE?

As I said at the beginning, much of what I covered here doesn’t work in Internet Explorer, most particularly :not() and outline.  (Oh, so basically everything?  -Ed.)

I can’t do much about the latter.  For the former, however, it’s possible to hack your way around the problem by doing some layered on-off stuff.  For example, for images, you replace the previously-shown rules with the following:

img {border: 5px solid red;}
img[alt][title] {border-width: 0;}
img[alt] {border-color: fuchsia;}
img[alt], img[title] {border-style: double;}
img[alt=""][title],
img[alt][title=""] {border-width: 3px;}
img[alt=""][title=""] {border-style: dotted;}

It won’t have exactly the same set of effects, given the inability to use both borders and outlines, but will still highlight troublesome images.



It’s also the case that IE6 and earlier lack support for even attribute selectors, whereas IE7 added pretty much all the attribute selector types there are, so the previous code block won’t have any effect previous to IE7.

In a broader sense, though, these kinds of styles probably aren’t going to be used in the wild, as it were.  Diagnostic styles are something only you see as you work on a site, so you can make sure to use a browser that supports outlines and :not() when you’re diagnosing.  The fact that IE users won’t see these styles is irrelevant since users of any browser probably won’t be seeing these styles.

Personally, I always develop in Firefox anyway, thanks to its ability to become a full-featured IDE through the addition of extensions like Firebug and the Web Developer Toolbar.


Yeah, About That…

It’s true that much of what I describe in this article is available in the WDT.  I feel there are two advantages to writing your own set of diagnostic styles.


	When you write your own styles, you can define exactly what the visual results will be, and how they will interact.  The WDT doesn’t let you make its outlines thicker or change their colors.
	You can combine a bunch of diagnostics into a single set of rules and add it to your site’s style sheet during the diagnostic portion, thus ensuring they persist as you surf around.  This can be done in the WDT, but it isn’t as easy (and, at least for me, not as reliable).


It’s also true that a markup validator will catch many of the errors I mentioned, such as missing alt and summary attributes.  For some, that’s sufficient.  But it won’t catch everything diagnostic styles can, like empty alt values or untargeted links, which are perfectly valid, syntactically speaking.


Diagnosis Complete?

I hope this has been a fun look at the concept of diagnostic styling as well as a quick introduction into possibly new concepts like :not() and outlines.  This isn’t all there is to say, of course: there is plenty more that could be added to a diagnostic style sheet.  And everyone’s diagnostics will be different, tuned to meet each person’s unique situation.

Mostly, though, I hope this small exploration triggers some creative thinking about the use of CSS to do more than just lay out pages and colorize text.  Given the familiarity we acquire with CSS, it only makes sense to use it wherever it might be useful, and setting up visible diagnostic flags is just one more place for it to help us.


title: Minification: A Christmas Diet
year: 2007
author: Gareth Rushgrove
author_slug: garethrushgrove
published: 2007-12-06T00:00:00+00:00
url: https://24ways.org/2007/minification-a-christmas-diet/
topic: process
contents:
The festive season is generally more about gorging ourselves than staying thin but we’re going to change all that with a quick introduction to minification.

Performance has been a hot topic this last year. We’re building more complex sites and applications but at the same time trying to make then load faster and behave more responsively. What is a discerning web developer to do?

Minification is the process of make something smaller, in the case of web site performance we’re talking about reducing the size of files we send to the browser. The primary front-end components of any website are HTML, CSS, Javascript and a sprinkling of images. Let’s find some tools to trim the fat and speed up our sites.

For those that want to play along at home you can download the various utilities for Mac or Windows. You’ll want to be familiar with running apps on the command line too.

HTMLTidy

HTMLTidy optimises and strips white space from HTML documents. It also has a pretty good go at correcting any invalid markup while it’s at it.

tidy -m page.html

CSSTidy

CSSTidy takes your CSS file, optimises individual rules (for instance transforming padding-top: 10px; padding-bottom: 10px; to padding: 10px 0;) and strips unneeded white space.

csstidy style.css style-min.css

JSMin

JSMin takes your javascript and makes it more compact. With more and more websites using javascript to power (progressive) enhancements this can be a real bandwidth hog. Look out for pre-minified versions of libraries and frameworks too.

jsmin <script.js >script-min.js

Remember to run JSLint before you run JSMin to catch some common problems.

OptiPNG

Images can be a real bandwidth hog and making all of them smaller with OptiPNG should speed up your site.

optipng image.png

All of these tools have an often bewildering array of options and generally good documentation included as part of the package. A little experimentation will get you even more bang for your buck.

For larger projects you likely won’t want to be manually minifying all your files. The best approach here is to integrate these tools into your build process and have your live website come out the other side smaller than it went in.

You can also do things on the server to speed things up; GZIP compression for instance or compilation of resources to reduce the number of HTTP requests. If you’re interested in performance a good starting point is the Exceptional Performance section on the Yahoo Developer Network and remember to install the YSlow Firebug extension while you’re at it.


title: Mobile 2.0
year: 2007
author: Brian Fling
author_slug: brianfling
published: 2007-12-21T00:00:00+00:00
url: https://24ways.org/2007/mobile-2-0/
topic: business
contents:
Thinking 2.0

As web geeks, we have a thick skin towards jargon. We all know that “Web 2.0” has been done to death. At Blue Flavor we even have a jargon bucket to penalize those who utter such painfully overused jargon with a cash deposit. But Web 2.0 is a term that has lodged itself into the conscience of the masses. This is actually a good thing.

The 2.0 suffix was able to succinctly summarize all that was wrong with the Web during the dot-com era as well as the next evolution of an evolving media. While the core technologies actually stayed basically the same, the principles, concepts, interactions and contexts were radically different.

With that in mind, this Christmas I want to introduce to you the concept of Mobile 2.0. While not exactly a new concept in the mobile community, it is relatively unknown in the web community. And since the foundation of Mobile 2.0 is the web, I figured it was about time for you to get to know each other.

It’s the Carriers’ world. We just live in it.

Before getting into Mobile 2.0, I thought first I should introduce you to its older brother. You know the kind, the kid with emotional problems that likes to beat up on you and your friends for absolutely no reason. That is the mobile of today.

The mobile ecosystem is a very complicated space often and incorrectly compared to the Web. If the Web was a freewheeling hippie — believing in freedom of information and the unity of man through communities — then Mobile is the cutthroat capitalist — out to pillage and plunder for the sake of the almighty dollar. Where the Web is relatively easy to publish to and ultimately make a buck, Mobile is wrought with layers of complexity, politics and obstacles. 

I can think of no better way to summarize these challenges than the testimony of Jason Devitt to the United States Congress in what is now being referred to as the “iPhone Hearing.” Jason is the co-founder and CEO of SkyDeck a new wireless startup and former CEO of Vindigo an early pioneer in mobile content.



As Jason points out, the mobile ecosystem is a closed door environment controlled by the carriers, forcing the independent publisher to compete or succumb to the will of corporate behemoths.

But that is all about to change.

Introducing Mobile 2.0

Mobile 2.0 is term used by the mobile community to describe the current revolution happening in mobile. It describes the convergence of mobile and web services, adding portability, ubiquitous connectivity and location-aware services to add physical context to information found on the Web.

It’s an important term that looks toward the future. Allowing us to imagine the possibilities that mobile technology has long promised but has yet to deliver. It imagines a world where developers can publish mobile content without the current constraints of the mobile ecosystem.

Like the transition from Web 1.0 to 2.0, it signifies the shift away from corporate or brand-centered experiences to user-centered experiences. A focus on richer interactions, driven by user goals. Moving away from proprietary technologies to more open and standard ones, more akin to the Web. And most importantly (from our perspective as web geeks) a shift away from kludgy one-off mobile applications toward using the Web as a platform for content and services.

This means the world of the Web and the world of Mobile are coming together faster than you can say ARPU (Average Revenue Per User, a staple mobile term to you webbies). And this couldn’t come at a better time. The importance of understanding and addressing user context is quickly becoming a crucial consideration to every interactive experience as the number of ways we access information on the Web increases.

Mobile enables the power of the Web, the collective information of millions of people, inherit payment channels and access to just about every other mass media to literally be overlaid on top of the physical world, in context to the person viewing it. 

Anyone who can’t imagine how the influence of mobile technology can’t transform how we perform even the simplest of daily tasks needs to get away from their desktop and see the new evolution of information.

The Instigators

But what will make Mobile 2.0 move from idillic concept to a hardened market reality in 2008 will be four key technologies. Its my guess that you know each them already.

1. Opera

Opera is like the little train that could. They have been a driving force on moving the Web as we know it on to mobile handsets. Opera technology has proven itself to be highly adaptable, finding itself preloaded on over 40 million handsets, available on televisions sets through Nintendo Wii or via the Nintendo DS.

2. WebKit

Many were surprised when Apple chose to use KHTML instead of Gecko (the guts of Firefox) to power their Safari rendering engine. But WebKit has quickly evolved to be a powerful and flexible browser in the mobile context. WebKit has been in Nokia smartphones for a few years now, is the technology behind Mobile Safari in the iPhone and the iPod Touch and is the default web technology in Google’s open mobile platform effort, Android.

3. The iPhone

The iPhone has finally brought the concepts and principles of Mobile 2.0 into the forefront of consumers minds and therefore developers’ minds as well. Over 500 web applications have been written specifically for the iPhone since its launch. It’s completely unheard of to see so many applications built for the mobile context in such a short period of time.

4. CSS & Javascript

Web 2.0 could not exist without the rich interactions offered by CSS and Javascript, and Mobile 2.0 is no different. CSS and Javascript support across multiple phones historically has been, well… to put it positively… utter crap.

Javascript finally allows developers to create interesting interactions that support user goals and the mobile context. Specially, AJAX allows us to finally shed the days of bloated Java applications and focus on portable and flexible web applications. While CSS — namely CSS3 — allows us to create designs that are as beautiful as they are economical with bandwidth and load times.

With Leaflets, a collection of iPhone optimized web apps we created, we heavily relied on CSS3 to cache and reuse design elements over and over, minimizing download times while providing an elegant and user-centered design.



In Conclusion

It is the combination of all these instigators that is significantly decreasing the bar to mobile publishing. The market as Jason Devitt describes it, will begin to fade into the background. And maybe the world of mobile will finally start looking more like the Web that we all know and love.

So after the merriment and celebration of the holiday is over and you look toward the new year to refresh and renew, I hope that you take a seriously consider the mobile medium. 

By this time next year, it is predicted that one-third of humanity will be using mobile devices to access the Web.


title: Capturing Caps Lock
year: 2007
author: Stuart Langridge
author_slug: stuartlangridge
published: 2007-12-04T00:00:00+00:00
url: https://24ways.org/2007/capturing-caps-lock/
topic: code
contents:
One of the more annoying aspects of having to remember passwords (along with having to remember loads of them) is that if you’ve got Caps Lock turned on accidentally when you type one in, it won’t work, and you won’t know why. Most desktop computers alert you in some way if you’re trying to enter your password to log on and you’ve enabled Caps Lock; there’s no reason why the web can’t do the same. What we want is a warning – maybe the user wants Caps Lock on, because maybe their password is in capitals – rather than something that interrupts what they’re doing. Something subtle.

But that doesn’t answer the question of how to do it. Sadly, there’s no way of actually detecting whether Caps Lock is on directly. However, there’s a simple work-around; if the user presses a key, and it’s a capital letter, and they don’t have the Shift key depressed, why then they must have Caps Lock on! Simple. 

DOM scripting allows your code to be notified when a key is pressed in an element; when the key is pressed, you get the ASCII code for that key. Capital letters, A to Z, have ASCII codes 65 to 90. So, the code would look something like:

on a key press
	if the ASCII code for the key is between 65 and 90 *and* if shift is pressed
		warn the user that they have Caps Lock on, but let them carry on
	end if
end keypress

The actual JavaScript for this is more complicated, because both event handling and keypress information differ across browsers. Your event handling functions are passed an event object, except in Internet Explorer where you use the global event object; the event object has a which parameter containing the ASCII code for the key pressed, except in Internet Explorer where the event object has a keyCode parameter; some browsers store whether the shift key is pressed in a shiftKey parameter and some in a modifiers parameter. All this boils down to code that looks something like this:

keypress: function(e) {
	var ev = e ? e : window.event;
	if (!ev) {
		return;
	}
	var targ = ev.target ? ev.target : ev.srcElement;
	// get key pressed
	var which = -1;
	if (ev.which) {
		which = ev.which;
	} else if (ev.keyCode) {
		which = ev.keyCode;
	}
	// get shift status
	var shift_status = false;
	if (ev.shiftKey) {
		shift_status = ev.shiftKey;
	} else if (ev.modifiers) {
		shift_status = !!(ev.modifiers & 4);
	}

	// At this point, you have the ASCII code in “which”, 
	// and shift_status is true if the shift key is pressed
}

Then it’s just a check to see if the ASCII code is between 65 and 90 and the shift key is pressed. (You also need to do the same work if the ASCII code is between 97 (a) and 122 (z) and the shift key is not pressed, because shifted letters are lower-case if Caps Lock is on.)

if (((which >= 65 && which <= 90) && !shift_status) || 
	((which >= 97 && which <= 122) && shift_status)) {
	// uppercase, no shift key
	/* SHOW THE WARNING HERE */
} else {
	/* HIDE THE WARNING HERE */
}

The warning can be implemented in many different ways: highlight the password field that the user is typing into, show a tooltip, display text next to the field. For simplicity, this code shows the warning as a previously created image, with appropriate alt text. Showing the warning means creating a new <img> tag with DOM scripting, dropping it into the page, and positioning it so that it’s next to the appropriate field. The image looks like this:



You know the position of the field the user is typing into (from its offsetTop and offsetLeft properties) and how wide it is (from its offsetWidth properties), so use createElement to make the new img element, and then absolutely position it with style properties so that it appears in the appropriate place (near to the text field). 

The image is a transparent PNG with an alpha channel, so that the drop shadow appears nicely over whatever else is on the page. Because Internet Explorer version 6 and below doesn’t handle transparent PNGs correctly, you need to use the AlphaImageLoader technique to make the image appear correctly.

newimage = document.createElement('img');
newimage.src = "http://farm3.static.flickr.com/2145/2067574980_3ddd405905_o_d.png";
newimage.style.position = "absolute";
newimage.style.top = (targ.offsetTop - 73) + "px";
newimage.style.left = (targ.offsetLeft + targ.offsetWidth - 5) + "px";
newimage.style.zIndex = "999";
newimage.setAttribute("alt", "Warning: Caps Lock is on");
if (newimage.runtimeStyle) {
	// PNG transparency for IE
	newimage.runtimeStyle.filter += "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='http://farm3.static.flickr.com/2145/2067574980_3ddd405905_o_d.png',sizingMethod='scale')";
}
document.body.appendChild(newimage);

Note that the alt text on the image is also correctly set. Next, all these parts need to be pulled together. On page load, identify all the password fields on the page, and attach a keypress handler to each. (This only needs to be done for password fields because the user can see if Caps Lock is on in ordinary text fields.)

var inps = document.getElementsByTagName("input");
for (var i=0, l=inps.length; i

The “create an image” code from above should only be run if the image is not already showing, so instead of creating a newimage object, create the image and attach it to the password field so that it can be checked for later (and not shown if it’s already showing). For safety, all the code should be wrapped up in its own object, so that its functions don’t collide with anyone else’s functions. So, create a single object called capslock and make all the functions be named methods of the object:

var capslock = {
	... 
	keypress: function(e) {
	}
	...
}

Also, the “create an image” code is saved into its own named function, show_warning(), and the converse “remove the image” code into hide_warning(). This has the advantage that developers can include the JavaScript library that has been written here, but override what actually happens with their own code, using something like:

<script src="jscapslock.js" type="text/javascript"></script>
<script type="text/javascript">
	capslock.show_warning(target) {
		// do something different here to warn the user
	}
	capslock.hide_warning(target) {
		// hide the warning that we created in show_warning() above
	}
</script>

And that’s all. Simply include the JavaScript library in your pages, override what happens on a warning if that’s more appropriate for what you’re doing, and that’s all you need.

 See the script in action.


title: 10 Ways To Get Design Approval
year: 2007
author: Paul Boag
author_slug: paulboag
published: 2007-12-10T00:00:00+00:00
url: https://24ways.org/2007/10-ways-to-get-design-approval/
topic: business
contents:
One of the most challenging parts of the web design process is getting design sign off. It can prove time consuming, demoralizing and if you are not careful can lead to a dissatisfied client. What is more you can end up with a design that you are ashamed to include in your portfolio.

How then can you ensure that the design you produce is the one that gets built? How can you get the client to sign off on your design? Below are 10 tips learnt from years of bitter experience.

1. Define the role of the client and designer

Many of the clients you work with will not have been involved in a web project before. Even if they have they may have worked in a very different way to what you would expect. Take the time at the beginning of the project to explain their role in the design of the site.

The best approach is to emphasis that their job is to focus on the needs of their users and business. They should concentrate on the broad issues, while you worry about the details of layout, typography and colour scheme.

By clarifying what you expect from the client, you help them to provide the right kind of input throughout the process.

2. Understand the business

Before you open up Photoshop or put pen to paper, take the time to make sure you properly understand not only the brief but the organization behind the site. By understanding their business objectives, organizational structure and marketing strategy your design decisions will be better informed.

You cannot rely upon the brief to provide all of the information you need. It is important to dig deeper and get as good an understanding of their business as possible. This information will prove invaluable when justifying your design decisions.

3. Understand the users

We all like to think of ourselves as user centric designers, but exactly how much effort do you put into knowing your users before beginning the design process?

Take the time to really understand them the best you can. Try to meet with some real prospective users and get to know their needs. Failing that work with the client to produce user personas to help picture exactly what kind of people they are. 

Understanding your users not only improves the quality of your work, but also helps move the discussion away from the personal preferences of the client, to the people who’s opinion really matters.

4. Avoid multiple concepts

Many clients like the idea of having the option to choose between multiple design concepts. However, although on the surface this might appear to be a good idea it can ultimately be counterproductive for design sign off.

In a world of limited budgets it is unwise to waste money on producing designs that are ultimately going to be thrown away. The resources would be better spent refining a single design through multiple iterations.

What is more, multiple concepts often cause confusion rather than clarity. It is common for a client to request one element from one design and another from the second. As any designer knows this seldom works.

5. Use mood boards

Clients are often better at expressing what they don’t like than what they do. This is one of the reasons why they favour producing multiple design concepts. An alternative less costly approach is to create a series of mood boards. These boards contain a collection of colours, typography and imagery which represent different “moods” or directions, which the design could take. 

Mood boards are quick and easy to produce allowing you to try out various design approaches with the client without investing the time needed to produce complete design concepts. This means that by the time you develop a concept the client and designer have already established an understanding about the direction of the design.

6. Say what you like

It is not uncommon for a client to ask for a design that looks similar to another site they like. The problem is that it can often be hard to establish exactly what it is about the site that attracts them. Also in many cases the sites they like are not something you are keen to emulate!

A better approach that was suggested to me by Andy Budd is to show them sites that you think the design should emulate. Keep a collection of screen captures from well designed sites and pick out a few that are relevant to that particular client. Explain why you feel these designs might suit their project and ask for their feedback. If they don’t like your choices then expose them to more of your collection and see what they pick out.

7. Wireframe the homepage

Often clients find it hard to distinguish between design and content and so sometimes reject a design on the basis that the content is not right. This is particularly true when signing off the homepage.

You may therefore find it useful to establish the homepage content before producing the design. That way once they see the design they will not be distracted by the content. One of the best ways to do this is by producing a basic wireframe consisting of a series of content boxes. Once this has been approved you will find the sign off of design much easier.

8. Present your designs

Although it is true that a good design should speak for itself it still needs presenting to the client. The client needs to understand why you have made the design decisions you have, otherwise they will judge the design purely on personal preference. 

Talk them through the design explaining how it meets the needs of their users and business objectives. Refer to the mood boards and preferred sites the client approved and explain how the design is a continuation of those. Never simply email the design through and hope the client interprets your work correctly!

9. Provide written supporting material

Unfortunately, no matter how well you justify the design to the client he is almost certain to want to show it to others. He may need his bosses approval or require internal buy in. At the very least he is going to want to get a second opinion from a friend or colleague.

The problem with this is that you are not going to be there to present to these people in the same way you did for the client. You cannot expect the client to present your ideas as well as you did. The reality is that you have lost control of how the design is perceived.

One way to minimize this problem is to provide written documentation supporting the design. This can be a summary of the presentation you gave to the client and allows him to distribute this along with the design. By putting a written explanation with the design you ensure that everybody who sees it gets the same message.

10. Control the feedback

My final piece of advice for managing design sign off is to control the way you receive feedback. A clients natural inclination will be to give you his personal opinion on the design. This is reinforced because you ask them what they think of the design. Instead ask them what their users will think of the design. Encourage them to think from the users perspective.

Also encourage them to keep that overarching focus I talked about in my first tip. Their tendency will be to try to improve the design, however that should be your problem not theirs. The role of a client should be to defend the needs of their users and business not do the design. Encourage the client to make comments such as “I am not sure that my female users will like the masculine colours” rather than “can we make the whole design pink.” It is down to them to identify the problems and for you as the designer to find the most appropriate solution.

So there you have it. My 10 tips to improve design sign off. Will this ensure design approval every time? Unfortunately not. However it should certainly help smooth the way.


title: How Media Studies Can Massage Your Message
year: 2007
author: Molly Holzschlag
author_slug: mollyholzschlag
published: 2007-12-22T00:00:00+00:00
url: https://24ways.org/2007/how-media-studies-can-massage-your-message/
topic: ux
contents:
A young web designer once told his teacher ‘just get to the meat already.’ He was frustrated with what he called the ‘history lessons and name-dropping’ aspects of his formal college course. He just wanted to learn how to build Web sites, not examine the reasons why.

Technique and theory are both integrated and necessary portions of a strong education. The student’s perspective has direct value, but also holds a distinct sorrow: Knowing the how without the why creates a serious problem. Without these surrounding insights we cannot tap into the influence of the history and evolved knowledge that came before. We cannot properly analyze, criticize, evaluate and innovate beyond the scope of technique.

History holds the key to transcending former mistakes. Philosophy encourages us to look at different points of view. Studying media and social history empowers us as Web workers by bringing together myriad aspects of humanity in direct relation to the environment of society and technology. Having an understanding of media, communities, communication arts as well as logic, language and computer savvy are all core skills of the best of web designers in today’s medium.

Controlling the Message


	‘The computer can’t tell you the emotional story. It can give you the exact mathematical design, but what’s missing is the eyebrows.’ – Frank Zappa


Media is meant to express an idea. The great media theorist Marshall McLuhan suggests that not only is media interesting because it’s about the expression of ideas, but that the media itself actually shapes the way a given idea is perceived.  This is what McLuhan meant when he uttered those famous words: ‘The medium is the message.’

If instead of actually serving a steak to a vegetarian friend, what might a painting of the steak mean instead? Or a sculpture of a cow? Depending upon the form of media in question, the message is altered.

Figure 1

Must we know the history of cows to appreciate the steak on our plate? Perhaps not, but if we begin to examine how that meat came to be on the plate, the social, cultural and ideological associations of that cow, we begin to understand the complexity of both medium and message. A piece of steak on my plate makes me happy. A vegetarian friend from India might disagree and even find that that serving her a steak was very insensitive.

Takeaway: Getting the message right involves understanding that message in order to direct it to your audience accordingly.

A Separate Piece

If we revisit the student who only wants technique, while he might become extremely adept at the rendering of an idea, without an understanding of the medium, how is he to have greater control over how that idea is perceived?  Ultimately, his creativity is limited and his perspective narrowed, and the teacher has done her student a disservice without challenging him, particularly in a scholastic environment, to think in liberal, creative and ultimately innovative terms.

For many years, web pundits including myself have promoted the idea of separation as a core concept within creating effective front-end media for the Web. By this, we’ve meant literal separation of the technologies and documents: Markup for content; CSS for presentation; DOM Scripting for behavior. While the message of separation was an important part of understanding and teaching best practices for manageable, scalable sites, that separation is really just a separation of pieces, not of entire disciplines.

For in fact, the medium of the Web is an integrated one. That means each part of the desired message must be supported by the media silos within a given site.  The visual designer must study the color, space, shape and placement of visual objects (including type) into a meaningful expression. The underlying markup is ideally written as semantically as possible, promote the meaning of the content it describes. Any interaction and functionality must make the process of the medium support, not take away from, the meaning of the site or Web application.  

Examination: The Glass Bead Game

Figure 2

Figure 2 shows two screenshots of CoreWave’s historic ‘Glass Bead Game.’ Fashioned after Herman Hesse’s novel of the same name, the game was an exploration of how ideas are connected to other ideas via multiple forms of media. It was created for the Web in 1996 using server-side randomization with .htmlx files in order to allow players to see how random associations are in fact not random at all.

Takeaway: We can use the medium itself to explore creative ideas, to link us from one idea to the next, and to help us better express those ideas to our audiences.

Computers and Human Interaction

Since our medium involves computers and human interaction, it does us well to look to foundations of computers and reason. Not long ago I was chatting with Jared Spool on IM about this and that, and he asked me ‘So how do you feel about that?’ This caused me no end of laughter and I instantly quipped back ‘It’s okay by me ELIZA.’ We both enjoyed the joke, but then I tried to share it with another dare I say younger colleague, and the reference was lost.

Raise your hand if you got the reference! Some of you will, but many people who come to the Web medium do not get the benefit of such historical references because we are not formally educated in them. Joseph Weizenbaum created the ELIZA program, which emulates a Rogerian Therapist, in 1966. It was an early study of computers and natural human language. I was a little over 2 years old, how about you?

Conversation with Eliza

There are fortunately a number of ELIZA emulators on the Web. I found one at http://www.chayden.net/eliza/Eliza.html that actually contains the source code (in Java) that makes up the ELIZA script.

Figure 3 shows a screen shot of the interaction. ELIZA first welcomes me, says ‘Hello, How do you do. Please state your problem’ and we continue in a short loop of conversation, the computer using cues from my answers to create new questions and leading fragments of conversation.

Figure 3

Albeit a very limited demonstration of how humans could interact with a computer in 1966, it’s amusing to play with now and compare it to something as richly interactive as the Microsoft Surface (Figure 4). Here, we see clear Lucite blocks that display projected video. Each side of the block has a different view of the video, so not only does one have to match up the images as they are moving, but do so in the proper directionality.

Figure 4

Takeway: the better we know our environment, the more we can alter it to emulate, expand and even supersede our message.

Leveraging Holiday Cheer

Since most of us at least have a few days off for the holidays now that Christmas is upon us, now’s a perfect time to reflect on ones’ environment and examine the messages within it. Convince your spouse to find you a few audio books for stocking stuffers. Find interactive games to play with your kids and observe them, and yourself, during the interaction. Pour a nice egg-nog and sit down with a copy of Marshall McLuhan’s ‘The Medium is the Massage.’ Leverage that holiday cheer and here’s to a prosperous, interactive new year.


title: Tracking Christmas Cheer with Google Charts
year: 2007
author: Brian Suda
author_slug: briansuda
published: 2007-12-11T00:00:00+00:00
url: https://24ways.org/2007/tracking-christmas-cheer-with-google-charts/
topic: ux
contents:
A note from the editors:  Since this article was written Google has retired the Charts API.
                
                
                      
                Let’s get something out in the open: I love statistics. As an informatician I can’t get enough graphs, charts, and numbers. So you can imagine when Google released their Charts API I thought Christmas had come early. I immediately began to draw up graphs for the holiday season using the new API; and using my new found chart-making skills I’ll show you what you can and can’t do with Google Charts.

Mummy, it’s my first chart

The Google Charts API allows you to send data to Google; in return they give you back a nicely-rendered graph. All the hard work is done on Google’s servers — you need only reference an image in your HTML. You pass along the data — the numbers for the charts, axis labels, and so on — in the query string of the image’s URL. If you want to add charts to your blog or web site, there’s probably no quicker way to get started.

Here’s a simple example: if we add the following line to an HTML page:

<img src="http://chart.apis.google.com/chart?cht=lc&chs=200x125&chd=s:ZreelPuevfgznf2008" />

Then we’ll see the line graph in Figure 1 appear in our page. That graph is hosted on Google’s own server1: http://chart.apis.google.com/.

Figure 1: A simple example of a line graph created with Google Charts.

If you look at the URL used in the example you’ll notice we’re passing some parameters along in the query string (the bit after the question mark). The query string looks like this:

cht=lc&chs=200x125&chd=s:ZreelPuevfgznf2008

It’s contains everything Google Charts needs to draw the graph.  There are three parameters in the query string:


	cht; this specifies the type of chart Google Charts will generate (in this case, lc is a line chart).
	chs, the value of which is 200x125; this defines the chart’s size (200 pixels wide by 125 pixels high).
	chd, the value of which is s:ZreelPuevfgznf2008; this is the actual chart data, which we’ll discuss in more detail later.


These three parameters are the minimum you need to send to Google Charts in order to create a chart.  There are lots more parameters you can send too (giving you more choice over how a chart is displayed), but you have to include at least these three before a chart can be created. Using these three parameters you can create pie charts, scatter plots, Venn diagrams, bar charts (and more) up to 1,000 pixels wide or 1,000 pixels high (but no more than 300,000 pixels in total).

Christmas pie

After I discovered the option to create a pie chart I instantly thought of graphing all the types of food and beverages that I’ll consume at this year’s Christmas feast. I can represent each item as a percentage of all the food on a pie chart (just thinking about that makes me hungry).

By changing the value of the cht parameter in the image’s query string I can change the chart type from a line chart to a pie chart. Google Charts offers two different types of pie chart: a fancy three-dimensional version and a two-dimensional overhead version. I want to stick with the latter, so I need to change cht=lc to cht=p (the p telling Google Charts to create a pie chart; if you want the three-dimensional version, use cht=p3). As a pie chart is circular I also need to adjust the size of the chart to make it square. Finally, it would be nice to add a title to the graph. I can do this by adding the optional parameter, chtt, to the end of the image URL. I end up with the chart you see in Figure 2.

Figure 2: Pie chart with a title.

To add this chart to your own page, you include the following (notice that you can’t include spaces in URLs, so you need to encode them as plus-signs.):

<img src="http://chart.apis.google.com/chart?chtt=Food+and+Drink+Consumed+Christmas+2007&cht=p&chs=300x300&chd=s:ZreelPuevfgznf2008" />

Ok, that’s great, but there are still two things I want to do before I can call this pie chart complete. First I want to label each slice of the pie. And second I want to include the proper data (at the moment the slices are meaningless). If 2007 is anything like 2006, the break down will be roughly as follows:


		
			Egg nog
			10%
		
		
			Christmas Ham
			20%
		
		
			Milk (not including egg nog)
			8%
		
		
			Cookies
			25%
		
		
			Roasted Chestnuts
			5%
		
		
			Chocolate
			3%
		
		
			Various Other Beverages
			15%
		
		
			Various Other Foods
			9%
		
		
			Snacks
			5%
		


I have nine categories of food and drink to be tracked, so I need nine slice labels. To add these to the chart, I use the chl parameter. All nine labels are sent in one value; I use the vertical-pipe character, |,  to separate them. So I need to append the following to the query string:

chl=Egg+nog|Christmas+Ham|Milk+(not+including+egg+nog)|Cookies|Roast+Chestnuts|Chocolate|Various+Other+Beverages|Various+Other+Foods|Snacks

Next I need to add the corresponding percentage values to the chart labels. Encoding the chart data is the trickiest part of the Google Charts API — but by no means complicated. There are three different ways to encode your data on a chart. As I’m only dealing with small numbers, I’m going to use what Google calls simple encoding.

Simple encoding offers a sixty-two value spectrum in which to represent data. Remember the mandatory option, chd, from the first example? The value for this is split into two parts: the type of encoding and the graph data itself.  These two parts are separated with a colon.  To use simple encoding, the first character of the chd option must be a lower case s. Follow this with a colon and everything after it is considered data for the graph.

In simple encoding, you have sixty-two values to represent your data. These values are lowercase and uppercase letters from the Latin alphabet (fifty-two characters in total) and the digits 0 to 9. Each letter of the alphabet represents a single number: A equals 0, B equals 1, and so on up to Z, which equals 25; a equals 26, b equals 27, and so on up to z, which equals 51. The ten digits represent the numbers 52 to 61: 0 equals 52, 1 equals 53, and 9 equals 61.

In the previous two examples we used the string ZreelPuevfgznf2008 as our chart data; the Z is equal to 25, the r is equal to 42, the e is equal to 30, and so on. I want to encode the percentage values 10, 20, 8, 25, 5, 3, 15, 9 and 5, so in simple encoding I would use the string KUIZFDPJF.

If you think figuring this out for each chart may make your head explode, don’t worry: help is out there.

Do you remember I said I needed to change the image dimensions to be square, to accommodate the pie chart? Well now I’m including labels I need even more room. And as I’m in a Christmassy mood I’m going to add some festive colours too.

The optional chco parameter is used to change the chart color. You set this using the same hexadecimal (“hex”) notation found in CSS. So let’s make our pie chart green by adding chco=00AF33 (don’t start it with a hash character as in CSS) to the image URL. If we only specify one hex colour for the pie chart Google Charts will use shades of that colour for each of the slices. To choose your own colours, pass a comma separated list of colours. The “Milk” and “Cookies” slices were consumed together, so we can make those two slices more of a redish colour.  I’ll use shades of green for the other slices. My chco parameter now looks like this:

chco=00AF33,4BB74C,EE2C2C,CC3232,33FF33,66FF66,9AFF9A,C1FFC1,CCFFCC.

After all this, I’m left with the following URL:

http://chart.apis.google.com/chart?chco=00AF33,4BB74C,EE2C2C,CC3232,33FF33,66FF66,9AFF9A,C1FFC1,CCFFCC&chl=Egg+nog|Christmas+Ham|Milk+(not+including+egg+nog)|Cookies|Roast+Chestnuts|Chocolate|Various+Other+Beverages|Various+Other+Foods|Snacks&chtt=Food+and+Drink+Consumed+Christmas+2007&cht=p&chs=600x300&chd=s:KUIZFDPJF

What does that give us?  I’m glad you asked.  I have the rather beautiful 600-pixel wide pie chart you see in Figure 3.

Figure 3: A Christmassy pie chart with labels.

But I don’t like pie charts

The pie chart was invented by the Scottish polymath William Playfair in 1801.  But not everyone is as excited by pie charts as wee Billy, so if you’re an anti-pie-chartist, what can you do?

You can easily reuse the same data but display it as a bar graph in a snap. The first thing we need to do is change the value of the cht parameter from p to bhg. This creates a horizontal bar graph (you can request a vertical bar graph using bvg). The data and labels all remain the same, but we need to decide where the labels will appear. I’ll talk more about how to do all this in the next section. 

In Figure 4 you’ll see the newly-converted bar graph. The URL for the graph is:

http://chart.apis.google.com/chart?cht=bhg&chs=600x300&chd=s:KUIZFDPJF&chxt=x,y&chtt=Food+and+Drink+Consumed+Christmas+2007&chxl=1:|Egg+nog|Christmas+Ham|Milk+(not+including+egg+nog)|Cookies|Roast+Chestnuts|Chocolate|Various+Other+Beverages|Various+Other+Foods|Snacks&chco=00AF33

Figure 4: The pie chart from Figure 3 represented as a bar chart.

Two lines, one graph

Pie charts and bar charts are interesting, but what if I want to compare last year’s Christmas cheer with this year’s? That sounds like I’ll need two lines on one graph.

The code is much the same as the previous examples; the most obvious difference is I need to set up the chart as a line graph. Creating some dummy values for the required parameters, I end up with:

<img src="http://chart.apis.google.com/chart?chs=800x300&cht=lxy&chd=t:0,100|0,100" />

The chs=800x300 sets the dimensions of the new chart, while cht=lxy describes the type of chart we are using (in this case a line chart with x and y co-ordinates). For the chart data I’m going to demostrate a different encoding, text encoding. To use this I start the value of the chd parameter with “t:”  instead of “s:”, and follow it with a list of x coordinates, a vertical pipe, |, and a list of y coordinates. Given the URL above, Google Charts will render the chart shown in Figure 5.

Figure 5: A simple line graph with x and y co-ordinates.

To make this graph a little more pleasing to the eye, I can add much the same as I did to the pie chart. I’ll add a chart title. Maybe something like “Projected Christmas Cheer for 2007”. Just as before I would add a chtt parameter to the image URL:

&chtt=Projected+Christmas+Cheer+for+2007

Next, let’s add some labels on the y axis to represent a scale from 0 to 100. On the x axis let’s label for the most important days of December. To do this I need to use the chart axis type parameter, chxt. This allows us to specify the axes and associate some labels with them. As I’m only interested in the y-axis (to the left of the chart) and the x-axis (below the chart), we add chxt=x,y to our image URL.

Now I need my label data. This is slightly more tricky because I want the data evenly spaced without labelling every item. The parameter for labels is chxl, the chart axis label. You match a label to an axis by using a number. So 0:Label1 is the zero index of chxt — in this case the x-axis. 1:Label2 is the first index of chxt — the y-axis. The order of these parameters or labels doesn’t matter as long as you associate them to their chxt correctly.

The next thing to know about chxl is that you can add an empty label. Labels are separated by vertical pipe; if you don’t put any text in a label, you just leave the two vertical pipes empty (“||”) and Google Charts will allocate space but no label.

For our vertical y axis, we want to label only 50% and 100% on the graph and plot them in their respective places. Since the y-axis is the second item, 1: (remember to start counting at zero), we add ten spaces to our image URL, chxl=1:||||||50|||||100 This will output the 50 halfway and the 100 at the top; all the other spaces will be empty.

We can do the same thing to get specific dates along the x-axis as well. Let’s add the 1st of December, St. Nick’s Day (the 6th), Christmas Day, Boxing Day (a holiday common in the UK and the Commonwealth, on the 26th), and the final day of the month, the 31st.  Since this is the x-axis I’ll use 0: as a reference in the chxt parameter tell Google Charts which axis to label. In full, the chxl parameter now looks like:

chxl=1:||||||50|||||100|0:|Dec+1st|||||6th||||10th|||||15th|||||20th|||||25th|26th|||||Dec+31st

That’s pretty.

Before we begin to graph our data, I’ll do one last thing: add some grid lines to the chart so to better connect the data to the labels. The parameter for this is chg, short for chart grid lines. The parameter takes four comma-separated arguments. The first is the x-axis spacing for the grid. I have thirty-one days, so I need thirty vertical lines. The chart is 100% wide, so 3.33 (100 divided by 30) is the required spacing.

As for the y-axis: the axis goes up to 100% but we probably only need to have a horizontal line every 10%, so the required spacing is 10 (100 divided by 10). That is the second argument.

The last two arguments control the dash-style of the grid-lines. The first number is the length of the line dash and the second is the space between the dashes. So 6,3 would mean a six-unit dash with a three-unit space. I like a ratio of 1,3 but you can change this as you wish. Now that I have the four arguments, the chg parameter looks like:

chg=3.333,10,1,3

If I add that to the chart URL I end up with:

http://chart.apis.google.com/chart?chs=800x300&cht=lxy&chd=t:0,100|0,100&chtt=Projected+Christmas+Cheer+for+2007&chxt=x,y&chxl=0:|Dec+1st|||||6th|||||||||||||||||||25th|26th|||||Dec+31st|1:||||||50|||||100&chg=3.3333,10,1,3

Which results in the chart shown in Figure 6.

Figure 6: Chart ready to receive the Christmas cheer values.

Real data

Now the chart is ready I can add historical data from 2006 and current data from 2007.

Having a look at last year’s cheer levels we find some highs and lows through-out the month:


		
			Dec 1st
			Advent starts; life is good
			30%
		
		
			Dec 6th
			St. Nick’s Day, awake to find good things in my shoes
			45%
		
		
			Dec 8th
			Went Christmas carolling, nearly froze
			20%
		
		
			Dec 10th
			Christmas party at work, very nice dinner
			50%
		
		
			Dec 18th
			Panic Christmas shopping, hate rude people
			15%
		
		
			Dec 23rd
			Off Work, home eating holiday food
			80%
		
		
			Dec 25th
			Opened presents, good year, but got socks again from Grandma
			60%
		
		
			Dec 26th
			Boxing Day; we’re off and no one knows why
			70%
		
		
			Dec 28th
			Third day of left overs
			40%
		
		
			Dec 29th
			Procured some fireworks for new years
			55%
		
		
			Dec 31st
			New Year’s Eve
			80%
		


Since I’m plotting data for 2006 and 2007 on the same graph I’ll need two different colours — one for each year’s line — and a key to denote what each colour represents. The key is controlled by the chdl (chart data legend) parameter. Again, each part of the parameter is separated by a vertical pipe, so for two labels I’ll use chdl=2006|2007. I also want to colour-code them, so I’ll need to add the chco as I did for the pie chart. I want a red line and a green line, so I’ll use chco=458B00,CD2626 and add this to the image URL.

Let’s begin to plot the 2006 data on the Chart, replacing our dummy data of chd=t:0,100|0,100 with the correct information. The chd works by first listing all the x coordinates (each separated by a comma), then a vertical pipe, and then all the y coordinates (also comma-separated). The chart is 100% wide, so I need to convert the days into a percentage of the month.

The 1st of December is 0 and the 31st is 100. Everything else is somewhere in between. Our formula is:

(d – 1) × 100 ÷ (31 – 1)

Where d is the day of the month. The formula states that each day will be printed every 3.333 units; so the 6th of December will be printed at 16.665 units. I can repeat the process for the other dates listed to get the following x coordinates: 0,16.7,23.3,33.3,60,76.7,83.3,86.7,93.3,96.7. The y axis coordinates are easy because our scale is 100%, just like our rating, so we can simply copy them across as 30,45,20,50,15,80,60,70,40,55,80. This gives us a final chd value of:

chd=t:0,16.7,23.3,33.3,60,76.7,83.3,86.7,93.3,96.7,100|30,45,20,50,15,80,60,70,40,55,80

Onto 2007: I can put the data for the month so far to see how we are trending.


		
			Dec 1st
			Christmas shopping finished already
			50%
		
		
			Dec 4th
			Computer hard disk drive crashed (not Christmas related accident, but put me in a bad mood)
			10%
		
		
			Dec 6th
			Missed St. Nick’s Day completely due to travelling
			30%
		
		
			Dec 9th
			Dinner with friends before they travel
			55%
		
		
			Dec 11th
			24ways article goes live
			60%
		


Using the same system we did for 2006, I can take the five data points and plot them on the chart. The new x axis values will be 0,10,16.7,26.7 and the new y axis 50,10,30,65. We incorporate those into the image URL by appending these values onto the chd parameter we already have, which then becomes:

chd=t:0,16.7,23.3,33.3,60,76.7,83.3,86.7,93.3,96.7,100|30,45,20,50,15,80,60,70,40,55,80|0,10,16.7,26.7,33.3|50,10,30,55,60

Passing this to Google Charts results in Figure 7.

http://chart.apis.google.com/chart?chs=800x300&cht=lxy&chd=t:0,100|0,100&chtt=Projected+Christmas+Cheer+for+2007&chxt=x,y&chxl=0:|Dec+1st|||||6th|||||||||||||||||||25th|26th|||||Dec+31st|1:||||||50|||||100&chg=3.3333,10,1,3&chd=t:0,16.7,23.3,33.3,60,76.7,83.3,86.7,93.3,96.7,100|30,45,20,50,15,80,60,70,40,55,80|0,10,16.7,26.7,33.3|50,10,30,55,60&chco=458B00,CD2626&chdl=2006|2007

Figure 7: Projected Christmas cheer for 2006 and 2007.

Did someone mention Edward Tufte?

Google Charts are a robust set of chart types that you can create easily and freely using their API. As you can see, you can graph just about anything you want using the line graph, bar charts, scatter plots, venn diagrams and pie charts. One type of chart conspicuously missing from the API is sparklines.  Sparklines were proposed by Edward Tufte as “small, high resolution graphics embedded in a context of words, numbers, images”.  They can be extremely useful, but can you create them in Google Charts?

The answer is: “Yes, but it’s an undocumented feature”. (The usual disclaimer about undocumented features applies.)

If we take our original line graph example, and change the value of the cht parameter from lc (line chart) to lfi (financial line chart) the axis-lines are removed. This allows you to make a chart — a sparkline — small enough to fit into a sentence. Google uses the lfi type all throughout the their financial site, but it’s not yet part of the official API.


		
			MerryChristmas
			
			http://chart.apis.google.com/chart?cht=lfi&chs=100x15&chd=s:MerryChristmas
		
		
			24ways
			
			http://chart.apis.google.com/chart?cht=lfi&chs=100x15&chd=s:24ways&chco=999999
		
		
			HappyHolidays
			
			http://chart.apis.google.com/chart?cht=lfi&chs=100x15&chd=s:HappyHolidays&chco=ff0000
		
		
			HappyNewYear
			
			http://chart.apis.google.com/chart?cht=lfi&chs=100x15&chd=s:HappyNewYear&chco=0000ff
		


Summary

The new Google Charts API is a powerful method for creating charts and graphs of all types. If you apply a little bit of technical skill you can create pie charts, bar graphs, and even sparklines as and when you need them. Now you’ve finished ready the article I hope you waste no more time: go forth and chart!

Further reading


	Google Charts API
	More on Google Charts
	How to handle negative numbers
	12 Days of Christmas Pie Chart


1 In order to remain within the 50,000 requests a day limit the Google Charts API imposes, chart images on this page have been cached and are being served from our own servers. But the URLs work – try them!


title: Keeping JavaScript Dependencies At Bay
year: 2007
author: Christian Heilmann
author_slug: chrisheilmann
published: 2007-12-18T00:00:00+00:00
url: https://24ways.org/2007/keeping-javascript-dependencies-at-bay/
topic: code
contents:
As we are writing more and more complex JavaScript applications we run into issues that have hitherto (god I love that word) not been an issue. The first decision we have to make is what to do when planning our app: one big massive JS file or a lot of smaller, specialised files separated by task. 

Personally, I tend to favour the latter, mainly because it allows you to work on components in parallel with other developers without lots of clashes in your version control. It also means that your application will be more lightweight as you only include components on demand.

Starting with a global object

This is why it is a good plan to start your app with one single object that also becomes the namespace for the whole application, say for example myAwesomeApp:

var myAwesomeApp = {};

You can nest any necessary components into this one and also make sure that you check for dependencies like DOM support right up front.

Adding the components

The other thing to add to this main object is a components object, which defines all the components that are there and their file names.

var myAwesomeApp = {
	components :{
		formcheck:{
			url:'formcheck.js',
			loaded:false
		},
		dynamicnav:{
			url:'dynamicnav.js',
			loaded:false
		},
		gallery:{
			url:'gallery.js',
			loaded:false
		},
		lightbox:{
			url:'lightbox.js',
			loaded:false
		}
	}
};

Technically you can also omit the loaded properties, but it is cleaner this way. The next thing to add is an addComponent function that can load your components on demand by adding new SCRIPT elements to the head of the documents when they are needed.

var myAwesomeApp = {
	components :{
		formcheck:{
			url:'formcheck.js',
			loaded:false
		},
		dynamicnav:{
			url:'dynamicnav.js',
			loaded:false
		},
		gallery:{
			url:'gallery.js',
			loaded:false
		},
		lightbox:{
			url:'lightbox.js',
			loaded:false
		}
	},
	addComponent:function(component){
		var c = this.components[component];
		if(c && c.loaded === false){
			var s = document.createElement('script');
			s.setAttribute('type', 'text/javascript');
			s.setAttribute('src',c.url);
			document.getElementsByTagName('head')[0].appendChild(s);
		}
	}
};

This allows you to add new components on the fly when they are not defined:

if(!myAwesomeApp.components.gallery.loaded){
	myAwesomeApp.addComponent('gallery');
};

Verifying that components have been loaded

However, this is not safe as the file might not be available. To make the dynamic adding of components safer each of the components should have a callback at the end of them that notifies the main object that they indeed have been loaded:

var myAwesomeApp = {
	components :{
		formcheck:{
			url:'formcheck.js',
			loaded:false
		},
		dynamicnav:{
			url:'dynamicnav.js',
			loaded:false
		},
		gallery:{
			url:'gallery.js',
			loaded:false
		},
		lightbox:{
			url:'lightbox.js',
			loaded:false
		}
	},
	addComponent:function(component){
		var c = this.components[component];
		if(c && c.loaded === false){
			var s = document.createElement('script');
			s.setAttribute('type', 'text/javascript');
			s.setAttribute('src',c.url);
			document.getElementsByTagName('head')[0].appendChild(s);
		}
	},
	componentAvailable:function(component){
		this.components[component].loaded = true;
	}
}

For example the gallery.js file should call this notification as a last line:

myAwesomeApp.gallery = function(){
	// [... other code ...]
}();
myAwesomeApp.componentAvailable('gallery');

Telling the implementers when components are available

The last thing to add (actually as a courtesy measure for debugging and implementers) is to offer a listener function that gets notified when the component has been loaded:

var myAwesomeApp = {
	components :{
		formcheck:{
			url:'formcheck.js',
			loaded:false
		},
		dynamicnav:{
			url:'dynamicnav.js',
			loaded:false
		},
		gallery:{
			url:'gallery.js',
			loaded:false
		},
		lightbox:{
			url:'lightbox.js',
			loaded:false
		}
	},
	addComponent:function(component){
		var c = this.components[component];
		if(c && c.loaded === false){
			var s = document.createElement('script');
			s.setAttribute('type', 'text/javascript');
			s.setAttribute('src',c.url);
			document.getElementsByTagName('head')[0].appendChild(s);
		}
	},
	componentAvailable:function(component){
		this.components[component].loaded = true;
		if(this.listener){
			this.listener(component);
		};
	}
};

This allows you to write a main listener function that acts when certain components have been loaded, for example:

myAwesomeApp.listener = function(component){
	if(component === 'gallery'){
	   showGallery();
	}
};

Extending with other components

As the main object is public, other developers can extend the components object with own components and use the listener function to load dependent components. Say you have a bespoke component with data and labels in extra files:

myAwesomeApp.listener = function(component){
	if(component === 'bespokecomponent'){
		myAwesomeApp.addComponent('bespokelabels');
	};
	if(component === 'bespokelabels'){
		myAwesomeApp.addComponent('bespokedata');
	};
	if(component === 'bespokedata'){
		myAwesomeApp,bespokecomponent.init();
	};
};
myAwesomeApp.components.bespokecomponent = {
	url:'bespoke.js',
	loaded:false
};
myAwesomeApp.components.bespokelabels = {
	url:'bespokelabels.js',
	loaded:false
};
myAwesomeApp.components.bespokedata = {
	url:'bespokedata.js',
	loaded:false
};
myAwesomeApp.addComponent('bespokecomponent');

Following this practice you can write pretty complex apps and still have full control over what is available when. You can also extend this to allow for CSS files to be added on demand.

Influences

If you like this idea and wondered if someone already uses it, take a look at the Yahoo! User Interface library, and especially at the YAHOO_config option of the global YAHOO.js object.


title: Conditional Love
year: 2007
author: Ethan Marcotte
author_slug: ethanmarcotte
published: 2007-12-15T00:00:00+00:00
url: https://24ways.org/2007/conditional-love/
topic: code
contents:
“Browser.” The four-letter word of web design.

I mean, let’s face it: on the good days, when things just work in your target browsers, it’s marvelous. The air smells sweeter, birds’ songs sound more melodious, and both your design and your code are looking sharp.

But on the less-than-good days (which is, frankly, most of them), you’re compelled to tie up all your browsers in a sack, heave them into the nearest river, and start designing all-imagemap websites. We all play favorites, after all: some will swear by Firefox, Opera fans are allegedly legion, and others still will frown upon anything less than the latest WebKit nightly.

Thankfully, we do have an out for those little inconsistencies that crop up when dealing with cross-browser testing: CSS patches.

Spare the Rod, Hack the Browser

Before committing browsercide over some rendering bug, a designer will typically reach for a snippet of CSS fix the faulty browser. Historically referred to as “hacks,” I prefer Dan Cederholm’s more client-friendly alternative, “patches”.

But whatever you call them, CSS patches all work along the same principle: supply the proper property value to the good browsers, while giving higher maintenance other browsers an incorrect value that their frustrating idiosyncratic rendering engine can understand.

Traditionally, this has been done either by exploiting incomplete CSS support:

#content {
	height: 1%;	 // Let's force hasLayout for old versions of IE.
	line-height: 1.6;
	padding: 1em;
}
html>body #content {
	height: auto; // Modern browsers get a proper height value.
}

or by exploiting bugs in their rendering engine to deliver alternate style rules:

#content p {
	font-size: .8em;
	/* Hide from Mac IE5 \*/
	font-size: .9em;
	/* End hiding from Mac IE5 */
}

We’ve even used these exploits to serve up whole stylesheets altogether:

@import url("core.css");
@media tty {
	i{content:"\";/*" "*/}} @import 'windows-ie5.css'; /*";}
}/* */

The list goes on, and on, and on. For every browser, for every bug, there’s a patch available to fix some rendering bug.

But after some time working with standards-based layouts, I’ve found that CSS patches, as we’ve traditionally used them, become increasingly difficult to maintain. As stylesheets are modified over the course of a site’s lifetime, inline fixes we’ve written may become obsolete, making them difficult to find, update, or prune out of our CSS. A good patch requires a constant gardener to ensure that it adds more than just bloat to a stylesheet, and inline patches can be very hard to weed out of a decently sized CSS file.

Giving the Kids Separate Rooms

Since I joined Airbag Industries earlier this year, every project we’ve worked on has this in the head of its templates:

<link rel="stylesheet" href="-/css/screen/main.css" type="text/css" media="screen, projection" />
<!--[if lt IE 7]>
<link rel="stylesheet" href="-/css/screen/patches/win-ie-old.css" type="text/css" media="screen, projection" />
<![endif]-->
<!--[if gte IE 7]>
<link rel="stylesheet" href="-/css/screen/patches/win-ie7-up.css" type="text/css" media="screen, projection" />
<![endif]-->

The first element is, simply enough, a link element that points to the project’s main CSS file. No patches, no hacks: just pure, modern browser-friendly style rules. Which, nine times out of ten, will net you a design that looks like spilled eggnog in various versions of Internet Explorer.

But don’t reach for the mulled wine quite yet. Immediately after, we’ve got a brace of conditional comments wrapped around two other link elements. These odd-looking comments allow us to selectively serve up additional stylesheets just to the version of IE that needs them. We’ve got one for IE 6 and below:

<!--[if lt IE 7]>
<link rel="stylesheet" href="-/css/screen/patches/win-ie-old.css" type="text/css" media="screen, projection" />
<![endif]-->

And another for IE7 and above:

<!--[if gte IE 7]>
<link rel="stylesheet" href="-/css/screen/patches/win-ie7-up.css" type="text/css" media="screen, projection" />
<![endif]-->

Microsoft’s conditional comments aren’t exactly new, but they can be a valuable alternative to cooking CSS patches directly into a master stylesheet. And though they’re not a W3C-approved markup structure, I think they’re just brilliant because they innovate within the spec: non-IE devices will assume that the comments are just that, and ignore the markup altogether.

This does, of course, mean that there’s a little extra markup in the head of our documents. But this approach can seriously cut down on the unnecessary patches served up to the browsers that don’t need them. Namely, we no longer have to write rules like this in our main stylesheet:

#content {
	height: 1%;	// Let's force hasLayout for old versions of IE.
	line-height: 1.6;
	padding: 1em;
}
html>body #content {
	height: auto;	// Modern browsers get a proper height value.
}

Rather, we can simply write an un-patched rule in our core stylesheet:

#content {
	line-height: 1.6;
	padding: 1em;
}

And now, our patch for older versions of IE goes in—you guessed it—the stylesheet for older versions of IE:

#content {
	height: 1%;
}

The hasLayout patch is applied, our design’s repaired, and—most importantly—the patch is only seen by the browser that needs it. The “good” browsers don’t have to incur any added stylesheet weight from our IE patches, and Internet Explorer gets the conditional love it deserves.

Most importantly, this “compartmentalized” approach to CSS patching makes it much easier for me to patch and maintain the fixes applied to a particular browser. If I need to track down a bug for IE7, I don’t need to scroll through dozens or hundreds of rules in my core stylesheet: instead, I just open the considerably slimmer IE7-specific patch file, make my edits, and move right along.

Even Good Children Misbehave

While IE may occupy the bulk of our debugging time, there’s no denying that other popular, modern browsers will occasionally disagree on how certain bits of CSS should be rendered. But without something as, well, pimp as conditional comments at our disposal, how do we bring the so-called “good browsers” back in line with our design?

Assuming you’re loving the “one patch file per browser” model as much as I do, there’s just one alternative: JavaScript.

function isSaf() {
	var isSaf = (document.childNodes && !document.all && !navigator.taintEnabled && !navigator.accentColorName) ? true : false;
	return isSaf;
}
function isOp() {
	var isOp = (window.opera) ? true : false;
	return isOp;
}

Instead of relying on dotcom-era tactics of parsing the browser’s user-agent string, we’re testing here for support for various DOM objects, whose presence or absence we can use to reasonably infer the browser we’re looking at. So running the isOp() function, for example, will test for Opera’s proprietary window.opera object, and thereby accurately tell you if your user’s running Norway’s finest browser.

With scripts such as isOp() and isSaf() in place, you can then reasonably test which browser’s viewing your content, and insert additional link elements as needed.

function loadPatches(dir) {
	if (document.getElementsByTagName() && document.createElement()) {
		var head = document.getElementsByTagName("head")[0];
		if (head) {
			var css = new Array();
			if (isSaf()) {
				css.push("saf.css");
			} else if (isOp()) {
				css.push("opera.css");
			}
			if (css.length) {
				var link = document.createElement("link");
				link.setAttribute("rel", "stylesheet");
				link.setAttribute("type", "text/css");
				link.setAttribute("media", "screen, projection");
				for (var i = 0; i < css.length; i++) {
					var tag = link.cloneNode(true);
					tag.setAttribute("href", dir + css[0]);
					head.appendChild(tag);
				}
			}
		}
	}
}

Here, we’re testing the results of isSaf() and isOp(), one after the other. For each function that returns true, then the name of a new stylesheet is added to the oh-so-cleverly named css array. Then, for each entry in css, we create a new link element, point it at our patch file, and insert it into the head of our template.

Fire it up using your favorite onload or DOMContentLoaded function, and you’re good to go.

Scripteat Emptor

At this point, some of the audience’s more conscientious ‘scripters may be preparing to lob figgy pudding at this author’s head. And that’s perfectly understandable; relying on JavaScript to patch CSS chafes a bit against the normally clean separation we have between our pages’ content, presentation, and behavior layers.

And beyond the philosophical concerns, this approach comes with a few technical caveats attached:

Browser detection? So un-133t.

Browser detection is not something I’d typically recommend. Whenever possible, a proper DOM script should check for the support of a given object or method, rather than the device with which your users view your content.

It’s JavaScript, so don’t count on it being available.

According to one site, roughly four percent of Internet users don’t have JavaScript enabled. Your site’s stats might be higher or lower than this number, but still: don’t expect that every member of your audience will see these additional stylesheets, and ensure that your content’s still accessible with JS turned off.

Be a constant gardener.

The sample isSaf() and isOp() functions I’ve written will tell you if the user’s browser is Safari or Opera. As a result, stylesheets written to patch issues in an old browser may break when later releases repair the relevant CSS bugs.

You can, of course, add logic to these simple little scripts to serve up version-specific stylesheets, but that way madness may lie. In any event, test your work vigorously, and keep testing it when new versions of the targeted browsers come out. Make sure that a patch written today doesn’t become a bug tomorrow.

Patching Firefox, Opera, and Safari isn’t something I’ve had to do frequently: still, there have been occasions where the above script’s come in handy. Between conditional comments, careful CSS auditing, and some judicious JavaScript, browser-based bugs can be handled with near-surgical precision.

So pass the ‘nog. It’s patchin’ time.


title: Get To Grips with Slippy Maps
year: 2007
author: Andrew Turner
author_slug: andrewturner
published: 2007-12-02T00:00:00+00:00
url: https://24ways.org/2007/get-to-grips-with-slippy-maps/
topic: code
contents:
Online mapping has definitely hit mainstream. Google Maps made ‘slippy maps’ popular and made it easy for any developer to quickly add a dynamic map to his or her website. You can now find maps for store locations, friends nearby, upcoming events, and embedded in blogs. 

In this tutorial we’ll show you how to easily add a map to your site using the Mapstraction mapping library. There are many map providers available to choose from, each with slightly different functionality, design, and terms of service. Mapstraction makes deciding which provider to use easy by allowing you to write your mapping code once, and then easily switch providers.

Assemble the pieces

Utilizing any of the mapping library typically consists of similar overall steps:


	Create an HTML div to hold the map
	Include the Javascript libraries
	Create the Javascript Map element
	Set the initial map center and zoom level
	Add markers, lines, overlays and more


Create the Map Div

The HTML div is where the map will actually show up on your page. It needs to have a unique id, because we’ll refer to that later to actually put the map here. This also lets you have multiple maps on a page, by creating individual divs and Javascript map elements. The size of the div also sets the height and width of the map. You set the size using CSS, either inline with the element, or via a CSS reference to the element id or class. For this example, we’ll use inline styling.

<div id="map" style="width: 400px; height: 400px;"></div>

Include Javascript libraries

A mapping library is like any Javascript library. You need to include the library in your page before you use the methods of that library. For our tutorial, we’ll need to include at least two libraries: Mapstraction, and the mapping API(s) we want to display. Our first example we’ll use the ubiquitous Google Maps library. However, you can just as easily include Yahoo, MapQuest, or any of the other supported libraries.

Another important aspect of the mapping libraries is that many of them require an API key. You will need to agree to the terms of service, and get an API key these.

<script src="http://maps.google.com/maps?file=api&v=2&key=YOUR_KEY" type="text/javascript"></script>
<script type="text/javascript" src="http://mapstraction.com/src/mapstraction.js"></script>

Create the Map

Great, we’ve now put in all the pieces we need to start actually creating our map. This is as simple as creating a new Mapstraction object with the id of the HTML div we created earlier, and the name of the mapping provider we want to use for this map. 

With several of the mapping libraries you will need to set the map center and zoom level before the map will appear. The map centering actually triggers the initialization of the map. 

var mapstraction = new Mapstraction('map','google');
var myPoint = new LatLonPoint(37.404,-122.008);
mapstraction.setCenterAndZoom(myPoint, 10);

A note about zoom levels. The setCenterAndZoom function takes two parameters, the center as a LatLonPoint, and a zoom level that has been defined by mapping libraries. The current usage is for zoom level 1 to be “zoomed out”, or view the entire earth – and increasing the zoom level as you zoom in. Typically 17 is the maximum zoom, which is about the size of a house. 

Different mapping providers have different quality of zoomed in maps over different parts of the world. This is a perfect reason why using a library like Mapstraction is very useful, because you can quickly change mapping providers to accommodate users in areas that have bad coverage with some maps. 

To switch providers, you just need to include the Javascript library, and then change the second parameter in the Mapstraction creation. Or, you can call the switch method to dynamically switch the provider.

So for Yahoo Maps  (demo):

var mapstraction = new Mapstraction('map','yahoo');

or Microsoft Maps (demo):

var mapstraction = new Mapstraction('map','microsoft');

want a 3D globe in your browser? try FreeEarth (demo):

var mapstraction = new Mapstraction('map','freeearth');

or even OpenStreetMap (free your data!)  (demo):

var mapstraction = new Mapstraction('map','openstreetmap');

Visit the Mapstraction multiple map demo page for an example of how easy it is to have many maps on your page, each with a different provider. 

Adding Markers

While adding your first map is fun, and you can probably spend hours just sliding around, the point of adding a map to your site is usually to show the location of something. So now you want to add some markers. There are a couple of ways to add to your map.

The simplest is directly creating markers. You could either hard code this into a rather static page, or dynamically generate these using whatever tools your site is built on.

var marker = new Marker( new LatLonPoint(37.404,-122.008) );
marker.setInfoBubble("It's easy to add maps to your site");
mapstraction.addMarker( marker );

There is a lot more you can do with markers, including changing the icon, adding timestamps, automatically opening the bubble, or making them draggable. 

While it is straight-forward to create markers one by one, there is a much easier way to create a large set of markers. And chances are, you can make it very easy by extending some data you already are sharing: RSS. 

Specifically, using GeoRSS you can easily add a large set of markers directly to a map. GeoRSS is a community built standard (like Microformats) that added geographic markup to RSS and Atom entries. It’s as simple as adding <georss:point>42 -83</georss:point> to your feeds to share items via GeoRSS. Once you’ve done that, you can add that feed as an ‘overlay’ to your map using the function:

mapstraction.addOverlay("http://api.flickr.com/services/feeds/groups_pool.gne?id=322338@N20&format=rss_200&georss=1");

Mapstraction also supports KML for many of the mapping providers. So it’s easy to add various data sources together with your own data. Check out Mapufacture for a growing index of available GeoRSS feeds and KML documents. 

Play with your new toys

Mapstraction offers a lot more functionality you can utilize for demonstrating a lot of geographic data on your website. It also includes geocoding and routing abstraction layers for making sure your users know where to go. You can see more on the Mapstraction website: http://mapstraction.com.


title: My Other Christmas Present Is a Definition List
year: 2007
author: Mark Norman Francis
author_slug: marknormanfrancis
published: 2007-12-05T00:00:00+00:00
url: https://24ways.org/2007/my-other-christmas-present-is-a-definition-list/
topic: code
contents:
A note from the editors:  readers should note that the HTML5 redefinition of definition lists has come to pass and is now à la mode.
                
                
                      
                Last year, I looked at how the markup for tag clouds was generally terrible. I thought this year I would look not at a method of marking up a common module, but instead just at a simple part of HTML and how it generally gets abused.

No, not tables. Definition lists. Ah, definition lists. Often used but rarely understood.

Examining the definition of definitions

To start with, let’s see what the HTML spec has to say about them.


	Definition lists vary only slightly from other types of lists in that list items consist of two parts: a term and a description.


The canonical example of a definition list is a dictionary. Words can have multiple descriptions (even the word definition has at least five). Also, many terms can share a single definition (for example, the word colour can also be spelt color, but they have the same definition).

Excellent, we can all grasp that. But it very quickly starts to fall apart. Even in the HTML specification the definition list is mis-used.


	Another application of DL, for example, is for marking up dialogues, with each DT naming a speaker, and each DD containing his or her words.


Wrong. Completely and utterly wrong. This is the biggest flaw in the HTML spec, along with dropping support for the start attribute on ordered lists. “Why?”, you may ask. Let me give you an example from Romeo and Juliet, act 2, scene 2.

<dt>Juliet</dt>
	<dd>Romeo!</dd>
<dt>Romeo</dt>
	<dd>My niesse?</dd>
<dt>Juliet</dt>
	<dd>At what o'clock tomorrow shall I send to thee?</dd>
<dt>Romeo</dt>
	<dd>At the hour of nine.</dd>

Now, the problem here is that a given definition can have multiple descriptions (the DD). Really the dialog “descriptions” should be rolled up under the terms, like so:

<dt>Juliet</dt>
	<dd>Romeo!</dd>
	<dd>At what o'clock tomorrow shall I send to thee?</dd>
<dt>Romeo</dt>
	<dd>My niesse?</dd>
	<dd>At the hour of nine.</dd>

Suddenly the play won’t make anywhere near as much sense. (If it’s anything, the correct markup for a play is an ordered list of CITE and BLOCKQUOTE elements.)

This is the first part of the problem. That simple example has turned definition lists in everyone’s mind from pure definitions to more along the lines of a list with pre-configured heading(s) and text(s).

Screen reader, enter stage left.

In many screen readers, a simple definition list would be read out as “definition term equals definition description”. So in our play excerpt, Juliet equals Romeo! That’s not right, either. But this also leads a lot of people astray with definition lists to believing that they are useful for key/value pairs.

Behaviour and convention

The WHAT-WG have noticed the common mis-use of the DL, and have codified it into the new spec. In the HTML5 draft, a definition list is no longer a definition list.


	The dl element introduces an unordered association list consisting of zero or more name-value groups (a description list). Each group must consist of one or more names (dt elements) followed by one or more values (dd elements).


They also note that the “dl element is inappropriate for marking up dialogue, since dialogue is ordered”. So for that example they have created a DIALOG (sic) element.

Strange, then, that they keep DL as-is but instead refer to it an “association list”. They have not created a new AL element, and kept DL for the original purpose. They have chosen not to correct the usage or to create a new opportunity for increased specificity in our HTML, but to “pave the cowpath” of convention.

How to use a definition list

Given that everyone else is using a DL incorrectly, should we? Well, if they all jumped off a bridge, would you too? No, of course you wouldn’t. We don’t have HTML5 yet, so we’re stuck with the existing semantics of HTML4 and XHTML1. Which means that:


	Listing dialogue is not defining anything.
	Listing the attributes of a piece of hardware (resolution = 1600×1200) is illustrating sample values, not defining anything (however, stating what ‘resolution’ actually means in this context would be a definition).
	Listing the cast and crew of a given movie is not defining the people involved in making movies. (Stuart Gordon may have been the director of Space Truckers, but that by no means makes him the true definition of a director.)
	A menu of navigation items is simply a nested ordered or unordered list of links, not a definition list.
	Applying styling handles to form labels and elements is not a good use for a definition list.


And so on.

Living by the specification, a definition list should be used for term definitions – glossaries, lexicons and dictionaries – only.

Anything else is a crime against markup.


title: Transparent PNGs in Internet Explorer 6
year: 2007
author: Drew McLellan
author_slug: drewmclellan
published: 2007-12-01T00:00:00+00:00
url: https://24ways.org/2007/supersleight-transparent-png-in-ie6/
topic: code
contents:
Newer breeds of browser such as Firefox and Safari have offered support for PNG images with full alpha channel transparency for a few years. With the use of hacks, support has been available in Internet Explorer 5.5 and 6, but the hacks are non-ideal and have been tricky to use. With IE7 winning masses of users from earlier versions over the last year, full PNG alpha-channel transparency is becoming more of a reality for day-to-day use.

However, there are still numbers of IE6 users out there who we can’t leave out in the cold this Christmas, so in this article I’m going to look what we can do to support IE6 users whilst taking full advantage of transparency for the majority of a site’s visitors.

So what’s alpha channel transparency?

Cast your minds back to the Ghost of Christmas Past, the humble GIF. Images in GIF format offer transparency, but that transparency is either on or off for any given pixel. Each pixel’s either fully transparent, or a solid colour. In GIF, transparency is effectively just a special colour you can chose for a pixel.

The PNG format tackles the problem rather differently. As well as having any colour you chose, each pixel also carries a separate channel of information detailing how transparent it is. This alpha channel enables a pixel to be fully transparent, fully opaque, or critically, any step in between.

This enables designers to produce images that can have, for example, soft edges without any of the ‘halo effect’ traditionally associated with GIF transparency. If you’ve ever worked on a site that has different colour schemes and therefore requires multiple versions of each graphic against a different colour, you’ll immediately see the benefit. 

What’s perhaps more interesting than that, however, is the extra creative freedom this gives designers in creating beautiful sites that can remain web-like in their ability to adjust, scale and reflow.

The Internet Explorer problem

Up until IE7, there has been no fully native support for PNG alpha channel transparency in Internet Explorer. However, since IE5.5 there has been some support in the form of proprietary filter called the AlphaImageLoader. Internet Explorer filters can be applied directly in your CSS (for both inline and background images), or by setting the same CSS property with JavaScript. 

CSS:

img {
	filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(...);
}

JavaScript:

img.style.filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(...)";

That may sound like a problem solved, but all is not as it may appear. Firstly, as you may realise, there’s no CSS property called filter in the W3C CSS spec. It’s a proprietary extension added by Microsoft that could potentially cause other browsers to reject your entire CSS rule. 

Secondly, AlphaImageLoader does not magically add full PNG transparency support so that a PNG in the page will just start working. Instead, when applied to an element in the page, it draws a new rendering surface in the same space that element occupies and loads a PNG into it. If that sounds weird, it’s because that’s precisely what it is. However, by and large the result is that PNGs with an alpha channel can be accommodated.

The pitfalls

So, whilst support for PNG transparency in IE5.5 and 6 is possible, it’s not without its problems.

Background images cannot be positioned or repeated

The AlphaImageLoader does work for background images, but only for the simplest of cases. If your design requires the image to be tiled (background-repeat) or positioned (background-position) you’re out of luck. The AlphaImageLoader allows you to set a sizingMethod to either crop the image (if necessary) or to scale it to fit. Not massively useful, but something at least.

Delayed loading and resource use

The AlphaImageLoader can be quite slow to load, and appears to consume more resources than a standard image when applied. Typically, you’d need to add thousands of GIFs or JPEGs to a page before you saw any noticeable impact on the browser, but with the AlphaImageLoader filter applied Internet Explorer can become sluggish after just a handful of alpha channel PNGs.

The other noticeable effect is that as more instances of the AlphaImageLoader are applied, the longer it takes to render the PNGs with their transparency. The user sees the PNG load in its original non-supported state (with black or grey areas where transparency should be) before one by one the filter kicks in and makes them properly transparent.

Both the issue of sluggish behaviour and delayed load only really manifest themselves with volume and size of image. Use just a couple of instances and it’s fine, but be careful adding more than five or six. As ever, test, test, test.

Links become unclickable, forms unfocusable 

This is a big one. There’s a bug/weirdness with AlphaImageLoader that sometimes prevents interaction with links and forms when a PNG background image is used. This is sometimes reported as a z-index issue, but I don’t believe it is. Rather, it’s an artefact of that weird way the filter gets applied to the document almost outside of the normal render process. 

Often this can be solved by giving the links or form elements hasLayout using position: relative; where possible. However, this doesn’t always work and the non-interaction problem cannot always be solved. You may find yourself having to go back to the drawing board.

Sidestepping the danger zones

Frankly, it’s pretty bad news if you design a site, have that design signed off by your client, build it and then find out only at the end (because you don’t know what might trigger a problem) that your search field can’t be focused in IE6. That’s an absolute nightmare, and whilst it’s not likely to happen, it’s possible that it might. It’s happened to me. So what can you do?

The best approach I’ve found to this scenario is


	Isolate the PNG or PNGs that are causing the problem. Step through the PNGs in your page, commenting them out one by one and retesting. Typically it’ll be the nearest PNG to the problem, so try there first. Keep going until you can click your links or focus your form fields.
	This is where you really need luck on your side, because you’re going to have to fake it. This will depend on the design of the site, but some way or other create a replacement GIF or JPEG image that will give you an acceptable result. Then use conditional comments to serve that image to only users of IE older than version 7.


A hack, you say? Well, you started it chum.

Applying AlphaImageLoader

Because the filter property is invalid CSS, the safest pragmatic approach is to apply it selectively with JavaScript for only Internet Explorer versions 5.5 and 6. This helps ensure that by default you’re serving standard CSS to browsers that support both the CSS and PNG standards correct, and then selectively patching up only the browsers that need it. 

Several years ago, Aaron Boodman wrote and released a script called sleight for doing just that. However, sleight dealt only with images in the page, and not background images applied with CSS. Building on top of Aaron’s work, I hacked sleight and came up with bgsleight for applying the filter to background images instead. That was in 2003, and over the years I’ve made a couple of improvements here and there to keep it ticking over and to resolve conflicts between sleight and bgsleight when used together. However, with alpha channel PNGs becoming much more widespread, it’s time for a new version.

Introducing SuperSleight

SuperSleight adds a number of new and useful features that have come from the day-to-day needs of working with PNGs.


	Works with both inline and background images, replacing the need for both sleight and bgsleight
	Will automatically apply position: relative to links and form fields if they don’t already have position set. (Can be disabled.)
	Can be run on the entire document, or just a selected part where you know the PNGs are. This is better for performance.
	Detects background images set to no-repeat and sets the scaleMode to crop rather than scale.
	Can be re-applied by any other JavaScript in the page – useful if new content has been loaded by an Ajax request.


  Download SuperSleight 

Implementation

Getting SuperSleight running on a page is quite straightforward, you just need to link the supplied JavaScript file (or the minified version if you prefer) into your document inside conditional comments so that it is delivered to only Internet Explorer 6 or older.

<!--[if lte IE 6]>
	<script type="text/javascript" src="supersleight-min.js"></script>
<![endif]-->

Supplied with the JavaScript is a simple transparent GIF file. The script replaces the existing PNG with this before re-layering the PNG over the top using AlphaImageLoaded. You can change the name or path of the image in the top of the JavaScript file, where you’ll also find the option to turn off the adding of position: relative to links and fields if you don’t want that.

The script is kicked off with a call to supersleight.init() at the bottom. The scope of the script can be limited to just one part of the page by passing an ID of an element to supersleight.limitTo(). And that’s all there is to it.

Update March 2008: a version of this script as a jQuery plugin is also now available.


title: Performance On A Shoe String
year: 2007
author: Drew McLellan
author_slug: drewmclellan
published: 2007-12-24T00:00:00+00:00
url: https://24ways.org/2007/performance-on-a-shoe-string/
topic: ux
contents:
Back in the summer, I happened to notice the official Wimbledon All England Tennis Club site had jumped to the top of Alexa’s Movers & Shakers list — a list that tracks sites that have had the biggest upturn or downturn in traffic. The lawn tennis championships were underway, and so traffic had leapt from almost nothing to crazy-busy in a no time at all. 

Many sites have similar peaks in traffic, especially when they’re based around scheduled events. No one cares about the site for most of the year, and then all of a sudden – wham! – things start getting warm in the data centre. Whilst the thought of chestnuts roasting on an open server has a certain appeal, it’s less attractive if you care about your site being available to visitors. Take a look at this Alexa traffic graph showing traffic patterns for superbowl.com at the beginning of each year, and wimbledon.org in the month of July.

Traffic graph from Alexa.com 

Whilst not on the same scale or with such dramatic peaks, we have a similar pattern of traffic here at 24ways.org. Over the last three years we’ve seen a dramatic pick up in traffic over the month of December (as would be expected) and then a much lower, although steady load throughout the year. What we do have, however, is the luxury of knowing when the peaks will be. For a normal site, be that a blog, small scale web app, or even a small corporate site, you often just cannot predict when you might get slashdotted, end up on the front page of Digg or linked to from a similarly high-profile site. You just don’t know when the peaks will be.

If you’re a big commercial enterprise like the Super Bowl, scaling up for that traffic is simply a cost of doing business. But for most of us, we can’t afford to have massive capacity sat there unused for 90% of the year. What you have to do instead is work out how to deal with as much traffic as possible with the modest resources you have.

In this article I’m going to talk about some of the things we’ve learned about keeping 24 ways running throughout December, whilst not spending a fortune on hosting we don’t need for 11 months of each year. We’ve not always got it right, but we’ve learned a lot along the way.

The Problem

To know how to deal with high traffic, you need to have a basic idea of what happens when a request comes into a web server. 24 ways is hosted on a single small virtual dedicated server with a great little hosting company in the UK. We run Apache with PHP and MySQL all on that one server. When a request comes in a new Apache process is started to deal with the request (or assigned if there’s one available not doing anything). Each process takes a bunch of memory, so there’s a finite number of processes that you can run, and therefore a finite number of pages you can serve at once before your server runs out of memory.

With our budget based on whatever is left over after beer, we need to get best performance we can out of the resources available. As the goal is to serve as many pages as quickly as possible, there are several approaches we can take:


	Reducing the amount of memory needed by each Apache process
	Reducing the amount of time each process is needed
	Reducing the number of requests made to the server


Yahoo! have published some information on what they call Exceptional Performance, which is well worth reading, and compliments many of my examples here. The Yahoo! guidelines very much look at things from a user perspective, which is always important.

Server tweaking

If you’re in the position of being able to change your server configuration (our set-up gives us root access to what is effectively a virtual machine) there are some basic steps you can take to maximise the available memory and reduce the memory footprint. Without getting too boring and technical (whole books have been written on this) there are a couple of things to watch out for.

Firstly, check what processes you have running that you might not need. Every megabyte of memory that you free up might equate to several thousand extra requests being served each day, so take a look at top and see what’s using up your resources. Quite often a machine configured as a web server will have some kind of mail server running by default. If your site doesn’t use mail (ours doesn’t) make sure it’s shut down and not using resources.

Secondly, have a look at your Apache configuration and particularly what modules are loaded. The method for doing this varies between versions of Apache, but again, every module loaded increases the amount of memory that each Apache process requires and therefore limits the number of simultaneous requests you can deal with.

The final thing to check is that Apache isn’t configured to start more servers than you have memory for. This is usually done by setting the MaxClients directive. When that limit is reached, your site is going to stop responding to further requests. However, if all else goes well that threshold won’t be reached, and if it does it will at least stop the weight of the traffic taking the entire server down to a point where you can’t even log in to sort it out.

Those are the main tidbits I’ve found useful for this site, although it’s worth repeating that entire books have been written on this subject alone.

Caching

Although the site is generated with PHP and MySQL, the majority of pages served don’t come from the database. The process of compiling a page on-the-fly involves quite a few trips to the database for content, templates, configuration settings and so on, and so can be slow and require a lot of CPU. Unless a new article or comment is published, the site doesn’t actually change between requests and so it makes sense to generate each page once, save it to a file and then just serve all following requests from that file.

We use QuickCache (or rather a plugin based on it) for this. The plugin integrates with our publishing system (Textpattern) to make sure the cache is cleared when something on the site changes. A similar plugin called WP-Cache is available for WordPress, but of course this could be done any number of ways, and with any back-end technology.

The important principal here is to reduce the time it takes to serve a page by compiling the page once and serving that cached result to subsequent visitors. Keep away from your database if you can.

Outsource your feeds

We get around 36,000 requests for our feed each day. That really only works out at about 7,000 subscribers averaging five-and-a-bit requests a day, but it’s still 36,000 requests we could easily do without. Each request uses resources and particularly during December, all those requests can add up. 

The simple solution here was to switch our feed over to using FeedBurner. We publish the address of the FeedBurner version of our feed here, so those 36,000 requests a day hit FeedBurner’s servers rather than ours. In addition, we get pretty graphs showing how the subscriber-base is building.



Off-load big files

Larger files like images or downloads pose a problem not in bandwidth, but in the time it takes them to transfer. A typical page request is very quick, a few seconds at the most, resulting in the connection being freed up promptly. Anything that keeps a connection open for a long time is going to start killing performance very quickly.

This year, we started serving most of the images for articles from a subdomain – media.24ways.org. Rather than pointing to our own server, this subdomain points to an Amazon S3 account where the files are held. It’s easy to pigeon-hole S3 as merely an online backup solution, and whilst not a fully fledged CDN, S3 works very nicely for serving larger media files. The roughly 20GB of files served this month have cost around $5 in Amazon S3 charges. That’s so affordable it may not be worth even taking the files back off S3 once December has passed.

I found this article on Scalable Media Hosting with Amazon S3 to be really useful in getting started. I upload the files via a Firefox plugin (mentioned in the article) and then edit the ACL to allow public access to the files. The way S3 enables you to point DNS directly at it means that you’re not tied to always using the service, and that it can be transparent to your users.

If your site uses photographs, consider uploading them to a service like Flickr and serving them directly from there. Many photo sharing sites are happy for you to link to images in this way, but do check the acceptable use policies in case you need to provide a credit or link back.

Off-load small files

You’ll have noticed the pattern by now – get rid of as much traffic as possible. When an article has a lot of comments and each of those comments has an avatar along with it, a great many requests are needed to fetch each of those images. In 2006 we started using Gravatar for avatars, but their servers were slow and were holding up page loads. To get around this we started caching the images on our server, but along with that came the burden of furnishing all the image requests.

Earlier this year Gravatar changed hands and is now run by the same team behind WordPress.com. Those guys clearly know what they’re doing when it comes to high performance, so this year we went back to serving avatars directly from them.

If your site uses avatars, it really makes sense to use a service like Gravatar where your users probably already have an account, and where the image requests are going to be dealt with for you. 

Know what you’re paying for

The server account we use for 24 ways was opened in November 2005. When we first hit the front page of Digg in December of that year, we upgraded the server with a bit more memory, but other than that we were still running on that 2005 spec for two years. Of course, the world of technology has moved on in those years, prices have dropped and specs have improved. For the same amount we were paying for that 2005 spec server, we could have an account with twice the CPU, memory and disk space.

So in November of this year I took out a new account and transferred the site from the old server to the new. In that single step we were prepared for dealing with twice the amount of traffic, and because of a special offer at the time I didn’t even have to pay the setup cost on the new server. So it really pays to know what you’re paying for and keep an eye out of ways you can make improvements without needing to spend more money.

Further steps

There’s nearly always more that can be done. For example, there are some media files (particularly for older articles) that are not on S3. We also serve our CSS directly and it’s not minified or compressed. But by tackling the big problems first we’ve managed to reduce load on the server and at the same time make sure that the load being placed on the server can be dealt with in the most frugal way.

Over the last 24 days we’ve served up articles to more than 350,000 visitors without breaking a sweat. On a busy day, that’s been nearly 20,000 visitors in just 24 hours. While in the grand scheme of things that’s not a huge amount of traffic, it can be a lot if you’re not prepared for it. However, with a little planning for the peaks you can help ensure that when the traffic arrives you’re ready to capitalise on it.

Of course, people only visit 24 ways for the wealth of knowledge and experience that’s tied up in the articles here. Therefore I’d like to take the opportunity to thank all our authors this year who have given their time as a gift to the community, and to wish you all a very happy Christmas.


title: Back To The Future of Print
year: 2007
author: Natalie Downe
author_slug: nataliedowne
published: 2007-12-09T00:00:00+00:00
url: https://24ways.org/2007/back-to-the-future-of-print/
topic: design
contents:
By now we have weathered the storm that was the early days of web development, a dangerous time when we used tables, inline CSS and separate pages for print only versions. We can reflect in a haggard old sea-dog manner (“yarrr… I remember back in the browser wars…”) on the bad practices of the time. We no longer need convincing that print stylesheets are the way to go1, though some of the documentation for them is a little outdated now.

I am going to briefly cover 8 tips and 4 main gotchas when creating print stylesheets in our more enlightened era.

Getting started

As with regular stylesheets, print CSS can be included in a number of ways2, for our purposes we are going to be using the link
element.

<link rel="stylesheet" type="text/css" media="print" href="print.css">

This is still my favourite way of linking to CSS files, its easy to see what files are being included and to what media they are being applied to. Without the media attribute specified the link element defaults to the media type ‘all’ which means that the styles within then apply to print and screen alike. The media type ‘screen’ only applies to the screen and wont be picked up by print, this is the best way of hiding styles from print.

Make sure you include your print styles after all your other CSS, because you will need to override certain rules and this is a lot easier if you are flowing with the cascade than against it!

Another thing you should be thinking is ‘does it need to be printed’. Consider the context3, if it is not a page that is likely to be printed, such as a landing page or a section index then the print styles should resemble the way the page looks on the screen.

Context is really important for the design of your print stylesheet, all the tips and tricks that follow should be taken in the context of the page. If for example you are designing a print stylesheet for an item in a shopping cart, it is irrelevant for the user to know the exact url of the link that takes them to your checkout.

Tips and tricks

During these tip’s we are going to build up print styles for a textileRef:11112857385470b854b8411:linkStartMarker:“simple
example”:/examples/back-to-the-future-of-print/demo-1.html

1. Remove the cruft

First things first, navigation, headers and most page furniture are pretty much useless and dead space in print so they will need to be removed, using display:none;.

2. Linearise your content

Content doesn’t work so well in columns in print, especially if the content columns are long and intend to stretch over multiple columns (as mentioned in the gotcha section below). You might want to consider Lineariseing the content to flow down the page. If you have your source order in correct priority this will make things a lot easier4.

3. Improve your type

Once you have removed all the useless cruft and jiggled things about a bit, you can concentrate more on the typography of the page.

Typography is a complex topic5, but simply put serif-ed fonts such as Georgia work better on print and sans serif-ed fonts such as Verdana are more appropriate for screen use. You will probably want to increase font size and line height and change from px to pt (which is specifically a print measurement).

4. Go wild on links

There are some incredibly fun things you can do with links in print using CSS. There are two schools of thought, one that consider it is best to disguise inline links as body text because they are not click-able on paper. Personally I believe it is useful to know for reference that the document did link to somewhere originally.

When deciding which approach to take, consider the context of your document, do people need to know where they would have gone to? will it help or hinder them to know this information? Also for an alternative to the below, take a look at Aaron Gustafson’s article on generating footnotes for print6.

Using some clever selector trickery and CSS generated content you can have the location of the link generated after the link itself.

HTML:

<p>I wish <a href="http://www.google.com/">Google</a> could find <a href="/photoOfMyKeys.jpg">my keys</a></p>

CSS:

a:link:after,
a:visited:after,
a:hover:after,
a:active:after {
	content: " <" attr(href) "> ";
}

But this is not perfect, in the above example the content of the href is just naively plonked after the link text:

I wish Google <http://www.google.com/> would find my keys </photoOfMyKeys.jpg>

As looking back over this printout the user is not immediately aware of the location of the link, a better solution is to use even more crazy selectors to deal with relative links. We can also add a style to the generated content so it is distinguishable from the link text itself.

CSS:

a:link:after,
a:visited:after,
a:hover:after,
a:active:after {
	content: " <" attr(href) "> ";
	color: grey;
	font-style: italic;
	font-weight: normal;
}
a[href^="/"]:after {
	content: " <http://www.example.com"attr(href)"> ";
}

The output is now what we were looking for (you will need to replace example.com with your own root URL):

I wish Google <http://www.google.com/> would find my keys <http://www.example.com/photoOfMyKeys.jpg>

Using regular expressions on the attribute selectors, one final thing you can do is to suppress the generated content on mailto: links, if for example you know the link text always reflects the email address. Eg:

HTML:

<a href="mailto:me@example.com">me@example.com</a>

CSS:

a[href^="mailto"]:after {
	content: "";
}

This example shows the above in action.

Of course with this clever technique, there are the usual browser support issues. While it won’t look as intended in browsers such as Internet Explorer 6 and 7 (IE6 and IE7) it will not break either and will just degrade gracefully because IE cannot do generated content. To the best of my knowledge Safari 2+ and Opera 9.X support a colour set on generated content whereas Firefox 2 & Camino display this in black regardless of the link or inherited text colour.

5. Jazz your headers for print

This is more of a design consideration, don’t go too nuts though; there are a lot more limitations in print media than on screen. For this example we are going to go for is having a bottom border on h2’s and styling other headings with graduating colors or font sizes.

And here is the example complete with jazzy headers.

6. Build in general hooks

If you are building a large site with many different types of page, you may find it useful to build into your CSS structure, classes that control what is printed (e.g. noprint and printonly). This may not be semantically ideal, but in the past I have found it really useful for maintainability of code across large and varied sites

7. For that extra touch of class

When printing pages from a long URL, even if the option is turned on to show the location of the page in the header, browsers may still display a truncated (and thus useless) version.

Using the above tip (or just simply setting to display:none in screen and display:block in print) you can insert the URL of the page you are currently on for print only, using JavaScript’s window.location.href variable.

function addPrintFooter() {
	var p = document.createElement('p');
	p.className = 'print-footer';
	p.innerHTML = window.location.href;
	document.body.appendChild(p);
}

You can then call this function using whichever onload or ondomready handler suits your fancy. Here is our familiar demo to show all the above in action

8. Tabular data across pages

If you are using tabled data in your document there are a number of things you can do to increase usability of long tables over several pages. If you use the <thead> element this should repeat your table headers on the next page should your table be split. You will need to set thead {display: table-header-group;} explicitly for IE even though this should be the default value.

Also if you use tr {page-break-inside: avoid;} this should (browser support depending) stop your table row from breaking across two pages. For more information on styling tables for print please see the CSS discuss wiki7.

Gotchas

1. Where did all my content go?

Absolutely the most common mistake I see with print styles is the truncated content bug. The symptom of this is that only the first page of a div’s content will be printed, the rest will look truncated after this.

Floating long columns may still have this affect, as mentioned in Eric Meyer’s article on ‘A List Apart’ article from 20028; though in testing I am no longer able to replicate this. Using overflow:hidden on long content in Firefox however still causes this truncation. Overflow hidden is commonly used to clear floats9.

A simple fix can be applied to resolve this, if the column is floated you can override this with float:none similarly overflow:hidden can be overridden with overflow:visible or the offending rules can be banished to a screen only stylesheet.

Using position:absolute on long columns also has a very similar effect in truncating the content, but can be overridden in print with position:static;

Whilst I only recommend having a print stylesheet for content pages on your site; do at least check other landing pages, section indexes and your homepage. If these are inaccessible in print possibly due to the above gotcha, it might be wise to provide a light dusting of print styles or move the offending overflow / float rules to a screen only stylesheet to fix the issues.

2. Damn those background browser settings

One of the factors of life you now need to accept is that you can’t control the user’s browser settings, no more than you can control whether or not they use IE6. Most browsers by default will not print background colours or images unless explicitly told to by the user.

Naturally this causes a number of problems, for starters you will need to rethink things like branding. At this point it helps if you are doing the print styles early in the project so that you can control the logo not being a background image for example.

Where colour is important to the meaning of the document, for example a status on an invoice, bear in mind that a textural representation will also need to be supplied as the user may be printing in black and white. Borders will print however regardless of setting, so assuming the user is printing in colour you can always use borders to indicate colour.

Check the colour contrast of the text against white, this may need to be altered without backgrounds. You should check how your page looks with backgrounds turned on too, for consistency with the default browser settings you may want to override your background anyway.

One final issue with backgrounds being off is list items. It is relatively common practice to suppress the list-style-type and replace with a background image to finely control the bullet positioning. This technique doesn’t translate to print, you will need to disable this background bullet and re-instate your trusty friend the list-style-type.

3. Using JavaScript in your CSS? … beware IE6

Internet explorer has an issue that when Javascript is used in a stylesheet it applies this to all media types even if only applied to screen. For example, if you happen to be using expressions to set a width for IE, perhaps to mimic min-width, a simple width:100% !important rule can overcome the effects the expression has on your print styles10.

4. De-enhance your Progressive enhancements

Quite a classic “doh” moment is when you realise that, of course paper doesn’t support Javascript. If you have any dynamic elements on the page, for example a document collapsed per section, you really should have been using Progressive enhancement techniques11 and building for browsers without Javascript first, adding in the fancy stuff later.

If this is the case it should be trivial to override your wizzy JS styles in your print stylesheet, to display all your content and make it accessible for print, which is by far the best method of achieving this affect.

And Finally…

I refer you back to the nature of the document in hand, consider the context of your site and the page. Use the tips here to help you add that extra bit of flair to your printed media.

Be careful you don’t get caught out by the common gotchas, keep the design simple, test cross browser and relish in the medium of print.

Further Reading

1 For more information constantly updated, please see the CSS discuss wiki on print stylesheets

2 For more information on media types and ways of including CSS please refer to the CSS discuss wiki on Media Stylesheets

3 Eric Meyer talks to ThinkVitamin about the importance of context when designing your print strategy.

4 Mark Boulton describes how he applies a newspaper like print stylesheet to an article in the Guardian website. Mark also has some persuasive arguments that print should not be left to last

5 Richard Rutter Has a fantastic resource on typography which also applies to print.

6 Aaron Gustafson has a great solution to link problem by creating footnotes at the end of the page.

7 The CSS discuss wiki has more detailed information on printing tables and detailed browser support

8 This ‘A List Apart’ article is dated May 10th 2002 though is still mostly relevant

9 Float clearing technique using ‘overflow:hidden’

10 Autistic Cuckoo describes the interesting insight with regards to expressions specified for screen in IE6 remaining in print

11 Wikipedia has a good article on the definition of progressive enhancement

12 For a really neat trick involving a dynamically generated column to displaying <abbr> and <dfn> meanings (as well as somewhere for the user to write notes), try print previewing on Brian Suda’s site


title: Unobtrusively Mapping Microformats with jQuery
year: 2007
author: Simon Willison
author_slug: simonwillison
published: 2007-12-12T00:00:00+00:00
url: https://24ways.org/2007/unobtrusively-mapping-microformats-with-jquery/
topic: code
contents:
Microformats are everywhere. You can’t shake an electronic stick these days without accidentally poking a microformat-enabled site, and many developers use microformats as a matter of course. And why not? After all, why invent your own class names when you can re-use pre-defined ones that give your site extra functionality for free?

Nevertheless, while it’s good to know that users of tools such as Tails and Operator will derive added value from your shiny semantics, it’s nice to be able to reuse that effort in your own code.

We’re going to build a map of some of my favourite restaurants in Brighton. Fitting with the principles of unobtrusive JavaScript, we’ll start with a semantically marked up list of restaurants, then use JavaScript to add the map, look up the restaurant locations and plot them as markers.

We’ll be using a couple of powerful tools. The first is jQuery, a JavaScript library that is ideally suited for unobtrusive scripting. jQuery allows us to manipulate elements on the page based on their CSS selector, which makes it easy to extract information from microformats.

The second is Mapstraction, introduced here by Andrew Turner a few days ago. We’ll be using Google Maps in the background, but Mapstraction makes it easy to change to a different provider if we want to later.

Getting Started

We’ll start off with a simple collection of microformatted restaurant details, representing my seven favourite restaurants in Brighton. The full, unstyled list can be seen in restaurants-plain.html. Each restaurant listing looks like this:

<li class="vcard">
	<h3><a class="fn org url" href="http://www.riddleandfinns.co.uk/">Riddle & Finns</a></h3>
	<div class="adr">
		<p class="street-address">12b Meeting House Lane</p>
		<p><span class="locality">Brighton</span>, <abbr class="country-name" title="United Kingdom">UK</abbr></p>
		<p class="postal-code">BN1 1HB</p>
	</div>
	<p>Telephone: <span class="tel">+44 (0)1273 323 008</span></p>
	<p>E-mail: <a href="mailto:info@riddleandfinns.co.uk" class="email">info@riddleandfinns.co.uk</a></p>
</li>

Since we’re dealing with a list of restaurants, each hCard is marked up inside a list item. Each restaurant is an organisation; we signify this by placing the classes fn and org on the element surrounding the restaurant’s name (according to the hCard spec, setting both fn and org to the same value signifies that the hCard represents an organisation rather than a person).

The address information itself is contained within a div of class adr. Note that the HTML <address> element is not suitable here for two reasons: firstly, it is intended to mark up contact details for the current document rather than generic addresses; secondly, address is an inline element and as such cannot contain the paragraphs elements used here for the address information.

A nice thing about microformats is that they provide us with automatic hooks for our styling. For the moment we’ll just tidy up the whitespace a bit; for more advanced style tips consult John Allsop’s guide from 24 ways 2006.

.vcard p {
	margin: 0;
}
.adr {
	margin-bottom: 0.5em;
}

To plot the restaurants on a map we’ll need latitude and longitude for each one. We can find this out from their address using geocoding. Most mapping APIs include support for geocoding, which means we can pass the API an address and get back a latitude/longitude point. Mapstraction provides an abstraction layer around these APIs which can be included using the following script tag:

<script type="text/javascript" src="http://mapstraction.com/src/mapstraction-geocode.js"></script>

While we’re at it, let’s pull in the other external scripts we’ll be using:

<script type="text/javascript" src="jquery-1.2.1.js"></script>
<script src="http://maps.google.com/maps?file=api&v=2&key=YOUR_KEY" type="text/javascript"></script>
<script type="text/javascript" src="http://mapstraction.com/src/mapstraction.js"></script>
<script type="text/javascript" src="http://mapstraction.com/src/mapstraction-geocode.js"></script>

That’s everything set up: let’s write some JavaScript!

In jQuery, almost every operation starts with a call to the jQuery function. The function simulates method overloading to behave in different ways depending on the arguments passed to it. When writing unobtrusive JavaScript it’s important to set up code to execute when the page has loaded to the point that the DOM is available to be manipulated. To do this with jQuery, pass a callback function to the jQuery function itself:

jQuery(function() {
	// This code will be executed when the DOM is ready
});

Initialising the map

The first thing we need to do is initialise our map. Mapstraction needs a div with an explicit width, height and ID to show it where to put the map. Our document doesn’t currently include this markup, but we can insert it with a single line of jQuery code:

jQuery(function() {
	// First create a div to host the map
	var themap = jQuery('<div id="themap"></div>').css({
		'width': '90%',
		'height': '400px'
	}).insertBefore('ul.restaurants');
});

While this is technically just a single line of JavaScript (with line-breaks added for readability) it’s actually doing quite a lot of work. Let’s break it down in to steps:

var themap = jQuery('<div id="themap"></div>')

Here’s jQuery’s method overloading in action: if you pass it a string that starts with a < it assumes that you wish to create a new HTML element. This provides us with a handy shortcut for the more verbose DOM equivalent:

var themap = document.createElement('div');
themap.id = 'themap';

Next we want to apply some CSS rules to the element. jQuery supports chaining, which means we can continue to call methods on the object returned by jQuery or any of its methods:

var themap = jQuery('<div id="themap"></div>').css({
	'width': '90%',
	'height': '400px'
})

Finally, we need to insert our new HTML element in to the page. jQuery provides a number of methods for element insertion, but in this case we want to position it directly before the <ul> we are using to contain our restaurants. jQuery’s insertBefore() method takes a CSS selector indicating an element already on the page and places the current jQuery selection directly before that element in the DOM.

var themap = jQuery('<div id="themap"></div>').css({
	'width': '90%',
	'height': '400px'
}).insertBefore('ul.restaurants');

Finally, we need to initialise the map itself using Mapstraction. The Mapstraction constructor takes two arguments: the first is the ID of the element used to position the map; the second is the mapping provider to use (in this case google ):

// Initialise the map
var mapstraction = new Mapstraction('themap','google');

We want the map to appear centred on Brighton, so we’ll need to know the correct co-ordinates. We can use www.getlatlon.com to find both the co-ordinates and the initial map zoom level.

// Show map centred on Brighton
mapstraction.setCenterAndZoom(
	new LatLonPoint(50.82423734980143, -0.14007568359375),
	15 // Zoom level appropriate for Brighton city centre
);

We also want controls on the map to allow the user to zoom in and out and toggle between map and satellite view.

mapstraction.addControls({
	zoom: 'large',
	map_type: true
});

Adding the markers

It’s finally time to parse some microformats. Since we’re using hCard, the information we want is wrapped in elements with the class vcard. We can use jQuery’s CSS selector support to find them:

var vcards = jQuery('.vcard');

Now that we’ve found them, we need to create a marker for each one in turn. Rather than using a regular JavaScript for loop, we can instead use jQuery’s each() method to execute a function against each of the hCards.

jQuery('.vcard').each(function() {
	// Do something with the hCard
});

Within the callback function, this is set to the current DOM element (in our case, the list item). If we want to call the magic jQuery methods on it we’ll need to wrap it in another call to jQuery:

jQuery('.vcard').each(function() {
	var hcard = jQuery(this);
});

The Google maps geocoder seems to work best if you pass it the street address and a postcode. We can extract these using CSS selectors: this time, we’ll use jQuery’s find() method which searches within the current jQuery selection:

var streetaddress = hcard.find('.street-address').text();
var postcode = hcard.find('.postal-code').text();

The text() method extracts the text contents of the selected node, minus any HTML markup.

We’ve got the address; now we need to geocode it. Mapstraction’s geocoding API requires us to first construct a MapstractionGeocoder, then use the geocode() method to pass it an address. Here’s the code outline:

var geocoder = new MapstractionGeocoder(onComplete, 'google');
geocoder.geocode({'address': 'the address goes here');

The onComplete function is executed when the geocoding operation has been completed, and will be passed an object with the resulting point on the map. We just want to create a marker for the point:

var geocoder = new MapstractionGeocoder(function(result) {
	var marker = new Marker(result.point);
	mapstraction.addMarker(marker);
}, 'google');   

For our purposes, joining the street address and postcode with a comma to create the address should suffice:

geocoder.geocode({'address': streetaddress + ', ' + postcode});   

There’s one last step: when the marker is clicked, we want to display details of the restaurant. We can do this with an info bubble, which can be configured by passing in a string of HTML. We’ll construct that HTML using jQuery’s html() method on our hcard object, which extracts the HTML contained within that DOM node as a string.

var marker = new Marker(result.point);
marker.setInfoBubble(
	'<div class="bubble">' + hcard.html() + '</div>'
);
mapstraction.addMarker(marker);

We’ve wrapped the bubble in a div with class bubble to make it easier to style. Google Maps can behave strangely if you don’t provide an explicit width for your info bubbles, so we’ll add that to our CSS now:

.bubble {
	width: 300px;
}

That’s everything we need: let’s combine our code together:

jQuery(function() {
	// First create a div to host the map
	var themap = jQuery('<div id="themap"></div>').css({
		'width': '90%',
		'height': '400px'
	}).insertBefore('ul.restaurants');
	// Now initialise the map
	var mapstraction = new Mapstraction('themap','google');
	mapstraction.addControls({
		zoom: 'large',
		map_type: true
	});
	// Show map centred on Brighton
	mapstraction.setCenterAndZoom(
		new LatLonPoint(50.82423734980143, -0.14007568359375),
		15 // Zoom level appropriate for Brighton city centre
	);
	// Geocode each hcard and add a marker
	jQuery('.vcard').each(function() {
		var hcard = jQuery(this);
		var streetaddress = hcard.find('.street-address').text();
		var postcode = hcard.find('.postal-code').text();
		var geocoder = new MapstractionGeocoder(function(result) {
			var marker = new Marker(result.point);
			marker.setInfoBubble(
				'<div class="bubble">' + hcard.html() + '</div>'
			);
			mapstraction.addMarker(marker);
		}, 'google');	 
		geocoder.geocode({'address': streetaddress + ', ' + postcode});
	});
});

Here’s the finished code.

There’s one last shortcut we can add: jQuery provides the $ symbol as an alias for jQuery. We could just go through our code and replace every call to jQuery() with a call to $(), but this would cause incompatibilities if we ever attempted to use our script on a page that also includes the Prototype library. A more robust approach is to start our code with the following:

jQuery(function($) {
	// Within this function, $ now refers to jQuery
	// ...
});

jQuery cleverly passes itself as the first argument to any function registered to the DOM ready event, which means we can assign a local $ variable shortcut without affecting the $ symbol in the global scope. This makes it easy to use jQuery with other libraries.

Limitations of Geocoding

You may have noticed a discrepancy creep in to the last example: whereas my original list included seven restaurants, the geocoding example only shows five. This is because the Google Maps geocoder incorporates a rate limit: more than five lookups in a second and it starts returning error messages instead of regular results.

In addition to this problem, geocoding itself is an inexact science: while UK postcodes generally get you down to the correct street, figuring out the exact point on the street from the provided address usually isn’t too accurate (although Google do a pretty good job).

Finally, there’s the performance overhead. We’re making five geocoding requests to Google for every page served, even though the restaurants themselves aren’t likely to change location any time soon. Surely there’s a better way of doing this?

Microformats to the rescue (again)! The geo microformat suggests simple classes for including latitude and longitude information in a page. We can add specific points for each restaurant using the following markup:

<li class="vcard">
	<h3 class="fn org">E-Kagen</h3>
	<div class="adr">
		<p class="street-address">22-23 Sydney Street</p>
		<p><span class="locality">Brighton</span>, <abbr class="country-name" title="United Kingdom">UK</abbr></p>
		<p class="postal-code">BN1 4EN</p>
	</div>
	<p>Telephone: <span class="tel">+44 (0)1273 687 068</span></p>
	<p class="geo">Lat/Lon: 
		<span class="latitude">50.827917</span>, 
		<span class="longitude">-0.137764</span>
	</p>
</li>

As before, I used www.getlatlon.com to find the exact locations – I find satellite view is particularly useful for locating individual buildings.

Latitudes and longitudes are great for machines but not so useful for human beings. We could hide them entirely with display: none, but I prefer to merely de-emphasise them (someone might want them for their GPS unit):

.vcard .geo {
	margin-top: 0.5em;
	font-size: 0.85em;
	color: #ccc;
}

It’s probably a good idea to hide them completely when they’re displayed inside an info bubble:

.bubble .geo {
	display: none;
}

We can extract the co-ordinates in the same way we extracted the address. Since we’re no longer geocoding anything our code becomes a lot simpler:

$('.vcard').each(function() {
	var hcard = $(this);
	var latitude = hcard.find('.geo .latitude').text();
	var longitude = hcard.find('.geo .longitude').text();
	var marker = new Marker(new LatLonPoint(latitude, longitude));
	marker.setInfoBubble(
		'<div class="bubble">' + hcard.html() + '</div>'
	);
	mapstraction.addMarker(marker);
});

And here’s the finished geo example.

Further reading

We’ve only scratched the surface of what’s possible with microformats, jQuery (or just regular JavaScript) and a bit of imagination. If this example has piqued your interest, the following links should give you some more food for thought.


	The hCard specification
	Notes on parsing hCards
	jQuery for JavaScript programmers – my extended tutorial on jQuery.
	Dann Webb’s Sumo – a full JavaScript library for parsing microformats, based around some clever metaprogramming techniques.
	Jeremy Keith’s Adactio Austin – the first place I saw using microformats to unobtrusively plot locations on a map. Makes clever use of hEvent as well.


