s that we are working with could be compared to layers in Photoshop. By applying a semi-transparent shade of grey, each successive layer can build on top of the darker layers beneath it. The effect accumulates, causing each successive layer to appear slightly darker than the last. In his 2009 article for 24 ways, Drew McLellan showed how to create a semi-transparent effect by working with RGBA colour. Here, we’ll use the colour black with an alpha value of 0.07.
#container div { background-color: rgba(0,0,0,0.07) }
Note that I haven’t used the immediate child selector here, which means that this rule will apply to all
elements inside the #container, no matter how deeply nested they are. You can view the result in Demo Two. As you can see, the golden rectangles alternate between landscape and portrait orientation.
Demo Three).
CSS3 specification indicates that a percentage can be used to set the border-radius property, but using percentages does not achieve consistent results in browsers today. Luckily, if you specify a border-radius in pixels using a value that is greater than the width and height of the element, then the resulting curve will use the shorter length side as its radius. This produces exactly the effect that we want, so we’ll use an arbitrarily high value of 10,000 pixels for each border-radius:
.cycle {
border-radius: 0px;
border-bottom-left-radius: 10000px;
}
.cycle > div {
border-radius: 0px;
border-bottom-right-radius: 10000px;
}
.cycle > div > div {
border-radius: 0px;
border-top-right-radius: 10000px;
}
.cycle > div > div > div {
border-radius: 0px;
border-top-left-radius: 10000px;
}
Note that the specification for the border-radius property is still in flux, so it is advisable to use vendor-specific prefixes. I have omitted them from the example above for the sake of clarity, but if you view source on Demo Four then you’ll see that the actual styles are not quite as brief.
Filling the available space
We have created an approximation of the Golden Spiral using only HTML and CSS. Neat! It’s a shame that it occupies just a fraction of the available space. As a finishing touch, let’s make the golden spiral expand or contract to use the full space available to it.
Ideally, the outermost container should use the full available width or height that could accomodate a rectangle of golden proportions. This behaviour is available for background images using the “ background-size: contain; property, but I know of no way to make block level HTML elements behave in this fashion (if I’m missing something, please enlighten me). Where CSS fails to deliver, JavaScript can usually provide a workaround. This snippet requires jQuery:
$(document).ready(function() {
var phi = (1 + Math.sqrt(5))/2;
$(window).resize(function() {
var goldenWidth = windowWidth = $(this).width(),
goldenHeight = windowHeight = $(this).height();
if (windowWidth/windowHeight > phi) {
// panoramic viewport – use full height
goldenWidth = windowHeight * phi;
} else {
// portrait viewport – use full width
goldenHeight = windowWidth / phi;
};
$(""#container > div.cycle"")
.width(goldenWidth)
.height(goldenHeight);
}).resize();
});
You can view the result by visiting Demo Five.
Is it just me, or can you see an elephant in there?
You can probably think of many ways to enhance this further, but for this study we’ll leave it there. It has been a good excuse to play with proportions, positioning and the immediate child selector, as well as new CSS3 features such as border-radius and RGBA colours. If you are not already designing with golden proportions, then perhaps this will inspire you to begin.",2010,Drew Neil,drewneil,2010-12-07T00:00:00+00:00,https://24ways.org/2010/golden-spirals/,design
233,Wrapping Things Nicely with HTML5 Local Storage,"HTML5 is here to turn the web from a web of hacks into a web of applications – and we are well on the way to this goal. The coming year will be totally and utterly awesome if you are excited about web technologies.
This year the HTML5 revolution started and there is no stopping it. For the first time all the browser vendors are rallying together to make a technology work. The new browser war is fought over implementation of the HTML5 standard and not over random additions. We live in exciting times.
Starting with a bang
As with every revolution there is a lot of noise with bangs and explosions, and that’s the stage we’re at right now. HTML5 showcases are often CSS3 showcases, web font playgrounds, or video and canvas examples.
This is great, as it gets people excited and it gives the media something to show. There is much more to HTML5, though. Let’s take a look at one of the less sexy, but amazingly useful features of HTML5 (it was in the HTML5 specs, but grew at such an alarming rate that it warranted its own spec): storing information on the client-side.
Why store data on the client-side?
Storing information in people’s browsers affords us a few options that every application should have:
You can retain the state of an application – when the user comes back after closing the browser, everything will be as she left it. That’s how ‘real’ applications work and this is how the web ones should, too.
You can cache data – if something doesn’t change then there is no point in loading it over the Internet if local access is so much faster
You can store user preferences – without needing to keep that data on your server at all.
In the past, storing local data wasn’t much fun.
The pain of hacky browser solutions
In the past, all we had were cookies. I don’t mean the yummy things you get with your coffee, endorsed by the blue, furry junkie in Sesame Street, but the other, digital ones. Cookies suck – it isn’t fun to have an unencrypted HTTP overhead on every server request for storing four kilobytes of data in a cryptic format. It was OK for 1994, but really neither an easy nor a beautiful solution for the task of storing data on the client.
Then came a plethora of solutions by different vendors – from Microsoft’s userdata to Flash’s LSO, and from Silverlight isolated storage to Google’s Gears. If you want to know just how many crazy and convoluted ways there are to store a bit of information, check out Samy’s evercookie.
Clearly, we needed an easier and standardised way of storing local data.
Keeping it simple – local storage
And, lo and behold, we have one. The local storage API (or session storage, with the only difference being that session data is lost when the window is closed) is ridiculously easy to use. All you do is call a few methods on the window.localStorage object – or even just set the properties directly using the square bracket notation:
if('localStorage' in window && window['localStorage'] !== null){
var store = window.localStorage;
// valid, API way
store.setItem(‘cow’,‘moo’);
console.log(
store.getItem(‘cow’)
); // => ‘moo’
// shorthand, breaks at keys with spaces
store.sheep = ‘baa’
console.log(
store.sheep
); // ‘baa’
// shorthand for all
store[‘dog’] = ‘bark’
console.log(
store[‘dog’]
); // => ‘bark’
}
Browser support is actually pretty good: Chrome 4+; Firefox 3.5+; IE8+; Opera 10.5+; Safari 4+; plus iPhone 2.0+; and Android 2.0+. That should cover most of your needs. Of course, you should check for support first (or use a wrapper library like YUI Storage Utility or YUI Storage Lite).
The data is stored on a per domain basis and you can store up to five megabytes of data in localStorage for each domain.
Strings attached
By default, localStorage only supports strings as storage formats. You can’t store results of JavaScript computations that are arrays or objects, and every number is stored as a string. This means that long, floating point numbers eat into the available memory much more quickly than if they were stored as numbers.
var cowdesc = ""the cow is of the bovine ilk, ""+
""one end is for the moo, the ""+
""other for the milk"";
var cowdef = {
ilk“bovine”,
legs,
udders,
purposes
front“moo”,
end“milk”
}
};
window.localStorage.setItem(‘describecow’,cowdesc);
console.log(
window.localStorage.getItem(‘describecow’)
); // => the cow is of the bovine…
window.localStorage.setItem(‘definecow’,cowdef);
console.log(
window.localStorage.getItem(‘definecow’)
); // => [object Object] = bad!
This limits what you can store quite heavily, which is why it makes sense to use JSON to encode and decode the data you store:
var cowdef = {
""ilk"":""bovine"",
""legs"":4,
""udders"":4,
""purposes"":{
""front"":""moo"",
""end"":""milk""
}
};
window.localStorage.setItem(‘describecow’,JSON.stringify(cowdef));
console.log(
JSON.parse(
window.localStorage.getItem(‘describecow’)
)
); // => Object { ilk=“bovine”, more…}
You can also come up with your own formatting solutions like CSV, or pipe | or tilde ~ separated formats, but JSON is very terse and has native browser support.
Some use case examples
The simplest use of localStorage is, of course, storing some data: the current state of a game; how far through a multi-form sign-up process a user is; and other things we traditionally stored in cookies. Using JSON, though, we can do cooler things.
Speeding up web service use and avoiding exceeding the quota
A lot of web services only allow you a certain amount of hits per hour or day, and can be very slow. By using localStorage with a time stamp, you can cache results of web services locally and only access them after a certain time to refresh the data.
I used this technique in my An Event Apart 10K entry, World Info, to only load the massive dataset of all the world information once, and allow for much faster subsequent visits to the site. The following screencast shows the difference:
For use with YQL (remember last year’s 24 ways entry?), I’ve built a small script called YQL localcache that wraps localStorage around the YQL data call. An example would be the following:
yqlcache.get({
yql: 'select * from flickr.photos.search where text=""santa""',
id: 'myphotos',
cacheage: ( 60*60*1000 ),
callback: function(data) {
console.log(data);
}
});
This loads photos of Santa from Flickr and stores them for an hour in the key myphotos of localStorage. If you call the function at various times, you receive an object back with the YQL results in a data property and a type property which defines where the data came from – live is live data, cached means it comes from cache, and freshcache indicates that it was called for the first time and a new cache was primed. The cache will work for an hour (60×60×1,000 milliseconds) and then be refreshed. So, instead of hitting the YQL endpoint over and over again, you hit it once per hour.
Caching a full interface
Another use case I found was to retain the state of a whole interface of an application by caching the innerHTML once it has been rendered. I use this in the Yahoo Firehose search interface, and you can get the full story about local storage and how it is used in this screencast:
The stripped down code is incredibly simple (JavaScript with PHP embed):
// test for localStorage support
if(('localStorage' in window) && window['localStorage'] !== null){
var f = document.getElementById(‘mainform’);
// test with PHP if the form was sent (the submit button has the name “sent”)
// get the HTML of the form and cache it in the property “state”
localStorage.setItem(‘state’,f.innerHTML);
// if the form hasn’t been sent…
// check if a state property exists and write back the HTML cache
if(‘state’ in localStorage){
f.innerHTML = localStorage.getItem(‘state’);
}
}
Other ideas
In essence, you can use local storage every time you need to speed up access. For example, you could store image sprites in base-64 encoded datasets instead of loading them from a server. Or you could store CSS and JavaScript libraries on the client. Anything goes – have a play.
Issues with local and session storage
Of course, not all is rainbows and unicorns with the localStorage API. There are a few niggles that need ironing out. As with anything, this needs people to use the technology and raise issues. Here are some of the problems:
Inadequate information about storage quota – if you try to add more content to an already full store, you get a QUOTA_EXCEEDED_ERR and that’s it. There’s a great explanation and test suite for localStorage quota available.
Lack of automatically expiring storage – a feature that cookies came with. Pamela Fox has a solution (also available as a demo and source code)
Lack of encrypted storage – right now, everything is stored in readable strings in the browser.
Bigger, better, faster, more!
As cool as the local and session storage APIs are, they are not quite ready for extensive adoption – the storage limits might get in your way, and if you really want to go to town with accessing, filtering and sorting data, real databases are what you’ll need. And, as we live in a world of client-side development, people are moving from heavy server-side databases like MySQL to NoSQL environments.
On the web, there is also a lot of work going on, with Ian Hickson of Google proposing the Web SQL database, and Nikunj Mehta, Jonas Sicking (Mozilla), Eliot Graff (Microsoft) and Andrei Popescu (Google) taking the idea beyond simply replicating MySQL and instead offering Indexed DB as an even faster alternative.
On the mobile front, a really important feature is to be able to store data to use when you are offline (mobile coverage and roaming data plans anybody?) and you can use the Offline Webapps API for that.
As I mentioned at the beginning, we have a very exciting time ahead – let’s make this web work faster and more reliably by using what browsers offer us. For more on local storage, check out the chapter on Dive into HTML5.",2010,Christian Heilmann,chrisheilmann,2010-12-06T00:00:00+00:00,https://24ways.org/2010/html5-local-storage/,code
217,Beyond Web Mechanics – Creating Meaningful Web Design,"It was just over three years ago when I embarked on becoming a web designer, and the first opinion piece about the state of web design I came across was a conference talk by Elliot Jay Stocks called ‘Destroy the Web 2.0 Look’. Elliot’s presentation was a call to arms, a plea to web designers the world over to stop the endless reproductions of the so called ‘Web 2.0 look’.
Three and a half years on from Elliot’s talk, what has changed? Well, from an aesthetic standpoint, not a whole lot. The Web 2.0 look has evolved, but it’s still with us and much of the web remains filled with cookie cutter websites that bear a striking resemblance to one another. This wouldn’t matter so much if these websites were selling comparable services or products, but they’re not. They look similar, they follow the same web design trends; their aesthetic style sends out a very similar message, yet they’re selling completely different services or products. How can you be communicating effectively with your users when your online book store is visually indistinguishable from an online cosmetic store? This just doesn’t make sense.
I don’t want to belittle the current version of the Web 2.0 look for the sake of it. I want to talk about the opportunity we have as web designers to create more meaningful experiences for the people using our websites. Using design wisely gives us the ability to communicate messages, ideas and attitudes that our users will understand and connect with.
Being human
As human beings we respond emotionally to everything around us – people, objects, posters, packaging or websites. We also respond in different ways to different kinds of aesthetic design and style. We care about style and aesthetics deeply, whether we realise it or not. Aesthetic design has the power to attract or repel. We often make decisions based purely on aesthetics and style – and don’t retailers the world over know it! We connect attitudes and strongly held beliefs to style. Individuals will proudly associate themselves with a certain style or aesthetic because it’s an expression of who they are. You know that old phrase, ‘Don’t judge a book by its cover’? Well, the problem is that people do, so it’s important we get the cover right.
Much is made of how to structure web pages, how to create a logical information hierarchy, how to use layout and typography to clearly communicate with your users. It’s important, however, not to mistake clarity of information or legibility with getting your message across. Few users actually read websites word by word: it’s far more likely they’ll just scan the page. If the page is copy-heavy and nothing grabs their attention, they may well just move on. This is why it’s so important to create a visual experience that actually means something to the user.
Meaningful design
When we view a poster or website, we make split-second assessments and judgements of what is in front of us. Our first impressions of what a website does or who it is aimed at are provoked by the style and aesthetic of the website. For example, with clever use of colour, typography, graphic design and imagery we can communicate to users that an organisation is friendly, edgy, compassionate, fun or environmentally conscious.
Using a certain aesthetic we can convey the personality of that organisation, target age ranges, different sexes or cultural groups, communicate brand attributes, and more. We can make our users feel like they’re part of something and, perhaps even more importantly, we can make new users want to be a part of something. And we can achieve all this before the user has read a single word.
By establishing a website’s aesthetic and creating a meaningful visual language, a design is no longer just a random collection of pretty gradients that have been plucked out of thin air. There can be a logic behind the design decisions we make. So, before you slap another generic piece of ribbon or an ultra shiny icon into the top-left corner of your website, think about why you are doing it. If you can’t come up with a reason better than “I saw it on another website”, it’s probably a poor application of style.
Design and style
There are a number of reasons why the web suffers from a lack meaningful design. Firstly, there are too many preconceptions of what a website should look like. It’s too easy for designers to borrow styles from other websites, thereby limiting the range of website designs we see on the web. Secondly, many web designers think of aesthetic design as of secondary importance, which shouldn’t be the case. Designing websites that are accessible and easy to use is, of course, very important but this is the very least a web designer should be delivering. Easy to use websites should come as standard – it’s equally important to create meaningful, compelling and beautiful experiences for everyone who uses our websites. The aesthetics of your site are part of the design, and to ignore this and play down the role of aesthetic design is just a wasted opportunity.
No compromise necessary
Easy to use, accessible websites and beautiful, meaningful aesthetics are not mutually exclusive. The key is to apply style and aesthetic design appropriately. We need to think about who and what we’re designing for and ask ourselves why we’re applying a certain kind of aesthetic style to our design. If you do this, there’s no reason why effective, functional design should come at the expense of jaw-dropping, meaningful aesthetics.
Web designers need to understand the differences between functional design and aesthetic design but, even more importantly, they need to know how to make them work together. It’s combining these elements of design successfully that makes for the best web design in the world.",2010,Mike Kus,mikekus,2010-12-05T00:00:00+00:00,https://24ways.org/2010/beyond-web-mechanics-creating-meaningful-web-design/,design
224,Go Forth and Make Awesomeness,"We’ve all dreamed of being a superhero: maybe that’s why we’ve ended up on the web—a place where we can do good deeds and celebrate them on a daily basis.
Wear your dreams
At age four, I wore my Wonder Woman Underoos around my house, my grandparents’ house, our neighbor’s house, and even around the yard. I wanted to be a superhero when I grew up. I was crushed to learn that there is no school for superheroes—no place to earn a degree in how to save the world from looming evil. Instead, I—like everyone else—was destined to go to ordinary school to focus on ABCs and 123s. Even still, I want to save the world.
Intend your goodness
Random acts of kindness make a difference. Books, films, and advertising campaigns tout random acts of kindness and the positive influence they can have on the world. But why do acts of kindness have to be so random? Why can’t we intend to be kind? A true superhero wakes each morning intending to perform selfless acts for the community. Why can’t we do the same thing?
As a child, my mother taught me to plan to do at least three good deeds each day. And even now, years later, I put on my invisible cape looking for ways to do good.
Here are some examples:
slowing down to allow another driver in before me from the highway on-ramp
bringing a co-worker their favorite kind of coffee or tea
sharing my umbrella on a rainy day
holding a door open for someone with full hands
listening intently when someone shares a story
complimenting someone on a job well done
thanking someone for a job well done
leaving a constructive, or even supportive comment on someone’s blog
As you can see, these acts are simple. Doing good and being kind is partially about being aware—aware of the words we speak and the actions we take. Like superheroes, we create our own code of conduct to live by. Hopefully, we choose to put the community before ourselves (within reason) and to do our best not to damage it as we move through our lives.
Take a bite out of the Apple
With some thought, we can weave this type of thinking and action into our business choices. We can take the simple acts of kindness concept and amplify it a bit. With this amplification, we can be a new kind of superhero.
In 1997, during a presentation, Steve Jobs stated Apple’s core value in a simple, yet powerful, sentence:
We believe that people with passion can change the world for the better.
Apple fan or not, those are powerful words.
Define your core
Every organization must define its core values. Core values help us to frame, recognize, and understand the principles our organization embodies and practices. It doesn’t matter if you’re starting a new organization or you want to define values within an existing organization. Even if you’re a freelancer, defining core values will help guide your decisions and actions.
If you can, work as a team to define core values. Gather the people who are your support system—your business partners, your colleagues, and maybe even a trusted client—this is now your core value creation team. Have a brainstorming session with your team. Let ideas flow. Give equal weight to the things people say. You may not hear everything you thought you might hear—that’s OK. You want the session to be free-flowing and honest. Ask yourself and your team questions like:
What do you think my/our/your core values are?
What do you think my/our/your priorities are?
What do you think my/our/your core values should be?
What do you think my/our/your priorities should be?
How do you think I/we should treat customers, clients, and each other?
How do we want others to treat us?
What are my/our/your success stories?
What has defined these experiences as successful?
From this brainstorming session, you will craft your superhero code of conduct. You will decide what you will and will not do. You will determine how you will and will not act. You’re setting the standards that you will live and work by—so don’t take this exercise lightly. Take your time. Use the exercise as a way to open a discussion about values. Find out what you and your team believe in. Set these values and keep them in place. Write them down and share these with your team and with the world. By sharing your core values, you hold yourself more accountable to them. You also send a strong message to the rest of the world about what type of organization you are and what you believe in. Other organizations and people may decide to align or not to align themselves with you because of your core values. This is good. Chances are, you’ll be happier and more profitable if you work with other organizations and people who share similar core values.
Photo: Laura Winn
During your brainstorming session, list keywords. Don’t edit. Allow things to take their course. Some examples of keywords might be:
Ability · Achievement · Adventure · Ambition · Altruism · Awareness · Balance · Caring · Charity · Citizenship · Collaboration · Commitment · Community · Compassion · Consideration · Cooperation · Courage · Courtesy · Creativity · Democracy · Dignity · Diplomacy · Discipline · Diversity · Education · Efficiency · Energy · Equality · Excellence · Excitement · Fairness · Family · Freedom · Fun · Goodness · Gratefulness · Growth · Happiness · Harmony · Helping · Honor · Hope · Humility · Humor · Imagination · Individuality · Innovation · Integrity · Intelligence · Joy · Justice · Kindness · Knowledge · Leadership · Learning · Loyalty · Meaning · Mindfulness · Moderation · Modesty · Nurture · Openness · Organization · Passion · Patience · Peace · Planning · Principles · Productivity · Purpose · Quality · Reliability · Respectfulness · Responsibility · Security · Sensitivity · Service · Sharing · Simplicity · Stability · Tolerance · Transparency · Trust · Truthfulness · Understanding · Unity · Variety · Vision · Wisdom
After you have a list of keywords, create your core values statement using the themes from your brainstorming session. There are no rules: while above, Steve Jobs summed up Apple’s core values in one sentence, Zappos has ten core values:
Deliver WOW Through Service
Embrace and Drive Change
Create Fun and A Little Weirdness
Be Adventurous, Creative, and Open-Minded
Pursue Growth and Learning
Build Open and Honest Relationships With Communication
Build a Positive Team and Family Spirit
Do More With Less
Be Passionate and Determined
Be Humble
To see how Zappos’ employees embrace these core values, watch the video they created and posted on their website.
Dog food is yummy
Although I find merit in every keyword listed, I’ve distilled my core values to their simplest form:
Make awesomeness. Do good.
How do you make awesomeness and do good? You need ambition, balance, collaboration, commitment, fun, and you need every keyword listed to support these actions. Again, there are no rules: your core values can be one sentence or a bulleted list. What matters is being true to yourself and creating core values that others can understand. Before I start any project I ask myself: is there a way to make awesomeness and to do good? If the answer is “yes,” I embrace the endeavor because it aligns with my core values. If the answer is “no,” I move on to a project that supports my core values.
Unleash your powers
Although every organization will craft different core values, I imagine that you want to be a superhero and that you will define “doing good” (or something similar) as one of your core values. Whether you work by yourself or with a team, you can use the web as a tool to help do good. It can be as simple as giving a free hug, or something a little more complex to help others and help your organization meet the bottom line. Some interesting initiatives that use the web to do good are:
Yahoo!: How Good Grows
Desigual: Happy Hunters
Edge Shave Gel: Anti-irritation campaign
Knowing your underlying desire to return to your Underoos-and-cape-sporting childhood and knowing that you don’t always have the opportunity to develop an entire initiative to “do good,” remember that as writers, designers, and developers, we can perform superhero acts on a daily basis by making content, design, and development accessible to the greatest number of people. By considering other people’s needs, we are intentionally performing acts of kindness—we’re doing good. There are many ways to write, design, and develop websites—many of which will be discussed in other 24ways.org articles. As we make content, design, and development decisions—as we develop campaigns and initiatives—we need to keep our core values in mind. It’s easy to make a positive difference in the world. Just be the superhero you’ve always wanted to be. Go forth and make awesomeness.
If you would like to do good today, support The United Nations Children’s Fund, an organization that works for children’s rights, their survival, development and protection, by purchasing this year’s 24 ways Annual 2010 created by Five Simple Steps. All proceeds go to UNICEF.",2010,Leslie Jensen-Inman,lesliejenseninman,2010-12-04T00:00:00+00:00,https://24ways.org/2010/go-forth-and-make-awesomeness/,business
240,My CSS Wish List,"I love Christmas. I love walking around the streets of London, looking at the beautifully decorated windows, seeing the shiny lights that hang above Oxford Street and listening to Christmas songs.
I’m not going to lie though. Not only do I like buying presents, I love receiving them too. I remember making long lists that I would send to Father Christmas with all of the Lego sets I wanted to get. I knew I could only get one a year, but I would spend days writing the perfect list.
The years have gone by, but I still enjoy making wish lists. And I’ll tell you a little secret: my mum still asks me to send her my Christmas list every year.
This time I’ve made my CSS wish list. As before, I’d be happy with just one present.
Before I begin…
… this list includes:
things that don’t exist in the CSS specification (if they do, please let me know in the comments – I may have missed them);
others that are in the spec, but it’s incomplete or lacks use cases and examples (which usually means that properties haven’t been implemented by even the most recent browsers).
Like with any other wish list, the further down I go, the more unrealistic my expectations – but that doesn’t mean I can’t wish. Some of the things we wouldn’t have thought possible a few years ago have been implemented and our wishes fulfilled (think multiple backgrounds, gradients and transformations, for example).
The list
Cross-browser implementation of font-size-adjust
When one of the fall-back fonts from your font stack is used, rather than the preferred (first) one, you can retain the aspect ratio by using this very useful property. It is incredibly helpful when the fall-back fonts are smaller or larger than the initial one, which can make layouts look less polished.
What font-size-adjust does is divide the original font-size of the fall-back fonts by the font-size-adjust value. This preserves the x-height of the preferred font in the fall-back fonts. Here’s a simple example:
p {
font-family: Calibri, ""Lucida Sans"", Verdana, sans-serif;
font-size-adjust: 0.47;
}
In this case, if the user doesn’t have Calibri installed, both Lucida Sans and Verdana will keep Calibri’s aspect ratio, based on the font’s x-height. This property is a personal favourite and one I keep pointing to.
Firefox supported this property from version three. So far, it’s the only browser that does. Fontdeck provides the font-size-adjust value along with its fonts, and has a handy tool for calculating it.
More control over overflowing text
The text-overflow property lets you control text that overflows its container. The most common use for it is to show an ellipsis to indicate that there is more text than what is shown. To be able to use it, the container should have overflow set to something other than visible, and white-space: nowrap:
div {
white-space: nowrap;
width: 100%;
overflow: hidden;
text-overflow: ellipsis;
}
This, however, only works for blocks of text on a single line. In the wish list of many CSS authors (and in mine) is a way of defining text-overflow: ellipsis on a block of multiple text lines. Opera has taken the first step and added support for the -o-ellipsis-lastline property, which can be used instead of ellipsis. This property is not part of the CSS3 spec, but we could certainly make good use of it if it were…
WebKit has -webkit-line-clamp to specify how many lines to show before cutting with an ellipsis, but support is patchy at best and there is no control over where the ellipsis shows in the text. Many people have spent time wrangling JavaScript to do this for us, but the methods used are very processor intensive, and introduce a JavaScript dependency.
Indentation and hanging punctuation properties
You might notice a trend here: almost half of the items in this list relate to typography. The lack of fine-grained control over typographical detail is a general concern among designers and CSS authors. Indentation and hanging punctuation fall into this category.
The CSS3 specification introduces two new possible values for the text-indent property: each-line; and hanging. each-line would indent the first line of the block container and each line after a forced line break; hanging would invert which lines are affected by the indentation.
The proposed hanging-punctuation property would allow us to specify whether opening and closing brackets and quotes should hang outside the edge of the first and last lines. The specification is still incomplete, though, and asks for more examples and use cases.
Text alignment and hyphenation properties
Following the typographic trend of this list, I’d like to add better control over text alignment and hyphenation properties. The CSS3 module on Generated Content for Paged Media already specifies five new hyphenation-related properties (namely: hyphenate-dictionary; hyphenate-before and hyphenate-after; hyphenate-lines; and hyphenate-character), but it is still being developed and lacks examples.
In the text alignment realm, the new text-align-last property allows you to define how the last line of a block (or a line just before a forced break) is aligned, if your text is set to justify. Its value can be: start; end; left; right; center; and justify. The text-justify property should also allow you to have more control over text set to text-align: justify but, for now, only Internet Explorer supports this.
calc()
This is probably my favourite item in the list: the calc() function. This function is part of the CSS3 Values and Units module, but it has only been implemented by Firefox (4.0). To take advantage of it now you need to use the Mozilla vendor code, -moz-calc().
Imagine you have a fluid two-column layout where the sidebar column has a fixed width of 240 pixels, and the main content area fills the rest of the width available. This is how you could create that using -moz-calc():
#main {
width: -moz-calc(100% - 240px);
}
Can you imagine how many hacks and headaches we could avoid were this function available in more browsers? Transitions and animations are really nice and lovely but, for me, it’s the ability to do the things that calc() allows you to that deserves the spotlight and to be pushed for implementation.
Selector grouping with -moz-any()
The -moz-any() selector grouping has been introduced by Mozilla but it’s not part of any CSS specification (yet?); it’s currently only available on Firefox 4.
This would be especially useful with the way HTML5 outlines documents, where we can have any number of variations of several levels of headings within numerous types of containers (think sections within articles within sections…).
Here is a quick example (copied from the Mozilla blog post about the article) of how -moz-any() works. Instead of writing:
section section h1, section article h1, section aside h1,
section nav h1, article section h1, article article h1,
article aside h1, article nav h1, aside section h1,
aside article h1, aside aside h1, aside nav h1, nav section h1,
nav article h1, nav aside h1, nav nav h1, {
font-size: 24px;
}
You could simply write:
-moz-any(section, article, aside, nav)
-moz-any(section, article, aside, nav) h1 {
font-size: 24px;
}
Nice, huh?
More control over styling form elements
Some are of the opinion that form elements shouldn’t be styled at all, since a user might not recognise them as such if they don’t match the operating system’s controls. I partially agree: I’d rather put the choice in the hands of designers and expect them to be capable of deciding whether their particular design hampers or improves usability.
I would say the same idea applies to font-face: while some fear designers might go crazy and litter their web pages with dozens of different fonts, most welcome the freedom to use something other than Arial or Verdana.
There will always be someone who will take this freedom too far, but it would be useful if we could, for example, style the default Opera date picker:
or Safari’s slider control (think star movie ratings, for example):
Parent selector
I don’t think there is one CSS author out there who has never come across a case where he or she wished there was a parent selector. There have been many suggestions as to how this could work, but a variation of the child selector is usually the most popular:
article < h1 {
…
}
One can dream…
Flexible box layout
The Flexible Box Layout Module sounds a bit like magic: it introduces a new box model to CSS, allowing you to distribute and order boxes inside other boxes, and determine how the available space is shared.
Two of my favourite features of this new box model are:
the ability to redistribute boxes in a different order from the markup
the ability to create flexible layouts, where boxes shrink (or expand) to fill the available space
Let’s take a quick look at the second case. Imagine you have a three-column layout, where the first column takes up twice as much horizontal space as the other two:
With the flexible box model, you could specify it like this:
body {
display: box;
box-orient: horizontal;
}
#main {
box-flex: 2;
}
#links {
box-flex: 1;
}
aside {
box-flex: 1;
}
If you decide to add a fourth column to this layout, there is no need to recalculate units or percentages, it’s as easy as that.
Browser support for this property is still in its early stages (Firefox and WebKit need their vendor prefixes), but we should start to see it being gradually introduced as more attention is drawn to it (I’m looking at you…). You can read a more comprehensive write-up about this property on the Mozilla developer blog.
It’s easy to understand why it’s harder to start playing with this module than with things like animations or other more decorative properties, which don’t really break your layouts when users don’t see them. But it’s important that we do, even if only in very experimental projects.
Nested selectors
Anyone who has never wished they could do something like the following in CSS, cast the first stone:
article {
h1 { font-size: 1.2em; }
ul { margin-bottom: 1.2em; }
}
Even though it can easily turn into a specificity nightmare and promote redundancy in your style sheets (if you abuse it), it’s easy to see how nested selectors could be useful. CSS compilers such as Less or Sass let you do this already, but not everyone wants or can use these compilers in their projects.
Every wish list has an item that could easily be dropped. In my case, I would say this is one that I would ditch first – it’s the least useful, and also the one that could cause more maintenance problems. But it could be nice.
Implementation of the ::marker pseudo-element
The CSS Lists module introduces the ::marker pseudo-element, that allows you to create custom list item markers. When an element’s display property is set to list-item, this pseudo-element is created.
Using the ::marker pseudo-element you could create something like the following:
Footnote 1: Both John Locke and his father, Anthony Cooper, are
named after 17th- and 18th-century English philosophers; the real
Anthony Cooper was educated as a boy by the real John Locke.
Footnote 2: Parts of the plane were used as percussion instruments
and can be heard in the soundtrack.
where the footnote marker is generated by the following CSS:
li::marker {
content: ""Footnote "" counter(notes) "":"";
text-align: left;
width: 12em;
}
li {
counter-increment: notes;
}
You can read more about how to use counters in CSS in my article from last year.
Bear in mind that the CSS Lists module is still a Working Draft and is listed as “Low priority”. I did say this wish list would start to grow more unrealistic closer to the end…
Variables
The sight of the word ‘variables’ may make some web designers shy away, but when you think of them applied to things such as repeated colours in your stylesheets, it’s easy to see how having variables available in CSS could be useful.
Think of a website where the main brand colour is applied to elements like the main text, headings, section backgrounds, borders, and so on. In a particularly large website, where the colour is repeated countless times in the CSS and where it’s important to keep the colour consistent, using variables would be ideal (some big websites are already doing this by using server-side technology).
Again, Less and Sass allow you to use variables in your CSS but, again, not everyone can (or wants to) use these.
If you are using Less, you could, for instance, set the font-family value in one variable, and simply call that variable later in the code, instead of repeating the complete font stack, like so:
@fontFamily: Calibri, ""Lucida Grande"", ""Lucida Sans Unicode"", Helvetica, Arial, sans-serif;
body {
font-family: @fontFamily;
}
Other features of these CSS compilers might also be useful, like the ability to ‘call’ a property value from another selector (accessors):
header {
background: #000000;
}
footer {
background: header['background'];
}
or the ability to define functions (with arguments), saving you from writing large blocks of code when you need to write something like, for example, a CSS gradient:
.gradient (@start:"""", @end:"""") {
background: -webkit-gradient(linear, left top, left bottom, from(@start), to(@end));
background: -moz-linear-gradient(-90deg,@start,@end);
}
button {
.gradient(#D0D0D0,#9F9F9F);
}
Standardised comments
Each CSS author has his or her own style for commenting their style sheets. While this isn’t a massive problem on smaller projects, where maybe only one person will edit the CSS, in larger scale projects, where dozens of hands touch the code, it would be nice to start seeing a more standardised way of commenting.
One attempt at creating a standard for CSS comments is CSSDOC, an adaptation of Javadoc (a documentation generator that extracts comments from Java source code into HTML). CSSDOC uses ‘DocBlocks’, a term borrowed from the phpDocumentor Project. A DocBlock is a human- and machine-readable block of data which has the following structure:
/**
* Short description
*
* Long description (this can have multiple lines and contain
tags
*
* @tags (optional)
*/
CSSDOC includes a standard for documenting bug fixes and hacks, colours, versioning and copyright information, amongst other important bits of data.
I know this isn’t a CSS feature request per se; rather, it’s just me pointing you at something that is usually overlooked but that could contribute towards keeping style sheets easier to maintain and to hand over to new developers.
Final notes
I understand that if even some of these were implemented in browsers now, it would be a long time until all vendors were up to speed. But if we don’t talk about them and experiment with what’s available, then it will definitely never happen.
Why haven’t I mentioned better browser support for existing CSS3 properties? Because that would be the same as adding chocolate to your Christmas wish list – you don’t need to ask, everyone knows you want it.
The list could go on. There are dozens of other things I would love to see integrated in CSS or further developed. These are my personal favourites: some might be less useful than others, but I’ve wished for all of them at some point.
Part of the research I did while writing this article was asking some friends what they would add to their lists; other than a couple of items I already had in mine, everything else was different. I’m sure your list would be different too. So tell me, what’s on your CSS wish list?",2010,Inayaili de León Persson,inayailideleon,2010-12-03T00:00:00+00:00,https://24ways.org/2010/my-css-wish-list/,code
239,Using the WebFont Loader to Make Browsers Behave the Same,"Web fonts give us designers a whole new typographic palette with which to work. However, browsers handle the loading of web fonts in different ways, and this can lead to inconsistent user experiences.
Safari, Chrome and Internet Explorer leave a blank space in place of the styled text while the web font is loading. Opera and Firefox show text with the default font which switches over when the web font has loaded, resulting in the so-called Flash of Unstyled Text (aka FOUT). Some people prefer Safari’s approach as it eliminates FOUT, others think the Firefox way is more appropriate as content can be read whilst fonts download. Whatever your preference, the WebFont Loader can make all browsers behave the same way.
The WebFont Loader is a JavaScript library that gives you extra control over font loading. It was co-developed by Google and Typekit, and released as open source. The WebFont Loader works with most web font services as well as with self-hosted fonts.
The WebFont Loader tells you when the following events happen as a browser downloads web fonts (or loads them from cache):
when fonts start to download (‘loading’)
when fonts finish loading (‘active’)
if fonts fail to load (‘inactive’)
If your web page requires more than one font, the WebFont Loader will trigger events for individual fonts, and for all the fonts as a whole. This means you can find out when any single font has loaded, and when all the fonts have loaded (or failed to do so).
The WebFont Loader notifies you of these events in two ways: by applying special CSS classes when each event happens; and by firing JavaScript events. For our purposes, we’ll be using just the CSS classes.
Implementing the WebFont Loader
As stated above, the WebFont Loader works with most web font services as well as with self-hosted fonts.
Self-hosted fonts
To use the WebFont Loader when you are hosting the font files on your own server, paste the following code into your web page:
Replace Font Family Name and Another Font Family with a comma-separated list of the font families you want to check against, and replace http://yourwebsite.com/styles.css with the URL of the style sheet where your @font-face rules reside.
Fontdeck
Assuming you have added some fonts to a website project in Fontdeck, use the afore-mentioned code for self-hosted solutions and replace http://yourwebsite.com/styles.css with the URL of the tag in your Fontdeck website settings page. It will look something like http://f.fontdeck.com/s/css/xxxx/domain/nnnn.css.
Typekit
Typekit’s JavaScript-based implementation incorporates the WebFont Loader events by default, so you won’t need to include any WebFont Loader code.
Making all browsers behave like Safari
To make Firefox and Opera work in the same way as WebKit browsers (Safari, Chrome, etc.) and Internet Explorer, and thus minimise FOUT, you need to hide the text while the fonts are loading.
While fonts are loading, the WebFont Loader adds a class of wf-loading to the element. Once the fonts have loaded, the wf-loading class is removed and replaced with a class of wf-active (or wf-inactive if all of the fonts failed to load). This means you can style elements on the page while the fonts are loading and then style them differently when the fonts have finished loading.
So, let’s say the text you need to hide while fonts are loading is contained in all paragraphs and top-level headings. By writing the following style rule into your CSS, you can hide the text while the fonts are loading:
.wf-loading h1, .wf-loading p {
visibility:hidden;
}
Because the wf-loading class is removed once the the fonts have loaded, the visibility:hidden rule will stop being applied, and the text revealed. You can see this in action on this simple example page.
That works nicely across the board, but the situation is slightly more complicated. WebKit doesn’t wait for all fonts to load before displaying text: it displays text elements as soon as the relevant font is loaded.
To emulate WebKit more accurately, we need to know when individual fonts have loaded, and apply styles accordingly. Fortunately, as mentioned earlier, the WebFont Loader has events for individual fonts too.
When a specific font is loading, a class of the form wf-fontfamilyname-n4-loading is applied. Assuming headings and paragraphs are styled in different fonts, we can make our CSS more specific as follows:
.wf-fontfamilyname-n4-loading h1,
.wf-anotherfontfamily-n4-loading p {
visibility:hidden;
}
Note that the font family name is transformed to lower case, with all spaces removed. The n4 is a shorthand for the weight and style of the font family. In most circumstances you’ll use n4 but refer to the WebFont Loader documentation for exceptions.
You can see it in action on this Safari example page (you’ll probably need to disable your cache to see any change occur).
Making all browsers behave like Firefox
To make WebKit browsers and Internet Explorer work like Firefox and Opera, you need to explicitly show text while the fonts are loading. In order to make this happen, you need to specify a font family which is not a web font while the fonts load, like this:
.wf-fontfamilyname-n4-loading h1 {
font-family: 'arial narrow', sans-serif;
}
.wf-anotherfontfamily-n4-loading p {
font-family: arial, sans-serif;
}
You can see this in action on the Firefox example page (again you’ll probably need to disable your cache to see any change occur).
And there’s more
That’s just the start of what can be done with the WebFont Loader. More areas to explore would be tweaking font sizes to reduce the impact of reflowing text and to better cater for very narrow fonts. By using the JavaScript events much more can be achieved too, such as fading in text as the fonts load.",2010,Richard Rutter,richardrutter,2010-12-02T00:00:00+00:00,https://24ways.org/2010/using-the-webfont-loader-to-make-browsers-behave-the-same/,code
220,Finding Your Way with Static Maps,"Since the introduction of the Google Maps service in 2005, online maps have taken off in a way not really possible before the invention of slippy map interaction. Although quickly followed by a plethora of similar services from both commercial and non-commercial parties, Google’s first-mover advantage, and easy-to-use developer API saw Google Maps become pretty much the de facto mapping service.
It’s now so easy to add a map to a web page, there’s no reason not to. Dropping an iframe map into your page is as simple as embedding a YouTube video.
But there’s one crucial drawback to both the solution Google provides for you to drop into your page and the code developers typically implement themselves – they don’t work without JavaScript.
A bit about JavaScript
Back in October of this year, The Yahoo! Developer Network blog ran some tests to measure how many visitors to the Yahoo! home page didn’t have JavaScript available or enabled in their browser. It’s an interesting test when you consider that the audience for the Yahoo! home page (one of the most visited pages on the web) represents about as mainstream a sample as you’ll find. If there’s any such thing as an ‘average Web user’ then this is them.
The results surprised me. It varied from region to region, but at most just two per cent of visitors didn’t have JavaScript running. To be honest, I was expecting it to be higher, but this quote from the article caught my attention:
While the percentage of visitors with JavaScript disabled seems like a low number, keep in mind that small percentages of big numbers are also big numbers.
That’s right, of course, and it got me thinking about what that two per cent means. For many sites, two per cent is the number of visitors using the Opera web browser, using IE6, or using Mobile Safari.
So, although a small percentage of the total, users without JavaScript can’t just be forgotten about, and catering for them is at the very heart of how the web is supposed to work.
Starting with content in HTML, we layer on presentation with CSS and then enhance interactivity with JavaScript. If anything fails along the way or the network craps out, or a browser just doesn’t support one of the technologies, the user still gets something they can work with.
It’s progressive enhancement – also known as doing our jobs properly.
Sorry, wasn’t this about maps?
As I was saying, the default code Google provides, and the example code it gives to developers (which typically just gets followed ‘as is’) doesn’t account for users without JavaScript. No JavaScript, no content.
When adding the ability to publish maps to our small content management system Perch, I didn’t want to provide a solution that only worked with JavaScript. I had to go looking for a way to provide maps without JavaScript, too.
There’s a simple solution, fortunately, in the form of static map tiles. All the various slippy map services use a JavaScript interface on top of what are basically rendered map image tiles. Dragging the map loads in more image tiles in the direction you want to view. If you’ve used a slippy map on a slow connection, you’ll be familiar with seeing these tiles load in one by one.
The Static Map API
The good news is that these tiles (or tiles just like them) can be used as regular images on your site. Google has a Static Map API which not only gives you a handy interface to retrieve a tile for the exact area you need, but also allows you to place pins, and zoom and centre the tile so that the image looks just so.
This means that you can create a static, non-JavaScript version of your slippy map’s initial (or ideal) state to load into your page as a regular image, and then have the JavaScript map hijack the image and make it slippy.
Clearly, that’s not going to be a perfect solution for every map’s requirements. It doesn’t allow for panning, zooming or interrogation without JavaScript. However, for the majority of straightforward map uses online, a static map makes a great alternative for those visitors without JavaScript.
Here’s the how
Retrieving a static map tile is staggeringly easy – it’s just a case of forming a URL with the correct arguments and then using that as the src of an image tag.
As you can see, there are a few key options that we pass along to the base URL. All of these should be familiar to anyone who’s worked with the JavaScript API.
center determines the point on which the map is centred. This can be latitude and longitude values, or simply an address which is then geocoded.
zoom sets the zoom level.
size is the pixel dimensions of the image you require.
maptype can be roadmap, satellite, terrain or hybrid.
markers sets one or more pin locations. Markers can be labelled, have different colours, and so on – there’s quite a lot of control available.
sensor states whether you are using a sensor to determine the user’s location. When just embedding a map in a web page, set this to false.
There are many options, including plotting paths and setting the image format, which can all be found in the straightforward documentation.
Adding to your page
If you’ve worked with the JavaScript API, you’ll know that it needs a container element which you inject the map into:
All you need to do is put your static image inside that container:
And then, in your JavaScript, find the image and remove it. For example, with jQuery you’d simply use:
$('#map img').remove();
Why not use a
element around the image? You could, and that would certainly work fine for browsers that do not support JavaScript. What that won’t cover, however, is the situation where the browser has JavaScript support but, for whatever reason, the JavaScript doesn’t run. This could be due to network issues, an aggressive corporate firewall, or even just a bug in your code. So for that reason, we put the image in for all browsers that show images, and then remove it when the JavaScript is successfully running.
See an example in action
About rate limits
The Google Static Map API limits the requests per site viewer – currently at one thousand distinct maps per day per viewer. So, for most sites you really don’t need to worry about the rate limit. Requests for the same tile aren’t normally counted, as the tile has already been generated and is cached. You can embed the images direct from Google and let it worry about the distribution and caching.
In conclusion
As you can see, adding a static map alongside your dynamic map for those users without JavaScript is very easy indeed. There may not be a huge percentage of web visitors browsing without JavaScript but, as we’ve seen, a small percentage of a big number is still a big number. When it’s so easy to add a static map, can you really justify not doing it?",2010,Drew McLellan,drewmclellan,2010-12-01T00:00:00+00:00,https://24ways.org/2010/finding-your-way-with-static-maps/,code
185,Make Your Mockup in Markup,"We aren’t designing copies of web pages, we’re designing web pages.
Andy Clarke, via Quotes on Design
The old way
I used to think the best place to design a website was in an image editor. I’d create a pixel-perfect PSD filled with generic content, send it off to the client, go through several rounds of revisions, and eventually create the markup.
Does this process sound familiar? You’re not alone. In a very scientific and official survey I conducted, close to 90% of respondents said they design in Photoshop before the browser.
That process is whack, yo!
Recently, thanks in large part to the influence of design hero Dan Cederholm, I’ve come to the conclusion that a website’s design should begin where it’s going to live: in the browser.
Die Photoshop, die
Some of you may be wondering, “what’s so bad about using Photoshop for the bulk of my design?” Well, any seasoned designer will tell you that working in Photoshop is akin to working in a minefield: you never know when it’s going to blow up in your face.
The application Adobe Photoshop CS4 has unexpectedly ruined your day.
Photoshop’s propensity to crash at crucial moments is a running joke in the industry, as is its barely usable interface. And don’t even get me started on the hot, steaming pile of crap that is text rendering.
Text rendered in Photoshop (left) versus Safari (right).
Crashing and text rendering issues suck, but we’ve learned to live with them. The real issue with using Photoshop for mockups is the expectations you’re setting for a client. When you send the client a static image of the design, you’re not giving them the whole picture — they can’t see how a fluid grid would function, how the design will look in a variety of browsers, basic interactions like :hover effects, or JavaScript behaviors. For more on the disadvantages to showing clients designs as images rather than websites, check out Andy Clarke’s Time to stop showing clients static design visuals.
A necessary evil?
In the past we’ve put up with Photoshop because it was vital to achieving our beloved rounded corners, drop shadows, outer glows, and gradients. However, with the recent adaptation of CSS3 in major browsers, and the slow, joyous death of IE6, browsers can render mockups that are just as beautiful as those created in an image editor. With the power of RGBA, text-shadow, box-shadow, border-radius, transparent PNGs, and @font-face combined, you can create a prototype that radiates shiny awesomeness right in the browser. If you can see this epic article through to the end, I’ll show you step by step how to create a gorgeous mockup using mostly markup.
Get started by getting naked
Content precedes design. Design in the absence of content is not design, it’s decoration.
Jeffrey Zeldman
In the beginning, don’t even think about style. Instead, start with the foundation: the content. Lay the groundwork for your markup order, and ensure that your design will be useable with styles and images turned off. This is great for prioritizing the content, and puts you on the right path for accessibility and search engine optimization. Not a bad place to start, amirite?
An example of unstyled content, in all its naked glory. View it large.
Flush out the layout
The next step is to structure the content in a usable way. With CSS, making basic layout changes is as easy as switching up a float, so experiment to see what structure suits the content best.
The mockup with basic layout work done.
Got your grids covered
There are a variety of tools that allow you to layer a grid over your browser window. For Mac users I recommend using Slammer, and PC users can check out one of the bookmarklets that are available, such as 960 Gridder.
The mockup with a grid applied using Slammer.
Once you’ve found a layout that works well for the content, pass it along to the client for review. This keeps them involved in the design process, and gives them an idea of how the site will be structured when it’s live.
Start your styling
Now for the fun part: begin applying the presentation layer. Let usability considerations drive your decisions about color and typography; use highlighted colors and contrasting typefaces on elements you wish to emphasize.
RGBA? More like RGByay!
Introducing color is easy with RGBA. I like to start with the page’s main color, then use white at varying opacities to empasize content sections.
In the example mockup the body background is set to rgba(203,111,21), the content containers are set to rgba(255,255,255,0.7), and a few elements are highlighted with rgba(255,255,255,0.1) If you’re not sure how RGBA works, check out Drew McLellan’s super helpful 24ways article.
Laying down type
Just like with color, you can use typography to evoke a feeling and direct a user’s attention. Have contrasting typefaces (like serif headlines and sans-serif body text) to group the content into meaningful sections.
In a recent A List Apart article, the Master of Web Typography™ Jason Santa Maria offers excellent advice on how to choose your typefaces:
Write down a general description of the qualities of the message you are trying to convey, and then look for typefaces that embody those qualities.
Sounds pretty straightforward. I wanted to give my design a classic feel with a hint of nostalgia, so I used Georgia for the headlines, and incorporated the ornate ampersand from Baskerville into the header.
A closeup on the site’s header.
Let’s get sexy
The design doesn’t look too bad as it is, but it’s still pretty flat. We can do better, and after mixing in some CSS3 and a couple of PNGs, it’s going to get downright steamy in here.
Give it some glow
Objects in the natural world reflect light, so to make your design feel tangible and organic, give it some glow. In the example design I achieved this by creating two white to transparent gradients of varying opacities. Both have a solid white border across their top, which gives edges a double border effect and makes them look sharper. Using CSS3’s text-shadow on headlines and box-shadow on content modules is another quick way to add depth.
A wide and closeup view of the design with gradients, text-shadow and box-shadow added. For information on how to implement text-shadow and box-shadow using RGBA, check out the article I wrote on it last week.
37 pieces of flair
Okay, maybe you don’t need that much flair, but it couldn’t hurt to add a little; it’s the details that will set your design apart. Work in imagery and texture, using PNGs with an alpha channel so you can layer images and still tweak the color later on.
The design with grungy textures, a noisy diagonal stripe pattern, and some old transportation images layered behind the text. Because the colors are rendered using RGBA, these images bleed through the content, giving the design a layered feel. Best viewed large.
Send it off
Hey, look at that. You’ve got a detailed, well structured mockup for the client to review. Best of all, your markup is complete too. If the client approves the design at this stage, your template is practically finished. Bust out the party hats!
Not so fast, Buster!
So I don’t know about you, but I’ve never gotten a design past the client’s keen eye for criticism on the first go. Let’s review some hypothetical feedback (none of which is too outlandish, in my experience), and see how we’d make the requested changes in the browser.
Updating the typography
My ex-girlfriend loved Georgia, so I never want to see it again. Can we get rid of it? I want to use a font that’s chunky and loud, just like my stupid ex-girlfriend.
Fakey McClient
Yikes! Thankfully with CSS, removing Georgia is as easy as running a find and replace on the stylesheet. In my revised mockup, I used @font-face and League Gothic on the headlines to give the typography the, um, unique feel the client is looking for.
The same mockup, using @font-face on the headlines. If you’re unfamiliar with implementing @font-face, check out Nice Web Type‘s helpful article.
Adding rounded corners
I’m not sure if I’ll like it, but I want to see what it’d look like with rounded corners. My cousin, a Web 2.0 marketing guru, says they’re trendy right now.
Fakey McClient
Switching to rounded corners is a nightmare if you’re doing your mockup in Photoshop, since it means recreating most of the shapes and UI elements in the design. Thankfully, with CSS border-radius comes to our rescue! By applying this gem of a style to a handful of classes, you’ll be rounded out in no time.
The mockup with rounded corners, created using border-radius. If you’re not sure how to implement border-radius, check out CSS3.info‘s quick how-to.
Making changes to the color
The design is too dark, it’s depressing! They call it ‘the blues’ for a reason, dummy. Can you try using a brighter color? I want orange, like Zeldman uses.
Fakey McClient
Making color changes is another groan-inducing task when working in Photoshop. Finding and updating every background layer, every drop shadow, and every link can take forever in a complex PSD. However, if you’ve done your mockup in markup with RGBA and semi-transparent PNGs, making changes to your color is as easy as updating the body background and a few font colors.
The mockup with an orange color scheme. Best viewed large.
Ahem, what about Internet Explorer?
Gee, thanks for reminding me, buzzkill. Several of the CSS features I’ve suggested you use, such as RGBA, text-shadow and box-shadow, and border-radius, are not supported in Internet Explorer. I know, it makes me sad too. However, this doesn’t mean you can’t try these techniques out in your markup based mockups. The point here is to get your mockups done as efficiently as possible, and to keep the emphasis on markup from the very beginning.
Once the design is approved, you and the client have to decide if you can live with the design looking different in different browsers. Is it so bad if some users get to see drop shadows and some don’t? Or if the rounded corners are missing for a portion of your audience? The design won’t be broken for IE people, they’re just missing out on a few visual treats that other users will see.
The idea of rewarding users who choose modern browsers is not a new concept; Dan covers it thoroughly in Handcrafted CSS, and it’s been written about in the past by Aaron Gustafson and Andy Clarke on several occasions. I believe we shouldn’t have to design for the lowest common denominator (cough, IE6 users, cough); instead we should create designs that are beautiful in modern browsers, but still degrade nicely for the other guy. However, some clients just aren’t that progressive, and in that case you can always use background images for drop shadows and rounded corners, as you have in the past.
Closing thoughts
With the advent of CSS3, browsers are just as capable of giving us beautiful, detailed mockups as Photoshop, and in half the time. I’m not the only one to make an argument for this revised process; in his article Time to stop showing clients static design visuals, and in his presentation Walls Come Tumbling Down, Andy Clarke makes a fantastic case for creating your mockups in markup.
So I guess my challenge to you for 2010 is to get out of Photoshop and into the code. Even if the arguments for designing in the browser aren’t enough to make you change your process permanently, it’s worthwhile to give it a try. Look at the New Year as a time to experiment; applying constraints and evaluating old processes can do wonders for improving your efficiency and creativity.",2009,Meagan Fisher,meaganfisher,2009-12-24T00:00:00+00:00,https://24ways.org/2009/make-your-mockup-in-markup/,process
189,Ignorance Is Bliss,"This is a true story.
Meet Mike
Mike’s a smart guy. He knows a great browser when he sees one. He uses Firefox on his Windows PC at work and Safari on his Mac at home. Mike asked us to design a Web site for his business. So we did.
We wanted to make the best Web site for Mike that we could, so we used all of the CSS tools that are available today. That meant using RGBa colour to layer elements, border-radius to add subtle rounded corners and (possibly most experimental of all new CSS), generated gradients.
The home page Mike sees in Safari on his Mac
Mike loves what he sees.
Meet Sam
Sam works with Mike. She uses Internet Explorer 7 because it came on the Windows laptop that the company bought her when she joined.
The home page Sam sees in Internet Explorer 7 on her PC
Sam loves the new Web site too.
How could both of them be happy when they experienced the Web site differently?
The new WYSIWYG
When I first presented my designs to Mike and Sam, I showed them a Web page made with HTML and CSS in their respective browsers and not a picture of a Web page. By showing neither a static image of my design, I set none of the false expectations that, by definition, a static Photoshop or Fireworks visual would have established.
Mike saw rounded corners and subtle shadows in Firefox and Safari. Sam saw something equally as nice, just a little different, in Internet Explorer. Both were very happy because they saw something that they liked.
Neither knew, or needed to know, about the subtle differences between browsers. Their users don’t need to know either.
That’s because in the real world, people using the Web don’t find a Web site that they like, then open up another browser to check that it looks they same. They simply buy what they came to buy, read what what they came to read, do what they came to do, then get on with their lives in blissful ignorance of what they might be seeing in another browser.
Often when I talk or write about using progressive CSS, people ask me, “How do you convince clients to let you work that way? What’s your secret?” Secret? I tell them what they need to know, on a need-to-know basis.
Epilogue
Sam has a new iPhone that Mike bought for her as a reward for achieving her sales targets. She loves her iPhone and was surprised at just how fast and good-looking the company Web site appears on that. So she asked,
“Andy, I didn’t know you optimised our site for mobile. I don’t remember seeing an invoice for that.”
I smiled.
“That one was on the house.”",2009,Andy Clarke,andyclarke,2009-12-23T00:00:00+00:00,https://24ways.org/2009/ignorance-is-bliss/,business
173,Real Fonts and Rendering: The New Elephant in the Room,"My friend, the content strategist Kristina Halvorson, likes to call content “the elephant in the room” of web design. She means it’s the huge problem that no one on the web development team or client side is willing to acknowledge, face squarely, and plan for.
A typical web project will pass through many helpful phases of research, and numerous beneficial user experience design iterations, while the content—which in most cases is supposed to be the site’s primary focus—gets handled haphazardly at the end. Hence, elephant in the room, and hence also artist Kevin Cornell’s recent use of elephantine imagery to illustrate A List Apart articles on the subject. But I digress.
Without discounting the primacy of the content problem, we web design folk have now birthed ourselves a second lumbering mammoth, thanks to our interest in “real fonts on the web“ (the unfortunate name we’ve chosen for the recent practice of serving web-licensed fonts via CSS’s decade-old @font-face declaration—as if Georgia, Verdana, and Times were somehow unreal).
For the fact is, even bulletproof and mo’ bulletproofer @font-face CSS syntax aren’t really bulletproof if we care about looks and legibility across browsers and platforms.
Hyenas in the Breakfast Nook
The problem isn’t just that foundries have yet to agree on a standard font format that protects their intellectual property. And that, even when they do, it will be a while before all browsers support that standard—leaving aside the inevitable politics that impede all standardization efforts. Those are problems, but they’re not the elephant. Call them the coyotes in the room, and they’re slowly being tamed.
Nor is the problem that workable, scalable business models (of which Typekit‘s is the most visible and, so far, the most successful) are still being shaken out and tested. The quality and ease of use of such services, their stability on heavily visited sites (via massively backed-up server clusters), and the fairness and sustainability of their pricing will determine how licensing and serving “real fonts” works in the short and long term for the majority of designer/developers.
Nor is our primary problem that developers with no design background may serve ugly or illegible fonts that take forever to load, or fonts that take a long time to download and then display as ordinary system fonts (as happens on, say, about.validator.nu). Ugliness and poor optimization on the web are nothing new. That support for @font-face in Webkit and Mozilla browsers (and for TrueType fonts converted to Embedded OpenType in Internet Explorer) adds deadly weapons to the non-designer’s toolkit is not the technology’s fault. JavaScript and other essential web technologies are equally susceptible to abuse.
Beauty is in the Eye of the Rendering Engine
No, the real elephant in the room—the thing few web developers and no “web font” enthusiasts are talking about—has to do with legibility (or lack thereof) and aesthetics (or lack thereof) across browsers and platforms. Put simply, even fonts optimized for web use (which is a whole thing: ask a type designer) will not look good in every browser and OS. That’s because every browser treats hinting differently, as does every OS, and every OS version.
Firefox does its own thing in both Windows and Mac OS, and Microsoft is all over the place because of its need to support multiple generations of Windows and Cleartype and all kinds of hardware simultaneously. Thus “real type” on a single web page can look markedly different, and sometimes very bad, on different computers at the same company. If that web page is your company’s, your opinion of “web fonts” may suffer, and rightfully. (The advantage of Apple’s closed model, which not everyone likes, is that it allows the company to guarantee the quality and consistency of user experience.)
As near as my font designer friends and I can make out, Apple’s Webkit in Safari and iPhone ignores hinting and creates its own, which Apple thinks is better, and which many web designers think of as “what real type looks like.” The forked version of Webkit in Chrome, Android, and Palm Pre also creates its own hinting, which is close to iPhone’s—close enough that Apple, Palm, and Google could propose it as a standard for use in all browsers and platforms. Whether Firefox would embrace a theoretical Apple and Google standard is open to conjecture, and I somehow have difficulty imagining Microsoft buying in—even though they know the web is more and more mobile, and that means more and more of their customers are viewing web content in some version of Webkit.
The End of Simple
There are ways around this ugly type ugliness, but they involve complicated scripting and sniffing—the very nightmares from which web standards and the simplicity of @font-face were supposed to save us. I don’t know that even mighty Typekit has figured out every needed variation yet (although, working with foundries, they probably will).
For type foundries, the complexity and expense of rethinking classic typefaces to survive in these hostile environments may further delay widespread adoption of web fonts and the resolution of licensing and formatting issues. The complexity may also force designers (even those who prefer to own) to rely on a hosted rental model simply to outsource and stay current with the detection and programming required.
Forgive my tears. I stand in a potter’s field of ideas like “Keep it simple,” by a grave whose headstone reads “Write once, publish everywhere.”",2009,Jeffrey Zeldman,jeffreyzeldman,2009-12-22T00:00:00+00:00,https://24ways.org/2009/real-fonts-and-rendering/,design
178,Make Out Like a Bandit,"If you are anything like me, you are a professional juggler. No, we don’t juggle bowling pins or anything like that (or do you? Hey, that’s pretty rad!). I’m talking about the work that we juggle daily. In my case, I’m a full-time designer, a half-time graduate student, a sometimes author and conference speaker, and an all-the-time social networker. Only two of these “positions” have actually put any money in my pocket (and, well, the second one takes a lot of money out). Still, this is all part of the work that I do. Your work situation is probably similar. We are workaholics.
So if we work so much in our daily lives, shouldn’t we be making out like bandits? Umm, honestly, I’m not hitting on you, silly. I’m talking about our success. We work and work and work. Shouldn’t we be filthy, stinking rich? Well… okay, that’s not quite what I mean either. I’m not necessarily talking about money (though that could potentially be a part of it). I’m talking about success — as in feeling a true sense of accomplishment and feeling happy about what we do and why we do it.
It’s important to feel accomplished and a general happiness in our work. To make out like a bandit (or have an incredible amount of success), you can either get lucky or work hard for it. And if you’re going to work hard for it, you might as well make it all meaningful and worthwhile. This is what I strive for in my own work and my life, and the following points I’m sharing with you are the steps I am taking to work toward this.
I know the price of success: dedication, hard work & an unremitting devotion to the things you want to see happen. — Frank Lloyd Wright
Learn. Participate. Do.
The best way to get good at something is to keep doing whatever it is you’re doing that you want to be good at. For example, a sushi-enthusiast might take a sushi-making class because she wants to learn to make sushi for herself. It totally makes sense while the teacher demonstrates all the procedures, materials, and methods needed to make good, beautiful sushi. Later, the student goes home and tries to make sushi on her own, she gets totally confused and lost. Okay, I’m not even going to hide it, I’m talking about myself (this happened to me). As much as I love sushi, I couldn’t even begin to make good sushi because I’ve never really practiced.
Take advantage of learning opportunities where possible. Whether you’re learning CSS, Actionscript, or visual design, the best way to grasp how to do things is to participate, practice, do. Apply what you learn in your work. Participation is so vital to your success. If you have problems, let people know, and ask. But definitely practice on your own. And as cliché as it may sound, believe in yourself because if you don’t think you can do it, no one else will think you can either.
Maintain momentum
With whatever it is you’re doing, if you find yourself “on a roll”, you should take advantage of that momentum and keep moving. Sure, you’ll definitely want to take breaks here or there, but remember that momentum can be very difficult to obtain again once you’ve lost it. Get it done!
Deal with people
Whether you love or hate people, the fact is, you gotta deal with them — even the difficult ones. If you’re in a management position, then you know pretty well that most people don’t like being told what to do (even if that’s their job). Find ways to get people excited about what they’re doing. Make people feel that they (and what they do) are needed — people respond better if they’re valued, not commanded. Even if you’re not in a management position, this still applies to the way you work with your coworkers, clients, vendors, etc.
Resolve any conflicts right away. Conflicts will inevitably happen. Move on to how you can improve the situation, and do it as quickly as possible. Don’t spend too much time focusing on whose screw up it is — nobody feels good in this situation. Also, try to keep people informed on whatever it is you need or what it is you’re doing. If you’re waiting on something from someone, and it’s been a while, don’t be afraid to say something (tactfully). Sometimes people are forgetful — or just slacking. Hey, it happens!
Help yourself by helping others
What are some of the small, simple things you can do when you’re working that will help the people you work with (and in most cases, will end up helping yourself)? For example: if you’re a designer, perhaps taking a couple minutes now to organize and name your Photoshop layers will end up saving time later (since it will be easier to find things). This is going to help both you and your team. Or, developers: taking some time to write some documentation (even if it’s as simple as a comment in the code, or a well-written commit message) could potentially save valuable time for both you and your team later. Maybe you have to take a little time to sit down with a coworker and explain why something works the way it does. This helps them out tremendously — and will most likely lead to them respecting you a little more. This is a benefit.
If you make little things like this a habit, people will notice. People will enjoy working with you. People will trust you and rely on you. Sure, it might seem beneficial at any given moment to be “in it for yourself” (and therefore only helping yourself), but that won’t last very long. Helping others (whether it be a small or large feat) will cause a positive impact in the long run — and that is what will be more valuable to you and your career.
Do work that is meaningful
One of the best ways to feel successful about what you do is to feel good and happy about it. And a great way to feel good and happy about what you’re doing is to actually do good. This could be purpose-driven work that focuses on sustainability and environmentalism, or work that helps support causes and charity. Perhaps the work simply inspires people. Or maybe the work is just something you are very passionate about. Whatever the work may be, try working on projects that are meaningful to you. You’ll do well simply by being more motivated and interested. And it’s a double-win if the project is meaningful to others as well.
I feel very fortunate to work at a place like Crush + Lovely, where we have found quite frequently that the projects that inspire people, focus on global and social good, and create some sort of positive impact are the very projects that bring us more paid projects. But more importantly, we are happy and excited to do it. You might not work at a company that takes on those types of projects. But perhaps you have your own personal endeavors that create this excitement for you. Elliot Jay Stocks wrote about having pet projects. Do you take on side projects? What are those projects?
Over the last couple years, I’ve seen some really fantastic side projects come out that are great examples of meaningful work. These projects reflect the passions and goals of the respective designers and developers involved, and therefore become quite successful (because the people involved simply love what they are doing while they’re doing it). Some of these projects include:
Typedia is a shared encyclopedia of typefaces which serves as a resource to classify, categorize, and connect typefaces. It was founded by Jason Santa Maria, a graphic designer with a love and passion for typography. He created it as a solution to a problem he faced as a designer: finding the right typeface.
Huffduffer was created by Jeremy Keith, a web developer who wanted to create a podcast of inspirational talks — but after he found that this could be tedious, he decided to create a tool to automate this.
Level & Tap was created by passionate photographer and web developer, Tom Watson. It began as a photography print store for Tom’s best personal photography. Over time, more photographers were added to the site and the site has grown to become quite a great collection of beautiful photography.
Heat Eat Review is a review blog created by information architect and user experience designer, Abi Jones. As a foodie, she is able to use this passion for this blog, as it focuses on reviewing TV Dinners, Frozen Meals, and Microwavable Foods.
Art in My Coffee, a favorite personal project of my own, is a photo blog of coffee art I created, after I found that my friends and I were frequently posting coffee art photos to Flickr, Twitter, and other websites. After the blog became more popular, I teamed up with Meagan Fisher on the project, who has just as much a passion for coffee art, if not more.
So, what’s important to you?
This is the very, very important question here. What really matters to you most? Beyond just working on meaningful projects you are passionate about, is the work you’re doing the right work for you, so that you can live a good lifestyle? Scott Boms wrote an excellent article, Burnout, in which he shares his own experience in battling stress and exhaustion, and what he learned from it. You should definitely read the article in its entirety, but a couple of his points that are particularly excellent are:
Make time for numero uno, in which you make time for the things in life that make you happy
Examine your values, goals, and measures of success, in which you work toward the things you are passionate about, your own personal development, and focusing on the things that matter.
A solid work-life balance can be a challenging struggle to obtain. Of course, you can cheat this by finding ways to combine the things you love with the things you do (so then it doesn’t even feel like you’re working — oh, you sneaky little bandit!). However, there are other factors to consider beyond your general love for the work you’re doing. Take proper care of yourself physically, mentally, and socially.
So, are you making out like a bandit?
Do you feel accomplished and generally happy with your work? If not, perhaps that is something to focus on for the next year. Consider your work (both in your job as well as any side projects you may take on) and how it benefits you — present and future. Take any steps necessary to get you to where you need to be. If you are miserable, fix it!
Finally, it’s important to be thankful for the things that matter to you and make you happy. Pass it along everyday. Thank people. It’s a simple thing, really. Saying “thank you” can and will have enormous impact on the people around you. Oh. And, I apologize if the title of this article led you to thinking it would teach you how to be an amazing kisser. That’s a different article entirely for 24 ways to impress your friends!",2009,Jina Anne,jina,2009-12-21T00:00:00+00:00,https://24ways.org/2009/make-out-like-a-bandit/,business
192,Cleaner Code with CSS3 Selectors,"The parts of CSS3 that seem to grab the most column inches on blogs and in articles are the shiny bits. Rounded corners, text shadow and new ways to achieve CSS layouts are all exciting and bring with them all kinds of possibilities for web design. However what really gets me, as a developer, excited is a bit more mundane.
In this article I’m going to take a look at some of the ways our front and back-end code will be simplified by CSS3, by looking at the ways we achieve certain visual effects now in comparison to how we will achieve them in a glorious, CSS3-supported future. I’m also going to demonstrate how we can use these selectors now with a little help from JavaScript – which can work out very useful if you find yourself in a situation where you can’t change markup that is being output by some server-side code.
The wonder of nth-child
So why does nth-child get me so excited? Here is a really common situation, the designer would like the tables in the application to look like this:
Setting every other table row to a different colour is a common way to enhance readability of long rows. The tried and tested way to implement this is by adding a class to every other row. If you are writing the markup for your table by hand this is a bit of a nuisance, and if you stick a row in the middle you have to change the rows the class is applied to. If your markup is generated by your content management system then you need to get the server-side code to add that class – if you have access to that code.
Striping every other row - using classes
Name
Cards sent
Cards received
Cards written but not sent
Ann
40
28
4
Joe
2
27
29
Paul
5
35
2
Louise
65
65
0
View Example 1
This situation is something I deal with on almost every project, and apart from being an extra thing to do, it just isn’t ideal having the server-side code squirt classes into the markup for purely presentational reasons. This is where the nth-child pseudo-class selector comes in. The server-side code creates a valid HTML table for the data, and the CSS then selects the odd rows with the following selector:
tr:nth-child(odd) td {
background-color: #86B486;
}
View Example 2
The odd and even keywords are very handy in this situation – however you can also use a multiplier here. 2n would be equivalent to the keyword ‘odd’ 3n would select every third row and so on.
Browser support
Sadly, nth-child has pretty poor browser support. It is not supported in Internet Explorer 8 and has somewhat buggy support in some other browsers. Firefox 3.5 does have support. In some situations however, you might want to consider using JavaScript to add this support to browsers that don’t have it. This can be very useful if you are dealing with a Content Management System where you have no ability to change the server-side code to add classes into the markup.
I’m going to use jQuery in these examples as it is very simple to use the same CSS selector used in the CSS to target elements with jQuery – however you could use any library or write your own function to do the same job. In the CSS I have added the original class selector to the nth-child selector:
tr:nth-child(odd) td, tr.odd td {
background-color: #86B486;
}
Then I am adding some jQuery to add a class to the markup once the document has loaded – using the very same nth-child selector that works for browsers that support it.
View Example 3
We could just add a background colour to the element using jQuery, however I prefer not to mix that information into the JavaScript as if we change the colour on our table rows I would need to remember to change it both in the CSS and in the JavaScript.
Doing something different with the last element
So here’s another thing that we often deal with. You have a list of items all floated left with a right hand margin on each element constrained within a fixed width layout. If each element has the right margin applied the margin on the final element will cause the set to become too wide forcing that last item down to the next row as shown in the below example where I have used a grey border to indicate the fixed width.
Currently we have two ways to deal with this. We can put a negative right margin on the list, the same width as the space between the elements. This means that the extra margin on the final element fills that space and the item doesn’t drop down.
The last item is different
View Example 4
The other solution will be to put a class on the final element and in the CSS remove the margin for this class.
ul.gallery li.last {
margin-right: 0;
}
This second solution may not be easy if the content is generated from server-side code that you don’t have access to change.
It could all be so different. In CSS3 we have marvellously common-sense selectors such as last-child, meaning that we can simply add rules for the last list item.
ul.gallery li:last-child {
margin-right: 0;
}
View Example 5
This removed the margin on the li which is the last-child of the ul with a class of gallery. No messing about sticking classes on the last item, or pushing the width of the item out wit a negative margin.
If this list of items repeated ad infinitum then you could also use nth-child for this task. Creating a rule that makes every 3rd element margin-less.
ul.gallery li:nth-child(3n) {
margin-right: 0;
}
View Example 6
A similar example is where the designer has added borders to the bottom of each element – but the last item does not have a border or is in some other way different. Again, only a class added to the last element will save you here if you cannot rely on using the last-child selector.
Browser support for last-child
The situation for last-child is similar to that of nth-child, in that there is no support in Internet Explorer 8. However, once again it is very simple to replicate the functionality using jQuery. Adding our .last class to the last list item.
$(""ul.gallery li:last-child"").addClass(""last"");
We could also use the nth-child selector to add the .last class to every third list item.
$(""ul.gallery li:nth-child(3n)"").addClass(""last"");
View Example 7
Fun with forms
Styling forms can be a bit of a trial, made difficult by the fact that any CSS applied to the input element will effect text fields, submit buttons, checkboxes and radio buttons. As developers we are left adding classes to our form fields to differentiate them. In most builds all of my text fields have a simple class of text whereas I wouldn’t dream of adding a class of para to every paragraph element in a document.
Syling form fields
Send your Christmas list to Santa
View Example 8
Attribute selectors provide a way of targeting elements by looking at the attributes of those elements. Unlike the other examples in this article which are CSS3 selectors, the attribute selector is actually a CSS2.1 selector – it just doesn’t get much use because of lack of support in Internet Explorer 6. Using attribute selectors we can write rules for text inputs and form buttons without needing to add any classes to the markup. For example after removing the text and button classes from my text and submit button input elements I can use the following rules to target them:
form input[type=""text""] {
border: 1px solid #333;
padding: 0.2em;
width: 400px;
}
form input[type=""submit""]{
border: 1px solid #333;
background-color: #eee;
color: #000;
padding: 0.1em;
}
View Example 9
Another problem that I encounter with forms is where I am using CSS to position my labels and form elements by floating the labels. This works fine as long as I want all of my labels to be floated, however sometimes we get a set of radio buttons or a checkbox, and I don’t want the label field to be floated. As you can see in the below example the label for the checkbox is squashed up into the space used for the other labels, yet it makes more sense for the checkbox to display after the text.
I could use a class on this label element however CSS3 lets me to target the label attribute directly by looking at the value of the for attribute.
label[for=""fOptIn""] {
float: none;
width: auto;
}
Being able to precisely target attributes in this way is incredibly useful, and once IE6 is no longer an issue this will really help to clean up our markup and save us from having to create all kinds of special cases when generating this markup on the server-side.
Browser support
The news for attribute selectors is actually pretty good with Internet Explorer 7+, Firefox 2+ and all other modern browsers all having support. As I have already mentioned this is a CSS2.1 selector and so we really should expect to be able to use it as we head into 2010! Internet Explorer 7 has slightly buggy support and will fail on the label example shown above however I discovered a workaround in the Sitepoint CSS reference comments. Adding the selector label[htmlFor=""fOptIn""] to the correct selector will create a match for IE7.
IE6 does not support these selector but, once again, you can use jQuery to plug the holes in IE6 support. The following jQuery will add the text and button classes to your fields and also add a checks class to the label for the checkbox, which you can use to remove the float and width for this element.
$('form input[type=""submit""]').addClass(""button"");
$('form input[type=""text""]').addClass(""text"");
$('label[for=""fOptIn""]').addClass(""checks"");
View Example 10
The selectors I’ve used in this article are easy to overlook as we do have ways to achieve these things currently. As developers – especially when we have frameworks and existing code that cope with these situations – it is easy to carry on as we always have done.
I think that the time has come to start to clean up our front and backend code and replace our reliance on classes with these more advanced selectors. With the help of a little JavaScript almost all users will still get the full effect and, where we are dealing with purely visual effects, there is definitely a case to be made for not worrying about the very small percentage of people with old browsers and no JavaScript. They will still receive a readable website, it may just be missing some of the finesse offered to the modern browsing experience.",2009,Rachel Andrew,rachelandrew,2009-12-20T00:00:00+00:00,https://24ways.org/2009/cleaner-code-with-css3-selectors/,code
184,Spruce It Up,"The landscape of web typography is changing quickly these days. We’ve gone from the wild west days of sIFR to Cufón to finally seeing font embedding seeing wide spread adoption by browser developers (and soon web designers) with @font-face. For those who’ve felt limited by the typographic possibilities before, this has been a good year.
As Mark Boulton has so eloquently elucidated, @font-face embedding doesn’t come without its drawbacks. Font files can be quite large and FOUT—that nasty flash of unstyled text—can be a distraction for users.
Data URIs
We can battle FOUT by using Data URIs. A Data URI allows the font to be encoded right into the CSS file. When the font comes with the CSS, the flash of unstyled text is mitigated. No extra HTTP requests are required.
Don’t be a grinch, though. Sending hundreds of kilobytes down the pipe still isn’t great. Sometimes, all we want to do is spruce up our site with a little typographic sugar.
Be Selective
Dan Cederholm’s SimpleBits is an attractive site.
Take a look at the ampersand within the header of his site. It’s the lovely (and free) Goudy Bookletter 1911 available from The League of Movable Type. The Opentype format is a respectable 28KB. Nothing too crazy but hold on here. Mr. Cederholm is only using the ampersand! Ouch. That’s a lot of bandwidth just for one character.
Can we optimize a font like we can an image? Yes. Image optimization essentially works by removing unnecessary image data such as colour data, hidden comments or using compression algorithms. How do you remove unnecessary information from a font? Subsetting.
If you’re the adventurous type, grab a copy of FontForge, which is an open source font editing tool. You can open the font, view and edit any of the glyphs and then re-generate the font. The interface is a little clunky but you’ll be able to select any character you don’t want and then cut the glyphs. Re-generate your font and you’ve now got a smaller file.
There are certainly more optimizations that can also be made such as removing hinting and kerning information. Keep in mind that removing this information may affect how well the type renders.
At this time of year, though, I’m sure you’re quite busy. Save yourself some time and head on over to the Font Squirrel Font Generator.
The Font Generator is extremely handy and allows for a number of optimizations and cross-platform options to be generated instantly. Select the font from your local system—make sure that you are only using properly licensed fonts!
In this particular case, we only want the ampersand. Click on Subset Fonts which will open up a new menu. Unselect any preselected sets and enter the ampersand into the Single Characters text box.
Generate your font and what are you left with? 3KB.
The Font Generator even generates a base64 encoded data URI stylesheet to be imported easily into your project.
Check out the Demo page. (This demo won’t work in Internet Explorer as we’re only demonstrating the Data URI font embedding and not using the EOT file format that IE requires.)
No Unnecessary Additives
If you peeked under the hood of that demo, did you notice something interesting? There’s no around the ampersand. The great thing about this is that we can take advantage of the font stack’s natural ability to switch to a fallback font when a character isn’t available.
Just like that, we’ve managed to spruce up our page with a little typographic sugar without having to put on too much weight.",2009,Jonathan Snook,jonathansnook,2009-12-19T00:00:00+00:00,https://24ways.org/2009/spruce-it-up/,code
170,"A Pet Project is For Life, Not Just for Christmas","I’m excited: as December rolls on, I’m winding down from client work and indulging in a big pet project I’ve been dreaming up for quite some time, with the aim of releasing it early next year. I’ve always been a bit of a sucker for pet projects and currently have a few in the works: the big one, two collaborations with friends, and my continuing (and completely un-web-related) attempt at music. But when I think about the other designers and developers out there whose work I admire, one thing becomes obvious: they’ve all got pet projects! Look around the web and you’ll see that anyone worth their salt has some sort of side project on the go. If you don’t have yours yet, now’s the time!
Have a pet project to collaborate with your friends
It’s not uncommon to find me staring at my screen, looking at beautiful websites my friends have made, grinning inanely because I feel so honoured to know such talented individuals. But one thing really frustrates me: I hardly ever get to work with these people! Sure, there are times when it’s possible to do so, but due to various project situations, it’s a rarity.
So, in order to work with my friends, I’ve found the best way is to instigate the collaboration outside of client work; in other words, have a pet project together! Free from the hard realities of budgets, time restraints, and client demands, you and your friends can come up with something purely for your own pleasures. If you’ve been looking for an excuse to work with other designers or developers whose work you love, the pet project is that excuse. They don’t necessarily have to be friends, either: if the respect is mutual, it can be a great way of breaking the ice and getting to know someone.
Figure 1: A forthcoming secret love-child from myself and Tim Van Damme
Have a pet project to escape from your day job
We all like to moan about our clients and bosses, don’t we? But if leaving your job or firing your evil client just isn’t an option, why not escape from all that and pour your creative energies into something you genuinely enjoy?
It’s not just about reacting to negativity, either: a pet project is a great way to give yourself a bit of variety. As web designers, our day-to-day work forces us to work within a set of web-related contraints and sometimes it can be demoralising to spend so many hours fixing IE bugs. The perfect antidote? Go and do some print design! If it’s not possible in your day job or client work, the pet project is the perfect place to exercise your other creative muscles. Yes, print design (or your chosen alternative) has its own constraints, but if they’re different to those you experience on a daily basis, it’ll be a welcome relief and you’ll return to your regular work feeling refreshed.
Figure 2: Ligature, Loop & Stem, from Scott Boms & Luke Dorny
Have a pet project to fulfill your own needs
Many pet projects come into being because the designers and/or developers behind them are looking for a tool to accomplish a task and find that it doesn’t exist, thus prompting them to create their own solution. In fact, the very app I’m using to write this article — Ommwriter, from Herraiz Soto & Co — was originally a tool they’d created for their internal staff, before releasing it to the public so that it could be enjoyed by others.
Just last week, Tina Roth Eisenberg launched Teux Deux, a pet project she’d designed to meet her own requirements for a to-do list, having found that no existing apps fulfilled her needs. Oh, and it was a collaboration with her studio mate Cameron. Remember what I was saying about working with your friends?
Figure 3: Teux Deux, the GTD pet project that launched just last week
Have a pet project to help people out
Ommwriter and Teux Deux are free for anyone to use. Let’s just think about that for a moment: the creators have invested their time and effort in the project, and then given it away to be used by others. That’s very cool and something we’re used to seeing a lot of in the web community (how lucky we are)! People love free stuff and giving away the fruits of your labour will earn you major kudos. Of course, there’s nothing wrong with making some money, either — more on that in a second.
Figure 4: Dan Rubin‘s extremely helpful Make Photoshop Faster
Have a pet project to raise your profile
So, giving away free stuff earns you kudos. And kudos usually helps you raise your profile in the industry. We all like a bit of shameless fame, don’t we? But seriously, if you want to become well known, make something cool. It could be free (to buy you the love and respect of the community) or it could be purchasable (if you’ve made something that’s cool enough to deserve hard-earned cash), but ultimately it needs to be something that people will love.
Figure 5: Type designer Jos Buivenga has shot to fame thanks to his beautiful typefaces and ‘freemium’ business model
If you’re a developer with no design skills, team up with a good designer so that the design community appreciate its aesthetic. If you’re a designer with no development skills, team up with a good developer so that it works. Oh, and not that I’d recommend you ever do this for selfish reasons, but collaborating with someone you admire — whose work is well-respected by the community — will also help raise your profile.
Have a pet project to make money
In spite of our best hippy-esque intentions to give away free stuff to the masses, there’s also nothing wrong with making a bit of money from your pet project. In fact, if your project involves you having to make a considerable financial investment, it’s probably a good idea to try and recoup those costs in some way.
Figure 6: The success of Shaun Inman‘s various pet projects — Mint, Fever, Horror Vacui, etc. — have allowed him to give up client work entirely.
A very common way to do that in both the online and offline worlds is to get some sort of advertising. For a slightly different approach, try contacting a company who are relevant to your audience and ask them if they’d be interesting in sponsoring your project, which would usually just mean having their brand associated with yours in some way. This is still a form of advertising but tends to allow for a more tasteful implementation, so it’s worth pursuing.
Advertising is a great way to cover your own costs and keep things free for your audience, but when costs are considerably higher (like if you’re producing a magazine with high production values, for instance), there’s nothing wrong with charging people for your product. But, as I mentioned above, you’ve got to be positive that it’s worth paying for!
Have a pet project just for fun
Sometimes there’s a very good reason for having a pet project — and sometimes even a viable business reason — but actually you don’t need any reason at all. Wanting to have fun is just as worthy a motivation, and if you’re not going to have fun doing it, then what’s the point? Assuming that almost all pet projects are designed, developed, written, printed, marketed and supported in our free time, why not do something enjoyable?
Figure 7: Jessica Hische‘s beautiful Daily Drop Cap
In conclusion
The fact that you’re reading 24 ways shows that you have a passion for the web, and that’s something I’m happy to see in abundance throughout our community. Passion is a term that’s thrown about all over the place, but it really is evident in the work that people do. It’s perhaps most evident, however, in the pet projects that people create. Don’t forget that the very site you’re reading this article on is… a pet project.
If you’ve yet to do so, make it a new year’s resolution for 2010 to have your own pet project so that you can collaborate with your friends, escape from your day job, fulfil your own needs, help people out, raise your profile, make money, and — above all — have fun.",2009,Elliot Jay Stocks,elliotjaystocks,2009-12-18T00:00:00+00:00,https://24ways.org/2009/a-pet-project-is-for-life-not-just-for-christmas/,business
186,The Web Is Your CMS,"It is amazing what you can do these days with the services offered on the web. Flickr stores terabytes of photos for us and converts them automatically to all kind of sizes, finds people in them and even allows us to edit them online. YouTube does almost the same complete job with videos, LinkedIn allows us to maintain our CV, Delicious our bookmarks and so on.
We don’t have to do these tasks ourselves any more, as all of these systems also come with ways to use the data in the form of Application Programming Interfaces, or APIs for short. APIs give us raw data when we send requests telling the system what we want to get back.
The problem is that every API has a different idea of what is a simple way of accessing this data and in which format to give it back.
Making it easier to access APIs
What we need is a way to abstract the pains of different data formats and authentication formats away from the developer — and this is the purpose of the Yahoo Query Language, or YQL for short.
Libraries like jQuery and YUI make it easy and reliable to use JavaScript in browsers (yes, even IE6) and YQL allows us to access web services and even the data embedded in web documents in a simple fashion – SQL style.
Select * from the web and filter it the way I want
YQL is a web service that takes a few inputs itself:
A query that tells it what to get, update or access
An output format – XML, JSON, JSON-P or JSON-P-X
A callback function (if you defined JSON-P or JSON-P-X)
You can try it out yourself – check out this link to get back Flickr photos for the search term ‘santa’*%20from%20flickr.photos.search%20where%20text%3D%22santa%22&format=xml in XML format. The YQL query for this is
select * from flickr.photos.search where text=""santa""
The easiest way to take your first steps with YQL is to look at the console. There you get sample queries, access to all the data sources available to you and you can easily put together complex queries. In this article, however, let’s use PHP to put together a web page that pulls in Flickr photos, blog posts, Videos from YouTube and latest bookmarks from Delicious.
Check out the demo and get the source code on GitHub.
query->results->results;
/* YouTube output */
$youtube = '';
foreach($results[0]->item as $r){
$cleanHTML = undoYouTubeMarkupCrimes($r->description);
$youtube .= ''.$cleanHTML.' ';
}
$youtube .= ' ';
/* Flickr output */
$flickr = '';
/* Delicious output */
$delicious = '';
/* Blog output */
$blog = '';
function undoYouTubeMarkupCrimes($str){
$cleaner = preg_replace('/555px/','100%',$str);
$cleaner = preg_replace('/width=""[^""]+""/','',$cleaner);
$cleaner = preg_replace('//',' ',$cleaner);
return $cleaner;
}
?>
What we are doing here is create a few different YQL statements and queue them together with the query.multi table. Each of these can be run inside YQL itself. Check out the YouTube, Flickr, Delicious and Blog example in the console if you don’t believe me. The benefit of using this table is that we don’t make individual requests for each query but we get all the data in one single request – which means a much better performing solution as the YQL server farm is faster on the web than our servers.
We point the query to the YQL web service end point and get the resulting data using cURL. All that we need to do then is to convert the returned data to HTML lists that can be printed out inside an HTML template.
Mixing, matching and using HTML as a data source
This was a simple example of what YQL can do for you. Where it gets really powerful however is by mixing and matching different APIs. YQL is also a good tool to get information from HTML documents. By using the html table you can load the content of an HTML document (which gets fixed automatically by HTMLTidy) and use XPATH to filter down results to what you need. Take the following example which takes headlines from the news.bbc.co.uk homepage and runs the results through Yahoo’s Term Extractor API to give you a list of currently hot topics.
select * from search.termextract where context in (
select content from html where url=""http://news.bbc.co.uk"" and xpath=""//table[@width=800]//a""
)
Try it out in the console or see the results here. In English, this means:
Go to http://news.bbc.co.uk and get me the HTML
Run it through HTML Tidy to clean it up.
Get me only the links inside the table with an attribute of width and the value 800
Get only the content of the link and for each of the links
Take the content and send it as context to the Yahoo Term Extractor API
If we choose JSON-P as the output format we can use the outcome directly in JavaScript (see this demo or see its source):
Using JSON, we can also use PHP which means the demo works for everybody – not only those with JavaScript enabled (see this demo or see its source):
query->results->Result);
echo join(' ',$topics);
?>
Summary
This article could only scratch the surface of YQL. You have not only read access to the web but you can also write to web services. For example you can update Twitter, post to your WordPress blog or shorten a URL with bit.ly. Using Open Tables you can add any web service to the YQL interface and you can even run server-side JavaScript which is for example useful to return Flickr photos as HTML or get the HTML content from a document that needs POST data.
The web of data is already here, and using YQL you don’t have to be a web services expert to use it and be part of it.",2009,Christian Heilmann,chrisheilmann,2009-12-17T00:00:00+00:00,https://24ways.org/2009/the-web-is-your-cms/,code
183,Designing For The Switch,"For a long time on the web, we’ve been typographically spoilt. Yes, you heard me correctly. Think about it: our computers come with web fonts already installed; fonts that have been designed specifically to work well online and at small size; and fonts that we can be sure other people have too.
Yes, we’ve been spoilt. We don’t need to think about using Verdana, Arial, Georgia or Cambria.
Yet, for a long time now, designers have felt we needed more. We want to choose whatever typeface we feel necessary for our designs. We did bad things along the way in pursuit of this goal such as images for text. Smart people dreamt up tools to help us such as sIFR, or Cufón. Only fairly recently, @font-face is supported in most browsers. The floodgates are opening. It really is the dawn of a new typographic era on the web. And we must tread carefully.
The New Typesetters
Many years ago, before the advent of desktop publishing, if you wanted words set in a particular typeface, you had to go to a Typesetter. A Typesetter, or Compositor, as they were sometimes called, was a person whose job it was to take the written word (in the form of a document or manuscript) and ‘set’ the type in the desired typeface. The designer would chose what typeface they wanted – and all the ligatures, underlines, italics and whatnot – and then scribble all over the manuscript so the typesetter could set the correct type.
Then along came Desktop Publishing and every Tom, Dick and Harry could choose type on their computer and an entire link in the typographic chain was removed within just a few years. Well, that’s progress I guess. That was until six months ago when Typesetting was reborn on the web in the guise of a font service: Typekit.
Typekit – and services like Typekit such as Typotheque, Kernest and the upcoming Fontdeck – are typesetting services for the web. You supply them with your content, in the form of a webpage, and they provide you with some JavaScript to render that webpage in the typeface you’ve specified simply by adding the font name in your CSS file.
Thanks to services like these, font foundries are now talking to create licensing structures to allow us to embed fonts into our web pages legally – which has always been a sticking point in the past. So, finally, us designers can get what we want: whatever typeface we want on the web.
Yes, but… there are hurdles. One of which is the subject of this article.
The differences between Web Fonts and other fonts
Web fonts are different to normal fonts. They differ in a whole bunch of ways, from loose letter spacing to larger x-heights. But perhaps the most notable practical difference is file size. Let’s take a look at one of Typekit’s latest additions from the FontFont library, Meta.
Meta Roman weighs in at 42 KB. This is a fairly typical file size for a single weight of a good font. Now, let’s have a look at Verdana. Verdana is 186 KB. For one weight. The four weight family for Verdana weighs in at 686 KB. Four weights for half a megabyte!? Why so huge?
Well, Verdana has a lot of information packed into its 186 KB. It has the largest hinting data table of any typeface (the information carried by a font that tells it how to align itself to the pixels on your screen). As it has been shipped with Microsoft products since 1996, it has had time to grow to support many, many languages. Along with its cousin, Georgia (283 KB), Verdana was a new breed of typeface. And it’s grown fat.
If really serious web typography takes off – and by that I mean typefaces specifically designed for the screen – then we’re going to see more fonts increase in file size as the font files include more data. So, if you’re embedding a font weighing in at 100 KB, what happens?
The Flash of Unstyled Text
We all remember the Flash of Unstyled Content bug on Internet Explorer, right? That annoying bug that caused a momentary flash of unstyled HTML page. Well, the same thing can happen with embedding fonts using @font-face. An effect called The Flash of Unstyled Text (FOUT), first coined by Paul Irish. Personally, I prefer to call it the Flash of UnTypeset Text (still FOUT), as the text is styled, just not with what you want.
If you embed a typeface in your CSS, then the browser will download that typeface. Typically, browsers differ in the way they handle this procedure.
Firefox and Opera will render the text using the next font in your font stack until the first (embedded) font is loaded. It will then switch to the embedded font.
Webkit takes the approach that you asked for that font so it will wait until it’s completely loaded before showing it you.
In Opera and Firefox, you get a FOUT. In Webkit, you don’t. You wait.
Hang on there. Didn’t I say that good web fonts weigh in considerably more than ‘normal’ fonts? And whilst the browser is downloading the font, the user gets what to look at? Some pictures, background colours and whatever else isn’t HTML? I believe Webkit’s handling of font embedding – as deliberate as it is – is damaging to the practice of font embedding. Why? Well, we can design to a switch in typeface (as jarring as that is for the user), but we can’t design to blank space.
Let’s have a closer look at how we can design to FOUT.
More considered font stacks
We all know that font stacks in CSS are there for when a user doesn’t have a font; the browser will jump to the next one in the stack. Adding embedded fonts into the font stack means that because of FOUT (in gecko and Opera), the user can see a switch, and depending on their connection that switch could happen well into any reading that the user may be doing.
The practicalities of this are that a user could be reading and be towards the end of a line when the paragraph they are reading changes shape. The word they were digesting suddenly changes to three lines down. It’s the online equivalent of someone turning the page for you when you least expect it. So, how can we think about our font stacks slightly differently so we can minimise the switch?
Two years ago, Richard Rutter wrote on this very site about increasing our font stacks. By increasing the font stacks (by using his handy matrix) we can begin to experiment with different typefaces. However, when we embed a typeface, we must look very carefully at the typefaces in the font stack and the relationship between them. Because, previously, the user would not see a switch from one typeface to another, they’d just get either one or the other. Not both. With FOUT, the user sees two typefaces.
By carefully looking at the characteristics of the typefaces you choose, you can minimise the typographic ‘distance’ between the type down the stack. In doing so, you minimise the jarring effect of the switch.
Let’s take a look at an example of how to go about this.
Micro Typography to build better font stacks
Let’s say I want to use a recent edition to Typekit – Meta Serif Book – as my embedded font. My font stack would start like this:
font-family: 'Meta Serif Bold';
Where do you go from here? Well, first, familiarise yourself with Richard’s Font Matrix so you get an idea of what fonts are available for different people. Then start by looking closely at the characters of the embedded font and then compare them to different fonts from the matrix.
When I do this, I’m looking to match type characteristics such as x-height, contrast (the thickness and thinness of strokes), the stress (the angle of contrast) and the shape of the serifs (if the typeface has any).
Using just these simple comparative metrics means you can get to a ‘best fit’ reasonably quickly. And remember, you’re not after an ideal match. You’re after a match that means the switch is less painful for the reader, but also a typeface that carries similar characteristics so your design doesn’t change too much.
Building upon my choice of embedded font, I can quickly build up a stack by comparing letters.
This then creates my ‘best fit’ stack.
This translates to the CSS as:
font-family: 'Meta Serif Bold', 'Lucida Bright', Cambria, Georgia, serif
Following this process, and ending up with considered font stacks, means that we can design to the Flash of UnTypeset Content and ensure that our readers don’t get a diminished experience.",2009,Mark Boulton,markboulton,2009-12-16T00:00:00+00:00,https://24ways.org/2009/designing-for-the-switch/,design
191,CSS Animations,"Friend: You should learn how to write CSS!
Me: …
Friend: CSS; Cascading Style Sheets. If you’re serious about web design, that’s the next thing you should learn.
Me: What’s wrong with tags?
That was 8 years ago. Thanks to the hard work of Jeffrey, Andy, Andy, Cameron, Colly, Dan and many others, learning how to decently markup a website and write lightweight stylesheets was surprisingly easy. They made it so easy even a complete idiot (OH HAI) was able to quickly master it.
And then… nothing. For a long time, it seemed like there wasn’t happening anything in the land of CSS, time stood still. Once you knew the basics, there wasn’t anything new to keep up with. It looked like a great band split, but people just kept re-releasing their music in various “Best Of!” or “Remastered!” albums.
Fast forward a couple of years to late 2006. On the official WebKit blog Surfin’ Safari, there’s an article about something called CSS animations. Great new stuff to play with, but only supported by nightly builds (read: very, very beta) of WebKit. In the following months, they release other goodies, like CSS gradients, CSS reflections, CSS masks, and even more CSS animation sexiness. Whoa, looks like the band got back together, found their second youth, and went into overdrive! The problem was that if you wanted to listen to their new albums, you had to own some kind of new high-tech player no one on earth (besides some early adopters) owned.
Back in the time machine. It is now late 2009, close to Christmas. Things have changed. Browsers supporting these new toys are widely available left and right. Even non-techies are using these advanced browsers to surf the web on a daily basis!
Epic win? Almost, but at least this gives us enough reason to start learning how we could use all this new CSS voodoo. On Monday, Natalie Downe showed you a good tutorial on Going Nuts with CSS Transitions. Today, I’m taking it one step further…
Howto: A basic spinner
No matter how fast internet tubes or servers are, we’ll always need spinners to indicate something’s happening behind the scenes. Up until now, people would go to some site, pick one of the available templates, customize their foreground and background colors, and download a beautiful GIF image.
There are some downsides to this though:
It’s only _semi_-transparent: If you change your mind and pick a slightly different background color, you need to go back to the site, set all the parameters again, and replace your current image. There isn’t even a way to pick an image or gradient as background.
Limited number of frames, probable to keep the file-size as small as possible (don’t forget this thing needs to be loaded before whatever process is finished in the background), and you don’t have that 24 frames per second smoothness.
This is just too fucking easy. As a front-end code geek, there must be a “cooler” way to do this!
What do we need to make a spinner with CSS animations? One image, and one element on our webpage we can hook on to. Yes, that’s it. I created a simple transparent PNG that looks it might be a spinner, and for the element on the page, I wrote this piece of genius HTML:
Please wait while we do what we do best.
Looks semantic enough to me! Here’s the basic HTML I’m using to position the element in the center of the screen, and make the text inside it disappear:
#spinner {
position: absolute;
top: 50%;
left: 50%;
margin: -100px 0 0 -100px;
height: 200px;
width: 200px;
text-indent: 250px;
white-space: nowrap;
overflow: hidden;
}
Cool, but now we don’t see anything. Let’s pull rabbit number one out of the hat: -webkit-mask-image (accompanied by the previously mentioned transparent PNG image):
#spinner {
...
-webkit-mask-image: url(../img/spinner.png);
}
By now you should be feeling like a magician already. Oh, wait, we still have a blank screen, looks like we left something in the hat (tip: not rabbit droppings):
#spinner {
...
-webkit-mask-image: url(../img/spinner.png);
background-color: #000;
}
Nice! What we’ve done right here is telling the element to clip onto the PNG. It’s a lot like clipping layers in Photoshop. So, spinners, they move, right? Into the hat again, and look what we pull out this time: CSS animations!
#spinner {
...
-webkit-mask-image: url(../img/spinner.png);
background-color: #000;
-webkit-animation-name: spinnerRotate;
-webkit-animation-duration: 2s;
-webkit-animation-iteration-count: infinite;
-webkit-animation-timing-function: linear;
}
Some explanation:
-webkit-animation-name: Name of the animation we’ll be defining later.
-webkit-animation-duration: The timespan of the animation.
-webkit-animation-iteration-count: Repeat once, a defined number of times or infinitely?
-webkit-animation-timing-function: Linear is the one you’ll be using mostly. Other options are ease-in, ease-out, ease-in-out…
Let’s define spinnerRotate:
@-webkit-keyframes spinnerRotate {
from {
-webkit-transform:rotate(0deg);
}
to {
-webkit-transform:rotate(360deg);
}
}
En Anglais: Rotate #spinner starting at 0 degrees, ending at 360 degrees, over a timespan of 2 seconds, at a constant speed, and keep repeating this animation forever.
That’s it! See it in action on the demo page.
Note: these examples only work when you’re using a WebKit-based browser like Safari, Mobile Safari or Google Chrome. I’m confident though that Mozilla and Opera will try their very best catching up with all this new CSS goodness soon.
When looking at this example, you see the possibilities are endless. Another advantage is you can change the look of it entirely by only changing a couple of lines of CSS, instead of re-creating and re-downloading the image from some website smelling like web 2.0 gone bad. I made another demo that shows how great it is to be able to change background and foreground colors (even on the fly!).
So there you have it, a smoothly animated, fully transparent and completely customizable spinner. Cool? I think so. (Ladies?)
But you can do a lot more with CSS animations than just create pretty spinners. Since I was fooling around with it anyway, I decided to test how far you can push this, space is the final limit, right?
Conclusion
CSS has never been more exciting than it is right now. I’m even prepared to say CSS is “cool” again, both for the more experienced front-end developers as for the new designers discovering CSS every day now.
But…
Remember when Javascript became popular? Remember when Flash became popular? Every time we’re been given new toys, some people aren’t ashamed to use it in a way you can barely call constructive. I’m thinking of Geocities websites, loaded with glowing blocks of text, moving images, bad color usage… In the wise words of Stan Lee: With great power there must also come great responsibility! A sprinkle of CSS animations is better than a bucket load. Apply with care.",2009,Tim Van Damme,timvandamme,2009-12-15T00:00:00+00:00,https://24ways.org/2009/css-animations/,code
180,Going Nuts with CSS Transitions,"I’m going to show you how CSS 3 transforms and WebKit transitions can add zing to the way you present images on your site.
Laying the foundations
First we are going to make our images look like mini polaroids with captions. Here’s the markup:
Found this little cutie on a walk in New Zealand!
You’ll notice we’re using a somewhat presentational class of pull-right here. This means the logic is kept separate from the code that applies the polaroid effect. The polaroid class has no positioning, which allows it to be used generically anywhere that the effect is required. The pull classes set a float and add appropriate margins—they can be used for things like blockquotes as well.
.polaroid {
width: 150px;
padding: 10px 10px 20px 10px;
border: 1px solid #BFBFBF;
background-color: white;
-webkit-box-shadow: 2px 2px 3px rgba(135, 139, 144, 0.4);
-moz-box-shadow: 2px 2px 3px rgba(135, 139, 144, 0.4);
box-shadow: 2px 2px 3px rgba(135, 139, 144, 0.4);
}
The actual polaroid effect itself is simply applied using padding, a border and a background colour. We also apply a nice subtle box shadow, using a property that is supported by modern WebKit browsers and Firefox 3.5+. We include the box-shadow property last to ensure that future browsers that support the eventual CSS3 specified version natively will use that implementation over the legacy browser specific version.
The box-shadow property takes four values: three lengths and a colour. The first is the horizontal offset of the shadow—positive values place the shadow on the right, while negative values place it to the left. The second is the vertical offset, positive meaning below. If both of these are set to 0, the shadow is positioned equally on all four sides. The last length value sets the blur radius—the larger the number, the blurrier the shadow (therefore the darker you need to make the colour to have an effect).
The colour value can be given in any format recognised by CSS. Here, we’re using rgba as explained by Drew behind the first door of this year’s calendar.
Rotation
For browsers that understand it (currently our old favourites WebKit and FF3.5+) we can add some visual flair by rotating the image, using the transform CSS 3 property.
-webkit-transform: rotate(9deg);
-moz-transform: rotate(9deg);
transform: rotate(9deg);
Rotations can be specified in degrees, radians (rads) or grads. WebKit also supports turns unfortunately Firefox doesn’t just yet.
For our example, we want any polaroid images on the left hand side to be rotated in the opposite direction, using a negative degree value:
.pull-left.polaroid {
-webkit-transform: rotate(-9deg);
-moz-transform: rotate(-9deg);
transform: rotate(-9deg);
}
Multiple class selectors don’t work in IE6 but as luck would have it, the transform property doesn’t work in any current IE version either. The above code is a good example of progressive enrichment: browsers that don’t support box-shadow or transform will still see the image and basic polaroid effect.
Animation
WebKit is unique amongst browser rendering engines in that it allows animation to be specified in pure CSS. Although this may never actually make it in to the CSS 3 specification, it degrades nicely and more importantly is an awful lot of fun!
Let’s go nuts.
In the next demo, the image is contained within a link and mousing over that link causes the polaroid to animate from being angled to being straight.
Here’s our new markup:
White water rafting in Queenstown
And here are the relevant lines of CSS:
a.polaroid {
/* ... */
-webkit-transform: rotate(10deg);
-webkit-transition: -webkit-transform 0.5s ease-in;
}
a.polaroid:hover,
a.polaroid:focus,
a.polaroid:active {
/* ... */
-webkit-transform: rotate(0deg);
}
The @-webkit-transition@ property is the magic wand that sets up the animation. It takes three values: the property to be animated, the duration of the animation and a ‘timing function’ (which affects the animation’s acceleration, for a smoother effect).
-webkit-transition only takes affect when the specified property changes. In pure CSS, this is done using dynamic pseudo-classes. You can also change the properties using JavaScript, but that’s a story for another time.
Throwing polaroids at a table
Imagine there are lots of differently sized polaroid photos scattered on a table. That’s the effect we are aiming for with our next demo.
As an aside: we are using absolute positioning to arrange the images inside a flexible width container (with a minimum and maximum width specified in pixels). As some are positioned from the left and some from the right when you resize the browser they shuffle underneath each other. This is an effect used on the UX London site.
This demo uses a darker colour shadow with more transparency than before. The grey shadow in the previous example worked fine, but it was against a solid background. Since the images are now overlapping each other, the more opaque shadow looked fake.
-webkit-box-shadow: 2px 2px 4px rgba(0,0, 0, 0.3);
-moz-box-shadow: 2px 2px 4px rgba(0,0, 0, 0.3);
box-shadow: 2px 2px 4px rgba(0,0, 0, 0.3);
On hover, as well as our previous trick of animating the image rotation back to straight, we are also making the shadow darker and setting the z-index to be higher than the other images so that it appears on top.
And Finally…
Finally, for a bit more fun, we’re going to simulate the images coming towards you and lifting off the page. We’ll achieve this by making them grow larger and by offsetting the shadow & making it longer.
Screenshot 1 shows the default state, while 2 shows our previous hover effect. Screenshot 3 is the effect we are aiming for, illustrated by demo 4.
a.polaroid {
/* ... */
z-index: 2;
-webkit-box-shadow: 2px 2px 4px rgba(0,0, 0, 0.3);
-moz-box-shadow: 2px 2px 4px rgba(0,0, 0, 0.3);
box-shadow: 2px 2px 4px rgba(0,0, 0, 0.3);
-webkit-transform: rotate(10deg);
-moz-transform: rotate(10deg);
transform: rotate(10deg);
-webkit-transition: all 0.5s ease-in;
}
a.polaroid:hover,
a.polaroid:focus,
a.polaroid:active {
z-index: 999;
border-color: #6A6A6A;
-webkit-box-shadow: 15px 15px 20px rgba(0,0, 0, 0.4);
-moz-box-shadow: 15px 15px 20px rgba(0,0, 0, 0.4);
box-shadow: 15px 15px 20px rgba(0,0, 0, 0.4);
-webkit-transform: rotate(0deg) scale(1.05);
-moz-transform: rotate(0deg) scale(1.05);
transform: rotate(0deg) scale(1.05);
}
You’ll notice we are now giving the transform property another transform function: scale, which takes increases the size by the specified factor. Other things you can do with transform include skewing, translating or you can go mad creating your own transforms with a matrix.
The box-shadow has both its offset and blur radius increased dramatically, and is darkened using the alpha channel of the rgba colour.
And because we want the effects to all animate smoothly, we pass a value of all to the -webkit-transition property, ensuring that any changed property on that link will be animated.
Demo 5 is the finished example, bringing everything nicely together.
CSS transitions and transforms are a great example of progressive enrichment, which means improving the experience for a portion of the audience without negatively affecting other users. They are also a lot of fun to play with!
Further reading
-moz-transform – the mozilla developer center has a comprehensive explanation of transform that also applies to -webkit-transform and transform.
CSS: Animation Using CSS Transforms – this is a good, more indepth tutorial on animations.
CSS Animation – the Safari blog explains the usage of -webkit-transform.
Dinky pocketbooks with transform – another use for transforms, create your own printable pocketbook.
A while back, Simon wrote a little bookmarklet to spin the entire page… warning: this will spin the entire page.",2009,Natalie Downe,nataliedowne,2009-12-14T00:00:00+00:00,https://24ways.org/2009/going-nuts-with-css-transitions/,code
171,Rock Solid HTML Emails,"At some stage in your career, it’s likely you’ll be asked by a client to design a HTML email. Before you rush to explain that all the cool kids are using social media, keep in mind that when done correctly, email is still one of the best ways to promote you and your clients online. In fact, a recent survey showed that every dollar spent on email marketing this year generated more than $40 in return. That’s more than any other marketing channel, including the cool ones.
There are a whole host of ingredients that contribute to a good email marketing campaign. Permission, relevance, timeliness and engaging content are all important. Even so, the biggest challenge for designers still remains building an email that renders well across all the popular email clients.
Same same, but different
Before getting into the details, there are some uncomfortable facts that those new to HTML email should be aware of. Building an email is not like building for the web. While web browsers continue their onward march towards standards, many email clients have stubbornly stayed put. Some have even gone backwards. In 2007, Microsoft switched the Outlook rendering engine from Internet Explorer to Word. Yes, as in the word processor. Add to this the quirks of the major web-based email clients like Gmail and Hotmail, sprinkle in a little Lotus Notes and you’ll soon realize how different the email game is.
While it’s not without its challenges, rest assured it can be done. In my experience the key is to focus on three things. First, you should keep it simple. The more complex your email design, the more likely is it to choke on one of the popular clients with poor standards support. Second, you need to take your coding skills back a good decade. That often means nesting tables, bringing CSS inline and following the coding guidelines I’ll outline below. Finally, you need to test your designs regularly. Just because a template looks nice in Hotmail now, doesn’t mean it will next week.
Setting your lowest common denominator
To maintain your sanity, it’s a good idea to decide exactly which email clients you plan on supporting when building a HTML email. While general research is helpful, the email clients your subscribers are using can vary significantly from list to list. If you have the time there are a number of tools that can tell you specifically which email clients your subscribers are using. Trust me, if the testing shows almost none of them are using a client like Lotus Notes, save yourself some frustration and ignore it altogether.
Knowing which email clients you’re targeting not only makes the building process easier, it can save you lots of time in the testing phase too. For the purpose of this article, I’ll be sharing techniques that give the best results across all of the popular clients, including the notorious ones like Gmail, Lotus Notes 6 and Outlook 2007. Just remember that pixel perfection in all email clients is a pipe dream.
Let’s get started.
Use tables for layout
Because clients like Gmail and Outlook 2007 have poor support for float, margin and padding, you’ll need to use tables as the framework of your email. While nested tables are widely supported, consistent treatment of width, margin and padding within table cells is not. For the best results, keep the following in mind when coding your table structure.
Set the width in each cell, not the table
When you combine table widths, td widths, td padding and CSS padding into an email, the final result is different in almost every email client. The most reliable way to set the width of your table is to set a width for each cell, not for the table itself.
Never assume that if you don’t specify a cell width the email client will figure it out. It won’t. Also avoid using percentage based widths. Clients like Outlook 2007 don’t respect them, especially for nested tables. Stick to pixels. If you want to add padding to each cell, use either the cellpadding attribute of the table or CSS padding for each cell, but never combine the two.
Err toward nesting
Table nesting is far more reliable than setting left and right margins or padding for table cells. If you can achieve the same effect by table nesting, that will always give you the best result across the buggier email clients.
Use a container table for body background colors
Many email clients ignore background colors specified in your CSS or the tag. To work around this, wrap your entire email with a 100% width table and give that a background color.
Your email code goes here.
You can use the same approach for background images too. Just remember that some email clients don’t support them, so always provide a fallback color.
Avoid unnecessary whitespace in table cells
Where possible, avoid whitespace between your tags. Some email clients (ahem, Yahoo! and Hotmail) can add additional padding above or below the cell contents in some scenarios, breaking your design for no apparent reason.
CSS and general font formatting
While some email designers do their best to avoid CSS altogether and rely on the dreaded tag, the truth is many CSS properties are well supported by most email clients. See this comprehensive list of CSS support across the major clients for a good idea of the safe properties and those that should be avoided.
Always move your CSS inline
Gmail is the culprit for this one. By stripping the CSS from the and of any email, we’re left with no choice but to move all CSS inline. The good news is this is something you can almost completely automate. Free services like Premailer will move all CSS inline with the click of a button. I recommend leaving this step to the end of your build process so you can utilize all the benefits of CSS.
Avoid shorthand for fonts and hex notation
A number of email clients reject CSS shorthand for the font property. For example, never set your font styles like this.
p {
font:bold 1em/1.2em georgia,times,serif;
}
Instead, declare the properties individually like this.
p {
font-weight: bold;
font-size: 1em;
line-height: 1.2em;
font-family: georgia,times,serif;
}
While we’re on the topic of fonts, I recently tested every conceivable variation of @font-face across the major email clients. The results were dismal, so unfortunately it’s web-safe fonts in email for the foreseeable future.
When declaring the color property in your CSS, some email clients don’t support shorthand hexadecimal colors like color:#f60; instead of color:#ff6600;. Stick to the longhand approach for the best results.
Paragraphs
Just like table cell spacing, paragraph spacing can be tricky to get a consistent result across the board. I’ve seen many designers revert to using double or DIVs with inline CSS margins to work around these shortfalls, but recent testing showed that paragraph support is now reliable enough to use in most cases (there was a time when Yahoo! didn’t support the paragraph tag at all).
The best approach is to set the margin inline via CSS for every paragraph in your email, like so:
p {
margin: 0 0 1.6em 0;
}
Again, do this via CSS in the head when building your email, then use Premailer to bring it inline for each paragraph later.
If part of your design is height-sensitive and calls for pixel perfection, I recommend avoiding paragraphs altogether and setting the text formatting inline in the table cell. You might need to use table nesting or cellpadding / CSS to get the desired result. Here’s an example:
your height sensitive text
Links
Some email clients will overwrite your link colors with their defaults, and you can avoid this by taking two steps. First, set a default color for each link inline like so:
this is a link
Next, add a redundant span inside the a tag.
this is a link
To some this may be overkill, but if link color is important to your design then a superfluous span is the best way to achieve consistency.
Images in HTML emails
The most important thing to remember about images in email is that they won’t be visible by default for many subscribers. If you start your design with that assumption, it forces you to keep things simple and ensure no important content is suppressed by image blocking.
With this in mind, here are the essentials to remember when using images in HTML email:
Avoid spacer images
While the combination of spacer images and nested tables was popular on the web ten years ago, image blocking in many email clients has ruled it out as a reliable technique today. Most clients replace images with an empty placeholder in the same dimensions, others strip the image altogether. Given image blocking is on by default in most email clients, this can lead to a poor first impression for many of your subscribers. Stick to fixed cell widths to keep your formatting in place with or without images.
Always include the dimensions of your image
If you forget to set the dimensions for each image, a number of clients will invent their own sizes when images are blocked and break your layout. Also, ensure that any images are correctly sized before adding them to your email. Some email clients will ignore the dimensions specified in code and rely on the true dimensions of your image.
Avoid PNGs
Lotus Notes 6 and 7 don’t support 8-bit or 24-bit PNG images, so stick with the GIF or JPG formats for all images, even if it means some additional file size.
Provide fallback colors for background images
Outlook 2007 has no support for background images (aside from this hack to get full page background images working). If you want to use a background image in your design, always provide a background color the email client can fall back on. This solves both the image blocking and Outlook 2007 problem simultaneously.
Don’t forget alt text
Lack of standards support means email clients have long destroyed the chances of a semantic and accessible HTML email. Even still, providing alt text is important from an image blocking perspective. Even with images suppressed by default, many email clients will display the provided alt text instead. Just remember that some email clients like Outlook 2007, Hotmail and Apple Mail don’t support alt text at all when images are blocked.
Use the display hack for Hotmail
For some inexplicable reason, Windows Live Hotmail adds a few pixels of additional padding below images. A workaround is to set the display property like so.
img {display:block;}
This removes the padding in Hotmail and still gives you the predicable result in other email clients.
Don’t use floats
Both Outlook 2007 and earlier versions of Notes offer no support for the float property. Instead, use the align attribute of the img tag to float images in your email.
If you’re seeing strange image behavior in Yahoo! Mail, adding align=“top” to your images can often solve this problem.
Video in email
With no support for JavaScript or the object tag, video in email (if you can call it that) has long been limited to animated gifs. However, some recent research I did into the HTML5 video tag in email showed some promising results.
Turns out HTML5 video does work in many email clients right now, including Apple Mail, Entourage 2008, MobileMe and the iPhone. The real benefit of this approach is that if the video isn’t supported, you can provide reliable fallback content such as an animated GIF or a clickable image linking to the video in the browser.
Of course, the question of whether you should add video to email is another issue altogether. If you lean toward the “yes” side check out the technique with code samples.
What about mobile email?
The mobile email landscape was a huge mess until recently. With the advent of the iPhone, Android and big improvements from Palm and RIM, it’s becoming less important to think of mobile as a different email platform altogether.
That said, there are a few key pointers to keep in mind when coding your emails to get a decent result for your more mobile subscribers.
Keep the width less than 600 pixels
Because of email client preview panes, this rule was important long before mobile email clients came of age. In truth, the iPhone and Pre have a viewport of 320 pixels, the Droid 480 pixels and the Blackberry models hover around 360 pixels. Sticking to a maximum of 600 pixels wide ensures your design should still be readable when scaled down for each device. This width also gives good results in desktop and web-based preview panes.
Be aware of automatic text resizing
In what is almost always a good feature, email clients using webkit (such as the iPhone, Pre and Android) can automatically adjust font sizes to increase readability. If testing shows this feature is doing more harm than good to your design, you can always disable it with the following CSS rule:
-webkit-text-size-adjust: none;
Don’t forget to test
While standards support in email clients hasn’t made much progress in the last few years, there has been continual change (for better or worse) in some email clients. Web-based providers like Yahoo!, Hotmail and Gmail are notorious for this. On countless occasions I’ve seen a proven design suddenly stop working without explanation.
For this reason alone it’s important to retest your email designs on a regular basis. I find a quick test every month or so does the trick, especially in the web-based clients. The good news is that after designing and testing a few HTML email campaigns, you will find that order will emerge from the chaos. Many of these pitfalls will become quite predictable and your inbox-friendly designs will take shape with them in mind.
Looking ahead
Designing HTML email can be a tough pill for new designers and standardistas to swallow, especially given the fickle and retrospective nature of email clients today. With HTML5 just around the corner we are entering a new, uncertain phase. Will email client developers take the opportunity to repent on past mistakes and bring email clients into the present? The aim of groups such as the Email Standards Project is to make much of the above advice as redundant as the long-forgotten and tags, however, only time will tell if this is to become a reality.
Although not the most compliant (or fashionable) medium, the results speak for themselves – email is, and will continue to be one of the most successful and targeted marketing channels available to you. As a designer with HTML email design skills in your arsenal, you have the opportunity to not only broaden your service offering, but gain a unique appreciation of how vital standards are.
Next steps
Ready to get started? There are a number of HTML email design galleries to provide ideas and inspiration for your own designs.
http://www.campaignmonitor.com/gallery/
http://htmlemailgallery.com/
http://inboxaward.com/
Enjoy!",2009,David Greiner,davidgreiner,2009-12-13T00:00:00+00:00,https://24ways.org/2009/rock-solid-html-emails/,code
190,Self-Testing Pages with JavaScript,"Working at an agency I am involved more and more on projects in which client side code is developed internally then sent out to a separate team for implementation. You provide static HTML, CSS and JavaScript which then get placed into the CMS and brought to life as an actual website. As you can imagine this can sometimes lead to frustrations. However many safeguards you include, handing over your code to someone else is always a difficult thing to do effectively.
In this article I will show you how you can create a JavaScript implementation checker and that will give you more time for drink based activity as your web site and apps are launched quicker and with less unwanted drama!
An all too frequent occurrence
You’ve been working on a project for weeks, fixed all your bugs and send it to be implemented. You hear nothing and assume all is going well then a few days before it’s meant to launch you get an email from the implementation team informing you of bugs in your code that you need to urgently fix.
The 24ways website with a misspelt ID for the years menu
Being paranoid you trawl through the preview URL, check they have the latest files, check your code for errors then notice that a required HTML attribute has been omitted from the build and therefore CSS or JavaScript you’ve hooked onto that particular attribute isn’t being applied and that’s what is causing the “bug”.
It takes you seconds drafting an email informing them of this, it takes then seconds putting the required attribute in and low and behold the bug is fixed, everyone is happy but you’ve lost a good few hours of your life – this time could have been better spent in the pub.
I’m going to show you a way that these kind of errors can be alerted immediately during implementation of your code and ensure that when you are contacted you know that there actually is a bug to fix. You probably already know the things that could be omitted from a build and look like bugs so you’ll soon be creating tests to look for these and alert when they are not found on the rendered page. The error is reported directly to those who need to know about it and fix it. Less errant bug reports and less frantic emails ahoy!
A page with an implementation issue and instant feedback on the problem
JavaScript selector engines to the rescue
Whether you’re using a library or indeed tapping into the loveliness of the new JavaScript Selector APIs looking for particular HTML elements in JavaScript is fairly trivial now.
For instance this is how you look for a div element with the id attribute of year (the missing attribute from top image) using jQuery (the library I’ll be coding my examples in):
if ($(‘div#year’).length) {
alert(‘win’);
}
Using this logic you can probably imagine how you can write up a quick method to check for the existence of a particular element and alert when it’s not present — but assuming you have a complex page you’re going to be repeating yourself a fair bit and we don’t want to be doing that.
Test scripts
If you’ve got a lot of complex HTML patterns that need testing across a number of different pages it makes sense to keep your tests out of production code. Chances are you’ve already got a load of heavy JavaScript assets, and when it comes to file size saving every little helps.
I don’t think that tests should contain code inside of them so keep mine externally as JSON. This also means that you can use the one set of tests in multiple places. We already know that it’s a good idea to keep our CSS and JavaScript separate so lets continue along those lines here.
The test script for this example looks like this:
{
""title"": ""JS tabs implementation test"",
""description"": ""Check that the correct HTML patterns has been used"",
""author"": ""Ross Bruniges"",
""created"": ""20th July 2009"",
""tests"": [
{
""name"": ""JS tabs elements"",
""description"": ""Checking that correct HTML elements including class/IDs are used on the page for the JS to progressively enhance"",
""selector"": ""div.tabbed_content"",
""message"": ""We couldn't find VAR on the page - it's required for our JavaScript to function correctly"",
""check_for"": {
""contains"": {
""elements"": [
""div.tab_content"", ""h2""
],
""message"": ""We've noticed some missing HTML:please refer to the examples sent for reference""
}
}
}
]
}
The first four lines are just a little bit of meta data so we remember what this test was all about when we look at it again in the future, or indeed if it ever breaks. The tests are the really cool parts and firstly you’ll notice that it’s an array – we’re only going to show one example test here but there is no reason why you can’t place in as many as you want. I’ll explain what each of the lines in the example test means:
name – short test name, I use this in pass/fail messaging later
description – meta data for future reference
selector – the root HTML element from which your HTML will be searched
message – what the app will alert if the initial selector isn’t found
check_for – a wrapper to hold inner tests – those run if the initial selector does match
contains – the type of check, we’re checking that the selector contains specified elements
elements – the HTML elements we are searching for
message – a message for when these don’t match (VAR is substituted when it’s appended to the page with the name of any elements that don’t exist)
It’s very important to pass the function valid JSON (JSONLint is a great tool for this) otherwise you might get a console showing no tests have even been run.
The JavaScript that makes this helpful
Again, this code should never hit a production server so I’ve kept it external. This also means that the only thing that’s needed to be done by the implementation team when they are ready to build is that they delete this code.
“View the full JavaScript:/examples/self-testing-pages-with-javascript/js/tests/test_suite.js
The init function appends the test console to the page and inserts the CSS file required to style it (you don’t need to use pictures of me when tests pass and fail though I see no reason why you shouldn’t), goes and grabs the JSON file referenced and parses it. The methods to pass (tests_pass) and fail (haz_fail) the test I hope are pretty self-explanatory as is the one which creates the test summary once everything has been run (create_summary).
The two interesting functions are init_tests and confirm_html.
init_tests
init_tests:function(i,obj) {
var $master_elm = $(obj.selector);
sleuth.test_page.$logger.append(""
"");
var $container = $('#test_' + i);
if (!$master_elm.length) {
var err_sum = obj.message.replace(/VAR/gi, obj.selector);
sleuth.test_page.haz_failed(err_sum, $container);
return;
}
if (obj.check_for) {
$.each(obj.check_for,function(key, value){
sleuth.test_page.assign_checks($master_elm, $container, key, value);
});
} else {
sleuth.test_page.tests_passed($container);
return;
}
}
The function gets sent the number of the current iteration (used to create a unique id for its test summary) and the current object that contains the data we’re testing against as parameters.
We grab a reference to the root element and this is used (pretty much in the example shown right at the start of this article) and its length is checked. If the length is positive we know we can continue to the inner tests (if they exist) but if not we fail the test and don’t go any further. We append the error to the test console for everyone to see.
If we pass the initial check we send the reference to the root element, message contains and the inner object to a function that in this example sends us on to confirm_html (if we had a more complex test suite it would do a lot more).
confirm_html
confirm_html:function(target_selector, error_elm, obj) {
var missing_elms = [];
$.each(obj.elements, function(i, val) {
if (!target_selector.find(val).length) {
missing_elms.push(val);
}
});
if (missing_elms.length) {
var file_list = missing_elms.join('');
var err_sum = obj.message.replace(/VAR/gi, file_list);
sleuth.test_page.haz_failed(err_sum, error_elm);
return;
}
sleuth.test_page.tests_passed(error_elm);
return;
}
We’re again using an array to check for a passed or failed test and checking its length but this time we push in a reference to each missing element we find.
If the test does fail we’re providing even more useful feedback by informing what elements have been missed out. All the implementation team need do is look for them in the files we’ve sent and include them as expected.
No more silly implementation bugs!
Here is an example of a successful implementation.
Here are some examples of failed implementations – one which fails at finding the root node and one that has the correct root node but none of the inner HTML tests pass.
Is this all we can check for?
Certainly not!
JavaScript provides pretty easy ways to check for attributes, included files (if the files being checked for are being referenced correctly and not 404ing) and even applied CSS.
Want to check that those ARIA attributes are being implemented correctly or that all images contain an alt attribute well this simple test suite can be extended to include tests for this – the sky is pretty much up to your imagination.",2009,Ross Bruniges,rossbruniges,2009-12-12T00:00:00+00:00,https://24ways.org/2009/self-testing-pages-with-javascript/,process
169,Incite A Riot,"Given its relatively limited scope, HTML can be remarkably expressive. With a bit of lateral thinking, we can mark up content such as tag clouds and progress meters, even when we don’t have explicit HTML elements for those patterns.
Suppose we want to mark up a short conversation:
Alice: I think Eve is watching.
Bob: This isn’t a cryptography tutorial …we’re in the wrong example!
A note in the the HTML 4.01 spec says it’s okay to use a definition list:
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.
That would give us:
Alice : I think Eve is watching.
Bob : This isn't a cryptography tutorial ...we're in the wrong example!
This usage of a definition list is proof that writing W3C specifications and smoking crack are not mutually exclusive activities. “I think Eve is watching” is not a definition of “Alice.” If you (ab)use a definition list in this way, Norm will hunt you down.
The conversation problem was revisited in HTML5. What if dt and dd didn’t always mean “definition title” and “definition description”? A new element was forged: dialog. Now the the “d” in dt and dd doesn’t stand for “definition”, it stands for “dialog” (or “dialogue” if you can spell):
Alice : I think Eve is watching.
Bob : This isn't a cryptography tutorial ...we're in the wrong example!
Problem solved …except that dialog is no longer in the HTML5 spec. Hixie further expanded the meaning of dt and dd so that they could be used inside details (which makes sense—it starts with a “d”) and figure (…um). At the same time as the content model of details and figure were being updated, the completely-unrelated dialog element was dropped.
Back to the drawing board, or in this case, the HTML 4.01 specification. The spec defines the cite element thusly:
Contains a citation or a reference to other sources.
Perfect! There’s even an example showing how this can applied when attributing quotes to people:
As Harry S. Truman said,
The buck stops here.
For longer quotes, the blockquote element might be more appropriate. In a conversation, where the order matters, I think an ordered list would make a good containing element for this pattern:
Alice : I think Eve is watching.
Bob : This isn't a cryptography tutorial ...we're in the wrong example!
Problem solved …except that the cite element has been redefined in the HTML5 spec:
The cite element represents the title of a work … A person’s name is not the title of a work … and the element must therefore not be used to mark up people’s names.
HTML5 is supposed to be backwards compatible with previous versions of HTML, yet here we have a semantic pattern already defined in HTML 4.01 that is now non-conforming in HTML5. The entire justification for the change boils down to this line of reasoning:
Given that: titles of works are often italicised and
given that: people’s names are not often italicised and
given that: most browsers italicise the contents of the cite element,
therefore: the cite element should not be used to mark up people’s names.
In other words, the default browser styling is now dictating semantic meaning. The tail is wagging the dog.
Not to worry, the HTML5 spec tells us how we can mark up names in conversations without using the cite element:
In some cases, the b element might be appropriate for names
I believe the colloquial response to this is a combination of the letters W, T and F, followed by a question mark.
The non-normative note continues:
In other cases, if an element is really needed, the span element can be used.
This is not a joke. We are seriously being told to use semantically meaningless elements to mark up content that is semantically meaningful.
We don’t have to take it.
Firstly, any conformance checker—that’s the new politically correct term for “validator”—cannot possibly check every instance of the cite element to see if it’s really the title of a work and not the name of a person. So we can disobey the specification without fear of invalidating our documents.
Secondly, Hixie has repeatedly stated that browser makers have a powerful voice in deciding what goes into the HTML5 spec; if a browser maker refuses to implement a feature, then that feature should come out of the spec because otherwise, the spec is fiction. Well, one of the design principles of HTML5 is the Priority of Constituencies:
In case of conflict, consider users over authors over implementors over specifiers over theoretical purity.
That places us—authors—above browser makers. If we resolutely refuse to implement part of the HTML5 spec, then the spec becomes fiction.
Join me in a campaign of civil disobedience against the unnecessarily restrictive, backwards-incompatible change to the cite element. Start using HTML5 but start using it sensibly. Let’s ensure that bad advice remains fictitious.
Tantek has set up a page on the WHATWG wiki to document usage of the cite element for conversations. Please contribute to it.",2009,Jeremy Keith,jeremykeith,2009-12-11T00:00:00+00:00,https://24ways.org/2009/incite-a-riot/,code
187,A New Year's Resolution,"The end of 2009 is fast approaching. Yet another year has passed in a split second. Our Web Designing careers are one year older and it’s time to reflect on the highs and lows of 2009. What was your greatest achievement and what could you have done better? Perhaps, even more importantly, what are your goals for 2010?
Something that I noticed in 2009 is that being a web designer 24/7; it’s easy to get consumed by the web. It’s easy to get caught up in the blog posts, CSS galleries, web trends and Twitter! Living in this bubble can lead to one’s work becoming stale, boring and basically like everyone else’s work on the web. No designer wants this.
So, I say on 1st January 2010 let’s make it our New Year’s resolution to create something different, something special or even ground-breaking! Make it your goal to break the mold of current web design trends and light the way for your fellow web designer comrades!
Of course I wouldn’t let you embark on the New Year empty handed. To help you on your way I’ve compiled a few thoughts and ideas to get your brains ticking!
Don’t design for the web, just design
A key factor in creating something original and fresh for the web is to stop thinking in terms of web design. The first thing we need to do is forget the notion of headers, footers, side bars etc. A website doesn’t necessarily need any of these, so even before we’ve started we’ve already limited our design possibilities by thinking in these very conventional and generally accepted web terms. The browser window is a 2D canvas like any other and we can do with it what we like.
With this in mind we can approach web design from a fresh perspective. We can take inspiration for web design from editorial design, packaging design, comics, poster design, album artwork, motion design, street signage and anything else you can think of. Web design is way more than the just the web and by taking this more wide angled view of what web design is and can be you’ll find there are a thousand more exiting design possibilities.
Note: Try leaving the wire framing till after you’ve gone to town with some initial design concepts. You might find it helps keep your head out of that ‘web space’ a little bit longer, thus enabling you to think more freely about your design. Really go crazy with these as you can always pull it back into line later. The key is to think big initially and then work backwards. There’s no point restricting your creativity early on because your technical knowledge can foresee problems down the line. You can always sort these problems out later on… let your creative juices flow!
Inspiration can come from anywhere! (Photo: modomatic)
Try something new!
Progress in web design or in any design discipline is a sort of evolution. Design trends and solutions merge and mutate to create new design trends and hopefully better solutions. This is fine but the real leaps are made when someone has the guts to do something different.
Don’t be afraid to challenge the status quo. To create truly original work you have to be prepared to get it wrong and that’s hard to do. When you’re faced with this challenge just remind yourself that in web design there is rarely a ‘best way to do something’, or why would we ever do it any other way?
If you do this and get it right the pay off can be immense. Not only will you work stand out from the crowd by a mile, you will have become a trend setter as opposed to a trend follower.
Tell a story with your design
Great web design is way more than just the aesthetics, functionality or usability. Great web design goes beyond the pixels on the screen. For your website to make a real impact on it’s users it has to connect with them emotionally. So, whether your website is promoting your own company or selling cheese it needs to move people. You need to weave a story into your design. It’s this story that your users will connect with.
To do this the main ingredients of your design need to be strongly connected. In my head those main ingredients are Copy, Graphic Design, Typography, imagery and colour.
Copy
Strong meaningful copy is the backbone to most great web design work. Pay special attention to strap lines and headlines as these are often the sparks that start the fire. All the other elements can be inspired by this backbone of strong copy.
Graphic Design
Use the copy to influence how you treat the page with your graphic design. Let the design echo the words.
Typography
What really excites me about typography isn’t the general text presentation on a page, most half decent web designer have a grasp of this already. What excites me is the potential there is to base a whole design on words and letters. Using the strong copy you already have, one has the opportunity the customise, distort, build and arrange words and letters to create beautiful and powerful compositions that can be the basis for an entire site design.
Get creative with Typography (Photo: Pam Sattler)
Imagery and Colour
With clever use of imagery (photographs or illustrations) and colour you further have the chance to deepen the story you are weaving into your design. The key is to use meaningful imagery, don’t to insert generic imagery for the sake of filling space… it’s just a wasted opportunity.
Remember, the main elements of your design combined are greater than the sum of their parts. Whatever design decisions you make on a page, make them for a good reason. It’s not good enough to try and seduce your users with slick and shiny web pages. For your site to leave a lasting impression on the user you need to make that emotional connection.
Telling the Story (Advertising Agency: Tita, Milano, Italy, Art Director: Emanuele Basso)
Go one step further
So you’ve almost finished your latest website design. You’ve fulfilled the brief, you’re happy with the result and you’re pretty sure your client will be too. It’s at this point we should ask ourselves “Can I push this further”? What touches could you add to the site that’ll take it beyond what was required and into something exceptional? The truth is, to produce exceptional work we need to do more than is required of us. We need to answer the brief and then some!
Go back through your site and make a note of what enhancements could be made to make the site not just good but outstanding. It might be revisiting a couple of pages that were neglected in the design process, it might be adding some CSS 3 gloss for the users that can benefit from it or it might just be adding some clever little easter eggs to show that you care. These touches will soon add up and make a massive difference to the finished product.
So, go one step further… take it further than you anyone else will. Then your work will stand out for sure.
Parting message
I love being a designer for many of reasons but the main one being that with every new project we embark on we have the chance to express ourselves. We have the chance to create something special, something that people will talk about. It’s this chance that drives us onwards day after day, year after year. So in 2010 shout louder than you ever have before, take chances, try something new and above all design your socks off!",2009,Mike Kus,mikekus,2009-12-10T00:00:00+00:00,https://24ways.org/2009/a-new-years-resolution/,business
188,Don't Lose Your :focus,"For many web designers, accessibility conjures up images of blind users with screenreaders, and the difficulties in making sites accessible to this particular audience. Of course, accessibility covers a wide range of situations that go beyond the extreme example of screenreader users. And while it’s true that making a complex site accessible can often be a daunting prospect, there are also many small things that don’t take anything more than a bit of judicious planning, are very easy to test (without having to buy expensive assistive technology), and can make all the difference to certain user groups.
In this short article we’ll focus on keyboard accessibility and how careless use of CSS can potentially make your sites completely unusable.
Keyboard Access
Users who for whatever reason can’t use a mouse will employ a keyboard (or keyboard-like custom interface) to navigate around web pages. By default, they will use TAB and SHIFT + TAB to move from one focusable element (links, form controls and area) of a page to the next.
Note: in OS X, you’ll first need to turn on full keyboard access under System Preferences > Keyboard and Mouse > Keyboard Shortcuts. Safari under Windows needs to have the option Press Tab to highlight each item on a webpage in Preferences > Advanced enabled. Opera is the odd one out, as it has a variety of keyboard navigation options – the most relevant here being spatial navigation via Shift+Down, Shift+Up, Shift+Left, and Shift+Right).
But I Don’t Like Your Dotted Lines…
To show users where they are within a page, browsers place an outline around the element that currently has focus. The “problem” with these default outlines is that some browsers (Internet Explorer and Firefox) also display them when a user clicks on a focusable element with the mouse. Particularly on sites that make extensive use of image replacement on links with “off left” techniques this can create very unsightly outlines that stretch from the replaced element all the way to the left edge of the browser.
Outline bleeding off to the left (image-replacement example from carsonified.com)
There is a trivial workaround to prevent outlines from “spilling over” by adding a simple overflow:hidden, which keeps the outline in check around the clickable portion of the image-replaced element itself.
Outline tamed with overflow:hidden
But for many designers, even this is not enough. As a final solution, many actively suppress outlines altogether in their stylesheets. Controversially, even Eric Meyer’s popular reset.css – an otherwise excellent set of styles that levels the playing field of varying browser defaults – suppresses outlines.
html, body, div, span, applet, object, iframe ... {
...
outline: 0;
...
}
/* remember to define focus styles! */
:focus {
outline: 0;
}
Yes, in his explanation (and in the CSS itself) Eric does remind designers to define relevant styles for :focus… but judging by the number of sites that seem to ignore this (and often remove the related comment from the stylesheet altogether), the message doesn’t seem to have sunk in.
Anyway… hurrah! No more unsightly dotted lines on our lovely design. But what about keyboard users? Although technically they can still TAB from one element to the next, they now get no default cue as to where they are within the page (one notable exception here is Opera, where the outline is displayed regardless of stylesheets)… and if they’re Safari users, they won’t even get an indication of a link’s target in the status bar, like they would if they hovered over it with the mouse.
Only Suppress outline For Mouse Users
Is there a way to allow users navigating with the keyboard to retain the standard outline behaviour they’ve come to expect from their browser, while also ensuring that it doesn’t show display for mouse users?
Testing some convoluted style combinations
After playing with various approaches (see Better CSS outline suppression for more details), the most elegant solution also seemed to be the simplest: don’t remove the outline on :focus, do it on :active instead – after all, :active is the dynamic pseudo-class that deals explicitly with the styles that should be applied when a focusable element is clicked or otherwise activated.
a:active { outline: none; }
The only minor issues with this method: if a user activates a link and then uses the browser’s back button, the outline becomes visible. Oh, and old versions of Internet Explorer notoriously get confused by the exact meaning of :focus, :hover and :active, so this method fails in IE6 and below. Personally, I can live with both of these.
Note: at the last minute before submitting this article, I discovered a fatal flaw in my test. It appears that outline still manages to appear in the time between activating a link and the link target loading (which in hindsight is logical – after activation, the link does indeed receive focus). As my test page only used in-page links, this issue never came up before. The slightly less elegant solution is to also suppress the outline on :hover.
a:hover, a:active { outline: none; }
In Conclusion
Of course, many web designers may argue that they know what’s best, even for their keyboard-using audience. Maybe they’ve removed the default outline and are instead providing some carefully designed :focus styles. If they know for sure that these custom styles are indeed a reliable alternative for their users, more power to them… but, at the risk of sounding like Jakob “blue underlined links” Nielsen, I’d still argue that sometimes the default browser behaviours are best left alone. Complemented, yes (and if you’re already defining some fancy styles for :hover, by all means feel free to also make them display on :focus)… but not suppressed.",2009,Patrick Lauke,patricklauke,2009-12-09T00:00:00+00:00,https://24ways.org/2009/dont-lose-your-focus/,code
172,The Construction of Instruction,"If the world were made to my specifications, all your clients would be happy to pay for a web writer to craft every sentence into something as elegant as it was functional, and the client would have planned the content so that you had it just when you asked, but we both know that won’t happen every time. Sometimes you just know they are going to write the About page, two company blog pages and a Facebook fan page before resigning their position as chief content writer and you are going to end up filling in all the details that will otherwise just be Lorem Ipsum.
Welcome to the big world of microcopy:
A man walks into a bar. The bartender nods a greeting and watches as the man scans the bottles behind the bar.
“Er, you have a lot of gin here. Is there one you would recommend?”
“Yes sir.”
Long pause.
“… Never mind, I’ll have the one in the green bottle.”
“Certainly, sir. But you can’t buy it from this part of the bar. You need to go through the double doors there.”
“But they look like they lead into the kitchen.”
“Really, sir? Well, no, that’s where we allow customers to purchase gin.”
The man walks through the doors. On the other side he is greeted by the same bartender.
“Y-you!” he stammers but the reticent bartender is now all but silent.
Unnerved, the man points to a green bottle, “Er, I’d like to buy a shot of that please. With ice and tonic water.”
The bartender mixes the drink and puts it on the bar just out of the reach of the man and looks up.
“Um, do you take cards?” the man asks, ready to present his credit card.
The bartender goes to take the card to put it through the machine.
“Wait! How much was it – with sales tax and everything? Do you take a gratuity?”
The bartender simply shrugs.
The man eyes him for a moment and decides to try his luck at the bar next door.
In the Choose Your Own Adventure version of this story there are plenty of ways to stop the man giving up. You could let him buy the gin right where he was; you could make the price more obvious; you could signpost the place to buy gin. The mistakes made by the bar and bartender are painfully obvious. And yet, there are websites losing users everyday due to the same lack of clear instruction.
A smidgen of well written copy goes a long way to reassure the nervous prospect. Just imagine if our man walked into the bar and the bartender explained that although the bar was here, sales were conducted in the next room because people were not then able to overhear the man’s card details. Instead, he is left to fend for himself. Online, we kick customers through the anonymous double doors with a merry ‘Paypal will handle your transaction!’.
Recently I worked on a site where the default error message, to account for anything happening that the developers hadn’t accounted for, was ‘SOMETHING HAS GONE WRONG!’. It might have been technically accurate but this is not how to inspire confidence in your customers that they can make a successful purchase through you. As everyone knows they can shop just fine, thank you very much, it is your site they will blame. Card declined? It’s the site. Didn’t know my email address has changed? It’s the site. Can’t log in? It’s the site.
Yes, yes. I know. None of these things are related to your site, or you the developer, but drop outs will be high and you’ll get imploring emails from your client asking you to wade knee deep into the site analytics to find a solution by testing 41 shades of blue because if it worked for Google…? Before you try a visual fix involving the Dulux paint chart breeding with a Pantone swatch, take an objective look at the information you are giving customers. How much are you assuming they know? How much are you relying on age-old labels and prompts without clarification?
Here’s a fun example for non-North Americans: ask your Granny to write out her billing address. If she looks at you blankly, tell her it is the address where the bank sends her statements. Imagine how many fewer instances of the wrong address there would be if we routinely added that information when people purchased from the UK? Instead, we rely on a language convention that hasn’t much common usage without explanation because, well, because we always have since the banks told us how we could take payments online.
So. Your client is busying themselves with writing the ultimate Facebook fan page about themselves and here you are left with creating a cohesive signup process or basket or purchase instructions. Here are five simple rules for bending puny humans to your will creating instructive instructions and constructive error messages that ultimately mean less hassle for you.
Plan what you want to say and plan it out as early as possible
This goes for all content. Walk a virtual mile in the shoes of your users. What specific help can you offer customers to actively encourage continuation and ensure a minimal amount of dropouts? Make space for that information. One of the most common web content mistakes is jamming too much into a space that has been defined by physical boundaries rather than planned out. If you manage it, the best you can hope for is that no-one notices it was a last-minute job. Mostly it reads like a bad game of Tetris with content sticking out all over the place.
Use your words
Microcopy often says a lot in a few words but without those words you could leave room for doubt. When doubt creeps in a customer wants reassurance just like Alice:
This time (Alice) found a little bottle… with the words ‘DRINK ME’ beautifully printed on it in large letters. It was all very well to say ‘Drink me,’ but the wise little Alice was not going to do that in a hurry. ‘No, I’ll look first,’ she said, ‘and see whether it’s marked “poison” or not’
Alice in Wonderland, Lewis Carroll.
Value clarity over brevity. Or a little more prosaically, “If in doubt, spell it out.” Thanks, Jeremy!
Be prepared to help
‘Login failed: email/password combination is incorrect.’
Oh.
‘Login failed: email/password combination is incorrect.
Are you typing in all capitals? Caps Lock may be on.
Have you changed your email address recently and not updated your account with us? Try your old email address first.
Can’t remember your password? We can help you reset it.’
Ah!
Be direct and be informative
There is rarely a site that doesn’t suffer from some degree of jargon. Squash it early by setting a few guidelines about what language and tone of voice you will use to converse with your users. Be consistent. Equally, try to be as specific as possible when giving error messages or instructions and allay fears upfront.
Card payments are handled by paypal but you do not need a paypal account to pay.
We will not display your email address but we might need it to contact you.
Sign up for our free trial (no credit card required).
Combine copy and visual cues, learn from others and test new combinations
While visual design and copy can work independently, they work best together. New phrases and designs are being tested all the time so take a peek at abtests.com for more ideas, then test some new ideas and add your own results. Have a look at the microcopy pool on Flickr for some wonderful examples of little words and pictures working together. And yes, you absolutely should join the group and post more examples.
A man walks into a bar. The bartender greets him in a friendly manner and asks him what he would like to drink.
“Gin and Tonic, please.”
“Yes sir, we have our house gin on offer but we also have a particularly good import here too.”
“The import, please.”
“How would you like it? With a slice of lemon? Over ice?”
“Both”
“That’s £3.80. We accept cash, cards or you could open a tab.”
“Card please.”
“Certainly sir. Move just over here so that you can’t be observed. Now, please enter your pin number.”
“Thank you.”
“And here is your drink. Do let me know if there is a problem with it. I shall just be here at the bar. Enjoy.”
Cheers!",2009,Relly Annett-Baker,rellyannettbaker,2009-12-08T00:00:00+00:00,https://24ways.org/2009/the-construction-of-instruction/,content
174,Type-Inspired Interfaces,"One of the things that terrifies me most about a new project is the starting point. How is the content laid out? What colors do I pick? Once things like that are decided, it becomes significantly easier to continue design, but it’s the blank page where I spend the most time.
To that end, I often start by choosing type. I don’t need to worry about colors or layout or anything else… just the right typefaces that support the art direction. (This article won’t focus on how to choose a typeface, but there are some really great resources if you interested in that sort of thing.)
And just like that, all your work is done. “Hold it just a second,” you might say. “All I’ve done is pick type. I still have to do the rest!”
To which I would reply, “Silly rabbit. You already have!” You see, picking the right typeface gets you farther than you might think. Here are a few tips on taking cues from type to design interfaces and interface elements.
Perfecting Web 2.0
If you’re going for that beloved rounded corner look, you might class it up a bit by choosing the wonderful Omnes Pro by Joshua Darden. As the typeface already has a rounded aesthetic, making buttons that fit the style should be pretty easy.
I’ve found that using multiples helps to keep your interfaces looking balanced and proportional. Noticing that the top left edge of the letter “P” has about an 12px corner radius, let’s choose a 24px radius for our button (a multiple of 2), so that we get proper rounded corners. By taking mathematical measurements from the typeface, our button looks more thought out than just “place arbitrary text on arbitrarily-sized button.” Pretty easy, eh?
What’s in a name(plate)?
Rounded buttons are pretty popular buttons nowadays, so let’s try something a bit more stylized.
Have a gander at Brothers, a sturdy face from Emigre. The chiseled edges give us a perfect cue for a stylized button. Using the same slope, you can make plated-looking buttons that fit a different kind of style.
Headlining
You might even take some cues from the style of the typeface itself. Didone serifs are known for their lack of bracketsーthat is, a gradual transition from the stem to the serif. Instead, they typically connect at a right angle. Another common characteristic is the high contrast in the strokes: very thick stems, very thin serifs.
So, when using a high contrast typeface, you can use it to your advantage to enhance hierarchy. Following our “multiples” guideline, a 12px measurement from the stems helps us create a top rule with a height of 24px (a multiple of 2). We can take the exact 1px measurement from the serif—a multiple of 1—to create the bottom rule. Voilà! I use this technique a lot.
Swashbucklers
And don’t forget the importance of visual “speed bumps” to break up long passages of text. A beautiful face like Alejandro Paul’s Ministry Script has over a thousand characters that can be manipulated or even combined to create elegant interface elements. Altering the partial differential character (∂) creates a delightful ornament that can help to guide the eye through content.
Stagger & Swagger
What about layout? How can we use typography to inform how our content is displayed?
Let’s take a typeface like Assembler. We might use this for a design that needs to feel uneasy or uncomfortable. In design terms, that might translate into using irregular shapes and asymmetry. Using the proportional distances and degrees from the perpendiculars, we could easily create a multi-column layout that jives with the general tone. And for all you skeptics that don’t think a layout like this is doable on the web, stranger things have happened.
Background texture generously offered by Bittbox.
Overall Design Direction
Finally, your typography could impact the entire look of the site, from the navigation to the interaction and everything in between. Check out how the (now-defunct) Nike Free site’s typography echoes the product itself, and in turn influences the navigation.
Find Your Type
With thousands of fonts to choose from, the possibilities are ridiculously open. From angles to radii to color to weight, you’ve got endless fodder before you. Great type designers spent countless hours slaving over these detailed letterforms; take advantage of it! Don’t feel like you have to limit yourself to the same old Helvetica and wet floors… unless your design calls for it.
Happy hunting!",2009,Dan Mall,danmall,2009-12-07T00:00:00+00:00,https://24ways.org/2009/type-inspired-interfaces/,design
175,Front-End Code Reusability with CSS and JavaScript,"Most web standards-based developers are more than familiar with creating their sites with semantic HTML with lots and lots of CSS. With each new page in a design, the CSS tends to grow and grow and more elements and styles are added. But CSS can be used to better effect.
The idea of object-oriented CSS isn’t new. Nicole Sullivan has written a presentation on the subject and outlines two main concepts: separate structure and visual design; and separate container and content. Jeff Croft talks about Applying OOP Concepts to CSS:
I can make a class of .box that defines some basic layout structure, and another class of .rounded that provides rounded corners, and classes of .wide and .narrow that define some widths, and then easily create boxes of varying widths and styles by assigning multiple classes to an element, without having to duplicate code in my CSS.
This concept helps reduce CSS file size, allows for great flexibility, rapid building of similar content areas and means greater consistency throughout the entire design. You can also take this concept one step further and apply it to site behaviour with JavaScript.
Build a versatile slideshow
I will show you how to build multiple slideshows using jQuery, allowing varying levels of functionality which you may find on one site design. The code will be flexible enough to allow you to add previous/next links, image pagination and the ability to change the animation type. More importantly, it will allow you to apply any combination of these features.
Image galleries are simply a list of images, so the obvious choice of marking the content up is to use a . Many designs, however, do not cater to non-JavaScript versions of the website, and thus don’t take in to account large multiple images. You could also simply hide all the other images in the list, apart from the first image. This method can waste bandwidth because the other images might be downloaded when they are never going to be seen.
Taking this second concept — only showing one image — the only code you need to start your slideshow is an tag. The other images can be loaded dynamically via either a per-page JavaScript array or via AJAX.
The slideshow concept is built upon the very versatile Cycle jQuery Plugin and is structured in to another reusable jQuery plugin. Below is the HTML and JavaScript snippet needed to run every different type of slideshow I have mentioned above.
Slideshow plugin
If you’re not familiar with jQuery or how to write and author your own plugin there are plenty of articles to help you out.
jQuery has a chainable interface and this is something your plugin must implement. This is easy to achieve, so your plugin simply returns the collection it is using:
return this.each(
function () {}
};
Local Variables
To keep the JavaScript clean and avoid any conflicts, you must set up any variables which are local to the plugin and should be used on each collection item. Defining all your variables at the top under one statement makes adding more and finding which variables are used easier. For other tips, conventions and improvements check out JSLint, the “JavaScript Code Quality Tool”.
var $$, $div, $images, $arrows, $pager,
id, selector, path, o, options,
height, width,
list = [], li = 0,
parts = [], pi = 0,
arrows = ['Previous', 'Next'];
Cache jQuery Objects
It is good practice to cache any calls made to jQuery. This reduces wasted DOM calls, can improve the speed of your JavaScript code and makes code more reusable.
The following code snippet caches the current selected DOM element as a jQuery object using the variable name $$. Secondly, the plugin makes its settings available to the Metadata plugin‡ which is best practice within jQuery plugins.
For each slideshow the plugin generates a with a class of slideshow and a unique id. This is used to wrap the slideshow images, pagination and controls.
The base path which is used for all the images in the slideshow is calculated based on the existing image which appears on the page. For example, if the path to the image on the page was /img/flowers/1.jpg the plugin would use the path /img/flowers/ to load the other images.
$$ = $(this);
o = $.metadata ? $.extend({}, settings, $$.metadata()) : settings;
id = 'slideshow-' + (i++ + 1);
$div = $('
').addClass('slideshow').attr('id', id);
selector = '#' + id + ' ';
path = $$.attr('src').replace(/[0-9]\.jpg/g, '');
options = {};
height = $$.height();
width = $$.width();
Note: the plugin uses conventions such as folder structure and numeric filenames. These conventions help with the reusable aspect of plugins and best practices.
Build the Images
The cycle plugin uses a list of images to create the slideshow. Because we chose to start with one image we must now build the list programmatically. This is a case of looping through the images which were added via the plugin options, building the appropriate HTML and appending the resulting
to the DOM.
$.each(o.images, function () {
list[li++] = '';
list[li++] = ' ';
list[li++] = ' ';
});
$images = $('').addClass('cycle-images');
$images.append(list.join('')).appendTo($div);
Although jQuery provides the append method it is much faster to create one really long string and append it to the DOM at the end.
Update the Options
Here are some of the options we’re making available by simply adding classes to the . You can change the slideshow effect from the default fade to the sliding effect. By adding the class of stopped the slideshow will not auto-play and must be controlled via pagination or previous and next links.
// different effect
if ($$.is('.slide')) {
options.fx = 'scrollHorz';
}
// don't move by default
if ($$.is('.stopped')) {
options.timeout = 0;
}
If you are using the same set of images throughout a website you may wish to start on a different image on each page or section. This can be easily achieved by simply adding the appropriate starting class to the .
// based on the class name on the image
if ($$.is('[class*=start-]')) {
options.startingSlide = parseInt($$.attr('class').replace(/.*start-([0-9]+).*/g, ""$1""), 10) - 1;
}
For example:
By default, and without JavaScript, the third image in this slideshow is shown. When the JavaScript is applied to the page the slideshow must know to start from the correct place, this is why the start class is required.
You could capture the default image name and parse it to get the position, but only the default image needs to be numeric to work with this plugin (and could easily be changed in future). Therefore, this extra specifically defined option means the plugin is more tolerant.
Previous/Next Links
A common feature of slideshows is previous and next links enabling the user to manually progress the images. The Cycle plugin supports this functionality, but you must generate the markup yourself. Most people add these directly in the HTML but normally only support their behaviour when JavaScript is enabled. This goes against progressive enhancement. To keep with the best practice progress enhancement method the previous/next links should be generated with JavaScript.
The follow snippet checks whether the slideshow requires the previous/next links, via the arrows class. It restricts the Cycle plugin to the specific slideshow using the selector we created at the top of the plugin. This means multiple slideshows can run on one page without conflicting each other.
The code creates a using the arrows array we defined at the top of the plugin. It also adds a class to the slideshow container, meaning you can style different combinations of options in your CSS.
// create the arrows
if ($$.is('.arrows') && list.length > 1) {
options.next = selector + '.next';
options.prev = selector + '.previous';
$arrows = $('').addClass('cycle-arrows');
$.each(arrows, function (i, val) {
parts[pi++] = '';
parts[pi++] = '';
parts[pi++] = '' + val + ' ';
parts[pi++] = ' ';
parts[pi++] = ' ';
});
$arrows.append(parts.join('')).appendTo($div);
$div.addClass('has-cycle-arrows');
}
The arrow array could be placed inside the plugin settings to allow for localisation.
Pagination
The Cycle plugin creates its own HTML for the pagination of the slideshow. All our plugin needs to do is create the list and selector to use. This snippet creates the pagination container and appends it to our specific slideshow container. It sets the Cycle plugin pager option, restricting it to the specific slideshow using the selector we created at the top of the plugin. Like the previous/next links, a class is added to the slideshow container allowing you to style the slideshow itself differently.
// create the clickable pagination
if ($$.is('.pagination') && list.length > 1) {
options.pager = selector + '.cycle-pagination';
$pager = $('').addClass('cycle-pagination');
$pager.appendTo($div);
$div.addClass('has-cycle-pagination');
}
Note: the Cycle plugin creates a with anchors listed directly inside without the surrounding . Unfortunately this is invalid markup but the code still works.
Demos
Well, that describes all the ins-and-outs of the plugin, but demos make it easier to understand! Viewing the source on the demo page shows some of the combinations you can create with a simple , a few classes and some thought-out JavaScript.
View the demos →
Decide on defaults
The slideshow plugin uses the exact same settings as the Cycle plugin, but some are explicitly set within the slideshow plugin when using the classes you have set.
When deciding on what functionality is going to be controlled via this class method, be careful to choose your defaults wisely. If all slideshows should auto-play, don’t make this an option — make the option to stop the auto-play. Similarly, if every slideshow should have previous/next functionality make this the default and expose the ability to remove them with a class such as “no-pagination”.
In the examples presented on this article I have used a class on each . You can easily change this to anything you want and simply apply the plugin based on the jQuery selector required.
Grab your images
If you are using AJAX to load in your images, you can speed up development by deciding on and keeping to a folder structure and naming convention. There are two methods: basing the image path based on the current URL; or based on the src of the image. The first allows a different slideshow on each page, but in many instances a site will have a couple of sets of images and therefore the second method is probably preferred.
Metadata ‡
A method which allows you to directly modify settings in certain plugins, which also uses the classes from your HTML already exists. This is a jQuery plugin called Metadata. This method allows for finer control over the plugin settings themselves. Some people, however, may dislike the syntax and prefer using normal classes, like above which when sprinkled with a bit more JavaScript allows you to control what you need to control.
The takeaway
Hopefully you have understood not only what goes in to a basic jQuery plugin but also learnt a new and powerful idea which you can apply to other areas of your website.
The idea can also be applied to other common interfaces such as lightboxes or mapping services such as Google Maps — for example creating markers based on a list of places, each with different pin icons based the anchor class.",2009,Trevor Morris,trevormorris,2009-12-06T00:00:00+00:00,https://24ways.org/2009/front-end-code-reusability-with-css-and-javascript/,code
177,"HTML5: Tool of Satan, or Yule of Santa?","It would lead to unseasonal arguments to discuss the title of this piece here, and the arguments are as indigestible as the fourth turkey curry of the season, so we’ll restrict our article to the practical rather than the philosophical: what HTML5 can you reasonably expect to be able to use reliably cross-browser in the early months of 2010?
The answer is that you can use more than you might think, due to the seasonal tinsel of feature-detection and using the sparkly pixie-dust of IE-only VML (but used in a way that won’t damage your Elf).
Canvas
canvas is a 2D drawing API that defines a blank area of the screen of arbitrary size, and allows you to draw on it using JavaScript. The pictures can be animated, such as in this canvas mashup of Wolfenstein 3D and Flickr. (The difference between canvas and SVG is that SVG uses vector graphics, so is infinitely scalable. It also keeps a DOM, whereas canvas is just pixels so you have to do all your own book-keeping yourself in JavaScript if you want to know where aliens are on screen, or do collision detection.)
Previously, you needed to do this using Adobe Flash or Java applets, requiring plugins and potentially compromising keyboard accessibility. Canvas drawing is supported now in Opera, Safari, Chrome and Firefox. The reindeer in the corner is, of course, Internet Explorer, which currently has zero support for canvas (or SVG, come to that).
Now, don’t pull a face like all you’ve found in your Yuletide stocking is a mouldy satsuma and a couple of nuts—that’s not the end of the story. Canvas was originally an Apple proprietary technology, and Internet Explorer had a similar one called Vector Markup Language which was submitted to the W3C for standardisation in 1998 but which, unlike canvas, was not blessed with retrospective standardisation.
What you need, then, is some way for Internet Explorer to translate canvas to VML on-the-fly, while leaving the other, more standards-compliant browsers to use the HTML5. And such a way exists—it’s a JavaScript library called excanvas. It’s downloadable from http://code.google.com/p/explorercanvas/ and it’s simple to include it via a conditional comment in the head for IE:
Simply include this, and your canvas will be natively supported in the modern browsers (and the library won’t even be downloaded) whereas IE will suddenly render your canvas using its own VML engine. Be sure, however, to check it carefully, as the IE JavaScript engine isn’t so fast and you’ll need to be sure that performance isn’t too degraded to use.
Forms
Since the beginning of the Web, developers have been coding forms, and then writing JavaScript to check whether an input is a correctly formed email address, URL, credit card number or conforms to some other pattern. The cumulative labour of the world’s developers over the last 15 years makes whizzing round in a sleigh and delivering presents seem like popping to the corner shop in comparison.
With HTML5, that’s all about to change. As Yaili began to explore on Day 3, a host of new attributes to the input element provide built-in validation for email address formats (input type=email), URLs (input type=url), any pattern that can be expressed with a JavaScript-syntax regex (pattern=""[0-9][A-Z]{3}"") and the like. New attributes such as required, autofocus, input type=number min=3 max=50 remove much of the tedious JavaScript from form validation.
Other, really exciting input types are available (see all input types). The datalist is reminiscent of a select box, but allows the user to enter their own text if they don’t want to choose one of the pre-defined options. input type=range is rendered as a slider, while input type=date pops up a date picker, all natively in the browser with no JavaScript required at all.
Currently, support is most complete in an experimental implementation in Opera and a number of the new attributes in Webkit-based browsers. But don’t let that stop you! The clever thing about the specification of the new Web Forms is that all the new input types are attributes (rather than elements). input defaults to input type=text, so if a browser doesn’t understand a new HTML5 type, it gracefully degrades to a plain text input.
So where does that leave validation in those browsers that don’t support Web Forms? The answer is that you don’t retire your pre-existing JavaScript validation just yet, but you leave it as a fallback after doing some feature detection. To detect whether (say) input type=email is supported, you make a new input type=email with JavaScript but don’t add it to the page. Then, you interrogate your new element to find out what its type attribute is. If it’s reported back as “email”, then the browser supports the new feature, so let it do its work and don’t bring in any JavaScript validation. If it’s reported back as “text”, it’s fallen back to the default, indicating that it’s not supported, so your code should branch to your old validation routines. Alternatively, use the small (7K) Modernizr library which will do this work for you and give you JavaScript booleans like Modernizr.inputtypes[email] set to true or false.
So what does this buy you? Well, first and foremost, you’re future-proofing your code for that time when all browsers support these hugely useful additions to forms. Secondly, you buy a usability and accessibility win. Although it’s tempting to style the stuffing out of your form fields (which can, incidentally, lead to madness), whatever your branding people say, it’s better to leave forms as close to the browser defaults as possible. A browser’s slider and date pickers will be the same across different sites, making it much more comprehensible to users. And, by using native controls rather than faking sliders and date pickers with JavaScript, your forms are much more likely to be accessible to users of assistive technology.
HTML5 DOCTYPE
You can use the new DOCTYPE !doctype html now and – hey presto – you’re writing HTML5, as it’s pretty much a superset of HTML4. There are some useful advantages to doing this. The first is that the HTML5 validator (I use http://html5.validator.nu) also validates ARIA information, whereas the HTML4 validator doesn’t, as ARIA is a new spec developed after HTML4. (Actually, it’s more accurate to say that it doesn’t validate your ARIA attributes, but it doesn’t automatically report them as an error.)
Another advantage is that HTML5 allows tabindex as a global attribute (that is, on any element). Although originally designed as an accessibility bolt-on, I ordinarily advise you don’t use it; a well-structured page should provide a logical tab order through links and form fields already.
However, tabindex=""-1"" is a legal value in HTML5 as it allows for the element to be programmatically focussable by JavaScript. It’s also very useful for correcting a bug in Internet Explorer when used with a keyboard; in-page links go nowhere if the destination doesn’t have a proprietary property called hasLayout set or a tabindex of -1.
So, whether it is the tool of Satan or yule of Santa, HTML5 is just around the corner. Some you can use now, and by the end of 2010 I predict you’ll be able to use a whole lot more as new browser versions are released.",2009,Bruce Lawson,brucelawson,2009-12-05T00:00:00+00:00,https://24ways.org/2009/html5-tool-of-satan-or-yule-of-santa/,code
176,What makes a website successful? It might not be what you expect!,"What makes some sites succeed and others fail? Put another way, when you are asked to redesign an existing website, what problems are you looking out for and where do you concentrate your efforts?
I would argue that as web designers we spend too much time looking at the wrong kind of problem.
I recently ran a free open door consultancy clinic to celebrate the launch of my new book (yes I know, two shameless plugs in one sentence). This involved various website owners volunteering their sites for review. Both myself and the audience then provided feedback.
What quickly became apparent is that the feedback being given by the audience was biased towards design and development.
Although their comments were excellent it focused almost exclusively on the quality of code, site aesthetics and usability. To address these issues in isolation is similar to treating symptoms and ignoring the underlying illness.
Cure the illness not the symptoms
Poor design, bad usability and terribly written code are symptoms of bigger problems. Often when we endeavour to address these symptoms, we meet resistance from our clients and become frustrated. This is because our clients are still struggling with fundamental concepts we take for granted.
Before we can address issues of aesthetics, usability and code, we need to tackle business objectives, calls to action and user tasks. Without dealing with these fundamental principles our clients’ website will fail.
Let me address each in turn:
Understand the business objectives
Do you ask your clients why they have a website? It feels like an obvious question. However, it is surprising how many clients do not have an answer.
Without having a clear idea of the siteʼs business objectives, the client has no way to know whether it is succeeding. This means they have no justification for further investment and that leads to quibbling over every penny.
However most importantly, without clearly defined business aims they have no standard against which to base their decisions. Everything becomes subjective and that will inevitably lead to problems.
Before we start discussing design, usability and development, we need to focus our clients on establishing concrete business objectives. This will provide a framework for decision making during the development phase.
This will not only help the client make decisions, it will also focus them on the business and away from micro managing the design.
Establish clear calls to action
Once business objectives have been set this opens up the possibility to establish clear calls to action.
I am amazed at how few website owners can name their calls to action. However, I am even more staggered at how few web designers ask about them.
Calls to action are not just limited to ecommerce sites. Whether you are asking people to sign up for a newsletter or complete a contact us form, every site should have a desired objective for users.
What is more, each page of a site should have micro calls to action that always draw users on and never leave them at a dead end.
Without clearly defined calls to action you cannot successfully design a site, structure the user experience or measure its success. They bring focus to the site and encourage the client to concentrate their efforts on helping people reach those goals.
Of course in order to know if a call to action is going to work, it is necessary to do some user testing.
Test against the right tasks
As web designers we all like to boast about being ʻuser centricʼ whatever that means! However, in reality I think many of us are paying lip service to the subject.
Sure, we ask our clients about who their users are and maybe even do some usability testing. However, usability testing is no good if we are not asking the right questions.
Again we find ourselves working on a superficial level rather than tackling the deeper issues.
Clients find it relatively easy to tell you who their target audience is. Admittedly the list they come back with is often overly long and contains a lot of edge cases. However, where they begin to struggle is articulating what these users will want to achieve on the website. They know who they want to reach. However, they cannot always tell you why those people would be interested in the site.
These user tasks are another fundamental building block for any successful website. Although it is important for a website owner to understand what their objectives are and what they want users to do, it is even more important that they understand the users objectives as well.
Again, this provides context for the decisions they are making about design, usability and functionality. Without it the site will become self serving, largely ignoring the needs of users.
User tasks help to focus the clientʼs mind on the needs of their user, rather than what they can get out of them.
So am I claiming that design, usability and code do not matter? Well the shocking truth is that to some extent I am!
The shocking truth
Whether we like it or not there is significant evidence that you can create a successful website with bad design, terrible code and without ever running a usability test session.
You only need to look at the design of Craigslist or the code of Amazon to see that this is true.
However, I do not believe it is possible to build a successful website without business objectives, calls to action and a clear idea of user tasks.
Do not misunderstand me. I do believe design, usability and code matters. I just believe that they only matter if the fundamentals are already in place. These things improve a solid foundation but are no use in their own right.
As web designers it is our responsibility to ensure fundamental questions are being asked, before we start exploring other issues. If we do not, our websites will look great, be well coded and have gone through endless usability tests, however it will not be truly successful.",2009,Paul Boag,paulboag,2009-12-04T00:00:00+00:00,https://24ways.org/2009/what-makes-a-website-successful/,business
179,Have a Field Day with HTML5 Forms,"Forms are usually seen as that obnoxious thing we have to markup and style. I respectfully disagree: forms (on a par with tables) are the most exciting thing we have to work with.
Here we’re going to take a look at how to style a beautiful HTML5 form using some advanced CSS and latest CSS3 techniques. I promise you will want to style your own forms after you’ve read this article.
Here’s what we’ll be creating:
The form. (Icons from Chalkwork Payments)
Meaningful markup
We’re going to style a simple payment form. There are three main sections on this form:
The person’s details
The address details
The credit card details
We are also going to use some of HTML5’s new input types and attributes to create more meaningful fields and use less unnecessary classes and ids:
email, for the email field
tel, for the telephone field
number, for the credit card number and security code
required, for required fields
placeholder, for the hints within some of the fields
autofocus, to put focus on the first input field when the page loads
There are a million more new input types and form attributes on HTML5, and you should definitely take a look at what’s new on the W3C website. Hopefully this will give you a good idea of how much more fun form markup can be.
A good foundation
Each section of the form will be contained within its own fieldset. In the case of the radio buttons for choosing the card type, we will enclose those options in another nested fieldset.
We will also be using an ordered list to group each label / input pair. This will provide us with a (kind of) semantic styling hook and it will also make the form easier to read when viewing with no CSS applied:
The unstyled form
So here’s the markup we are going to be working with:
Your details
Name
Email
Phone
Delivery address
Address
Post code
Country
Card details
Card type
VISA
AmEx
Mastercard
Card number
Security code
Name on card
Buy it!
Making things look nice
First things first, so let’s start by adding some defaults to our form by resetting the margins and paddings of the elements and adding a default font to the page:
html, body, h1, form, fieldset, legend, ol, li {
margin: 0;
padding: 0;
}
body {
background: #ffffff;
color: #111111;
font-family: Georgia, ""Times New Roman"", Times, serif;
padding: 20px;
}
Next we are going to style the form element that is wrapping our fields:
form#payment {
background: #9cbc2c;
-moz-border-radius: 5px;
-webkit-border-radius: 5px;
border-radius: 5px;
padding: 20px;
width: 400px;
}
We will also remove the border from the fieldset and apply some bottom margin to it. Using the :last-of-type pseudo-class, we remove the bottom margin of the last fieldset — there is no need for it:
form#payment fieldset {
border: none;
margin-bottom: 10px;
}
form#payment fieldset:last-of-type {
margin-bottom: 0;
}
Next we’ll make the legends big and bold, and we will also apply a light-green text-shadow, to add that little extra special detail:
form#payment legend {
color: #384313;
font-size: 16px;
font-weight: bold;
padding-bottom: 10px;
text-shadow: 0 1px 1px #c0d576;
}
Our legends are looking great, but how about adding a clear indication of how many steps our form has? Instead of adding that manually to every legend, we can use automatically generated counters.
To add a counter to an element, we have to use either the :before or :after pseudo-elements to add content via CSS. We will follow these steps:
create a counter using the counter-reset property on the form element
call the counter with the content property (using the same name we’ve created before)
with the counter-incremet property, indicate that for each element that matches our selector, that counter will be increased by 1
form#payment > fieldset > legend:before {
content: ""Step "" counter(fieldsets) "": "";
counter-increment: fieldsets;
}
Finally, we need to change the style of the legend that is part of the radio buttons group, to make it look like a label:
form#payment fieldset fieldset legend {
color: #111111;
font-size: 13px;
font-weight: normal;
padding-bottom: 0;
}
Styling the lists
For our list elements, we’ll just add some nice rounded corners and semi-transparent border and background. Because we are using RGBa colors, we should provide a fallback for browsers that don’t support them (that comes before the RBGa color). For the nested lists, we will remove these properties because they would be overlapping:
form#payment ol li {
background: #b9cf6a;
background: rgba(255,255,255,.3);
border-color: #e3ebc3;
border-color: rgba(255,255,255,.6);
border-style: solid;
border-width: 2px;
-moz-border-radius: 5px;
-webkit-border-radius: 5px;
border-radius: 5px;
line-height: 30px;
list-style: none;
padding: 5px 10px;
margin-bottom: 2px;
}
form#payment ol ol li {
background: none;
border: none;
float: left;
}
Form controls
Now we only need to style our labels, inputs and the button element.
All our labels will look the same, with the exception of the one for the radio elements. We will float them to the left and give them a width.
For the credit card type labels, we will add an icon as the background, and override some of the properties that aren’t necessary. We will be using the attribute selector to specify the background image for each label — in this case, we use the for attribute of each label.
To add an extra user-friendly detail, we’ll add a cursor: pointer to the radio button labels on the :hover state, so the user knows that he can simply click them to select that option.
form#payment label {
float: left;
font-size: 13px;
width: 110px;
}
form#payment fieldset fieldset label {
background:none no-repeat left 50%;
line-height: 20px;
padding: 0 0 0 30px;
width: auto;
}
form#payment label[for=visa] {
background-image: url(visa.gif);
}
form#payment label[for=amex] {
background-image: url(amex.gif);
}
form#payment label[for=mastercard] {
background-image: url(mastercard.gif);
}
form#payment fieldset fieldset label:hover {
cursor: pointer;
}
Almost there! Now onto the input elements. Here we want to match all inputs, except for the radio ones, and the textarea. For that we will use the negation pseudo-class (:not()). With it we can target all input elements except for the ones with type of radio.
We will also make sure to add some :focus styles and add the appropriate styling for the radio inputs:
form#payment input:not([type=radio]),
form#payment textarea {
background: #ffffff;
border: none;
-moz-border-radius: 3px;
-webkit-border-radius: 3px;
-khtml-border-radius: 3px;
border-radius: 3px;
font: italic 13px Georgia, ""Times New Roman"", Times, serif;
outline: none;
padding: 5px;
width: 200px;
}
form#payment input:not([type=submit]):focus,
form#payment textarea:focus {
background: #eaeaea;
}
form#payment input[type=radio] {
float: left;
margin-right: 5px;
}
And finally we come to our submit button. To it, we will just add some nice typography and text-shadow, align it to the center of the form and give it some background colors for its different states:
form#payment button {
background: #384313;
border: none;
-moz-border-radius: 20px;
-webkit-border-radius: 20px;
-khtml-border-radius: 20px;
border-radius: 20px;
color: #ffffff;
display: block;
font: 18px Georgia, ""Times New Roman"", Times, serif;
letter-spacing: 1px;
margin: auto;
padding: 7px 25px;
text-shadow: 0 1px 1px #000000;
text-transform: uppercase;
}
form#payment button:hover {
background: #1e2506;
cursor: pointer;
}
And that’s it! See the completed form.
This form will not look the same on every browser. Internet Explorer and Opera don’t support border-radius (at least not for now); the new input types are rendered as just normal inputs on some browsers; and some of the most advanced CSS, like the counter, :last-of-type or text-shadow are not supported on some browsers. But that doesn’t mean you can’t use them right now, and simplify your development process. My gift to you!",2009,Inayaili de León Persson,inayailideleon,2009-12-03T00:00:00+00:00,https://24ways.org/2009/have-a-field-day-with-html5-forms/,code
182,Breaking Out The Edges of The Browser,"HTML5 contains more than just the new entities for a more meaningful document, it also contains an arsenal of JavaScript APIs. So many in fact, that some APIs have outgrown the HTML5 spec’s backyard and have been sent away to grow up all on their own and been given the prestigious honour of being specs in their own right.
So when I refer to (bendy finger quote) “HTML5”, I mean the HTML5 specification and a handful of other specifications that help us authors build web applications.
Examples of those specs I would include in the umbrella term would be: geolocation, web storage, web databases, web sockets and web workers, to name a few.
For all you guys and gals, on this special 2009 series of 24 ways, I’m just going to focus on data storage and offline applications: boldly taking your browser where no browser has gone before!
Web Storage
The Web Storage API is basically cookies on steroids, a unhealthy dosage of steroids. Cookies are always a pain to work with. First of all you have the problem of setting, changing and deleting them. Typically solved by Googling and blindly relying on PPK’s solution. If that wasn’t enough, there’s the 4Kb limit that some of you have hit when you really don’t want to.
The Web Storage API gets around all of the hoops you have to jump through with cookies. Storage supports around 5Mb of data per domain (the spec’s recommendation, but it’s open to the browsers to implement anything they like) and splits in to two types of storage objects:
sessionStorage – available to all pages on that domain while the window remains open
localStorage – available on the domain until manually removed
Support
Ignoring beta browsers for our support list, below is a list of the major browsers and their support for the Web Storage API:
Latest: Internet Explorer, Firefox, Safari (desktop & mobile/iPhone)
Partial: Google Chrome (only supports localStorage)
Not supported: Opera (as of 10.10)
Usage
Both sessionStorage and localStorage support the same interface for accessing their contents, so for these examples I’ll use localStorage.
The storage interface includes the following methods:
setItem(key, value)
getItem(key)
key(index)
removeItem(key)
clear()
In the simple example below, we’ll use setItem and getItem to store and retrieve data:
localStorage.setItem('name', 'Remy');
alert( localStorage.getItem('name') );
Using alert boxes can be a pretty lame way of debugging. Conveniently Safari (and Chrome) include database tab in their debugging tools (cmd+alt+i), so you can get a visual handle on the state of your data:
Viewing localStorage
As far as I know only Safari has this view on stored data natively in the browser. There may be a Firefox plugin (but I’ve not found it yet!) and IE… well that’s just IE.
Even though we’ve used setItem and getItem, there’s also a few other ways you can set and access the data.
In the example below, we’re accessing the stored value directly using an expando and equally, you can also set values this way:
localStorage.name = ""Remy"";
alert( localStorage.name ); // shows ""Remy""
The Web Storage API also has a key method, which is zero based, and returns the key in which data has been stored. This should also be in the same order that you set the keys, for example:
alert( localStorage.getItem(localStorage.key(0)) );
// shows ""Remy""
I mention the key() method because it’s not an unlikely name for a stored value. This can cause serious problems though.
When selecting the names for your keys, you need to be sure you don’t take one of the method names that are already on the storage object, like key, clear, etc. As there are no warnings when you try to overwrite the methods, it means when you come to access the key() method, the call breaks as key is a string value and not a function.
You can try this yourself by creating a new stored value using localStorage.key = ""foo"" and you’ll see that the Safari debugger breaks because it relies on the key() method to enumerate each of the stored values.
Usage Notes
Currently all browsers only support storing strings. This also means if you store a numeric, it will get converted to a string:
localStorage.setItem('count', 31);
alert(typeof localStorage.getItem('count'));
// shows ""string""
This also means you can’t store more complicated objects natively with the storage objects. To get around this, you can use Douglas Crockford’s JSON parser (though Firefox 3.5 has JSON parsing support baked in to the browser – yay!) json2.js to convert the object to a stringified JSON object:
var person = {
name: 'Remy',
height: 'short',
location: 'Brighton, UK'
};
localStorage.setItem('person', JSON.stringify(person));
alert( JSON.parse(localStorage.getItem('person')).name );
// shows ""Remy""
Alternatives
There are a few solutions out there that provide storage solutions that detect the Web Storage API, and if it’s not available, fall back to different technologies (for instance, using a flash object to store data). One comprehensive version of this is Dojo’s storage library. I’m personally more of a fan of libraries that plug missing functionality under the same namespace, just as Crockford’s JSON parser does (above).
For those interested it what that might look like, I’ve mocked together a simple implementation of sessionStorage. Note that it’s incomplete (because it’s missing the key method), and it could be refactored to not using the JSON stringify (but you would need to ensure that the values were properly and safely encoded):
// requires json2.js for all browsers other than Firefox 3.5
if (!window.sessionStorage && JSON) {
window.sessionStorage = (function () {
// window.top.name ensures top level, and supports around 2Mb
var data = window.top.name ? JSON.parse(window.top.name) : {};
return {
setItem: function (key, value) {
data[key] = value+""""; // force to string
window.top.name = JSON.stringify(data);
},
removeItem: function (key) {
delete data[key];
window.top.name = JSON.stringify(data);
},
getItem: function (key) {
return data[key] || null;
},
clear: function () {
data = {};
window.top.name = '';
}
};
})();
}
Now that we’ve cracked the cookie jar with our oversized Web Storage API, let’s have a look at how we take our applications offline entirely.
Offline Applications
Offline applications is (still) part of the HTML5 specification. It allows developers to build a web app and have it still function without an internet connection. The app is access via the same URL as it would be if the user were online, but the contents (or what the developer specifies) is served up to the browser from a local cache. From there it’s just an everyday stroll through open web technologies, i.e. you still have access to the Web Storage API and anything else you can do without a web connection.
For this section, I’ll refer you to a prototype demo I wrote recently of a contrived Rubik’s cube (contrived because it doesn’t work and it only works in Safari because I’m using 3D transforms).
Offline Rubik’s cube
Support
Support for offline applications is still fairly limited, but the possibilities of offline applications is pretty exciting, particularly as we’re seeing mobile support and support in applications such as Fluid (and I would expect other render engine wrapping apps).
Support currently, is as follows:
Latest: Safari (desktop & mobile/iPhone)
Sort of: Firefox‡
Not supported: Internet Explorer, Opera, Google Chrome
‡ Firefox 3.5 was released to include offline support, but in fact has bugs where it doesn’t work properly (certainly on the Mac), Minefield (Firefox beta) has resolved the bug.
Usage
The status of the application’s cache can be tested from the window.applicationCache object. However, we’ll first look at how to enable your app for offline access.
You need to create a manifest file, which will tell the browser what to cache, and then we point our web page to that cache:
For the manifest to be properly read by the browser, your server needs to serve the .manifest files as text/manifest by adding the following to your mime.types:
text/cache-manifest manifest
Next we need to populate our manifest file so the browser can read it:
CACHE MANIFEST
/demo/rubiks/index.html
/demo/rubiks/style.css
/demo/rubiks/jquery.min.js
/demo/rubiks/rubiks.js
# version 15
The first line of the manifest must read CACHE MANIFEST. Then subsequent lines tell the browser what to cache.
The HTML5 spec recommends that you include the calling web page (in my case index.html), but it’s not required. If I didn’t include index.html, the browser would cache it as part of the offline resources.
These resources are implicitly under the CACHE namespace (which you can specify any number of times if you want to).
In addition, there are two further namespaces: NETWORK and FALLBACK.
NETWORK is a whitelist namespace that tells the browser not to cache this resource and always try to request it through the network.
FALLBACK tells the browser that whilst in offline mode, if the resource isn’t available, it should return the fallback resource.
Finally, in my example I’ve included a comment with a version number. This is because once you include a manifest, the only way you can tell the browser to reload the resources is if the manifest contents changes. So I’ve included a version number in the manifest which I can change forcing the browser to reload all of the assets.
How it works
If you’re building an app that makes use of the offline cache, I would strongly recommend that you add the manifest last. The browser implementations are very new, so can sometimes get a bit tricky to debug since once the resources are cached, they really stick in the browser.
These are the steps that happen during a request for an app with a manifest:
Browser: sends request for your app.html
Server: serves all associated resources with app.html – as normal
Browser: notices that app.html has a manifest, it re-request the assets in the manifest
Server: serves the requested manifest assets (again)
Browser: window.applicationCache has a status of UPDATEREADY
Browser: reloads
Browser: only request manifest file (which doesn’t show on the net requests panel)
Server: responds with 304 Not Modified on the manifest file
Browser: serves all the cached resources locally
What might also add confusion to this process, is that the way the browsers work (currently) is if there is a cache already in place, it will use this first over updated resources. So if your manifest has changed, the browser will have already loaded the offline cache, so the user will only see the updated on the next reload.
This may seem a bit convoluted, but you can also trigger some of this manually through the applicationCache methods which can ease some of this pain.
If you bind to the online event you can manually try to update the offline cache. If the cache has then updated, swap the updated resources in to the cache and the next time the app loads it will be up to date. You could also prompt your user to reload the app (which is just a refresh) if there’s an update available.
For example (though this is just pseudo code):
addEvent(applicationCache, 'updateready', function () {
applicationCache.swapCache();
tellUserToRefresh();
});
addEvent(window, 'online', function () {
applicationCache.update();
});
Breaking out of the Browser
So that’s two different technologies that you can use to break out of the traditional browser/web page model and get your apps working in a more application-ny way.
There’s loads more in the HTML5 and non-HTML5 APIs to play with, so take your Christmas break to check them out!",2009,Remy Sharp,remysharp,2009-12-02T00:00:00+00:00,https://24ways.org/2009/breaking-out-the-edges-of-the-browser/,code
181,Working With RGBA Colour,"When Tim and I were discussing the redesign of this site last year, one of the clear goals was to have a graphical style without making the pages heavy with a lot of images. When we launched, a lot of people were surprised that the design wasn’t built with PNGs. Instead we’d used RGBA colour values, which is part of the CSS3 specification.
What is RGBA Colour?
We’re all familiar with specifying colours in CSS using by defining the mix of red, green and blue light required to achieve our tone. This is fine and dandy, but whatever values we specify have one thing in common — the colours are all solid, flat, and well, a bit boring.
Flat RGB colours
CSS3 introduces a couple of new ways to specify colours, and one of those is RGBA. The A stands for Alpha, which refers to the level of opacity of the colour, or to put it another way, the amount of transparency. This means that we can set not only the red, green and blue values, but also control how much of what’s behind the colour shows through. Like with layers in Photoshop.
Don’t We Have Opacity Already?
The ability to set the opacity on a colour differs subtly from setting the opacity on an element using the CSS opacity property. Let’s look at an example.
Here we have an H1 with foreground and background colours set against a page with a patterned background.
Heading with no transparency applied
h1 {
color: rgb(0, 0, 0);
background-color: rgb(255, 255, 255);
}
By setting the CSS opacity property, we can adjust the transparency of the entire element and its contents:
Heading with 50% opacity on the element
h1 {
color: rgb(0, 0, 0);
background-color: rgb(255, 255, 255);
opacity: 0.5;
}
RGBA colour gives us something different – the ability to control the opacity of the individual colours rather than the entire element. So we can set the opacity on just the background:
50% opacity on just the background colour
h1 {
color: rgb(0, 0, 0);
background-color: rgba(255, 255, 255, 0.5);
}
Or leave the background solid and change the opacity on just the text:
50% opacity on just the foreground colour
h1 {
color: rgba(0, 0, 0, 0.5);
background-color: rgb(255, 255, 255);
}
The How-To
You’ll notice that above I’ve been using the rgb() syntax for specifying colours. This is a bit less common than the usual hex codes (like #FFF) but it makes sense when starting to use RGBA. As there’s no way to specify opacity with hex codes, we use rgba() like so:
color: rgba(255, 255, 255, 0.5);
Just like rgb() the first three values are red, green and blue. You can specify these 0-255 or 0%-100%. The fourth value is the opacity level from 0 (completely transparent) to 1 (completely opaque).
You can use this anywhere you’d normally set a colour in CSS — so it’s good for foregrounds and background, borders, outlines and so on. All the transparency effects on this site’s current design are achieved this way.
Supporting All Browsers
Like a lot of the features we’ll be looking at in this year’s 24 ways, RGBA colour is supported by a lot of the newest browsers, but not the rest. Firefox, Safari, Chrome and Opera browsers all support RGBA, but Internet Explorer does not.
Fortunately, due to the robust design of CSS as a language, we can specify RGBA colours for browsers that support it and an alternative for browsers that do not.
Falling back to solid colour
The simplest technique is to allow the browser to fall back to using a solid colour when opacity isn’t available. The CSS parsing rules specify that any unrecognised value should be ignored. We can make use of this because a browser without RGBA support will treat a colour value specified with rgba() as unrecognised and discard it.
So if we specify the colour first using rgb() for all browsers, we can then overwrite it with an rgba() colour for browsers that understand RGBA.
h1 {
color: rgb(127, 127, 127);
color: rgba(0, 0, 0, 0.5);
}
Falling back to a PNG
In cases where you’re using transparency on a background-color (although not on borders or text) it’s possible to fall back to using a PNG with alpha channel to get the same effect. This is less flexible than using CSS as you’ll need to create a new PNG for each level of transparency required, but it can be a useful solution.
Using the same principal as before, we can specify the background in a style that all browsers will understand, and then overwrite it in a way that browsers without RGBA support will ignore.
h1 {
background: transparent url(black50.png);
background: rgba(0, 0, 0, 0.5) none;
}
It’s important to note that this works because we’re using the background shorthand property, enabling us to set both the background colour and background image in a single declaration. It’s this that enables us to rely on the browser ignoring the second declaration when it encounters the unknown rgba() value.
Next Steps
The really great thing about RGBA colour is that it gives us the ability to create far more graphically rich designs without the need to use images. Not only does that make for faster and lighter pages, but sites which are easier and quicker to build and maintain. CSS values can also be changed in response to user interaction or even manipulated with JavaScript in a way that’s just not so easy using images.
Opacity can be changed on :hover or manipulated with JavaScript
div {
color: rgba(255, 255, 255, 0.8);
background-color: rgba(142, 213, 87, 0.3);
}
div:hover {
color: rgba(255, 255, 255, 1);
background-color: rgba(142, 213, 87, 0.6);
}
Clever use of transparency in border colours can help ease the transition between overlay items and the page behind.
Borders can receive the RGBA treatment, too
div {
color: rgb(0, 0, 0);
background-color: rgb(255, 255, 255);
border: 10px solid rgba(255, 255, 255, 0.3);
}
In Conclusion
That’s a brief insight into RGBA colour, what it’s good for and how it can be used whilst providing support for older browsers. With the current lack of support in Internet Explorer, it’s probably not a technique that commercial designs will want to heavily rely on right away – simply because of the overhead of needing to think about fallback all the time.
It is, however, a useful tool to have for those smaller, less critical touches that can really help to finesse a design. As browser support becomes more mainstream, you’ll already be familiar and practised with RGBA and ready to go.",2009,Drew McLellan,drewmclellan,2009-12-01T00:00:00+00:00,https://24ways.org/2009/working-with-rgba-colour/,code
103,Recession Tips For Web Designers,"For web designers, there are four keys to surviving bad economic times: do good work, charge a fair price, lower your overhead, and be sure you are communicating with your client. As a reader of 24 ways, you already do good work, so let’s focus on the rest.
I know something about surviving bad times, having started my agency, Happy Cog, at the dawn of the dot-com bust. Of course, the recession we’re in now may end up making the dot-com bust look like the years of bling and gravy. But the bust was rough enough at the time.
Bad times are hard on overweight companies and over-leveraged start-ups, but can be kind to freelancers and small agencies. Clients who once had money to burn and big agencies to help them burn it suddenly consider the quality of work more important than the marquee value of the business card. Fancy offices and ten people at every meeting are out. A close relationship with an individual or small team that listens is in.
Thin is in
If you were good in client meetings when you were an employee, print business cards and pick a name for your new agency. Once some cash rolls in, see an accountant.
If the one-person entrepreneur model isn’t you, it’s no problem. Form a virtual agency with colleagues who complement your creative, technical, and business skills. Athletics is a Brooklyn-based multi-disciplinary “art and design collective.” Talk about low overhead: they don’t have a president, a payroll, or a pension plan. But that hasn’t stopped clients like adidas, Nike, MTV, HBO, Disney, DKNY, and Sundance Channel from knocking on their (virtual) doors.
Running a traditional business is like securing a political position in Chicago: it costs a fortune. That’s why bad times crush so many companies. But you are a creature of the internets. You don’t need an office to do great work. I ran Happy Cog out of my apartment for far longer than anyone realized. My clients, when they learned my secret, didn’t care.
Keep it lean: if you can budget your incoming freelance money, you don’t have to pay yourself a traditional salary. Removing the overhead associated with payroll means more of the budget stays in your pocket, enabling you to price your projects competitively, while still within industry norms. (Underpricing is uncool, and clients who knowingly choose below-market-rate vendors tend not to treat those vendors with respect.)
Getting gigs
Web design is a people business. If things are slow, email former clients. If you just lost your job, email former agency clients with whom you worked closely to inform them of your freelance business and find out how they’re doing. Best practice: focus the email on wishing them a happy holiday and asking how they’re doing. Let your email signature file tell them you’re now the president of Your Name Design. Leading with the fact that you just lost your job may earn sympathy (or commiseration: the client may have lost her job, too) but it’s not exactly a sure-fire project getter.
The qualities that help you land a web design project are the same in good times or bad. Have a story to tell about the kind of services you offer, and the business benefits they provide. (If you design with web standards, you already have one great story line. What are the others?)
Don’t be shy about sharing your story, but don’t make it the focus of the meeting. The client is the focus. Before you meet her, learn as much as you can about her users, her business, and her competitors. At the very least, read her site’s About pages, and spend some quality time with Google.
Most importantly, go to the meeting knowing how much you don’t know. Arrive curious, and armed with questions. Maintain eye contact and keep your ears open. If a point you raise causes two people to nod at each other, follow up on that point, don’t just keep grinding through your Keynote presentation.
If you pay attention and think on your feet, it tells the potential client that they can expect you to listen and be flexible. (Clients are like unhappy spouses: they’re dying for someone to finally listen.) If you stick to a prepared presentation, it might send the message that you are inflexible or nervous or both. “Nervous” is an especially bad signal to send. It indicates that you are either dishonest or inexperienced. Neither quality invites a client to sign on. Web design is a people business for the client, too: they should feel that their interactions with you will be pleasant and illuminating. And that you’ll listen. Did I mention that?
Give it time
Securing clients takes longer and requires more effort in a recession. If two emails used to land you a gig, it will now take four, plus an in-person meeting, plus a couple of follow-up calls. This level of salesmanship is painful to geeks and designers, who would rather spend four hours kerning type or debugging a style sheet than five minutes talking business on the telephone. I know. I’m the same way. But we must overcome our natural shyness and inwardness if we intend not to fish our next meal out of a neighbor’s garbage can.
As a bonus, once the recession ends, your hard-won account management skills will help you take your business to the next level. By the time jobs are plentiful again, you may not want to work for anyone but yourself. You’ll be a captain of our industry. And talented people will be emailing to ask you for a job.",2008,Jeffrey Zeldman,jeffreyzeldman,2008-12-24T00:00:00+00:00,https://24ways.org/2008/recession-tips-for-web-designers/,business
105,Contract Killer,"When times get tough, it can often feel like there are no good people left in the world, only people who haven’t yet turned bad. These bad people will go back on their word, welch on a deal, put themselves first. You owe it to yourself to stay on top. You owe it to yourself to ensure that no matter how bad things get, you’ll come away clean. You owe it yourself and your business not to be the guy lying bleeding in an alley with a slug in your gut.
But you’re a professional, right? Nothing bad is going to happen to you.
You’re a good guy. You do good work for good people.
Think again chump.
Maybe you’re a gun for hire, a one man army with your back to the wall and nothing standing between you and the line at a soup kitchen but your wits. Maybe you work for the agency, or like me you run one of your own. Either way, when times get tough and people get nasty, you’ll need more than a killer smile to save you. You’ll need a killer contract too.
It was exactly ten years ago today that I first opened my doors for business. In that time I’ve thumbed through enough contracts to fill a filing cabinet. I’ve signed more contracts than I can remember, many so complicated that I should have hired a lawyer (or detective) to make sense of their complicated jargon and solve their cross-reference puzzles. These documents had not been written to be understood on first reading but to spin me around enough times so as to give the other player the upper-hand.
If signing a contract I didn’t fully understand made me a stupid son-of-a-bitch, not asking my customers to sign one just makes me plain dumb. I’ve not always been so careful about asking my customers to sign contracts with me as I am now. Somehow in the past I felt that insisting on a contract went against the friendly, trusting relationship that I like to build with my customers. Most of the time the game went my way. On rare the occasions when a fight broke out, I ended up bruised and bloodied. I learned that asking my customers to sign a contract matters to both sides, but what also matters to me is that these contracts should be more meaningful, understandable and less complicated than any of those that I have ever autographed.
Writing a killer contract
If you are writing a contract between you and your customers it doesn’t have to conform to the seemingly standard format of jargon and complicated legalese. You can be creative. A killer contract will clarify what is expected of both sides and it can also help you to communicate your approach to doing business. It will back-up your brand values and help you to build a great relationship between you and your customers. In other words, a creative contract can be a killer contract.
Your killer contract should cover:
A simple overview of who is hiring who, what they are being hired to do, when and for how much
What both parties agree to do and what their respective responsibilities are
The specifics of the deal and what is or isn’t included in the scope
What happens when people change their minds (as they almost always do)
A simple overview of liabilities and other legal matters
You might even include a few jokes
To help you along, I will illustrate those bullet points by pointing both barrels at the contract that I wrote and have been using at Stiffs & Nonsense for the past year. My contract has been worth its weight in lead and you are welcome to take all or any part of it to use for yourself. It’s packing a creative-commons attribution share-a-like license. That means you are free to re-distribute it, translate it and otherwise re-use it in ways I never considered. In return I only ask you mention my name and link back to this article. As I am only an amateur detective, you should have it examined thoroughly by your own, trusted legal people if you use it.
NB: The specific details of this killer contract work for me and my customers. That doesn’t mean that they will work for you and yours. The ways that I handle design revisions, testing, copyright ownership and other specifics are not the main focus of this article. That you handle each of them carefully when you write your own killer contract is.
Kiss Me, Deadly
Setting a tone and laying foundations for agreement
The first few paragraphs of a killer contract are the most important. Just like a well thought-out web page, these first few words should be simple, concise and include the key points in your contract. As this is the part of the contract that people absorb most easily, it is important that you make it count. Start by setting the overall tone and explaining how your killer contract is structured and why it is different.
We will always do our best to fulfill your needs and meet your goals, but sometimes it is best to have a few simple things written down so that we both know what is what, who should do what and what happens if stuff goes wrong. In this contract you won’t find complicated legal terms or large passages of unreadable text. We have no desire to trick you into signing something that you might later regret. We do want what’s best for the safety of both parties, now and in the future.
In short
You ([customer name]) are hiring us ([company name]) located at [address] to [design and develop a web site] for the estimated total price of [total] as outlined in our previous correspondence. Of course it’s a little more complicated, but we’ll get to that.
The Big Kill
What both parties agree to do
Have you ever done work on a project in good faith for a junior member of a customer’s team, only to find out later that their spending hadn’t been authorized? To make damn sure that does not happen to you, you should ask your customer to confirm that not only are they authorized to enter into your contract but that they will fulfill all of their obligations to help you meet yours. This will help you to avoid any gunfire if, as deadline day approaches, you have fulfilled your side of the bargain but your customer has not come up with the goods.
As our customer, you have the power and ability to enter into this contract on behalf of your company or organization. You agree to provide us with everything that we need to complete the project including text, images and other information as and when we need it, and in the format that we ask for. You agree to review our work, provide feedback and sign-off approval in a timely manner too. Deadlines work two ways and you will also be bound by any dates that we set together. You also agree to stick to the payment schedule set out at the end of this contract.
We have the experience and ability to perform the services you need from us and we will carry them out in a professional and timely manner. Along the way we will endeavor to meet all the deadlines set but we can’t be responsible for a missed launch date or a deadline if you have been late in supplying materials or have not approved or signed off our work on-time at any stage. On top of this we will also maintain the confidentiality of any information that you give us.
My Gun Is Quick
Getting down to the nitty gritty
What appear at first to be a straight-forward projects can sometimes turn long and complicated and unless you play it straight from the beginning your relationship with your customer can suffer under the strain. Customers do, and should have the opportunity to, change their minds and give you new assignments. After-all, projects should be flexible and few customers know from the get-go exactly what they want to see. If you handle this well from the beginning you will help to keep yourself and your customers from becoming frustrated. You will also help yourself to dodge bullets in the event of a fire-fight.
We will create designs for the look-and-feel, layout and functionality of your web site. This contract includes one main design plus the opportunity for you to make up to two rounds of revisions. If you’re not happy with the designs at this stage, you will pay us in full for all of the work that we have produced until that point and you may either cancel this contract or continue to commission us to make further design revisions at the daily rate set out in our original estimate.
We know from plenty of experience that fixed-price contracts are rarely beneficial to you, as they often limit you to your first idea about how something should look, or how it might work. We don’t want to limit either your options or your opportunities to change your mind.
The estimate/quotation prices at the beginning of this document are based on the number of days that we estimate we’ll need to accomplish everything that you have told us you want to achieve. If you do want to change your mind, add extra pages or templates or even add new functionality, that won’t be a problem. You will be charged the daily rate set out in the estimate we gave you. Along the way we might ask you to put requests in writing so we can keep track of changes.
As I like to push my luck when it comes to CSS, it never hurts to head off the potential issue of progressive enrichment right from the start. You should do this too. But don’t forget that when it comes to technical matters your customers may have different expectations or understanding, so be clear about what you will and won’t do.
If the project includes XHTML or HTML markup and CSS templates, we will develop these using valid XHTML 1.0 Strict markup and CSS2.1 + 3 for styling. We will test all our markup and CSS in current versions of all major browsers including those made by Apple, Microsoft, Mozilla and Opera. We will also test to ensure that pages will display visually in a ‘similar’, albeit not necessarily an identical way, in Microsoft Internet Explorer 6 for Windows as this browser is now past it’s sell-by date.
We will not test these templates in old or abandoned browsers, for example Microsoft Internet Explorer 5 or 5.5 for Windows or Mac, previous versions of Apple’s Safari, Mozilla Firefox or Opera unless otherwise specified. If you need to show the same or similar visual design to visitors using these older browsers, we will charge you at the daily rate set out in our original estimate for any necessary additional code and its testing.
The Twisted Thing
It is not unheard of for customers to pass off stolen goods as their own. If this happens, make sure that you are not the one left holding the baby. You should also make it clear who owns the work that you make as customers often believe that because they pay for your time, that they own everything that you produce.
Copyrights
You guarantee to us that any elements of text, graphics, photos, designs, trademarks, or other artwork that you provide us for inclusion in the web site are either owned by your good selfs, or that you have permission to use them. When we receive your final payment, copyright is automatically assigned as follows:
You own the graphics and other visual elements that we create for you for this project. We will give you a copy of all files and you should store them really safely as we are not required to keep them or provide any native source files that we used in making them.
You also own text content, photographs and other data you provided, unless someone else owns them. We own the XHTML markup, CSS and other code and we license it to you for use on only this project.
Vengeance Is Mine!
The fine print
Unless your work is pro-bono, you should make sure that your customers keep you in shoe leather. It is important that your customers know from the outset that they must pay you on time if they want to stay on good terms.
We are sure you understand how important it is as a small business that you pay the invoices that we send you promptly. As we’re also sure you’ll want to stay friends, you agree to stick tight to the following payment schedule.
[Payment schedule]
No killer contract would be complete without you making sure that you are watching your own back. Before you ask your customers to sign, make it clear-cut what your obligations are and what will happen if any part of your killer contract finds itself laying face down in the dirt.
We can’t guarantee that the functions contained in any web page templates or in a completed web site will always be error-free and so we can’t be liable to you or any third party for damages, including lost profits, lost savings or other incidental, consequential or special damages arising out of the operation of or inability to operate this web site and any other web pages, even if you have advised us of the possibilities of such damages.
Just like a parking ticket, you cannot transfer this contract to anyone else without our permission. This contract stays in place and need not be renewed. If any provision of this agreement shall be unlawful, void, or for any reason unenforceable, then that provision shall be deemed severable from this agreement and shall not affect the validity and enforceability of any remaining provisions.
Phew.
Although the language is simple, the intentions are serious and this contract is a legal document under exclusive jurisdiction of [English] courts. Oh and don’t forget those men with big dogs.
Survival… Zero!
Take it from me, packing a killer contract will help to keep you safe when times get tough, but you must still keep your wits about you and stay on the right side of the law.
Don’t be a turkey this Christmas.
Be a contract killer.
Update, May 2010: For a follow-on to this article see Contract Killer: The Next Hit",2008,Andy Clarke,andyclarke,2008-12-23T00:00:00+00:00,https://24ways.org/2008/contract-killer/,business
98,Absolute Columns,"CSS layouts have come quite a long way since the dark ages of web publishing, with all sorts of creative applications of floats, negative margins, and even background images employed in order to give us that most basic building block, the column. As the title implies, we are indeed going to be discussing columns today—more to the point, a handy little application of absolute positioning that may be exactly what you’ve been looking for…
Care for a nightcap?
If you’ve been developing for the web for long enough, you may be familiar with this little children’s fable, passed down from wizened Shaolin monks sitting atop the great Mt. Geocities: “Once upon a time, multiple columns of the same height could be easily created using TABLES.” Now, though we’re all comfortably seated on the standards train (and let’s be honest: even if you like to think you’ve fallen off, if you’ve given up using tables for layout, rest assured your sleeper car is still reserved), this particular—and as page layout goes, quite basic—trick is still a thorn in our CSSides compared to the ease of achieving the same effect using said Tables of Evil™.
See, the orange juice masks the flavor…
Creative solutions such as Dan Cederholm’s Faux Columns do a good job of making it appear as though adjacent columns maintain equal height as content expands, using a background image to fill the space that the columns cannot.
Now, the Holy Grail of CSS columns behaving exactly how they would as table cells—or more to the point, as columns—still eludes us (cough CSS3 Multi-column layout module cough), but sometimes you just need, for example, a secondary column (say, a sidebar) to match the height of a primary column, without involving the creation of images. This is where a little absolute positioning can save you time, while possibly giving your layout a little more flexibility.
Shaken, not stirred
You’re probably familiar by now with the concept of Making the Absolute, Relative as set forth long ago by Doug Bowman, but let’s quickly review just in case: an element set to position:absolute will position itself relative to its nearest ancestor set to position:relative, rather than the browser window (see Figure 1).
Figure 1.
However, what you may not know is that we can anchor more than two sides of an absolutely positioned element. Yes, that’s right, all four sides (top, right, bottom, left) can be set, though in this example we’re only going to require the services of three sides (see Figure 2 for the end result).
Figure 2.
Trust me, this will make you feel better
Our requirements are essentially the same as the standard “absolute-relative” trick—a container set to position:relative, and our sidebar
set to position:absolute — plus another
that will serve as our main content column. We’ll also add a few other common layout elements (wrapper, header, and footer) so our example markup looks more like a real layout and less like a test case:
#header
#left
Lorem ipsum dolor sit amet…
#right
#footer
In this example, our main column (#column-left) is only being given a width to fit within the context of the layout, and is otherwise untouched (though we’re using pixels here, this trick will of course work with fluid layouts as well), and our right keeping our styles nice and minimal:
#container {
position: relative;
}
#column-left {
width: 480px;
}
#column-right {
position: absolute;
top: 10px;
right: 10px;
bottom: 10px;
width: 250px;
}
The trick is a simple one: the #container
will expand vertically to fit the content within #column-left. By telling our sidebar
(#column-right) to attach itself not only to the top and right edges of #container, but also to the bottom, it too will expand and contract to match the height of the left column (duplicate the “lorem ipsum” paragraph a few times to see it in action).
Figure 3.
On the rocks
“But wait!” I hear you exclaim, “when the right column has more content than the left column, it doesn’t expand! My text runneth over!” Sure enough, that’s exactly what happens, and what’s more, it’s supposed to: Absolutely positioned elements do exactly what you tell them to do, and unfortunately aren’t very good at thinking outside the box (get it? sigh…).
However, this needn’t get your spirits down, because there’s an easy way to address the issue: by adding overflow:auto to #column-right, a scrollbar will automatically appear if and when needed:
#column-right {
position: absolute;
top: 10px;
right: 10px;
bottom: 10px;
width: 250px;
overflow: auto;
}
While this may limit the trick’s usefulness to situations where the primary column will almost always have more content than the secondary column—or where the secondary column’s content can scroll with wild abandon—a little prior planning will make it easy to incorporate into your designs.
Driving us to drink
It just wouldn’t be right to have a friendly, festive holiday tutorial without inviting IE6, though in this particular instance there will be no shaming that old browser into admitting it has a problem, nor an intervention and subsequent 12-step program. That’s right my friends, this tutorial has abstained from IE6-abuse now for 30 days, thanks to the wizard Dean Edwards and his amazingly talented IE7 Javascript library.
Simply drop the Conditional Comment and
Eggnog is supposed to be spiked, right?
Of course, this is one simple example of what can be a much more powerful technique, depending on your needs and creativity. Just don’t go coding up your wildest fantasies until you’ve had a chance to sleep off the Christmas turkey and whatever tasty liquids you happen to imbibe along the way…",2008,Dan Rubin,danrubin,2008-12-22T00:00:00+00:00,https://24ways.org/2008/absolute-columns/,code
109,Geotag Everywhere with Fire Eagle,"A note from the editors: Since this article was written Yahoo! has retired the Fire Eagle service.
Location, they say, is everywhere. Everyone has one, all of the time. But on the web, it’s taken until this year to see the emergence of location in the applications we use and build.
The possibilities are broad. Increasingly, mobile phones provide SDKs to approximate your location wherever you are, browser extensions such as Loki and Mozilla’s Geode provide browser-level APIs to establish your location from the proximity of wireless networks to your laptop. Yahoo’s Brickhouse group launched Fire Eagle, an ambitious location broker enabling people to take their location from any of these devices or sources, and provide it to a plethora of web services. It enables you to take the location information that only your iPhone knows about and use it anywhere on the web.
That said, this is still a time of location as an emerging technology. Fire Eagle stores your location on the web (protected by application-specific access controls), but to try and give an idea of how useful and powerful your location can be — regardless of the services you use now — today’s 24ways is going to build a bookmarklet to call up your location on demand, in any web application.
Location Support on the Web
Over the past year, the number of applications implementing location features has increased dramatically. Plazes and Brightkite are both full featured social networks based around where you are, whilst Pownce rolled in Fire Eagle support to allow geotagging of all the content you post to their microblogging service. Dipity’s beautiful timeline shows for you moving from place to place and Six Apart’s activity stream for Movable Type started exposing your movements.
The number of services that hook into Fire Eagle will increase as location awareness spreads through the developer community, but you can use your location on other sites indirectly too.
Consider Flickr. Now world renowned for their incredible mapping and places features, geotagging on Flickr started out as a grassroots extension of regular tagging. That same technique can be used to start rolling geotagging in any publishing platform you come across, for any kind of content. Machine-tags (geo:lat= and geo:lon=) and the adr and geo microformats can be used to enhance anything you write with location information.
A crash course in avian inflammability
Fire Eagle is a location store. A broker between services and devices which provide location and those which consume it. It’s a switchboard that controls which pieces of your location different applications can see and use, and keeps hidden anything you want kept private. A blog widget that displays your current location in public can be restricted to display just your current city, whilst a service that provides you with a list of the nearest ATMs will operate better with a precise street address.
Even if your iPhone tells Fire Eagle exactly where you are, consuming applications only see what you want them to see. That’s important for users to realise that they’re in control, but also important for application developers to remember that you cannot rely on having super-accurate information available all the time. You need to build location aware applications which degrade gracefully, because users will provide fuzzier information — either through choice, or through less accurate sources.
Application specific permissions are controlled through an OAuth API. Each application has a unique key, used to request a second, user-specific key that permits access to that user’s information. You store that user key and it remains valid until such a time as the user revokes your application’s access. Unlike with passwords, these keys are unique per application, so revoking the access rights of one application doesn’t break all the others.
Building your first Fire Eagle app; Geomarklet
Fire Eagle’s developer documentation can take you through examples of writing simple applications using server side technologies (PHP, Python). Here, we’re going to write a client-side bookmarklet to make your location available in every site you use. It’s designed to fast-track the experience of having location available everywhere on web, and show you how that can be really handy. Hopefully, this will set you thinking about how location can enhance the new applications you build in 2009.
An oddity of bookmarklets
Bookmarklets (or ‘favlets’, for those of an MSIE persuasion) are a strange environment to program in. Critically, you have no persistent storage available. As such, using token-auth APIs in a static environment requires you to build you application in a slightly strange way; authing yourself in advance and then hardcoding the keys into your script.
Get started
Before you do anything else, go to http://fireeagle.com and log in, get set up if you need to and by all means take a look around. Take a look at the mobile updaters section of the application gallery and perhaps pick out an app that will update Fire Eagle from your phone or laptop.
Once that’s done, you need to register for an application key in the developer section. Head straight to /developer/create and complete the form. Since you’re building a standalone application, choose ‘Auth for desktop applications’ (rather than web applications), and select that you’ll be ‘accessing location’, not updating.
At the end of this process, you’ll have two application keys, a ‘Consumer Key’ and a ‘Consumer Secret’, which look like these:
Consumer Key
luKrM9U1pMnu
Consumer Secret
ZZl9YXXoJX5KLiKyVrMZffNEaBnxnd6M
These keys combined allow your application to make requests to Fire Eagle.
Next up, you need to auth yourself; granting your new application permission to use your location. Because bookmarklets don’t have local storage, you can’t integrate the auth process into the bookmarklet itself — it would have no way of storing the returned key. Instead, I’ve put together a simple web frontend through which you can auth with your application.
Head to Auth me, Amadeus!, enter the application keys you just generated and hit ‘Authorize with Fire Eagle’. You’ll be taken to the Fire Eagle website, just as in regular Fire Eagle applications, and after granting access to your app, be redirected back to Amadeus which will provide you your user tokens. These tokens are used in subsequent requests to read your location.
And, skip to the end…
The process of building the bookmarklet, making requests to Fire Eagle, rendering it to the page and so forth follows, but if you’re the impatient type, you might like to try this out right now. Take your four API keys from above, and drag the following link to your Bookmarks Toolbar; it contains all the code described below. Before you can use it, you need to edit in your own API keys. Open your browser’s bookmark editor and where you find text like ‘YOUR_CONSUMER_KEY_HERE’, swap in the corresponding key you just generated.
Get Location
Bookmarklet Basics
To start on the bookmarklet code, set out a basic JavaScript module-pattern structure:
var Geomarklet = function() {
return ({
callback: function(json) {},
run: function() {}
});
};
Geomarklet.run();
Next we’ll add the keys obtained in the setup step, and also some basic Fire Eagle support objects:
var Geomarklet = function() {
var Keys = {
consumer_key: 'IuKrJUHU1pMnu',
consumer_secret: 'ZZl9YXXoJX5KLiKyVEERTfNEaBnxnd6M',
user_token: 'xxxxxxxxxxxx',
user_secret: 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
};
var LocationDetail = {
EXACT: 0,
POSTAL: 1,
NEIGHBORHOOD: 2,
CITY: 3,
REGION: 4,
STATE: 5,
COUNTRY: 6
};
var index_offset;
return ({
callback: function(json) {},
run: function() {}
});
};
Geomarklet.run();
The Location Hierarchy
A successful Fire Eagle query returns an object called the ‘location hierarchy’. Depending on the level of detail shared, the index of a particular piece of information in the array will vary. The LocationDetail object maps the array indices of each level in the hierarchy to something comprehensible, whilst the index_offset variable is an adjustment based on the detail of the result returned.
The location hierarchy object looks like this, providing a granular breakdown of a location, in human consumable and machine-friendly forms.
""user"": {
""location_hierarchy"": [{
""level"": 0,
""level_name"": ""exact"",
""name"": ""707 19th St, San Francisco, CA"",
""normal_name"": ""94123"",
""geometry"": {
""type"": ""Point"",
""coordinates"": [ - 0.2347530752, 67.232323]
},
""label"": null,
""best_guess"": true,
""id"": ,
""located_at"": ""2008-12-18T00:49:58-08:00"",
""query"": ""q=707%2019th%20Street,%20Sf""
},
{
""level"": 1,
""level_name"": ""postal"",
""name"": ""San Francisco, CA 94114"",
""normal_name"": ""12345"",
""woeid"": ,
""place_id"": """",
""geometry"": {
""type"": ""Polygon"",
""coordinates"": [],
""bbox"": []
},
""label"": null,
""best_guess"": false,
""id"": 59358791,
""located_at"": ""2008-12-18T00:49:58-08:00""
},
{
""level"": 2,
""level_name"": ""neighborhood"",
""name"": ""The Mission, San Francisco, CA"",
""normal_name"": ""The Mission"",
""woeid"": 23512048,
""place_id"": ""Y12JWsKbApmnSQpbQg"",
""geometry"": {
""type"": ""Polygon"",
""coordinates"": [],
""bbox"": []
},
""label"": null,
""best_guess"": false,
""id"": 59358801,
""located_at"": ""2008-12-18T00:49:58-08:00""
},
}
In this case the first object has a level of 0, so the index_offset is also 0.
Prerequisites
To query Fire Eagle we call in some existing libraries to handle the OAuth layer and the Fire Eagle API call. Your bookmarklet will need to add the following scripts into the page:
The SHA1 encryption algorithm
The OAuth wrapper
An extension for the OAuth wrapper
The Fire Eagle wrapper itself
When the bookmarklet is first run, we’ll insert these scripts into the document. We’re also inserting a stylesheet to dress up the UI that will be generated.
If you want to follow along any of the more mundane parts of the bookmarklet, you can download the full source code.
Rendering
This bookmarklet can be extended to support any formatting of your location you like, but for sake of example I’m going to build three common formatters that you’ll find useful for common location scenarios: Sites which already ask for your location; and in publishing systems that accept tags or HTML mark-up.
All the rendering functions are items in a renderers object, so they can be iterated through easily, making it trivial to add new formatting functions as your find new use cases (just add another function to the object).
var renderers = {
geotag: function(user) {
if(LocationDetail.EXACT !== index_offset) {
return false;
}
else {
var coords =
user.location_hierarchy[LocationDetail.EXACT].geometry.coordinates;
return ""geo:lat="" + coords[0] + "", geo:lon="" + coords[1];
}
},
city: function(user) {
if(LocationDetail.CITY < index_offset) {
return false;
}
else {
return user.location_hierarchy[LocationDetail.CITY - index_offset].name;
}
}
You should always fail gracefully, and in line with catering to users who choose not to share their location precisely, always check that the location has been returned at the level you require. Geotags are expected to be precise, so if an exact location is unavailable, returning false will tell the rendering aspect of the bookmarklet to ignore the function altogether.
These first two are quite simple, geotag returns geo:lat=-0.2347530752, geo:lon=67.232323 and city returns San Francisco, CA.
This final renderer creates a chunk of HTML using the adr and geo microformats, using all available aspects of the location hierarchy, and can be used to geotag any content you write on your blog or in comments:
html: function(user) {
var geostring = '';
var adrstring = '';
var adr = [];
adr.push('
');
// city
if(LocationDetail.CITY >= index_offset) {
adr.push(
'\n '
+ user.location_hierarchy[LocationDetail.CITY-index_offset].normal_name
+ ' ,'
);
}
// county
if(LocationDetail.REGION >= index_offset) {
adr.push(
'\n '
+ user.location_hierarchy[LocationDetail.REGION-index_offset].normal_name
+ ' ,'
);
}
// locality
if(LocationDetail.STATE >= index_offset) {
adr.push(
'\n '
+ user.location_hierarchy[LocationDetail.STATE-index_offset].normal_name
+ ' ,'
);
}
// country
if(LocationDetail.COUNTRY >= index_offset) {
adr.push(
'\n '
+ user.location_hierarchy[LocationDetail.COUNTRY-index_offset].normal_name
+ ' '
);
}
// postal
if(LocationDetail.POSTAL >= index_offset) {
adr.push(
'\n '
+ user.location_hierarchy[LocationDetail.POSTAL-index_offset].normal_name
+ ' ,'
);
}
adr.push('\n
\n');
adrstring = adr.join('');
if(LocationDetail.EXACT === index_offset) {
var coords =
user.location_hierarchy[LocationDetail.EXACT].geometry.coordinates;
geostring = '
'
+'\n '
+ coords[0]
+ ' ;'
+ '\n '
+ coords[1]
+ ' \n
\n';
}
return (adrstring + geostring);
}
Here we check the availability of every level of location and build it into the adr and geo patterns as appropriate. Just as for the geotag function, if there’s no exact location the geo markup won’t be returned.
Finally, there’s a rendering method which creates a container for all this data, renders all the applicable location formats and then displays them in the page for a user to copy and paste. You can throw this together with DOM methods and some simple styling, or roll in some components from YUI or JQuery to handle drawing full featured overlays.
You can see this simple implementation for rendering in the full source code.
Make the call
With a framework in place to render Fire Eagle’s location hierarchy, the only thing that remains is to actually request your location. Having already authed through Amadeus earlier, that’s as simple as instantiating the Fire Eagle JavaScript wrapper and making a single function call. It’s a big deal that whilst a lot of new technologies like OAuth add some complexity and require new knowledge to work with, APIs like Fire Eagle are really very simple indeed.
return {
run: function() {
insert_prerequisites();
setTimeout(
function() {
var fe = new FireEagle(
Keys.consumer_key,
Keys.consumer_secret,
Keys.user_token,
Keys.user_secret
);
var script = document.createElement('script');
script.type = 'text/javascript';
script.src = fe.getUserUrl(
FireEagle.RESPONSE_FORMAT.json,
'Geomarklet.callback'
);
document.body.appendChild(script);
},
2000
);
},
callback: function(json) {
if(json.rsp && 'fail' == json.rsp.stat) {
alert('Error ' + json.rsp.code + "": "" + json.rsp.message);
}
else {
index_offset = json.user.location_hierarchy[0].level;
draw_selector(json);
}
}
};
We first insert the prerequisite scripts required for the Fire Eagle request to function, and to prevent trying to instantiate the FireEagle object before it’s been loaded over the wire, the remaining instantiation and request is wrapped inside a setTimeout delay.
We then create the request URL, referencing the Geomarklet.callback callback function and then append the script to the document body — allowing a cross-domain request.
The callback itself is quite simple. Check for the presence and value of rsp.status to test for errors, and display them as required. If the request is successful set the index_offset — to adjust for the granularity of the location hierarchy — and then pass the object to the renderer.
The result? When Geomarklet.run() is called, your location from Fire Eagle is read, and each renderer displayed on the page in an easily copy and pasteable form, ready to be used however you need.
Deploy
The final step is to convert this code into a long string for use as a bookmarklet. Easiest for Mac users is the JavaScript bundle in TextMate — choose Bundles: JavaScript: Copy as Bookmarklet to Clipboard. Then create a new ‘Get Location’ bookmark in your browser of choice and paste in.
Those without TextMate can shrink their code down into a single line by first running their code through the JSLint tool (to ensure the code is free from errors and has all the required semi-colons) and then use a find-and-replace tool to remove line breaks from your code (or even run your code through JSMin to shrink it down).
With the bookmarklet created and added to your bookmarks bar, you can now call up your location on any page at all. Get a feel for a web where your location is just another reliable part of the browsing experience.
Where next?
So, the Geomarklet you’ve been guided through is a pretty simple premise and pretty simple output. But from this base you can start to extend: Add code that will insert each of the location renderings directly into form fields, perhaps, or how about site-specific handlers to add your location tags into the correct form field in Wordpress or Tumblr? Paste in your current location to Google Maps? Or Flickr?
Geomarklet gives you a base to start experimenting with location on your own pages and the sites you browse daily.
The introduction of consumer accessible geo to the web is an adventure of discovery; not so much discovering new locations, but discovering location itself.",2008,Ben Ward,benward,2008-12-21T00:00:00+00:00,https://24ways.org/2008/geotag-everywhere-with-fire-eagle/,code
118,Ghosts On The Internet,"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
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.
about 3 hours ago
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.",2008,Gavin Bell,gavinbell,2008-12-20T00:00:00+00:00,https://24ways.org/2008/ghosts-on-the-internet/,ux
100,Moo'y Christmas,"A note from the editors: Moo has changed their API since this article was written.
As the web matures, it is less and less just about the virtual world. It is becoming entangled with our world and it is harder to tell what is virtual and what is real. There are several companies who are blurring this line and make the virtual just an extension of the physical. Moo is one such company.
Moo offers simple print on demand services. You can print business cards, moo mini cards, stickers, postcards and more. They give you the ability to upload your images, customize them, then have them sent to your door. Many companies allow this sort of digital to physical interaction, but Moo has taken it one step further and has built an API.
Printable stocking stuffers
The Moo API consists of a simple XML file that is sent to their servers. It describes all the information needed to dynamically assemble and print your object. This is very helpful, not just for when you want to print your own stickers, but when you want to offer them to your customers, friends, organization or community with no hassle. Moo handles the check-out and shipping, all you need to do is what you do best, create!
Now using an API sounds complicated, but it is actually very easy. I am going to walk you through the options so you can easily be printing in no time.
Before you can begin sending data to the Moo API, you need to register and get an API key. This is important, because it allows Moo to track usage and to credit you. To register, visit http://www.moo.com/api/ and click “Request an API key”.
In the following examples, I will use {YOUR API KEY HERE} as a place holder, replace that with your API key and everything will work fine.
First thing you need to do is to create an XML file to describe the check-out basket. Open any text-editor and start with some XML basics. Don’t worry, this is pretty simple and Moo gives you a few tools to check your XML for errors before you order.
0.7
{YOUR API KEY HERE}
build
http://www.example.com/return.html
http://www.example.com/fail.html
...
Much like HTML’s and , Moo has created
and elements all wrapped in a element.
The element contains a few pieces of information that is the same across all the API calls. The element describes which version of the API is being used. This is more important for Moo than for you, so just stick with “0.7” for now.
The allows Moo to track sales, referrers and credit your account.
The element can only take “build” so that is pretty straight forward. The and elements are URLs. These are optional and are the URLs the customer is redirected to if there is an error, or when the check out process is complete. This allows for some basic branding and a custom “thank you” page which is under your control. That’s it for the element, pretty easy so far!
Next up is the element. What goes inside here describes what is to be printed. There are two possible elements, we can put