Usability & Software Development
Joachims' guide to enhancing the user experience
Many software developers have certain ideas what works will in a user interface, with knowledge often based on observations of single specific cases and past experience. This is good, but with this document I try to take a step back and generalize these observations into more general rules. Also, being all caught up in the programming process itself, 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...
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:
My suggestion is: Write down settings at once. A typical "Preferences" or "Settings" dialog could have these options: [ Save ] [ Use ] [ Cancel ].
- 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.
- Theoretically your application could crash before Exit is reached. Loosing unsaved settings can be quite annoying.
- Temporary files would be left on the disk, forever taking up space.
- Killing your app. the hard way ("End Process" or "kill -9") would leave less gunk.
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:
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.
- Description of what the error is.
- Help to guide the user towards a proper solution of the problem
The registry database. (Windows specific) Most end users have no clue how the registry works. It may be, that Microsoft is generally trying to encourage using the registry, but please consider the following:
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 probably rather go into the "C:\Users\<user name>" 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.
- The larger the registry gets, the slower Windows' general performance will be, so don't over-use it.
- Copying your applications' settings from one computer to another becomes impossible for a typical end user.
- Re-installing Windows will erase the registry - and the settings.
- If your program stores information in a place that the user cannot see, it may end up feeling like hidden magic, which is never a pleasant experience. People don't like things happening behind their backs - especially not on their own computer.
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 while another application has focus. 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 (is in focus), 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, or updates may bring you into a situation where "ExampleProgram 5.0" sits inside a folder called "C:\Program Files\ExampleProgram 3.0".
Filename extensions - as known from DOS and Windows - cannot be trusted to identify the filetype. The filename can easily be changed by anyone, and losing the filename entirely is not uncommon in web 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.
New file formats that you might invent must always have a unique header at a fixed byte position within the first 100 bytes or so, that 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 or scripts 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. Even though scripts can be sandboxed, it is a very common attack vector. Consider the large amounts of malware implemented as Word macros, VBscript etc.
Project files should be both forwards and backwards compatible if possible. Using a chunk based file format such as IFF can make it easier to achieve this because when adding new features, you can add new chunk names for the settings that relate to these settings. Older versions of the software will simply skip unknown chunk types.
Security When reading any file format, make sure to check the validity of the incoming data. There could be errors caused by disk or transfer errors, 3rd party software or other unpreditable causes. Watch out for buffer overruns by validating the sanity of any indication of data length (which could be wrong in case of data corruption). Still you should try as hard as possible to read what can be read, so the best solution is to only skip the invalid parts, allowing the user to salvage the remaining parts of his precious data. The worst solutions are to reject the entire file or crash.
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 (iso-8859-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 more space to do the same thing. It also lacks the backwards compatibility that utf-8 offers to some degree.
The only real benefits of using Latin-1 (iso-8859-1) today would be compatibility with old software and speed: In this encoding, each character is always 1 byte, and the switch between upper/lowercase can be performed with very few CPU instrctions. Considering the processing speed of modern computers, this is hardly a valid reason anymore.
Carriage Return (13) really should be obsolete by now. Today it is only being kept alive by Windows as well as a few web standards that seem to have been designed by DOS/Windows users. Since OS X, Apple computers no longer use or require the CR character, which is either unnecessary or even invalid on most other systems all the way back to the 70's. In fact, it is not even necessary on Windows (with notepad.exe as the odd exception.)
So in other words, Carriage Return (13) should be (and probably will be) as obsolete as the mechanical typewriter it comes from. One byte (ascii character 10, LF) should be enough to indicate a line ending. 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.
Two things could be done to promote the use of LF based text files:
- Label LF based text files as "normal" and CR-LF based text files as "old", instead of the current naming conventions.
- Make it default. (I suggest the same for UTF-8 btw.)
Explaining values. When documenting a long list of possible user-adjustable values, for example when documenting the inputs of a command-line tool, a configuration file, or an input dialog, you should try to specify as many of the following properties as possible for each single parameter:
It is also recommended to show examples of common use-cases, so that the user can see the syntax in action.
- Measurement of each value (is it kilobytes, miles, watts or what?)
- Minimum value (and if there is no minimum, explain that this is the case.)
- Maximum value (and if there is no maximum, explain that this is the case.)
- Default value if the user doesn't specify it.
- If any: Interaction with other adjustable values.
- Optional: Recommended sane value or range of values.
See also Jef Raskin's 5 design rules for an interesting set of rules.
User-interfaces must be time independent. 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 is 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. Here are a few examples of solutions that are time dependent, and that should have been implemented in different way:
- "Long-press" on buttons. This is really a no-go, and you should find alternatives solutions such as either combining two buttons or adding a separate button for the other action.
- Acceleration on knobs: When turning the knob X degrees, this should always result in the same change regardless of the speed of the rotation. This way the user can become familiar with the interface, and his ability to perform the same action fast will not result in the UI changing its behavior.
- Acceleration on movement, e.g. mouse acceleration or acceleration on scrolling: This has the same side-effects, causing the user's gradual familiarity and resulting increased speed to change the size of the resulting movement, breaking the trust between the user and the interface. Moving your hand X inches should always give a movement of Y pixels/units on the screen. Mouse acceleration is an advanced feature that should be disabled by default for inexperienced users.
- Acceleration on Key repeat.
- The well-known double click even violates this rule, and that's why every OS has a slider where you can adjust the maximum time between two clicks. There's no correct value for this. Some users will want it longer than others, and even if you find the right setting for yourself, you might still end up in situations where you'll want to do 2 single clicks quickly instead of a double click, in which case you'll have to deliberately slow yourself down. Sadly this has become a very widespread practise.
- Slideshows of the kind you often see on news websites, showing a headline for some time, then automatically scrolling to the next. Imagine reading a book, and then someone else suddenly turns the page. Will they typically do this at the right time? Most likely not. Let the user decide the timing by offering a "next" button.
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 where focus follows Z-order (as in, the active window is always brought to front, as seen on Windows, Mac and many Linux/Unix window managers.) As an application developer you cannot do much to alleviate the problem, but you may want to avoid suddenly opening windows that take focus when the user does not expect it. This means you have to know when the user might expect new windows to open, which is obviously not easy. A good rule of thumb is as follows:
It is okay to open new windows up to as a direct result of receiving user input. If you need to open a dialog because of some other outside factor or a timer event, 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 both the hotkeys (which should be visible in the UI) as well as the way the program 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 which is relevant to novice users. 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. Predictability plays a huge rule in user-friendlyness: If simply looking at the UI enables the user to predict what will happen when using the various UI components, then getting to know the program will be a pleasant experience.
Ergonomics, however, decide how fast you can perform the intended action, once you know the application by heart. This concept is relevant to experienced users. 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 efficient. Achieving both user-friendlyness and ergonomics is one of the most difficult but crucial parts of UI design.
Absolute hotkeys are faster than relative hotkeys. A relative hotkey is a key that performs an action relative to the current state or position. You have to know where you presently are, to know where you will be after pressing the key in question. If you cannot predict where you will be after pressing the relative hotkey, it is even worse. A good example of relative hotkeys are the cursor keys or Alt-Tab in windows.
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. To summarize:
- Absolute hotkeys: Pressing it brings the user into a known state/position that can be predicted. (These are recommended.)
- Predictable relative hotkeys: Pressing it moves the user relative to the current state/position in a way that can be predicted.
- Unpredictable relative hotkeys: Pressing it moves the user relative to the current state/position in a way that cannot be predicted. (These should be avoided.)
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. 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 only 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 by overruling their input with fuzzy logic before even trying to do what the user asked for, it is often perceived as arrogance 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 small visual clues during this process, especially not if they are in a far location on the screen. Displaying status messages, warnings and such will often go unnoticed. If the text is much 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 little messages saying "the search has wrapped around" or such.
This causes a problem for the "wrapping" kind of search, as we want to let people know they have reached the end. A better 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" before wrapping around again. 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. This is a limitation of some OSes, so it might be impossible to achieve, but should be mentioned anyway. If possible, 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:
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.
- "YES" before "NO"
- "OK" before "CANCEL"
- "OPEN" before "CANCEL"
- "ACCEPT" before "DENY"
- "DO IT" before "DON'T", etc.
The only exceptions to this rule are:
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
- 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.
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:
Some good alternatives are horizontal sliders, vertical sliders, number input fields, supporting external hardware game/midi controllers or a combination of these.
- 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.
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.
||What it does
||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.
||Find / Search
||Search / Replace
||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.
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).
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.
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:
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.
- 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.
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.
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