Log on
Main page Graphics Photography Audio Video Tools Web Design Documents Space & Astro Amiga Funny Surreal Gallery Links & Contact

Usability & Software Development

Joachims' guide to enhancing the user experience

Many software developers seem to forget what a normal user really likes. Also being all caught up in complicated programming issues, it's easy to drift away from a design that is easy for normal people to understand. As a result, there's a lot of software out there, that is rather awkward and tricky to use for normal people. I've written the following set of rules, to help you overcome at least some of these issues. They're completely based on my own personal views on how i like software and web pages to be. If you're a developer, please at least consider the following things, before calling me a fruitcake...

General programming:

  • Remember to close files

    after loading or saving them. There's absolutely no reason for keeping a file open anymore, once it's been loaded into your programs memory. It won't disappear from the memory, just because it's not on the disk anymore. And sometimes people actually do load a file into your app, and then wish to remove it. So remember using fclose() as soon as you've done reading/writing the file.

  • Reading/writing stuff on exit.

    If your application has to write out a lot of stuff on exit, perhaps you should have done this as soon as you had a chance. This might not always be the possible, but I do see two good reasons to consider writing settings or cleaning up temporary files on the disk as soon as possible, instead of waiting for program exit:
    1. Waiting for a program to exit seems like a pointless waste of time to most users, as they do not understand why this should take time.
    2. Theoretically your application could crash before Exit is reached. Loosing unsaved settings can be quite annoying.
    3. Temporary files would be left on the disk, forever taking up space.
    4. Killing your app. the hard way ("End Process" or "kill -9") would leave less gunk.
    My suggestion is: Write down settings at once. A typical "Preferences" or "Settings" dialog could have these options: [ Save ] [ Use ] [ Cancel ].

  • Check your CPU usage.

    Unless an application is actively calculating or processing data, it should not occupy an entire CPU. Your application should never occupy the CPU more than a few percent while idle or waiting for input.

  • Release unnused memory.

    Well this should go without saying, i guess, but then again even large companies forget this. For example Photoshop does not deallocate its memory until you exit the entire application. This is wrong. It should deallocate as soon as you close the image (because at this point it is impossible to regain that data anyway.)

  • Error messages

    are very important. Someone unfamiliar with your application will inevitably use your application in a wrong way, thus invoking error situations. Each error message must be as specific to it's problem as possible, and should contain two things:
    1. Description of what the error is.
    2. Help to guide the user towards a proper solution of the problem
    Make sure to write the error message in a way that even unexperienced users will have a chance to understand. It's better to explain too much than too little.

  • Avoid the registry.

    (Windows specific) Most users have no clue how the registry works. It may be, that Microsoft is trying to encourage using the registry, but please consider the following observations:

    1. The larger the registry gets, the slower will Windows' performance be.

    2. Copying your applications' settings from one computer to another becomes impossible for a normal person.

    3. Re-installing Windows will erase the registry - and the settings.

    4. If your program stores information in a place that the user cannot see, it gives a bad impression. People don't like things happening behind their backs - especially not on their own computer.

    This is why i strongly recommend storing stuff in files, instead of the registry. If you need to store some settings that have to be globally accessible by several applications, put them in the program directory. This way you can also move around the program on e.g. a USB stick. User-specific settings should (officially) go into the "Application Data" folder. You could use the registry to store the location of said settings file, but I don't recommend putting the settings themselves or anything else there. You can find the Application Data folder by linking to shell32.lib and then do:
    #include <shlobj.h>
    char path[MAX_PATH]; SHGetSpecialFolderPath(NULL, path, CSIDL_APPDATA, false);
  • Temp files

    should go into the system temp folder, "temporary" files meaning: Files that are not crucial, and that can be deleted without any severe consequence other than performance. This could be cache files, auto generated thumbnails etc. Every modern operating system has an easy way to tell you where the temp folder is.

    On Windows and DOS it's the environment variable called TMP, on OS-X, Linux and FreeBSD the environment variable is called TMPDIR, on the amiga you use the device T: and in .NET you simply call Path.GetTempPath(). The reason it's important to use the system temp folder, and not some random folder you invent yourself, is that it becomes quite difficult to clean up the harddrive if every single program puts temporary files in a different folder. It also helps keeping important files like user settings separated from temporary files that are okay to delete.

  • Consider saving to a temp file instead of over-writing

    when the user chooses Save (usually Ctrl-S). If your save process is lengthy and/or complicated, a crash or power-outage could occur while saving. This is a thing most users fear a lot.

    If this seems to be an issue, the trick is to save to a different file (on the same device, not in the system temp folder, so this is an exception to the above), then after having written the entire file, you delete the old file, and rename the new file into the filename of the old one. This will give you a much more fail-safe save operation.

    The drawbacks are that you use more disk space while saving, and you may loose the original permissions on some filesystems.

  • Be careful if using keyboard hooks or "global hotkeys".

    I've seen several programs that stop doing what they're doing, if you press Esc in another application. This of course is totally wrong. First of all, you should really avoid using hooks, but if you're really forced into doing this, always test if your own window is actually active, before reacting on this key-press.

  • Installers.

    There should always be a way to manually install your application. Most Windows-programs today just come as a "setup.exe" or similar file. If this one does not work, the user is simply lost. Especially if you're using InstallShield, you should provide an alternative setup method. This could be done by e.g. making an installer-less version public on your website, along with a simple text document, that explains where to put the files, and how to register any dll's if necessary.

    In Windows, make sure to install into the directory suggested by the registry. Please don't create a directory within a directory. One directory is enough. Also, don't use spaces or version numbers in the install directory name.

  • Filename extensions

    as known from DOS and Windows should not be used to identify the filetype. Trusting the filename to truely reflect the contents of the file, can lead to an increased number of error scenarios. Always look at the file header if possible. Using other techniques as mime types etc. is to be considered a less reliable solution than trusting the file header, but still more reliable than trusting the filename.

  • Use UTF-8 where possible.

    As long as you write plain english (or programming languages or similar), utf-8 is identical to the Latin-1 encoding that it is supposed to replace. When using international characters you can combine german, swedish, spanish, korean and thai without any problems. For web pages utf-8 is the obvious choice, no matter the language.

    UTF-16 seems to me like an unnecessary alternative, as it potentially introduces big/little endian issues, and in most cases it takes up twice as much space to do the same thing. It also lacks the backwards compatibility that utf-8 offers to some degree.

    Iso-8859-1 (or "Latin-1") is still the most common encoding, often used by older software and systems, which is why these typically only support a limited range of languages. This is a bad choice in case you should suddenly need to implement support for foreign languages, but it has the advantage that every character is always 1 byte wide, which makes it very fast and easy to work with.

  • Carriage Return (13) really should be obsolete by now.

    Today it is only being kept alive by one operating system, Windows, as well as a few web standards that must have been designed by DOS/Windows users. With the change to OS X, Apple computers no longer require the CR character, which is invalid or at least unnecessary on most other systems all the way back to the 70's, and not even necessary on Windows (with notepad.exe as the odd exception.)

    So in other words, Carriage Return (13) should be and will be as obsolete as the mechanical typewriter it comes from. One byte (ascii character 10, LF) should be enough to indicate a line break, so I suggest always outputting this kind of text files whenever compatibility with notepad.exe is not a requirement. Even when creating software for Windows, I recommend testing that all text input is fully capable of handling text without CR characters.

    As a result of this, lots of text conversions are suddenly no longer necessary. Thus, we can get rid of the potentially damaging "auto" and "text" conversion modes in protocols like FTP and NFS. For this reason I recommend these to be "binary" by default in FTP, NFS and such clients, leaving file any conversion to the text editor if needed.

  • New file formats

    that you might invent must always have a unique header at a fixed byte position within the first 100 bytes you can use to identify the file with. This ensures that even if the filename, the extension and mimetype information are lost, it is still possible to quickly identify the filetype from it's contents.

    Your file format must have a defined byte order. Despite the currently wide-spread use of Intel CPUs who are little endian (or "Intel byte order"), it is recommended to use big endian because most platforms offer calls to read and write TCP/IP which uses this byte order. In C you can use the ntohl( ) call. More on this topic here.

    It is also a good idea to use a chunk-based format such as IFF because this often improves both forwards and backwards compatibility. The IFF format even offers a standardized way to indicate the file format (byte 9 to 12). Microsoft's RIFF format is closely related to IFF, and is also recommended for files that are not expected to become "large" (approaching IFF and RIFF's max size of 4 GB).

    Two other important concerns when inventing a file format are: 1) The simplicity of the parser, and 2) security and safety when reading foreign files. Both these principles will most likely be violated if code is stored in the file format, so try as much as possible to avoid storing code of any kind in a data file. I am even tempted to propose a kind of stamp-of-approval for file formats that do not contain code, and label them "pure" file formats, to spread awareness of this issue.

  • Project files

    should be both forward and backwards compatible if possible. This can be achived by using a chunk based file format such as IFF. When adding new features, you can add new chunk names for the settings that relate to these settings.

    When reading back project, setup and configuration files make sure to check the validity of the incoming data. There could be errors caused by disk errors, 3rd party software or other unpreditable causes. The best solution is to skip only the invalid parts, allowing the user to use the remaining parts. The worst solution is to reject the entire file or crash.

  • Explaining values.

    When documenting a long list of possible user-adjustable values, for example when documenting the inputs of a command-line tool, a config file or an input dialog, you must remember to somehow specify all the following for each single parameter:
    • Measurement of each value (is it kilobytes, miles, watts or what?)
    • Minimum value (and if there is no minimum, explain that)
    • Maximum value (and if there is no maximum, explain that)
    • Default value if the user doesn't specify it
    • If any: Interaction with other adjustable values
    • Optional: Recommended sane value or range of values
    It is also recommended to show examples of common use-cases, so that the user can see the syntax in action.

