Skip to content

24 ways to impress your friends

Subliminal User Experience

The term ‘user experience’ is often used vaguely to quantify common elements of the interaction design process: wireframing, sitemapping and so on. UX undoubtedly involves all of these principles to some degree, but there really is a lot more to it than that.

Good UX is characterized by providing the user with constant feedback as they step through your interface. It means thinking about and providing fallbacks and error resolutions in even the rarest of scenarios. It’s about omitting clutter to make way for the necessary, and using the most fundamental of design tools to influence a user’s path. It means making no assumptions, designing right down to the most distinct details and going one step further every single time. In many cases, good UX is completely subliminal.

There are simple tools and subtleties we can build into our products to enhance the overall experience but, in order to do so, we really have to step beyond where we usually draw the line on what to design.

The purpose of this article is not to provide technical how-tos, as the functionality is, in most cases, quite simple and could be implemented in a myriad of ways. Rather, it will present a handful of ideas for enhancing the experience of an interface at a deeper level of design without relying on the container.

We’ll cover three elements that should get you thinking in the right mindset:

  1. progress activity and post-active states
  2. pseudo-class preloading
  3. buttons and their (mis)behaviour

Progress activity and the post-active state

We’ve long established that we can’t control the devices our products are viewed on, which browser they’ll run in or what connection speed will be used to access them. We accept this all as factual, so why is it so often left to the browser to provide feedback to the user when an event is triggered or an error encountered? The browser isn’t part of the interface — it’s merely a container. A simple, visual recognition of your users’ activity may be all it takes to make or break the product.

Let’s begin with a commonly overlooked case: progress activity.

A user moves their cursor over a hyperlink or button, which is clearly defined as one by the visual language of your content. Upon doing so, they trigger the :hover state to confirm this element is indeed interactive. So far, so good. What happens next is where it starts to fall apart: the user hits this link, presumably triggering an :active state, which is then returned to the normal state upon release. And then what?

Button states

From this point on, your user is in limbo. The link has fallen back to either its regular or :visited state. You’ve effectively abandoned them and are relying entirely on the browser they’re using to communicate that something is happening. This poses quite a few problems:

  • The user may lose focus of what they were doing.
  • There is little consistency between progress indication in browsers.
  • The user may not even notice that their action has been acknowledged.

How many times have one or more of these events happened to you due to a lack of communication from the interface?

Think about the differences between Safari and Chrome in this area — two browsers that, when compared to each other, are relatively similar in nature, though this basic feature differs in execution.

Safari and Chrome - progress indication

Like all aspects of designing the user experience, there is no one true way to fix this problem, but we can introduce details that many users will unconsciously appreciate.

Consider the basic loading indicator. It’s nothing new — in fact, some would argue it’s quite a cliché. However, whether using a spinning wheel or a progress bar, a gif or JavaScript, or something more sophisticated, these simple tools create an illusion of movement, progress and activity. Depending on the implementation, progress indication graphics can significantly increase a user’s perception of the speed in which an event is taking place. Combine this with a cursor change and a lock over the element to prevent double-clicking or reloading, and your chances of keeping your user’s valuable attention have significantly increased.

Demo: Progress activity and the post-active state

This same logic applies to all aspects of defaulting in a browser, from micro-elements like this up to something as simple as a 404 page. The difference in a user’s reaction to hitting the default Apache 404 and a hand-crafted, branded page are phenomenal and there are no prizes for guessing which one they’re more likely to exit from.

Pseudo-class preloading

Another detail that it pays well to look after is the use and abuse of the :hover element and, more importantly, the content revealed by it. Chances are you’re using the :hover pseudo-class somewhere in almost every screen you create. If content is being revealed on :hover and that content takes some time to load, there will inevitably be a delay the first time it is initiated. It appears tacky and half-finished when a tooltip or drop-down loads instantly, only to have its background or supporting elements follow through a second or two later. So, let’s preload the elements we know we’ll need.

A very simple application of this would be to load each file into the default state of a visible element and offset them by a large number. This ensures our elements have loaded and are ready if and when they need to be displayed.

element {
    background: url(path/to/image.jpg) -9999em -9999em no-repeat;
element .tooltip {
    display: none;
element:hover .tooltip {
    display: block;
    background: url(path/to/image.jpg) 0 0;

Background images are just one example. Of course, the same logic can apply to any form of revealed content. Using a sprite graphic can also be a clever — albeit tedious — method for achieving the same goal, so if you’re using a sprite, preloading in this way may not be necessary

The differences between preloading and not can only be visualized properly with an actual demonstration.

Demo: Preloading revealed content

Buttons and their (mis)behaviour

Almost all of the time, a button serves just one purpose: to be clicked (or tapped). When a button’s pressed, therefore, if anything other than triggering the desired event occurs, a user naturally becomes frustrated. I often get funny looks when talking about this, but designing the details of a button is something I consider essential.

It goes without saying that a button should always visually recognise :hover and :active states. We can take that one step further and disable some actions that get in the way of pressing the button.

It’s rare that a user would ever want to select and use the text on a button, so let’s cleanly disable it:

element {
    -moz-user-select: -moz-none;
    -webkit-user-select: none;
    user-select: none;

If the button is image-based or contains an image, we could also disable user dragging to make sure the image element stays locked to the button:

element {
    -moz-user-drag: -moz-none;
    -webkit-user-drag: none;
    user-drag: none;

Demo: A more usable button

Disabling global features like this should be done with utmost caution as it’s very easy to cross the line between enhancement and friction. Cases where this is acceptable are very rare, but it’s a good trick to keep in mind nevertheless. Both Apple’s iCloud and Metalab’s Flow applications use these tools appropriately and to great extent.

You could argue that the visual feedback of having the text selected or image dragged when a user mis-hits the button is actually a positive effect, informing the user that their desired action did not work. However, covering for human error should be a designer’s job, not that of our users. We can (almost) ensure it does work for them by accommodating for errors like this in most cases.

Final thoughts

Designing to this level of detail can seem obsessive, but as a designer and user of many interfaces and applications, I believe it can be the difference between a good user experience and a great one.

The samples you’ve just seen are only a fraction of the detail we can design for. Keep in mind that the demonstrations, code and methods above outline just one way to do this. You may not agree with all of these processes or have the time and desire to consider them, but one fact remains: it’s not the technology, or the way it’s done that’s important — it’s the logic and the concept of designing everything.

About the author

Chris Sealey is a UI designer and front-end developer with a passion for obsessively detailed graphics, clean-cut code and copious amounts of caffeine. Having worked on the web for roughly a quarter of its lifespan, he lives in Sydney and is employed full-time as a web designer/developer for Holy Cow! Design. He occasionally writes, designs and codes under the moniker of 51bits where his work, ramblings and pet projects reside.

More articles by Chris