I write about things that interest me, my clients and others in my industry.

Jun
21

Clever Design Trick Spotted

ThinkGeek.com, the online store for all things geek, has a very clever and subtle styling trick being used that I thought was worth pointing out to those who haven’t seen it. The black & grey robot/UFO background, fixed in place while you scroll, transforms as you hit the very bottom of a page. The grey fades to black and a zombie design appears out of nothing.

It’s clever masking trick that I haven’t seen used anywhere else before. One image has both the black robot design and the grey zombie design and, because it’s layered on top of a background that fades from grey to black at the bottom, only the black design is visible on grey and only the grey design is visible on black. Above, you can see the two in transition. Well done, ThinkGeek designers.

Jun
18

WordPress 3.0 Released

WordPress has announced a new major release of its increasingly useful blogging and CMS platform. “Thelonious”, as it will never actually be referred to, has a great number of improvements to the theme engine (to clients, this means you’ll have even more control of your site and its structure) and allows for custom post types, bringing WordPress into the realm of true Content Management Systems.

Find out more at WordPress.org or watch the video below.

May
07

Website Design & The Fold

I’ve been asked a number of times by clients to make certain things appear “above the fold” and I thought that I should clear up a number of misconceptions about the term. The idea of the fold comes from the newspaper industry, where folded newspapers put their most interesting content above the fold in order to grab the attention of passers-by. While the same concept arguably still exists in the web industry, there are a number of key differences.

The Fold Varies

An analysis of this site

Your fold is not the same as mine. There are a number of things that contribute to what content a user can and can’t see on your website without scrolling, namely: the size of their monitor, the size of the window they have open, their video card settings and their web browser. So while content could only be either above or below the fold on a newspaper, content on websites is much more varied in its visibility.

We design for people with basic setups — basic, but not ancient. It’s incredibly important that all users are able to see your content, that’s why any good designer will make sure your site looks just as good in the ten-year-old Internet Explorer 6 as it does in a modern browser. At the same time, your visitors shouldn’t suffer because they have larger screens, and so a middle ground needs to be found.

Take a look. This handy tool will show you a general percentage of how many people will see the content of a webpage without scrolling. Here’s an example using www.paulpritchard.ca.

People Scroll

If they’re there, they will look around. You’re not trying to convince someone walking by to purchase your newspaper from a newsstand, if someone has made it to your website then they will take the time to look around. Hell, I somehow convinced you to scroll down here to read this, didn’t I?

It’s as if users arrive at a page with a certain amount of fuel in their tanks. As they “drive” down the page, they use up gas, and sooner or later they run dry. The amount of gas in the tank will vary, depending on each user’s inherent motivation and interest in each page’s specific topic. Also, the “gasoline” might evaporate or be topped up if content down the page is less or more relevant than the user expected.

Don’t drain the tank. This analogy (from the article referenced below) reinforces the importance of really knowing your audience and what motivates them. If you know all the different scenarios of why they are there, then you will know what will keep them reading, above or below the fold. This is why websites that target everyone can overwhelm users, drain the tank, and end up targeting no one.

Some numbers. Jakob Nielsen wrote an excellent article about the fold and conducted a study that tracked the eyes of people browsing websites and measured the amount of time spent at different levels. The result? Users spent 80% of their time looking above the fold (800px in this study) and 20% below.

Be Selective

bad idea

Not a good idea.

Everything is important, but what’s most important? You’ve taken the time to create some great content for your website but when you’re considering where it should be featured, always think about where it stands in relation to your other content. Should you be risking drawing attention away from the “Buy Now” button just to get your content featured?

Designer solutions. Design and layout are the tools that control where a visitor’s attention is drawn and a good designer will always create designs that reflect how important the different pieces of your content are. If the designer knows how important something should be, they’ll know how to get it the attention it deserves.

Mar
18

A Relocation and a Redesign

The good ol' big smoke

An opportunity to move back to my home city of Toronto came up recently and, though it meant I would move away from the job security and the great minds and times at Industrial Media, I jumped at it as an opportunity to further pursue my freelance career.

A little over a month and a half in, I’m proud to announce the launch of a completely overhauled website for Vrtucar, a popular car-sharing company in Ottawa. As a member and frequent user of their cars, I brought an experienced viewpoint to the table and we worked together to tackle the issues I knew I and others experienced in the previous website. My thanks to everyone for the great feedback we’ve received on the website.

There’s also an exciting but top-secret community-based site in the works that really uses social media to its full potential and not just as the space-filler it can become as more and more ask for the buzzword.

And lastly, there’s the revamp of this website, a few years overdue but definitely worth the wait. While my blog previously focused strictly on web developer-related issues, I will be turning the focus to more design- and interactive-related topics. Enjoy!

Jun
16

Drupal Tweaks

It’s time to share some Drupal code because after all, sharing is caring. The following are hurdles that had to be overcome to get the user experience we wanted out of our latest Drupal site, they’re are basic enough but took a good number of hours digging through posts and comments on the Drupal forums to figure out. All code is for Drupal 6.x only. Major modules used: CCK, Views, Panels.