User interface:

  • User-interfaces must be time independant.

    Making a button with a special function that is activated after e.g. holding down a certain button for x milliseconds will simply slow down any experienced user. If you feel that it's necessary to introduce a delay in your GUI code, it's a clear indication that you've designed the GUI in a bad way. Consider using combinations of hotkeys or even adding new buttons instead.

  • Be careful not to steal focus.

    Being interrupted while typing is quite annoying and also risky, as the user might be accidentally activate unwanted features if inside the wrong window.

    This becomes more difficult on operating systems and window managers that have window activation linked with the window order (as in, the active window is always brought to front, as seen on Windows, Mac and many Linux/Unix window managers.) On these systems you should try not to suddenly open and thus activate windows when the user does not expect it. This means you have to know when the user might expect new windows to open. A good rule of thumb is as follows:

    It is okay to open new windows up to appx. one second after receiving user input (key presses or mouse clicks.) Later than this, and you have to either be able to pop up a window that is not in focus, or think of some other solution that does not involve hijacking window focus.

    Also, never ever call the API function that steals focus. What should be in focus is a entirely user decision, and not a developer decision.

  • Keyboard is faster than mouse.

    When learning to use a new program, users typically use the mouse to visually maneuver around. Beginners generally navigate visually, thus using the mouse more than the keyboard. Once the user starts getting more familiar with the computer and it's applications, he learns and remembers the way the computer behaves, reducing the amount of times he has to double check what's going on on the screen. This is why the use of the keyboard typically gradually replaces the use of the mouse over time.

    We must understand and distinguish between two basic concepts in gui design: User-friendlyness and ergonomics. User-friendlyness is largely a visual and logic thing. This is what makes a program easy to use the first time you use it. Careful use of visual clues and properly designed graphics can make even complicated tasks easier to comprehend at first sight. To study the user-friendlyness, I suggest presenting your application to beginners, watching closely what causes them trouble.

    Ergonomics, however, decide how fast you can perform the intended action, once you know the application by heart. Keyboard shortcuts and a reduction of the amount of times you have to click the mouse or keybord to perform a certain task, are some of the most important ways to achieve good ergonomics. To study the ergonomic aspects of your application, I suggest working closely together with experienced users to make the relevant functionality more accessible.

  • Absolute hotkeys are faster than relative hotkeys.

    A relative hotkey is a key that performs an action relative to the current state or position. A good example of a relative hotkey is a cursor key or Alt-Tab in windows. You have to know where you presently are, to know where you will be after pressing the key in question.

    An absolute hotkey always brings you to a certain state or position. That way you don't have to remember where you currently are, and you also don't have to look at the screen to double-check the effect of the hotkey pressed.

    So let's say your application has several screens. In that case it is better to assign one hotkey to each screen, than to have people "tabbing" through the screens until the users gets to the desired page. Whenever possible, make sure a certain screen always ends up on the same hotkey, so that the user can learn it by heart. This will make working with your program a lot faster.

  • Context dependant hotkeys vs. global hotkeys

    is something you should consider as well. Certain gui elements such as sliders and radio buttons tend to bind to certain frequently used keys like the cursor keys, space and enter. In some cases the important parts of the keyboard changes behaviour depending on the last item touched by the mouse. This often forces the user into using the mouse all the time, which is a bad thing because a the mouse is generally slower than the keyboard.help In most cases it is desirable to let the keyboard work the same way, no matter what button/slider the mouse activated the last time. You should carefully consider when to make exceptions.

  • Do not assume people are wrong.

    Try following the user's input first, and after that you may try helping them with fuzzy logic (for example, if you want to come up with suggestions on what the user may have been trying to achieve.) If you start second guessing people with fuzzy logic first, before even trying to do what the user asked for, it is often considered arrogant and it will leave a bad impression. This brings me to the next point...

  • Do not change the contents of an input field while the user is editing.

    You cannot safely predict how a user inputs text, or in what order. You also cannot know when he is done typing. Because of this you should never try to alter, suggest or auto-complete the contents until the user has somehow stated that he wants this to happen. (For .NET developers this can be explained simply as: Always use AutoCompleteMode "Suggest" for normal free text input fields rather than "Append" or "AppendSuggest".) You can see an example of user reactions to forced auto-completion here

    The same rule applies for input validation. Do not insert new missing characters or change characters until the user has indicated that he is done editing. Simple filtering away of single illegal keystrokes is okay though, as long as the filtering is clearly understandable (e.g. not reacting to the letter "G" while entering a numeric value.)

  • Circular searching aka. "wrap":

    When searching for a specific word or phrase in a piece of text, the eye is busy looking at the various search results, while repeatedly hitting the "find next" key. Do not expect people to pick up any visual clues during this process. Displaying status messages, warnings and such will often go unnoticed. If the text is longer than the visible screen area, the page will typically scroll to make the search result visible. And if the text is not known to the user, it will be hard to tell where in the text we are, making people pay even less attention to any additional visual information.

    This causes a problem for the "wrapping" kind of search, as we want to let people know they have reached the end. The only proper way to make sure people really notice, is to use a non visual clue. This could be a beep (if we are certain audio is available) or we could simply require the user to press a different key than the one used for "find next" in order to allow wrapping to occur. Displaying a pop-up message is also an option, but this pop-up must not react to the key used for "find next".

  • Avoid frozen windows.

    When a dialog box or a file requester or similar windows are open, the main program should still be responding to the user moving and resizing any window he desires. The user should also be allowed to have several dialogs open at once, so that he can work with several parts of the program at once. And then there's the problem with getting to the stuff underneath such a frozen window. E.g. if you maximize the program, and then open a file requester, the entire desktop will typically be covered and unaccessible! This is really annoying. Being able to at least un-maximize, move and resize the locked window would be a big improvement.

    This is actually a basic design flaw in Microsoft Windows - which is probably why a lot of developers don't feel obliged to addressing this problem. But considering how reluctant Microsoft seems in changing this kind of stuff, i think that the programmer would be a real gentleman, trying to compensate for such oddities.

    Avoiding a locked main window may of course be rather problematic in some cases - E.g. with file requesters. What if the user chooses to save the project, but removes the project while the Save requester is still present? Suddenly there won't be anything to save. This is a severe case, because the file requester is "out of reach" for the programmer, and in this specific case it may be too time-consuming coming up with a proper solution. So in this case i can almost accept the main window being locked. But the perfect solution in my opinion, would be ghosting all the functions in the main window, but still allowing the user to move and resize it.

  • MDI = Multiple Document Interface.

    (Windows specific) I just can't see the advantage of having windows caught inside one big window. It seems to me like a big waste of desktop space. If you really think this is a good idea, at least make sure that people can still completely disable this behaviour, because only a few people actually like this, as far as i've experienced.

  • Button order.

    Whenever your program presents the user with a choice of action or no action, you should place the buttons in the following order:
    • "YES" before "NO"
    • "OK" before "CANCEL"
    • "OPEN" before "CANCEL"
    • "ACCEPT" before "DENY"
    • "DO IT" before "DON'T", etc.
    That means that "YES" must be placed left of, or above "NO" in countries that read left-to-right. Notice that if you right-align the buttons inside the window, this would place "Cancel" and such in the corner of the window, thus emphasizing this. Typically you want to emphasize the "OK" choice instead, which is why you should not right-aligning the buttons in the window.

    The only exceptions to this rule are:

    • Apple computers.
    • The Gnome window manager.
    • Possibly languages that read right to left, e.g. Arabic (unconfirmed)
    • Wizards where you press "NEXT" a lot of times, to give an impression of being pages in a book. These wizards must be clearly marked as being a set of pages, and not just a matter of Action / No action.

    Generally applications should at respect what the operating system / window manager suggests. This means that programs running under Windows, KDE, Amiga, Irix and anything else not in the above list, should use the left-to-right button order and placement.

    More examples or discussion...

  • Filtered file requesters.

    (Windows specific) Many programmers choose to let their file requesters show only files with a certain extention. In my opinion this behaviour should be optional, or at least something you could permanently change in Preferences.

    Hiding stuff from the user can be confusing, because people might believe that their other files (of other file types) have disappeared! If you don't know what i mean by "hidden files", try starting Notepad, then choose Open, then type * in the File Name field, and press return. Now you will see all file types, and not just *.txt files.

  • Don't waste screen space.

    People often run out of space on their desktop. Please try to be conservative about how much desktop space you occupy. Does your buttons have to be this large? Test how small your application can be configured to be. Now of course visually impaired persons will like larger letters, but they usually already use a low screen resolution, in which case using too much space for window borders etc. is even worse.

    The important thing to judge, is how much of the area your application occupies serves a functional purpose, and how much is there for lesser important or design reasons. Calculate the percentage. If more than 20-30% of the screen area is just there for looks, you really need to change your design.

    This is especially important for windows that are typially open for a long period of time, like instant messengers, browsers, status read-outs etc.

  • Custom GUIs

    are more often an element of confusion than a benefit to the user. When running inside a certain OS, they expect all windows and GUI elements to behave the same way across applications, unless there's an obvious reason for them to be special. Weird windows decorations can be sweet, but often the user has selected his favorite set of colors and window decorations (themes etc.)

    A custom GUI often interacts badly with such customizations, and if you decide to implement such, make sure there's an option to turn it off.

  • Round knobs

    on physical gadgets are nice. You can adjust them without even looking, which is a good thing. On a computer screen they are pretty and they might save some space, but you never know how to operate them, and you have to look at the screen and figure out the connection between mouse moves and what actually happens, to figure out how they work. This requires quite some attention from the user, which is bad because he probably already has enough things on his mind.

    I suggest avoiding turning knobs on computer screens as far as possible. The best solution is something you can operate without looking at the GUI itself. A few examples why:
    • When adjusting an audio plugin, i like to close my eyes to concentrate on the sound while i adjust a certain value.
    • When adjusting a visual parameter like contrast/brightness i want to look at the image being adjusted, rather than having to concentrate on the GUI.
    Some good alternatives are horizontal sliders, vertical sliders, number input fields, supporting external hardware game/midi controllers or a combination of these.

  • Mouse acceleration

    means that the mouse gearing changes depending on how fast you move the mouse. When disabled, 1 inch on the table always corresponds to a certain distance on the screen. The human brain can quickly figure out this ratio, which means you'll be able to predict distances.

    With acceleration enabled, 1 inch on the table does not correspond to a certain distance on the screen. If you move the mouse slowly a few inches left, then move it quickly back to where it came from, you'll see that the mouse pointer does not return to the original position, as it would if acceleration was disabled. This makes predicting distances on the screen more complicated for the brain. I have conducted an experiment on eight users unfamiliar with using a mouse, and observed that using an accelerated mouse is more difficult to beginners.

    The advantage of using acceleration is that you can cover a large screen area with less hand-movement. Also using a mouse with too low a resolution (dpi) is less problematic.

    The peculiar thing is that on most operating systems (Windows, Mac and X), mouse acceleration is enabled by default. On OS-X you even need odd command line statements in order to disable acceleration.

    Conclusion: Mouse acceleration should be disabled by default. Advanced users who need it, will enable it themselves.

  • Key repeat acceleration

    means a kind of key repeat where the speed gradually increases the longer you hold the button or turn the knob. It is often used as a method to navigate very long lists or to change values. Unfortunately, this method makes it almost impossible for the brain to predict when to release the button in order to stop at the desired position. If you feel you need to implement this feature, you should either come up with a better way to navigate such long lists or - even better - somehow divide the list into smaller lists that can be navigated using a normal fixed keyrepeat rate. Presenting a too long list is bad gui design to begin with.

  • Sorting alphabetically

    should always be case insensitive when presented to the user. Most people expect "A" and "a" to be the same letter, because they do not understand the concept of ascii character values. This might seem obvious but lots of software still sorts upper- and lowercase seperately, especially on Unix.

  • Progress indicators

    have two purposes in life: The most important one is to tell the user how much time remains. This is best achieved by displaying how far we are from the end of the process going on. I suggest either displaying graphics that have a visible end, or counting to a specific number - one that the user is expected to know. This could be either counting down to 0 or counting from 0% to 100% (remember the % sign, so that people know we're talking about percent.)

    The secondary purpose is to indicate that the software is not frozen. This is optional, but can easily be achieved by animating any part of the progress indicator. Using a seperate thread for such an animation might perform better, but it might also create a false impression of everything being okay, despite the progress being halted for unexpected reasons. This would be like lying to the user, which is never acceptable.

    A progress indicator should be displayed if the user initiates an action that takes more than 1-2 seconds to complete before anything happens.

  • Greyed out

    (or "ghosted") buttons and checkboxes should be used with caution. It should always be understandable to an inexperienced user, why parts of the userinterface is greyed out. You might want to write some text next to the greyed out items that explain why those gui items are not selectable, so that the user understands the situation.

  • Recommended standard hot-keys:

    Please try to conform to the following unwritten "standard" as much as possible. This set of hotkeys is an attempt to gather all hotkeys that seem to be common across various operating systems. "Qual" means the standard qualifier key which is the Ctrl key on Windows and Linux/Unix, the Apple or ⌘ Command key on a Mac, the Amiga key on Amiga etc. I generally think one should conform to cross-platform conventions, which is why I suggest Ctrl-Q and not Alt-F4 etc.

    Hotkey Alternative What it does Applies to
    Brings you out of stuff or closes dialogs, message windows and windows that do not contain data entered by the user. For OK/Cancel dialogs Esc maps to Cancel.
    Open file
    Save file
    Select all
    Find / Search Text
    Search / Replace Text editing
    Qual-Z Qual-U Undo
    Qual-Y Qual-Shift-Z Redo
    Print Printable stuff
    Create new file/project
    Quit application (ask if unsaved data)
    Close current file/project (ask if unsaved data)

  • Keep undo buffer after saving

    Some applications purge their undo buffers when you save. This is highly unlogic to the user, and also quite unpratical for when you wanna make a change, save and test, and then undo back, if the desired output wasn't good enough.
See also Jef Raskin's 5 design rules for an interesting set of rules.

Games design:

  • Game controls

    are crucial to the user experience. When constructing a game you often have to adjust the difficulty of the game. Doing so by decreasing the quality of the input controls will make the game annoying to play, so never sacrifice controllability. It is better to adjust other parameters (there are plenty of ways to make a game more difficult).

Web design:

  • Proper use of OnMouseOver.

    Holding the mouse over a certain item is most likely not an indication of the user wanting to perform an action! It is ok to use this for highlighting stuff, making sounds and all these kinds of design related things. But never activate any actual functions or features or make too large changes to the graphics, before the user has actually clicked a mousebutton.

    It can be argued that games and interactive art-related pages could be excused from this rule, when the mouse is used for placing or navigating views or objects, or in similar situations where you are creating some kind of game-like interactive environment.

  • Warn people before going into full-screen.

    Javascript allows you to take over the entire screen area. This can be very nice for certain art pages and galleries etc. But taking over a persons entire screen area, should never happen without the users' prior concent. That is why you must always warn the user that the next step will go into full-screen. My personal reaction to pages that just goes directly into fullscreen, is usually a very quick hit at the Exit button. Most people have tried accidentally tried going into one of those aggressive and malicious web pages, that wish to take over your entire computer. Don't be like them. Be polite. Warn people.

  • If you define the foreground color, you must also define the background color.

    If you define the foreground color to e.g. black, users who are using black as their standard background color, will get black text on black background (unreadable). You can never presume anything about peoples' default colors. Therefore you must either define both foreground and background colors, or you must not define any of those. This goes for both input forms and the HTML document itself.

  • Use black or grey background for image galleries.

    If you put a relatively dark picture on a white background, all the light emitted from the screen will stress the eyes. The iris (the size of the pupil) will then close to decrease the amount of light coming in. This makes it difficult to see dark details. Old or cheap CRT screens might even make noises and loose the correct blacklevel if large areas of bright colors are used.

    Good background colors for an image gallery should be dark and not too colorful. So anything between black and grey should do.

  • Browser checks are wrong.

    In the 90's it was very popular to put in a browser check. The result was generally that less people could view the web page. The browser check mainly fails in two aspects:
    1. When testing for browser versions, there are three categories of browsers you can detect:

      A.: Browsers known to display your content properly.
      B.: Browsers that cannot display your content properly.
      C.: Unknown browser types.

      Many browser checks allow "A" but deny access to both "B" and "C". To deny group "C" is very wrong as you cannot make assumptions about a browser you do not know. You have to allow unknown browsers to view your content.
    2. Using javascript test whether flash is installed does not make much sense. Getting past the javascript code is statistically more difficult than running the flash. Flash is at least as widely supported as javascript and to make things worse, javascript implementations in old browsers are not completely compatible. So if you use flash on your webpage, just insert it and skip the browser tests.
    Now there are rare cases where you won't be able to do what you want. For example Internet Explorer 6 missing support for the "min-height" CSS attribute and such. In these cases you have to make sure only to apply your work-around for the browsers you know cannot display properly (group B above.) For entirely unknown browsers, stick to the html and css standards, and trust the unknown browser to work properly.

  • Navigation should be bookmarkable.

    The user should be able to bookmark or send links to any specific sub page. Make sure to update the URL with all the relevant values, so that if the user bookmarks or sends a link to a friend, this link will actually point to what the user saw, at the moment of copying the URL string.

    This is especially relevant for people considering using Flash, javascript, java, frames, "web 2.0" and similar technologies that interface poorly with the browser itself.

    Q: "But i want the users to see my pretty flash intro."
    A: You should offer it, but not force it onto the user. It is not your job to decide how the users should behave. Also, annoying the user will not make him want to come back more often. Treat people well, and they will treat you well.

  • Detecting language

    for a web page should follow what the browser dictates, rather than being based on an IP-check. Just because people live in a certain country doesn't guarantee he speaks (or likes to speak) the language of that region. The user will have his browser set to his prefered language.

    Technical note: The browser conveniently sends a language string in the "Accept-Language" http header. In PHP this can easily be accessed by reading the $_SERVER['HTTP_ACCEPT_LANGUAGE'] variable.

FAQ (Ficticiously Asked Questions):

Q: "Why spend extra time handling crash situations when I know my code is stable. My code is good."
A: You should see what kind of crap machines people are using. End-users have an amazing ability to create error situations that defy logic. Fear them.

More to come...


A Quick Guide for F/OSS Developers by Benjamin Roe
About having design goals
Why default values matter

Website by Joachim Michaelis