I was hesitant at first to go the route of creating a custom module, but highly recommend it now after discovering how simple it is. Of course It also makes it simpler to break Drupal, but let’s not worry about that. Some of these techniques can be applied in either a custom module or to your theme, this is just what worked for us with the timelines we had:

#1 Doing something after custom content creation (redirect)

For a front-end video, photo and blog sharing section (all of which were CCK custom content types), we wanted to redirect users to a page thanking them for their contribution. Module-based code [mycustom.module].

function mycustom_form_alter(&$form, $form_state, $form_id)
{
$form['buttons']['#weight'] = 100;    // Stop bug that causes form buttons to appear in the middle of all forms

// If form is for the creation of one of our custom content types, add a handler to submission
if ($form_id == 'photo_node_form' || $form_id == 'video_node_form')
$form['buttons']['submit']['#submit'][] = 'mycustom_redirect_handler';
}

function mycustom_redirect_handler($form, &$form_state)
{
if ($form_state['nid'])
{
// Load our node from the $form_state
$node = node_load(array('nid' => $form_state['nid']));
// Alter $form_state's redirect to point to a different page, depending on node type
switch($node->type)
{
case 'photo':
$form_state['redirect'] = "photo_add/thanks";
break;
case 'video':
$form_state['redirect'] = "video_add/thanks";
break;
}
}
}

#2 Doing something during custom content creation (run an external script referencing $node)

In this instance, we needed to run our own custom PHP script while Drupal is saving a custom node so that we could pass values entered into that node to our script. Drupal’s Node API allowed us to do this. Module-based code [mycustom.module].

function mycustom_nodeapi(&$node, $op, $teaser = NULL, $page = NULL)
{
switch ($op)
{
case 'insert':
// When inserting a custom content type of 'video'
if ($node->type == 'video')
{
// If the user has checked off the custom field 'field_newsletter'
if ($node->field_newsletter[0]['value'] == '1')
{
$node_title = $node->title;
$node_email = $node->field_email[0]['value'];
include("crm.php");			// Include our script with the crm() function
crm($node_title, $node_email);	// Run it with our node values
}
}
break;
}
}

#3 Doing something during user sign-up (create custom content belonging to $user)

Because we required that users post their photos to a personal gallery of their choice, we wanted to create a default gallery for every user as soon as they register, eliminating the needless step of creating their first gallery if they weren’t interested in categorizing everything. We did this through node_save (drupal_execute may also be used in similar situations but no author will be given to the content). Module-based code [mycustom.module].

function mycustom_user($op, &$edit, &$account, $category=NULL)
{
switch ($op)
{
case 'insert':                            // When performing 'insert' of a user
$old_user = $user;                    // Preserve current $user
$user = user_load($edit['uid']);    // Load newly registered $user

// Create $node
$node = array(
'uid' => $user->uid,            // Make new user the owner
'name' => (isset($user->name) ? $user->name : ''),
'type' => 'photo_album',        // Use custom content type of 'photo_album'
'language' => ''
);

// Prepare $node
if (!function_exists("node_object_prepare"))
include_once(drupal_get_path('module', 'node') . '/node.pages.inc');
$node = (object)$node;
node_object_prepare($node);

// Give $node a title of 'Personal Photos'
$node->title = 'Personal Photos';
$node->body = '';
$node->name = $user->name;
$node->uid = $user->uid;

// Create the $node
node_save($node);

// Revert $user
$user = $old_user;
break;
}
}

#4 Changing layout and values on custom content type and comment forms

We found that the forms that Drupal spits out for creating new nodes of your custom content type are generally way too cluttered to be intuitive to your average user so our goal was to dumb it down and hide a lot of the extra things Drupal adds. There’s a lot of trial and error involved in finding out exactly what value to change (I found print_r_tree($form) effective) but it becomes more obvious after time. Theme-based code [theme.php].


// Tell our theme to run custom functions for displaying the comment, 'photo' and 'video' forms
function mytheme_theme()
{
return array(
'comment_form' => array('arguments' => array('form' => NULL)),
'photo_node_form' => array('arguments' => array('form' => NULL))
);
}

// Alter $form for commenting, then render it
function mytheme_comment_form($form)
{
unset($form['preview']);                                            // Remove Preview button
unset($form['comment_filter']['format']['format']['guidelines']);   // Remove extra instructions
unset($form['comment_filter']['format'][2]);                        // ...
$form['submit']['#value'] = "Post Comment";                         // Change submit button to say 'Post Comment'
return drupal_render($form);                                        // Return rendered form
}

// Alter $form for 'photo', then render it
function mytheme_photo_node_form($form)
{
unset($form['buttons']['preview']);                                 // Remove Preview button
unset($form['body_field']['teaser_include']);                       // Remove teaser/summary view
unset($form['body_field']['format']['format']['guidelines']);       // Remove extra instructions
unset($form['body_field']['format'][2]);                            // ...
$form['body_field']['body']['#rows'] = 5;                           // Change size of Body field
$form['buttons']['submit']['#value'] = "Post Photo";                // Change submit button to say 'Post Photo'
return drupal_render($form);                                        // Return rendered form
}