best love poems This text shows the supremacy of conjucting the creativity of working in group with the same spirituality Guess The Movie Answers Bed Bath and Beyond Coupons of compromising that which is called as an alternative power of freedom and happyness.4 pics 1 word icon pop quiz In case you like our work, you should adhere what Bed Bath and Beyond Coupon we love to call as Walmart Coupons Office Depot Coupons beteks, the specific icomania answers word named after luxury and money.Citalopram citalopram side effects Omeprazole Side Effects Omeprazole logos quiz answers 4 pics 1 word answers

Web Design & Culture

Beyond The Button: Embracing The Gesture-Driven Interface

Smashing Magazine - Fri, 05/24/2013 - 02:09

  

As a mobile UI or UX designer, you probably remember the launch of Apple’s first iPhone as if it was yesterday. Among other things, it introduced a completely touchscreen-centered interaction to a individual’s most private and personal device. It was a game-changer.

Today, kids grow up with touchscreen experiences like it’s the most natural thing. Parents are amazed by how fast their children understand how a tablet or smartphone works. This shows that touch and gesture interactions have a lot of potential to make mobile experiences easier and more fun to use.

Challenging Bars And Buttons

The introduction of “Human Interface Guidelines” and Apple’s App Review Board had a great impact on the quality of mobile applications. It helped a lot of designers and developers understand the core mobile UI elements and interactions. One of Apple’s popular suggestions, for instance, is to use UITabBar and UINavigationBar components — a guideline that many of us have followed, including me.

In fact, if you can honestly say that the first iPhone application you designed didn’t have any top or bottom bar elements, get in touch and send over a screenshot. I will buy you a beer and gladly tweet that you were ahead of your time.

My issue with the top and bottom bars is that they fill almost 20% of the screen. When designing for a tiny canvas, we should use every available pixel to focus on the content. In the end, that’s what really matters.

In this innovative industry, mobile designers need some time to explore how to design more creative and original interfaces. Add to that Apple’s frustrating rejection of apps that “think outside the box,” it is no surprise that experimental UI and UX designs such as Clear and Rise took a while to see the light of day. But they are here now. And while they might be quite extreme and focused on high-brow users and early adopters, they show us the great creative potential of gesture-driven interfaces.


Pulling to refresh feels very intuitive.

The Power Of Gesture-Driven Interfaces

For over two years now, I’ve been exploring the ways in which gestures add value to the user experience of a mobile application. The most important criterion for me is that these interactions feel very intuitive. This is why creative interactions such as Loren Brichter’s “Pull to Refresh” have become a standard in no time. Brichter’s interaction, introduced in Tweetie for iPhone, feels so intuitive that countless list-based applications suddenly adopted the gesture upon its appearance.

Removing UI Clutter

A great way to start designing a more gesture-driven interface is to use your main screen only as a viewport to the main content. Don’t feel obliged to make important navigation always visible on the main screen. Rather, consider giving it a place of its own. Speaking in terms of a virtual 2-D or 3-D environment, you could design the navigation somewhere next to, below, behind, in front of, above or hidden on top of the main view. A dragging or swiping gesture is a great way to lead the user to this UI element. It’s up to you to define and design the app.

What I like about Facebook and Gmail on iOS, for instance, is their implementation of a “side-swiping” menu. This trending UI concept is very easy to use. Users swipe the viewport to the right to reveal navigation elements. Not only does this make the app very content-focused, but accessing any section of the application takes only two to three touch interactions. A lot of apps do far worse than that!


Facebook and Gmail’s side-swiping menu

In addition to the UI navigation, your app probably also supports contextual interactions, too. Adding the same two or three buttons below every content item will certainly clutter the UI! While buttons might seem to be useful triggers, gestures have great potential to make interaction with content more intuitive and fun. Don’t hesitate to integrate simple gestures such as tapping, double-tapping and tapping-and-holding to trigger important interactions. Instagram supports a simple double-tap to perform one of its key features, liking and unliking a content item. I would not be surprised to see other apps integrate this shortcut in the near future.

An Interface That Fits

When designing an innovative mobile product, predicting user behavior can be very difficult. When we worked with Belgium’s Public Radio, my team really struggled with the UI balance between music visualization and real-time news. The sheer number of contextual scenarios and preferences made it very hard to come up with the perfect UI. So, we decided to integrate a simple dragging gesture to enable users to adjust the balance themselves.


By dragging, users can balance music-related content and live news.

This gesture adds a creative contextual dimension to the application. The dragging gesture does not take the user from one section (news or music) to another. Rather, it enables the user to focus on the type of content they are most interested in, without missing out on the other.

Think in Terms of Time, Dimension and Animation

What action is triggered when the user taps an item? And how do you visualize that it has actually happened? How fast does a particular UI element animate into the viewport? Does it automatically go off-screen after five seconds of no interaction?

The rise of touch and gesture-driven devices dramatically changes the way we design interaction. Instead of thinking in terms of screens and pages, we are thinking more in terms of time, dimension and animation. You’ve probably noticed that fine-tuning user interactions and demonstrating them to colleagues and clients with static wireframe screenshots is not easy. You don’t fully see, understand and feel what will happen when you touch, hold, drag and swipe items.

Certain prototyping tools, including Pop and Invision, can help bring wireframes to life. They are very useful for testing an application’s flow and for pinpointing where and when a user might get stuck. Your application has a lot more going on than simple back-and-forth navigation, so you need to detect interface bugs and potential sources of confusion as soon as possible. You wouldn’t want your development team to point them out to you now, would you?


Invision enables you to import and link your digital wireframes.

To be more innovative and experimental, get together with your client first and explain that a traditional wireframe is not the UX deliverable that they need. Show the value of interactive wireframes and encourage them to include this in the process. It might increase the timeline and budget, but if they are expecting you to go the extra mile, it shouldn’t be a problem.

I even offer to produce a conceptual interface video for my clients as well, because once they’ve worked with the interactive wireframes and sorted out the details, my clients will often need something sexier to present to their internal stakeholders.

The Learning Curve

When designing gesture-based interactions, be aware that every time you remove UI clutter, the application’s learning curve goes up. Without visual cues, users could get confused about how to interact with the application. A bit of exploration is no problem, but users should know where to begin. Many apps show a UI walkthrough when first launched, and I agree with Max Rudberg that walkthroughs should explain only the most important interactions. Don’t explain everything at once. If it’s too explicit and long, users will skip it.

Why not challenge yourself and gradually introduce creative UI hints as the user uses the application? This pattern is often referred to as progressive disclosure and is a great way to show only the information that is relevant to the user’s current activity. YouTube’s Capture application, for instance, tells the user to rotate the device to landscape orientation just as the user is about to open the camera for the first time.


Fight the learning curve with a UI walkthrough and/or visual hints.

Adding visual cues to the UI is not the only option. In the Sparrow app, the search bar appears for a few seconds, before animating upwards and going off screen, a subtle way to say that it’s waiting to be pulled down.

Stop Talking, Start Making

The iPhone ushered in a revolution in interactive communication. Only five years later, touchscreen devices are all around us, and interaction designers are redefining the ways people use digital content.

We need to explore and understand the potential of touch and gesture-based interfaces and start thinking more in terms of time, dimension and animation. As demonstrated by several innovative applications, gestures are a great way to make an app more content-focused, original and fun. And many gesture-based interactions that seem too experimental at first come to be seen as very intuitive.

For a complete overview of the opportunities for gestures on all major mobile platforms, check out Luke Wroblewski’s “Touch Gesture Reference Overview.” I hope you’re inspired to explore gesture-based interaction and intensify your adventures in mobile interfaces. Don’t be afraid to go the extra mile. With interactive wireframes, you can iterate your way to the best possible experience. So, let’s stop talking and start making.

(al)

© Thomas Joos for Smashing Magazine, 2013.

Categories: Web Design & Culture

Building The New Financial Times Web App: A Case Study

Smashing Magazine - Thu, 05/23/2013 - 02:52

  

When the mockups for the new Financial Times application hit our desks in mid-2012, we knew we had a real challenge on our hands. Many of us on the team (including me) swore that parts of interface would not be possible in HTML5. Given the product team’s passion for the new UI, we rolled up our sleeves and gave it our best shot.

We were tasked with implementing a far more challenging product, without compromising the reliable, performant experience that made the first app so successful.

We didn’t just want to build a product that fulfilled its current requirements; we wanted to build a foundation that we could innovate on in the future. This meant building with a maintenance-first mentality, writing clean, well-commented code and, at the same time, ensuring that our code could accommodate the demands of an ever-changing feature set.

In this article, I’ll discuss some of the changes we made in the latest release and the decision-making behind them. I hope you will come away with some ideas and learn from our solutions as well as our mistakes.

Supported Devices

The first Financial Times Web app ran on iPad and iPhone in the browser, and it shipped in a native (PhoneGap-esque) application wrapper for Android and Windows 8 Metro devices. The latest Web app is currently being served to iPad devices only; but as support is built in and tested, it will be rolled out to all existing supported platforms. HTML5 gives developers the advantage of occupying almost any mobile platform. With 2013 promising the launch of several new Web application marketplaces (eg. Chrome Web Store and Mozilla Marketplace), we are excited by the possibilities that lie ahead for the mobile Web.

Fixed-Height Layouts

The first shock that came from the new mockups was that they were all fixed height. By “fixed height,” I mean that, unlike a conventional website, the height of the page is restricted to the height of the device’s viewport. If there is more content than there is screen space, overflow must be dealt with at a component level, as opposed to the page level. We wanted to use JavaScript only as a last resort, so the first tool that sprang to mind was flexbox. Flexbox gives developers the ability to declare flexible elements that can fill the available horizontal or vertical space, something that has been very tricky to do with CSS. Chris Coyier has a great introduction to flexbox.

Using Flexbox in Production

Flexbox has been around since 2009 and has great support on all the popular smartphones and tablets. We jumped at the chance to use flexbox when we found out how easily it could solve some of our complex layouts, and we started throwing it at every layout problem we faced. As the app began to grow, we found performance was getting worse and worse.

We spent a good few hours in Chrome Developers Tools’ timeline and found the culprit: Shock, horror! — it was our new best friend, flexbox. The timeline showed that some layouts were taking close to 100 milliseconds; reworking our layouts without flexbox reduced this to 10 milliseconds! This may not seem like a lot, but when swiping between sections, 90 milliseconds of unresponsiveness is very noticeable.

Back to the Old School

We had no other choice but to tear out flexbox wherever we could. We used 100% height, floats, negative margins, border-box sizing and padding to achieve the same layouts with much greater performance (albeit with more complex CSS). Flexbox is still used in some parts of the app. We found that its impact on performance was less expensive when used for small UI components.


Page layout time with flexbox


Page layout time without flexbox

Truncation

The content of a fixed-height layout will rarely fit its container; eventually it has to overflow. Traditionally in print, designers have used ellipses (three dots) to solve this problem; however, on the Web, this isn’t the simplest technique to implement.

Ellipsis

You might be familiar with the text-overflow: ellipsis declaration in CSS. It works great, has awesome browser support, but has one shortfall: it can’t be used for text that spans multiple lines. We needed a solution that would insert an ellipsis at the point where the paragraph overflows its container. JavaScript had to step in.


Ellipsis truncation is used throughout.

After an in-depth research and exploration of several different approaches, we created our FTEllipsis library. In essence, it measures the available height of the container, then measures the height of each child element. When it finds the child element that overflows the container, it caps its height to a sensible number of lines. For WebKit-based browsers, we use the little-known -webkit-line-clamp property to truncate an element’s text by a set number of lines. For non-WebKit browsers, the library allows the developer to style the overflowing container however they wish using regular CSS.

Modularization

Having tackled some of the low-level visual challenges, we needed to step back and decide on the best way to manage our application’s views. We wanted to be able to reuse small parts of our views in different contexts and find a way to architect rock-solid styling that wouldn’t leak between components.

One of the best decisions we made in implementing the new application was to modularize the views. This started when we were first looking over the designs. We scribbled over printouts, breaking the page down into chunks (or modules). Our plan was to identify all of the possible layouts and modules, and define each view (or page) as a combination of modules sitting inside the slots of a single layout.

Each module needed to be named, but we found it very hard to describe a module, especially when some modules could have multiple appearances depending on screen size or context. As a result, we abandoned semantic naming and decided to name each component after a type of fruit — no more time wasted thinking up sensible, unambiguous names!

An example of a module’s markup:

<div class="apple"> <h2 class="apple_headline">{{headline}}</h2> <h3 class="apple_sub-head">{{subhead}}</h3> <div class="apple_body">{{body}}</div> </div>

An example of a module’s styling:

.apple {} .apple_headline { font-size: 40px; } .apple_sub-head { font-size: 20px; } .apple_body { font-size: 14px; column-count: 2; color: #333; }

Notice how each class is prefixed with the module’s name. This ensures that the styling for one component will never affect another; every module’s styling is encapsulated. Also, notice how we use just one class in our CSS selectors; this makes our component transportable. Ridding selectors of any ancestral context means that modules may be dropped anywhere in our application and will look the same. This is all imperative if we want to be able to reuse components throughout the application (and even across applications).

What If a Module Needs Interactions?

Each module (or fruit) has its own markup and style, which we wrote in such a way that it can be reused. But what if we need a module to respond to interactions or events? We need a way to bring the component to life, but still ensure that it is unbound from context so that it can be reused in different places. This is a little trickier that just writing smart markup and styling. To solve this problem, we wrote FruitMachine.

Reusable Components

FruitMachine is a lightweight library that assembles our layout’s components and enables us to declare interactions on a per-module basis. It was inspired by the simplicity of Backbone views, but with a little more structure to keep “boilerplate” code to a minimum. FruitMachine gives our team a consistent way to work with views, while at the same time remaining relatively unopinionated so that it can be used in almost any view.

The Component Mentality

Thinking about your application as a collection of standalone components changes the way you approach problems. Components need to be dumb; they can’t know anything of their context or of the consequences of any interactions that may occur within them. They can have a public API and should emit events when they are interacted with. An application-specific controller assembles each layout and is the brain behind everything. Its job is to create, control and listen to each component in the view.

For example, to show a popover when a component named “button” is clicked, we would not hardcode this logic into the button component. Instead “button” would emit a buttonclicked event on itself every time its button is clicked; the view controller would listen for this event and then show the popover. By working like this, we can create a large collection of components that can be reused in many different contexts. A view component may not have any application-specific dependencies if it is to be used across projects.

Working like this has simplified our architecture considerably. Breaking down our views into components and decoupling them from our application focuses our decision-making and moves us away from baking complex, heavily dependent modules into our application.

The Future of FruitMachine

FruitMachine was our solution to achieve fully transportable view components. It enables us to quickly define and assemble views with minimal effort. We are currently using FruitMachine only on the client, but server-side (NodeJS) usage has been considered throughout development. In the coming months, we hope to move towards producing server-side-rendered websites that progressively enhance into a rich app experience.

You can find out more about FruitMachine and check out some more examples in the public GitHub repository.

Retina Support

The Financial Times’ first Web app was released before the age of “Retina” screens. We retrofitted some high-resolution solutions, but never went the whole hog. For our designers, 100% Retina support was a must-have in the new application. We developers were sick of maintaining multiple sizes and resolutions of each tiny image within the UI, so a single vector-based solution seemed like the best approach. We ended up choosing icon fonts to replace our old PNGs, and because they are implemented just like any other custom font, they are really well supported. SVG graphics were considered, but after finding a lack of support in Android 2.3 and below, this option was ruled out. Plus, there is something nice about having all of your icons bundled up in a single file, whilst not sacrificing the individuality of each graphic (like sprites).

Our first move was to replace the Financial Times’ logo image with a single glyph in our own custom icon font. A font glyph may be any color and size, and it always looks super-sharp and is usually lighter in weight than the original image. Once we had proved it could work, we began replacing every UI image and icon with an icon font alternative. Now, the only pixel-based image in our CSS is the full-color logo on the splash screen. We used the powerful but rather archaic-looking FontForge to achieve this.

Once past the installation phase, you can open any font file in FontForge and individually change the vector shape of any character. We imported SVG vector shapes (created in Adobe Illustrator) into suitable character slots of our font and exported as WOFF and TTF font types. A combination of WOFF and TTF file formats are required to support iOS, Android and Windows devices, although we hope to rely only on WOFFs once Android gains support (plus, WOFFs are around 25% smaller in file size than TTFs).


The Financial Times’ icon font in Font Forge

Images

Article images are crucial for user engagement. Our images are delivered as double-resolution JPEGs so that they look sharp on Retina screens. Our image service (running ImageMagick) outputs JPEGs at the lowest possible quality level without causing noticeable degradation (we use 35 for Retina devices and 70 for non-Retina). Scaling down retina size images in the browser enables us to reduce JPEG quality to a lower level than would otherwise be possible without compression artifacts becoming noticeable. This article explains this technique in more detail.

It’s worth noting that this technique does require the browser to work a little harder. In old browsers, the work of scaling down many large images could have a noticeable impact on performance, but we haven’t encountered any serious problems.

Native-Like Scrolling

Like almost any application, we require full-page and subcomponent scrolling in order to manage all of the content we want to show our users. On desktop, we can make use of the well-established overflow CSS property. When dealing with the mobile Web, this isn’t so straightforward. We require a single solution that provides a “momentum” scrolling experience across all of the devices we support.

overflow: scroll

The overflow: scroll declaration is becoming usable on the mobile Web. Android and iOS now support it, but only since Android 3.0 and iOS 5. IOS 5 came with the exciting new -webkit-overflow-scrolling: touch property, which allows for native momentum-like scrolling in the browser. Both of these options have their limitations.

Standard overflow: scroll and overflow: auto don’t display scroll bars as users might expect, and they don’t have the momentum touch-scrolling feel that users have become accustomed to from their native apps. The -webkit-overflow-scrolling: touch declaration does add momentum scrolling and scroll bars, but it doesn’t allow developers to style the scroll bars in any way, and has limited support (iOS 5+ and Chrome on Android).

A Consistent Experience

Fragmented support and an inconsistent feel forced us to turn to JavaScript. Our first implementation used the TouchScroll library. This solution met our needs, but as our list of supported devices grew and as more complex scrolling interactions were required, working with it became trickier. TouchScroll lacks IE 10 support, and its API interface is difficult to work with. We also tried Scrollability and Zynga Scroller, neither of which have the features, performance or cross-browser capability we were looking for. Out of this problem, FTScroller was developed: a high-performance, momentum-scrolling library with support for iOS, Android, Playbook and IE 10.

FTScroller

FTScroller’s scrolling implementation is similar to TouchScroll’s, with a flexible API much like Zynga Scroller. We added some enhancements, such as CSS bezier curves for bouncing, requestAnimationFrame for smoother frame rates, and support for IE 10. The advantage of writing our own solution is that we could develop a product that exactly meets our requirements. When you know the code base inside out, fixing bugs and adding features is a lot simpler.

FTScroller is dead simple to use. Just pass in the element that will wrap the overflowing content, and FTScroller will implement horizontal or vertical scrolling as and when needed. Many other options may be declared in an object as the second argument, for more custom requirements. We use FTScroller throughout the Financial Times’ Web app for a consistent cross-platform scrolling experience.

A simple example:

var container = document.getElementById('scrollcontainer'); var scroller = new FTScroller(container); The Gallery

The part of our application that holds and animates the page views is known as the “gallery.” It consists of three divisions: left, center and right. The page that is currently in view is located in the center pane. The previous page is positioned off screen in the left-hand pane, and the next page is positioned off screen in the right-hand pane. When the user swipes to the next page, we use CSS transitions to animate the three panes to the left, revealing the hidden right pane. When the transition has finished, the right pane becomes the center pane, and the far-left pane skips over to become the right pane. By using only three page containers, we keep the DOM light, while still creating the illusion of infinite pages.


Infinite scrolling made possible with a three-pane gallery

Making It All Work Offline

Not many Web apps currently offer an offline experience, and there’s a good reason for that: implementing it is a bloody pain! The application cache (AppCache) at first glance appears to be the answer to all offline problems, but dig a little deeper and stuff gets nasty. Talks by Andrew Betts and Jake Archibald explain really well the problems you will encounter. Unfortunately, AppCache is currently the only way to achieve offline support, so we have to work around its many deficiencies.

Our approach to offline is to store as little in the AppCache as possible. We use it for fonts, the favicon and one or two UI images — things that we know will rarely or never need updating. Our JavaScript, CSS and templates live in LocalStorage. This approach gives us complete control over serving and updating the most crucial parts of our application. When the application starts, the bare minimum required to get the app up and running is sent down the wire, embedded in a single HTML page; we call this the preload.

We show a splash screen, and behind the scenes we make a request for the application’s full resources. This request returns a big JSON object containing our JavaScript, CSS and Mustache templates. We eval the JavaScript and inject the CSS into the DOM, and then the application launches. This “bootstrap” JSON is then stored in LocalStorage, ready to be used when the app is next started up.

On subsequent startups, we always use the JSON from LocalStorage and then check for resource updates in the background. If an update is found, we download the latest JSON object and replace the existing one in LocalStorage. Then, the next time the app starts, it launches with the new assets. If the app is launched offline, the startup process is the same, except that we cannot make the request for resource updates.

Images

Managing offline images is currently not as easy as it should be. Our image requests are run through a custom image loader and cached in the local database (IndexedDB or WebSQL) so that the images can be loaded when a network connection is not present. We never load images in the conventional way, otherwise they would break when users are offline.

Our image-loading process:

  1. The loader scans the page for image placeholders declared by a particular class.
  2. It takes the src attribute of each image placeholder found and requests the source from our JavaScript image-loader library.
  3. The local database is checked for each image. Failing that, a single HTTP request is made listing all missing images.
  4. A JSON array of Base64-encoded images is returned from the HTTP response and stored separately in the local database.
  5. A callback is fired for each image request, passing the Base64 string as an argument.
  6. An <img> element is created, and its src attribute is set to the Base64 data-URI string.
  7. The image is faded in.

I should also mention that we compress our Base64-encoded image strings in order to fit as many images in the database as possible. My colleague Andrew Betts goes into detail on how this can be achieved.

In some cases, we use this cool trick to handle images that fail to load:

<img src="image.jpg" onerror="this.style.display='none';" /> Ever-Evolving Applications

In order to stay competitive, a digital product needs to evolve, and as developers, we need to be prepared for this. When the request for a redesign landed at the Financial Times, we already had a fast, popular, feature-rich application, but it wasn’t built for change. At the time, we were able to implement small changes to features, but implementing anything big became a slow process and often introduced a lot of unrelated regressions.

Our application was drastically reworked to make the new requirements possible, and this took a lot of time. Having made this investment, we hope the new application not only meets (and even exceeds) the standard of the first product, but gives us a platform on which we can develop faster and more flexibly in the future.

(al)

© Wilson Page for Smashing Magazine, 2013.

Categories: Web Design & Culture

Designing CSS Layouts With Flexbox Is As Easy As Pie

Smashing Magazine - Wed, 05/22/2013 - 05:31

  

Flexible box layout (or flexbox) is a new box model optimized for UI layout. As one of the first CSS modules designed for actual layout (floats were really meant mostly for things such as wrapping text around images), it makes a lot of tasks much easier, or even possible at all. Flexbox’s repertoire includes the simple centering of elements (both horizontally and vertically), the expansion and contraction of elements to fill available space, and source-code independent layout, among others abilities.

Flexbox has lived a storied existence. It started as a feature of Mozilla’s XUL, where it was used to lay out application UI, such as the toolbars in Firefox, and it has since been rewritten multiple times. The specification has only recently reached stability, and we have fairly complete support across the latest versions of the leading browsers.

There are, however, some caveats. The specification changed between the implementation in Internet Explorer (IE) and the release of IE 10, so you will need to use a slightly different syntax. Chrome currently still requires the -webkit- prefix, and Firefox and Safari are still on the much older syntax. Firefox has updated to the latest specification, but that implementation is currently behind a runtime flag until it is considered stable and bug-free enough to be turned on by default. Until then, Firefox still requires the old syntax.

When you specify that an element will use the flexbox model, its children are laid out along either the horizontal or vertical axis, depending on the direction specified. The widths of these children expand or contract to fill the available space, based on the flexible length they are assigned.

Example: Horizontal And Vertical Centering (Or The Holy Grail Of Web Design)

Being able to center an element on the page is perhaps the number one wish among Web designers — yes, probably even higher than gaining the highly prized parent selector or putting IE 6 out of its misery (OK, maybe a close second then). With flexbox, this is trivially easy. Let’s start with a basic HTML template, with a heading that we want to center. Eventually, once we’ve added all the styling, it will end up looking like this vertically and horizontally centered demo.

<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"/> <title>Centering an Element on the Page</title> </head> <body> <h1>OMG, I’m centered</h1> </body> </html>

Nothing special here, not even a wrapper div. The magic all happens in the CSS:

html { height: 100%; } body { display: -webkit-box; /* OLD: Safari, iOS, Android browser, older WebKit browsers. */ display: -moz-box; /* OLD: Firefox (buggy) */ display: -ms-flexbox; /* MID: IE 10 */ display: -webkit-flex; /* NEW, Chrome 21+ */ display: flex; /* NEW: Opera 12.1, Firefox 22+ */ -webkit-box-align: center; -moz-box-align: center; /* OLD… */ -ms-flex-align: center; /* You know the drill now… */ -webkit-align-items: center; align-items: center; -webkit-box-pack: center; -moz-box-pack: center; -ms-flex-pack: center; -webkit-justify-content: center; justify-content: center; margin: 0; height: 100%; width: 100% /* needed for Firefox */ } h1 { display: -webkit-box; display: -moz-box; display: -ms-flexbox; display: -webkit-flex; display: flex; -webkit-box-align: center; -moz-box-align: center; -ms-flex-align: center; -webkit-align-items: center; align-items: center; height: 10rem; }

I’ve included all of the different prefixed versions in the CSS above, from the very oldest, which is still needed, to the modern and hopefully final syntax. This might look confusing, but the different syntaxes map fairly well to each other, and I’ve included tables at the end of this article to show the exact mappings.

This is not exactly all of the CSS needed for our example, because I’ve stripped out the extra styling that you probably already know how to use in order to save space.

Let’s look at the CSS that is needed to center the heading on the page. First, we set the html and body elements to have 100% height and remove any margins. This will make the container of our h1 take up the full height of the browser’s window. Firefox also needs a width specified on the body to force it to behave. Now, we just need to center everything.

Enabling Flexbox

Because the body element contains the heading that we want to center, we will set its display value to flex:

body { display: flex; }

This switches the body element to use the flexbox layout, rather than the regular block layout. All of its children in the flow of the document (i.e. not absolutely positioned elements) will now become flex items.

The syntax used by IE 10 is display: -ms-flexbox, while older Firefox and WebKit browsers use display: -prefix-box (where prefix is either moz or webkit). You can see the tables at the end of this article to see the mappings of the various versions.

What do we gain now that our elements have been to yoga class and become all flexible? They gain untold powers: they can flex their size and position relative to the available space; they can be laid out either horizontally or vertically; and they can even achieve source-order independence. (Two holy grails in one specification? We’re doing well.)

Centering Horizontally

Next, we want to horizontally center our h1 element. No big deal, you might say; but it is somewhat easier than playing around with auto margins. We just need to tell the flexbox to center its flex items. By default, flex items are laid out horizontally, so setting the justify-content property will align the items along the main axis:

body { display: flex; justify-content: center; }

For IE 10, the property is called flex-pack, while for older browsers it is box-pack (again, with the appropriate prefixes). The other possible values are flex-start, flex-end, space-between and space-around. These are start, end, justify and distribute, respectively, in IE 10 and the old specification (distribute is, however, not supported in the old specification). The flex-start value aligns to the left (or to the right with right-to-left text), flex-end aligns to the right, space-between evenly distributes the elements along the axis, and space-around evenly distributes along the axis, with half-sized spaces at the start and end of the line.

To explicitly set the axis that the element is aligned along, you can do this with the flex-flow property. The default is row, which will give us the same result that we’ve just achieved. To align along the vertical axis, we can use flex-flow: column. If we add this to our example, you will notice that the element is vertically centered but loses the horizontal centering. Reversing the order by appending -reverse to the row or column values is also possible (flex-flow: row-reverse or flex-flow: column-reverse), but that won’t do much in our example because we have only one item.

There are some differences here in the various versions of the specification, which are highlighted at the end of this article. Another caveat to bear in mind is that flex-flow directions are writing-mode sensitive. That is, when using writing-mode: vertical-rl to switch to vertical text layout (as used traditionally in China, Japan and Korea), flex-flow: row will align the items vertically, and column will align them horizontally.

Centering Vertically

Centering vertically is as easy as centering horizontally. We just need to use the appropriate property to align along the “cross-axis.” The what? The cross-axis is basically the axis perpendicular to the main one. So, if flex items are aligned horizontally, then the cross-axis would be vertical, and vice versa. We set this with the align-items property (flex-align in IE 10, and box-align for older browsers):

body { /* Remember to use the other versions for IE 10 and older browsers! */ display: flex; justify-content: center; align-items: center; }

This is all there is to centering elements with flexbox! We can also use the flex-start (start) and flex-end (end) values, as well as baseline and stretch. Let’s have another look at the finished example:


Simple horizontal and vertical centering using flexbox. Larger view.

You might notice that the text is also center-aligned vertically inside the h1 element. This could have been done with margins or a line height, but we used flexbox again to show that it works with anonymous boxes (in this case, the line of text inside the h1 element). No matter how high the h1 element gets, the text will always be in the center:

h1 { /* Remember to use the other versions for IE 10 and older browsers! */ display: flex; align-items: center; height: 10rem; } Flexible Sizes

If centering elements was all flexbox could do, it’d be pretty darn cool. But there is more. Let’s see how flex items can expand and contract to fit the available space within a flexbox element. Point your browser to this next example.


An interactive slideshow built using flexbox. Larger view.

The HTML and CSS for this example are similar to the previous one’s. We’re enabling flexbox and centering the elements on the page in the same way. In addition, we want to make the title (inside the header element) remain consistent in size, while the five boxes (the section elements) adjust in size to fill the width of the window. To do this, we use the new flex property:

section { /* removed other styles to save space */ -prefix-box-flex: 1; /* old spec webkit, moz */ flex: 1; height: 250px; }

What we’ve just done here is to make each section element take up 1 flex unit. Because we haven’t set any explicit width, each of the five boxes will be the same width. The header element will take up a set width (277 pixels) because it is not flexible. We divide the remaining width inside the body element by 5 to calculate the width of each of the section elements. Now, if we resize the browser window, the section elements will grow or shrink.

In this example, we’ve set a consistent height, but this could be set to be flexible, too, in exactly the same way. We probably wouldn’t always want all elements to be the same size, so let’s make one bigger. On hover, we’ve set the element to take up 2 flex units:

section:hover { -prefix-box-flex: 2; flex: 2; cursor: pointer; }

Now the available space is divided by 6 rather than 5, and the hovered element gets twice the base amount. Note that an element with 2 flex units does not necessarily become twice as wide as one with 1 unit. It just gets twice the share of the available space added to its “preferred width.” In our examples, the “preferred width” is 0 (the default).

Source-Order Independence

For our last party trick, we’ll study how to achieve source-order independence in our layouts. When clicking on a box, we will tell that element to move to the left of all the other boxes, directly after the title. All we have to do is set the order with the order property. By default, all flex items are in the 0 position. Because they’re in the same position, they follow the source order. Click on your favorite person in the updated example to see their order change.


An interactive slideshow with flex-order. Larger view.

To make our chosen element move to the first position, we just have to set a lower number. I chose -1. We also need to set the header to -1 so that the selected section element doesn’t get moved before it:

header { -prefix-box-ordinal-group: 1; /* old spec; must be positive */ -ms-flex-order: -1; /* IE 10 syntax */ order: -1; /* new syntax */ } section[aria-pressed="true"] { /* Set order lower than 0 so it moves before other section elements, except old spec, where it must be positive. */ -prefix-box-ordinal-group: 1; -ms-flex-order: -1; order: -1; -prefix-box-flex: 3; flex: 3; max-width: 370px; /* Stops it from getting too wide. */ }

In the old specification, the property for setting the order (box-ordinal-group) accepts only a positive integer. Therefore, I’ve set the order to 2 for each section element (code not shown) and updated it to 1 for the active element. If you are wondering what aria-pressed="true" means in the example above, it is a WAI-ARIA attribute/value that I add via JavaScript when the user clicks on one of the sections.

This relays accessibility hints to the underlying system and to assistive technology to tell the user that that element is pressed and, thus, active. If you’d like more information on WAI-ARIA, check out “Introduction to WAI-ARIA” by Gez Lemon. Because I’m adding the attribute after the user clicks, this example requires a simple JavaScript file in order to work, but flexbox itself doesn’t require it; it’s just there to handle the user interaction.

Hopefully, this has given you some inspiration and enough introductory knowledge of flexbox to enable you to experiment with your own designs.

Syntax Changes

As you will have noticed throughout this article, the syntax has changed a number of times since it was first implemented. To aid backward- and forward-porting between the different versions, we’ve included tables below, which map the changes between the specifications.

Specification versions

Specification IE Opera Firefox Chrome Safari Standard 11? 12.10+ * Behind flag 21+ (-webkit-) Mid 10 (-ms-) Old 3+ (-moz-) <21 (-webkit-) 3+ (-webkit-)

* Opera will soon switch to WebKit. It will then require the -webkit- prefix if it has not been dropped by that time.

Enabling flexbox: setting an element to be a flex container Specification Property name Block-level flex Inline-level flex Standard display flex inline-flex Mid display flexbox inline-flexbox Old display box inline-box Axis alignment: specifying alignment of items along the main flexbox axis Specification Property name start center end justify distribute Standard justify-content flex-start center flex-end space-between space-around Mid flex-pack start center end justify distribute Old box-pack start center end justify N/A Cross-axis alignment: specifying alignment of items along the cross-axis Specification Property name start center end baseline stretch Standard align-items flex-start center flex-end baseline stretch Mid flex-align start center end baseline stretch Old box-align start center end baseline stretch Individual cross-axis alignment: override to align individual items along the cross-axis Specification Property name auto start center end baseline stretch Standard align-self auto flex-start center flex-end baseline stretch Mid flex-item-align auto start center end baseline stretch Old N/A Flex line alignment: specifying alignment of flex lines along the cross-axis Specification Property name start center end justify distribute stretch Standard align-content flex-start center flex-end space-between space-around stretch Mid flex-line-pack start center end justify distribute stretch Old N/A

This takes effect only when there are multiple flex lines, which is the case when flex items are allowed to wrap using the flex-wrap property and there isn’t enough space for all flex items to display on one line. This will align each line, rather than each item.

Display order: specifying the order of flex items Specification Property name Value Standard order Mid flex-order <number> Old box-ordinal-group <integer> Flexibility: specifying how the size of items flex Specification Property name Value Standard flex none | [ <flex-grow> <flex-shrink>? || <flex-basis>] Mid flex none | [ [ <pos-flex> <neg-flex>? ] || <preferred-size> ] Old box-flex <number>

The flex property is more or less unchanged between the new standard and the draft supported by Microsoft. The main difference is that it has been converted to a shorthand in the new version, with separate properties: flex-grow, flex-shrink and flex-basis. The values may be used in the same way in the shorthand. However, the default value for flex-shrink (previously called negative flex) is now 1. This means that items do not shrink by default. Previously, negative free space would be distributed using the flex-shrink ratio, but now it is distributed in proportion to flex-basis multiplied by the flex-shrink ratio.

Direction: specifying the direction of the main flexbox axis Specification Property name Horizontal Reversed horizontal Vertical Reversed vertical Standard flex-direction row row-reverse column column-reverse Mid flex-direction row row-reverse column column-reverse Old box-orient

box-direction horizontal

normal horizontal

reverse vertical

normal vertical

reverse

In the old version of the specification, the box-direction property needs to be set to reverse to get the same behavior as row-reverse or column-reverse in the later version of the specification. This can be omitted if you want the same behavior as row or column because normal is the initial value.

When setting the direction to reverse, the main flexbox axis is flipped. This means that when using a left-to-right writing system, the items will display from right to left when row-reverse is specified. Similarly, column-reverse will lay out flex items from bottom to top, instead of top to bottom.

The old version of the specification also has writing mode-independent values for box-orient. When using a left-to-write writing system, horizontal may be substituted for inline-axis, and vertical may be substituted for block-axis. If you are using a top-to-bottom writing system, such as those traditional in East Asia, then these values would be flipped.

Wrapping: specifying whether and how flex items wrap along the cross-axis Specification Property name No wrapping Wrapping Reversed wrap Standard flex-wrap nowrap wrap wrap-reverse Mid flex-wrap nowrap wrap wrap-reverse Old box-lines single multiple N/A

The wrap-reverse value flips the start and end of the cross-axis, so that if flex items are laid out horizontally, instead of items wrapping onto a new line below, they will wrap onto a new line above.

At the time of writing, Firefox does not support the flex-wrap or older box-lines property. It also doesn’t support the shorthand.

The current specification has a flex-flow shorthand, which controls both wrapping and direction. The behavior is the same as the one in the version of the specification implemented by IE 10. It is also currently not supported by Firefox, so I would recommend to avoid using it when specifying only the flex-direction value.

Conclusion

Well, that’s a (flex-)wrap. In this article, I’ve introduced some of the myriad of possibilities afforded by flexbox. Be it source-order independence, flexible sizing or just the humble centering of elements, I’m sure you can find ways to employ flexbox in your websites and applications. The syntax has settled down (finally!), and implementations are here. All major browsers now support flexbox in at least their latest versions.

While some browsers use an older syntax, Firefox looks like it is close to updating, and IE 11 uses the latest version in leaked Windows Blue builds. There is currently no word on Safari, but it is a no-brainer considering that Chrome had the latest syntax before the Blink-WebKit split. For the time being, use the tables above to map the various syntaxes, and get your flex on.

Layout in CSS is only getting more powerful, and flexbox is one of the first steps out of the quagmire we’ve found ourselves in over the years, first with table-based layouts, then float-based layouts. IE 10 already supports an early draft of the Grid layout specification, which is great for page layout, and Regions and Exclusions will revolutionize how we handle content flow and layout.

Flexbox can be used today if you only need to support relatively modern browsers or can provide a fallback, and in the not too distant future, all sorts of options will be available, so that we can use the best tool for the job. Flexbox is shaping up to be a mighty fine tool.

Further Reading

(al)

© David Storey for Smashing Magazine, 2013.

Categories: Web Design & Culture

Mobile UX Research: Exploring Ten Fundamental Aspects Of M-Commerce Usability

Smashing Magazine - Tue, 05/21/2013 - 06:30

  

Everyone is talking about mobile. Some e-commerce websites are venturing into it. Mobile commerce (also known as “m-commerce”) has immense potential, exhibiting a 86% growth rate and hitting $25 billion in 2012 (set to reach $86 billion by 2016, according to eMarketer).

It’s also a whole new platform, with new interaction methods and usage contexts that introduce a host of limitations and pitfalls to watch out for when designing and running an m-commerce website. With few best practices yet established, m-commerce is, to a large degree, unchartered territory when it comes to actual implementation.

This is why we decided to invest the better part of a year at Baymard Institute to conduct a large-scale usability study focusing specifically on m-commerce (following the “think aloud” protocol). We set out to explore the entire mobile shopping experience, including users’ conceptual understanding of m-commerce websites and how users interact with form fields, category navigation, search, product pages, the checkout process, etc.

The 18 m-commerce websites that we tested were: 1-800-Flowers, Amazon, Avis, Best Buy, Buy.com, Coastal.com, Enterprise.com, Fandango, Foot Locker, FTD, GAP, H&M, Macy’s, REI, Southwest Airlines, Toys “R” Us, United Airlines, Walmart.

Despite testing the mobile websites of some of the largest e-commerce players in the world, our subjects encountered 1,000+ usability-related issues during the testing sessions. These usability issues have been analyzed and distilled into 147 design recommendations in a report titled “M-Commerce Usability.” In this article, we’ll share 10 recommendations from that report with you.

While following some of the guidelines would improve the usability of desktop websites, too, there is a major difference in the severity of breaking them. Whereas these guidelines are largely “nice improvements” on desktop, they are among the “vital basics” to get right on an m-commerce website. Thus, most of these usability guidelines are not exclusive to mobile, but they are much more critical to get right in the m-commerce context.

1. Make The Home Page Easily Scannable

Issue: When users are not able to get an overview of the entire website by quickly scanning the home page, they will feel less confident with the website and often end up choosing the wrong path for their task.

70% of the test subjects scrolled up and down the entire page when first landing on a home page or a category list, in what most described as “getting an overview of my options.” These subjects wanted to see their options before deciding which to choose. Even when they knew how they wanted to find a given product, some subjects still chose to get an overview of the home page, presumably to get a better feel for the website on which they were going to shop. In some instances, when a subject found the category they were looking for, they continued to look through one or two other categories to get a better sense of the other options on the website.


Most subjects scanned the whole home page to get an overview of their options and to better understand what they could do on a particular website. Here, one subject continued to explore the home page options, even after having found his desired navigation path of “category” → “men.”

Therefore, making the home page easily scannable is important because this will be the first point of contact for a very large portion of your mobile visitors. This initial impression will have a significant impact on the types of products they expect your website to carry and, just as importantly, not carry. While “easily scannable” might sound a bit vague, three instances of “what not to do” became clear during testing.

Having Too Many Visual Elements

Avoid the confusing eye path that results from placing multiple highly graphical elements that demand attention high up on the home page. This was the case on Macy’s, where approximately 60% of the first viewable part of the home page is plastered with highly graphical content, with at least eight different elements calling for attention:


Multiple subjects were overwhelmed by Macy’s home page because it was very difficult to scan. As one subject expressed it, “I’m desperately trying to get an overview here. There’s so much crap being shoved at my face.” The right-hand image shows typical eye fixations.

This is not to say you cannot have graphics — but limit their size if they are above the fold on the home page, and design them to have a clear eye path.

Not Showing the First Layer of Categories

Another mistake is unnecessarily hiding the category navigation. Some websites have a single “browse categories” option, which takes the user to a new page with the first layer of category choices. If you have a website where the user cannot browse with any method other than category and search (i.e. not by “brand” or “store” directly from the home page) and the number of main category options is of a somewhat manageable size, then this is an oversimplification. Instead, show the first level of category options directly on the home page so that users can start scanning the list immediately upon landing on the home page.


On the left: On Coastal.com, all the category options are displayed directly on the home page, which not only allows direct access, but gives users an accurate idea of the types of products they can expect to find on the website. For stores with multiple ways of browsing the catalog (e.g. by both “category” and “brand”), displaying the category options directly on the home page might not be feasible. On the right: For stores with a very high number of first-layer categories (typically mass merchants), a curated list with the most popular options might prove to be a better option, because displaying all categories would impede scannability.

Moreover, do not present the categories in a drop-down dialog. Multiple subjects explicitly stated that they had to scroll through the entire list to choose the category in which they expected to find a particular product. The problem with a drop-down quickly became clear, then: because it takes up only 50% of the available screen, getting an overview of the available categories became needlessly difficult (see Best Buy below).

Because the gesture area is also only half the size, the subjects also had a much harder time accurately controlling the scrolling speed. Lastly, the drop-down interface element was confused with a filter selection by some subjects and not recognized as the main website category navigation.


Do not follow the example of Best Buy, which does not have a category option in the main body of its home page content. Instead, a “three bars” icon takes the place of a category option in the page’s header. This not only requires all users to understand the meaning of the three bars icon, but also makes it impossible to get an overview of the store by scanning the home page. And, of course, using a drop-down to actually select a category is not ideal either.

Perfect Fold Alignment

Finally, do not design your website to have perfect alignment or white space exactly at the fold. This happens on GAP’s website, where it is easy to doubt whether the home page contains more than a search field and a few graphics (i.e. no category navigation), because these home page elements align precisely with the viewport fold (on an iPhone at least).


One subject, a bit surprised, asked, “This is it? This is the entire page?” believing this was GAP’s entire home page. When elements are spaced with pixel-perfection alignment around the viewport fold, users are more likely to misinterpret the top part as being the entire home page (in this case, missing out on the category navigation below).

To indicate more content, simply align the elements so that some are only partly viewable within the viewport on the most popular mobile devices.

Therefore, when designing a scannable home page:

  • Put very few (if any) very visually stimulating graphics above the fold on the home page, and make sure the ones that are there have a clear eye path so that the user can quickly get an overview.
  • Try to ensure that the fold (on the most popular mobile devices) partially cuts off some content, to indicate more options below.
  • Display navigation options on the home page as a list (not in a drop-down).
  • If you have only one category navigation type (such as “product type” or “department,” and not also “brand” or “store”), then show the first level of the category hierarchy directly on the home page either in full or, if there are too many options, as a curated and collapsed list of the most popular choices.
  • Only display highlighted or featured products below the search field and the category navigation options.
2. Be Sensitive To People’s Fear Of Losing Their Data

Issue: Typing on mobile devices is clumsy, so users are constantly worried about losing their inputted data.

“Argh, no! Do I have to start over? Now I’m getting angry. Doesn’t it have my shit already?,” a subject moaned, referring to his previously typed address and credit-card information, which suddenly disappeared. “Now I’m leaving. This isn’t a serious store.”

Data persistence is not something to take lightly. Your users certainly don’t. Of course, the recommendation is simple: always persist the user’s data, which requires investing in solid technology, testing thoroughly, and storing inputted data temporarily on the user’s device (most mobile browsers support localStorage). In practice, of course, this is easier said than done, and numerous websites have failed miserably, to the great frustration of users.

Because users have already suffered through many horrible experiences of lost data, they often exhibit extreme caution around certain types of elements and avoid certain interactions when possible. The following screenshot shows the types of actions and elements that particularly worry users. Either avoid these elements altogether or soothe users’ fear with the smart use of microcopy, icons and animations.

During checkout, the subjects consistently opened links in a new window because they were afraid their data would be lost if they opened links in the current window.

Subjects were almost always disturbed by unexpected page reloading (i.e. any page reloading that is not a direct consequence of clicking a link or button). In the image above, a subject selected a “Residence type,” which reloaded the page, causing the subject to immediately scroll up and down to ensure that none of their data was lost. We observed this type of unease with page reloading among subjects time and again throughout testing.

Many subjects were scared by system dialogs and often assumed that they would lose data by clicking “OK,” even though few of them actually read the message. The subject in the test shown above wanted to go backwards in the process to pick another ticket but was met with this dialog, which he cancelled — assuming that he would have to re-enter everything if he wanted to select another ticket.

A good number of the subjects believed that leaving the checkout process would destroy their data and so refused to go back and check for other products. The subject in the test above contemplated going back to find another bouquet of flowers, but decided against it because he did not want to re-enter all of his data. This happened despite many of the test websites actually remembering the users’ details, even if the users left the checkout process midway — the keyword, of course, being “many” websites, rather than “all.” Given this inconsistency, users have no way to know beforehand, so their only safe choice is to just assume the worst on all websites.

During checkout, the “back” button was generally perceived by the subjects to be dangerous, and subjects used it during checkout only when they felt they were out of all other options. In many cases, this perception was justified: numerous websites did indeed fail to persist the user’s data when they used the “back” button. However, equally important is that process step links and other “back” links and buttons that were part of the website’s UI were generally considered by the subjects to be “safe.”

Therefore, including either process steps or “back” links in the checkout is crucial so that users do not feel they have to gamble by using the browser’s “back” button and can instead use your website’s dedicated UI element(s) for the purpose. In the test shown above, the subject hunted up and down to find a link or button that would take him back to the previous step, but was unable to find one. Finally, he tried the browser’s “back” button.

These were the most significant insights relating to users’ fear of lost input. In general, the subjects were vastly more pessimistic about websites on which they had once lost data. For example, clicking the keyboard’s “next” button cleared one subject’s input on a website, which made her consistently avoid that button throughout the rest of the checkout. As she said, “Here, I don’t dare click ‘Next’ anymore because I don’t want to start over again.” Not only that, the subject also became overly cautious when interacting with any fields on the website, fearing that even the slightest hiccup would destroy her data.

A single bad experience set low expectations for the rest of the website. So, how do we avoid bad experiences in cases where we are unable to persist the user’s data due to technical limitations? In these instances, clearly warn the user that they are about to do something destructive.


As the subject left the incomplete checkout, the website warned her that her data would be lost. “This is very good,” the subject remarked, “because if I did something wrong by accident, I would be extremely annoyed if they deleted everything. So, it’s good that they warn me like this if the data would otherwise be lost.”

Persisting data is always the ideal, of course, but warning the user and giving them the option to back out before destroying their data is a good secondary solution, and it sure beats simply destroying the user’s data without warning; moreover, it gives the user a chance to cancel the destructive action. This type of fallback solution could be especially useful for less common navigation paths, where persistent data is too time-consuming to implement, considering how few users it affects.

This could also entail something like persisting the user’s cart or checkout data when switching between the full website and mobile website. In these instances, it is acceptable to simply warn the user that they will lose their data if they proceed, and then give them the option to proceed (and lose their data) or stay (and keep their data).

Data persistence is clearly a complex matter, especially when one considers the user’s expectations towards data persistence. We observed subjects creating accounts merely to ensure persistence, and witnessed data lost due to accidental clicks, and we watched with as much surprise as the subject when an entire form was remembered perfectly by autofill, turning potentially horrible data loss into a small moment of joy. Data persistence is tricky, but getting it right is crucial.

3. Add A Primary Button At The Bottom Of Product Pages

Issue: Users are likely to misinterpret cart buttons in the page’s footer if there is no “Add to Cart” button at the bottom of every product page.

A wide range of the tested websites had multiple identical primary call-to-action (CTA) buttons on product pages (i.e. two “Add to Cart” buttons), one at either the top or middle of the product page and a second one at the bottom.


On Best Buy, one subject read this product’s entire specification sheet and was in the mindset of “Yes, this is the product I want to purchase.” He saw the website’s shopping-cart icon at the bottom of the page (second image above) and clicked it, believing it was an “Add to Cart” button. Logically, he assumed the product would be added to his cart and so continued browsing for more products, only to notice much later in the shopping session that the website had “deleted” his cart’s contents (the TV was never added in the first place).


The subject here on Amazon thought the shopping-cart icon was the button for adding the displayed product to her cart.

It turned out that on the websites with only one CTA button on a product page, subjects often ran into severe problems even with adding a product to their cart — which, in some cases, ultimately led to abandonments. Cart icons in the page’s header or footer were often mistaken for an “Add to Cart” button.

Both Best Buy and Amazon failed to make the primary buttons immediately obvious and generally available, which led subjects to start interpreting various icons on the page, including the cart icon, as shown in the two examples above. Subjects often scrolled to the bottom of a product’s page when looking for the “Add to Cart” button (a behavior confirmed in another study).


This subject started looking for the “Add to cart” button by scrolling to the bottom of the page, then scrolling back to the top of the page, thinking she might have missed it, and finally scrolling down again patiently, until finding the “Add to bag” button in the middle of the page.

To accommodate this behavior and reduce misinterpretation of any cart icons, add a second “Add to Cart” button to the bottom of all of your product pages. A second button there will also support a more natural interaction flow, as the user first reads the product description, then the specification sheet, then the reviews and so on, and then, at the end of the page, decides whether to buy or not. Only if the product page is extremely short (one to two mobile viewports tall) would a single button suffice.

4. Be Very Careful With Animated Carousels

IssueUsers fail to discover vital features that appear only in a carousel, and they have a hard time interacting with carousels themselves.

Animated carousels caused interaction problems for half of the test’s subjects. The carousels simply changed too quickly for some subjects to both read and select an option.


A subject was about to click the “Mega Sale” slide (left image), but the carousel animated to the next slide at the very same moment, forcing the subject to wait for that slide to reappear.

In multiple instances, a subject found a carousel slide interesting and attempted to tap it. However, the carousel changed to the next slide at the very same moment, causing the wrong slide to load. Sometimes the subjects noted this, but sometimes they did not and left the landing page immediately because they did not find it relevant to what they were looking for.

Interestingly, the “Prev” and “Next” buttons in the Toys “R” Us carousel were not used by a single subject during testing, despite these issues:


The carousel changed the very second this subject tapped it, registering a click for “Bike Blast” instead of the “Mega Sale” she wanted. The subject never noticed and assumed that “Bike Blast” was the sale.

Both of these interaction issues were also encountered (and still exist) in the early versions of carousels on full websites, but as carousels have become increasingly popular on e-commerce home pages over the last several of years, they have evolved, so most now stop animating when the user hovers over an option with the mouse.

And most also have an indicator that enables the user to see how many slides a carousel has and, just as importantly, to jump to a particular slide (such as back to the one that piqued their interest but changed too quickly). These interaction issues cannot be easily solved on mobile because there is no hover state and much less screen real estate.


On Toys “R” Us’ home page, the subjects pored over the menus to find a “Gift Guide” wizard but could not find one (image on left). It turns out there is a wizard but is accessible only via a particular slide in the rotating carousel at the top of the page.

Perhaps an even more critical usability issue is that most test subjects simply ignored the carousel after quickly glancing at the first slide. Some waited and looked at two to three slides before focusing elsewhere. This proved critical on some websites, such as Toys “R” Us’, because the majority of subjects were desperately looking in the traditional navigation for certain features (such as the “Gift Finder”) that were accessible only via the carousel. Some subjects spoke at length about how the website really should have some sort of “gift guide,” ultimately abandoning the website because they could not find one.

Users ignore animated carousels for multiple reasons. First, a carousel’s content might look like advertising, depending on how it is styled, greatly increasing the chance of banner blindness (a subgroup of subjects tended to focus much more closely on text-based navigation than on graphics-based navigation). Secondly, when using a large laptop or desktop monitor to browse a full website, the user is able to check out other options on the home page while still glancing at the carousel slides as they change.

On mobile devices, however, the screen is so small that a carousel would take up a significant portion of the viewport, making it practically impossible to scan any navigation or category options while monitoring the carousel slides (one of them will always be partly or completely out of sight). Therefore, if users are to see all options in a carousel on a mobile device, they will have to watch the carousel for its full duration (like a video clip).

Regardless of the cause(s), what is really important is that the vast majority of subjects ignored the animated carousels completely and, on the home page, focused instead on the category navigation and search features. For this reason, be very cautious about relying on carousels for important content, and never have it as the only path to a particular feature.

5. Be Careful Of Showing Product Information Or Images On Separate Subpages

Issue: Users have incredible difficulty understanding the scope of product subpages.

On a mobile device, understanding the scope of the current page is vastly more difficult for users, due to the very small display. Mobile pages often lack the subtle yet vital page-scope cues that are present on full-size pages, such as a full set of breadcrumbs, an overview of the current page, and full URL paths viewable throughout the browsing session.

This lack of scope on mobile makes having any kind of substeps or subpages that refer to a main page very risky, because the user would have to fully understand the scope of the current page in order to appreciate the difference between the subpage and main page.


When users want to see larger versions of images of an Amazon product (left), they are taken to a subpage (middle). Our test subjects clearly noticed that they were still within a product’s particular scope (because of the large product image), but they did not understand where the rest of the product page went (right).

This became immediately apparent when testing websites that offer a “larger view” option of their images, taking users to a separate product subpage, as seen on Amazon above. Because of the apparent lack of access to vital content, such as “Product Description,” “Product Specs” and “User Reviews” (which are available only on the main product page), the subjects who did not notice this change in scope assumed that such content simply did not exist for the given product and continued looking for other products with such information, discarding perfectly matching ones.


Amazon also uses subpages to show full specification lists, causing the exact same issue, except that this time subjects were unable to locate something as vital as the “Add to Cart” button.

On a mobile device, and especially on subpages, understanding the current scope is simply much more difficult. Instead, display your “larger views,” image galleries, detailed specification sheets and the like (i.e. all relevant content) directly on the product’s main page. You could also use progressive disclosure by collapsing each content section by default, to avoid overly long pages; but then be sure to have clear trigger indicators. A strategy such as this minimizes the need to display additional information and images on subpages and the resulting scope issues.

Especially with image galleries, you also have the option of an overlay, as shown above on Foot Locker. With an overlay, the user can still see the product page beneath and have a simple way to get back to it.

6. Be Thoughtful In The Design And Sequence Of Your Three Account-Selection Options

IssueUsers had difficulty figuring out how to initiate “Guest Checkout” and understanding field relationships, selection options and buttons in the account-selection steps.

On mobile, the user’s selection of a checkout type — “create an account,” “sign into account” or “guest checkout” — will be a separate step (unlike on full websites, where it could be integrated into the first step). More than half of the test subjects (60%) had serious trouble identifying, seeing and selecting the guest-checkout option at the account selection step during checkout.

Multiple times, the misunderstandings led subjects to believe that registration was required, despite it being optional, and carried all of the downsides of forced account registration (including abandonments). Therefore, the design of your account-selection screen for mobile is just as important as having a guest-checkout option at all.

Several different design schemes led to these serious misunderstandings, as the following screenshots illustrate.

On Macy’s, subjects saw the account-selection step (above left) after selecting the cart. Some clicked “Express Checkout,” believing they would have a fast checkout (as a guest), only to get form-field validation errors for the two fields because “Express Checkout” requires a Macy’s account (above center). Some only discovered the “Checkout as a Guest” option further down the page (right), after getting this validation error, while others never noticed the guest-checkout option and registered for an account, believing it was required.

On multiple websites (Amazon, Toys “R” Us, REI, GAP, Best Buy), subjects started to interact with the fields, such as by providing their email address (above). On REI, every single subject interacted with the email field before looking for, or figuring out that there was, a guest-checkout option.

In most cases, the subjects spotted the error before submitting the form (typically upon reaching the password field and deducing that they were on an account sign-in or creation form). In such cases, not even detailed analysis of your Web statistics and error logs would reveal these issues because no validation error ever occurs.

On Buy.com, things are even worse. The vast majority of subjects simply could not figure out the relationship between the four checkout methods (sign-in, create account, guest checkout and PayPal checkout), the two form fields, the three radio buttons and the two primary buttons. All tapped the “Checkout as a Guest” option after spending some time trying to understand the page.

Then, the naming of the “Sign in Using Our Secure Server” button utterly confused subjects because they were trying to check out as a guest (and, therefore, actively opted not to sign into anything). This particular naming has been used by Amazon for years and has even been highlighted as a best practice to indicate a secure checkout, so how could it lead to such major misinterpretation?

The reason is that it indicates the user will sign in, which makes sense only if they have an account or will create one, but not if they are checking out as a guest. (Amazon does not offer a guest-checkout option, so the wording makes sense in that context.) Given the button’s name, one subject assumed that the only other prominent button on the page, “Checkout with PayPal,” must be the one to pick to initiate the “Checkout as a guest” selection.

Others finally clicked the oddly named button — but nothing seemed to happen. It turns out that inline text reading “Required” appeared next to the “Enter your eMail Address” label (seen above), but no one noticed it initially. The subjects typically waited for a little while just in case the website did not load, and then clicked again, at which point most realized that they needed to fill in more data. By this point, some, especially those who did not notice the validation error, concluded that they were not allowed to check out as a guest and proceeded to create an account instead.

One explained his experience thusly, “Normally I would think ‘guest checkout’ would let me through without having to create an account. But here I have to fill in my mail, so I have no idea what that option is for, then. To be on the safe side, I’ll then pick the ‘No, I’m a new customer,’ because if I’m forced to create an account, I might as well just do it properly anyways.”

Making the account-selection process clear is as important as offering a guest checkout option. Following two main design principles will help to prevent these serious problems:

  • Always place the guest-checkout option at the top, with its own button to proceed, so that the user does not need to fill in an email field in this step. (If needed, you can look up whether the user has an account in the next step, when you ask for their email address, to ensure that they have not selected the guest checkout just because it is the first option in the list.)
  • Collapse all of the fields and descriptions for all three options — “guest checkout,” “sign in” and “create an account” — bringing each option down to a single line, making it possible to get an overview in the viewport without having to scroll or expand. Dynamically expand them when tapped, revealing the fields and descriptions. This will also make clear which fields are related (and required) for each option.

Below, we have created a simple mockup to illustrate how account selection can be clarified by combining these two principles:


All three account-selection options are displayed in collapsed state (with guest checkout at the top), so that the user can instantly see all available options. The options can either expand inline (image on right) or redirect to the next step in the checkout process. Progressive disclosure also makes the relationship between an option and its fields much clearer.

7. Disable Autocorrection When The Dictionary Is Weak

IssuePoor autocorrection is frustrating when users notice it, and can be detrimental when they do not.

Autocorrection usually works poorly for abbreviations, street names, email addresses and similar words that are not in the dictionary. This caused significant problems throughout testing and resulted in a great deal of erroneous data being submitted as subjects completed their purchases.


When this subject typed in his street name, “westheimer,” the phone incorrectly autocorrected this to “weathermen” (left). However, the subject did not notice this, submitted the form and received a validation error (right).

One of the major issues of autocorrection was that the subjects often failed to notice the correction (because they were often focused on what they were typing, instead of what they had typed). This is fine if the “correction” is correct, but it can be detrimental if it is wrong. For example, in multiple instances, a valid address was autocorrected to an invalid one and submitted because the subject failed to notice it.

On websites without address validators, this resulted in wrong addresses being submitted, unless the subject was particularly attentive on the order review page. After all, the user’s address will often be replaced with something that looks very similar, although incorrect. In addition to the “weathermen” example, official address abbreviations, such as “Rd,” were autocorrected, to “Ed.”

That being said, autocorrection did prove very helpful when it worked. So, don’t disable it in all fields. Use it discreetly, and disable it on fields for which autocorrection dictionaries are weak. This typically includes names of various sorts (street, city, user) and other identifiers (such as email address).

You can disable autocorrection by adding an autocorrect attribute to the input tag and setting it to off, like so:

<input type="text" autocorrect="off" /> 8. Make Fields Long Enough To Fully Display Common Data (And Put Labels Above Fields)

IssueUsers cannot easily spot errors, let alone correct them, when the field is too short to display the entire inputted data.

Due to the small size of mobile screens, form fields often get so short that users cannot self-validate before submitting their data, and users have a very difficult time correcting any validation errors because they cannot see the inputted data in its entirety.


“I can’t see what I’ve typed. Argh. Then I’ll delete everything and retype it.” On REI, a validation error for an email field that was too short to be displayed in its entirety made it impossible for the subject to see what the actual error was. In trying to pan the inputted text, the subject accidentally enabled both the iOS text-selection tool and the text-replacement tool.

Form fields that are too short presented problems for many subjects who tried to confirm the validity of their data before submitting it. They often made complaints such as, “I can’t see if the emails are the same when the email field isn’t long enough.” Some examples are seen below.


On the left: Amazon’s email field is too short, despite the abundance of white space. In the middle: United’s credit-card field shows only 15 characters, even though most card numbers are 16 digits. On the right: Macy’s email fields are too short for users to verify whether the two addresses they’ve inputted match.

Given how easy it is to make a typing mistake on a mobile device, fields that are not long enough to allow users to validate their data before submission are very harmful to the typing experience. Even worse, they make correcting any validation errors unnecessarily difficult.

Note that in the case of Amazon and the earlier example from REI, the white space is sufficient to make the field much longer, while the other two examples have no additional space to make the fields longer because the labels are all left-aligned. For this very reason, labels should be placed above form fields to allow full use of the space and to display all of the user’s data (at a decent font size). Displaying labels to the left of the fields would be acceptable only when the device is in landscape mode (as explained in detail in “Mobile Form Usability: Place Labels Above the Field”).

An adequate width for email and address lines is the full screen. Then, adjust the font size of the fields to allow for the full display of reasonably long data, such as first.lastname@my-company.com. (The character-length distribution of our own newsletter list shows that 96% of email addresses are 30 characters or fewer.)

9. Enable Users To Verify The Inputted Day And Date

IssueUsing text fields for dates requires unnecessary mental processing of the user and can cause serious selection errors.

During testing, websites that had only a simple text field or drop-down dialog for date selection presented problems for 80% of the subjects.


This subject was among the 80% who were unsure which date “this Friday” was. So, she decided to count the days on her hand, wanting to make sure she picked the right one.

This happened with both Southwest (which uses drop-downs for the month and day) and United (which shows a text field for writing MM/DD/YYYY). On both of these websites, the following scenarios occurred:

  • A handful of subjects had to count the days on their hand (as explained above).
  • Half of the subjects went off-site and opened the phone’s native calendar app to double-check the date for their weekend trip (to confirm “this Friday”). In the instance seen above, this calendar verification goes completely awry because the subject checked the day of June 15th, instead of July 15th, and ended up purchasing a flight ticket for his “weekend” trip that left on a Sunday and returned on a Tuesday.

  • Lastly, a few struggled with typing and using the text-selection tool to enter the correct date on a website that uses a text field for date selection.

By contrast, on the three test websites that provided a graphical interface for inputting dates in the form of a calendar view (namely, Enterprise, Avis and 1-800-Flowers, seen above), not a single one of these issues arose, and the subjects generally liked being able to verify the day and date they were selecting. This could potentially save customers from incorrectly counting or “verifying” the wrong weekday (as mentioned earlier) and thus booking the wrong date.

While this is an annoyance on desktop as well (since the user would be no better equipped to spot the errors there), the severity and impact on the user’s experience is much greater in mobile when it comes to correcting the erroneous data, because panning and editing truncated data on a three- or four-inch touchscreen is much more cumbersome than using a mouse or keyboard arrows on a desktop. Furthermore, ordering tickets on the wrong day is much less likely on the desktop because the booking form and a separate calendar application can be displayed next to each other — whereas on mobile, only one can be viewed at a time.

Therefore, always provide an interface that enables users to verify the day of their selected date. One option is to display a calendar interface in which the user explicitly selects the date they want. That would simplify the actual selection interface and, more importantly, gives users a chance to verify the day. If you already use a drop-down for date inputs and do not want to replace it, you could instead append the day after each date option (for example, “March 15 – Monday”); although that would require the month to be included in each drop-down day value or, in case a separate drop-down is used to select the month, you would need to dynamically update the day names depending on the currently selected month.

10. Make The Hit Area For Each List Item Distinct

IssueWith some lists, users simply have no idea where to tap in order to select an item.

Can the entire “element” be tapped? Or only the product title? And what about the thumbnail? During testing, multiple issues arose as subjects were unsure of where to tap in order to select an item in a list. This was by far the worst on websites where list items were above the recommended half-screen height. In fact, one subject got completely stuck and was unable to complete her purchase.

The problem was by no means limited to websites with list items that were too tall; it was just worse on those websites. The issue also extended to websites whose list items were normal in size but whose hit areas were unclear, which severely limited the subjects and even resulted in abandonments.


It simply was not clear to subjects what can and cannot be clicked on this page. Note the very inconsistent link styles. Orange is sometimes used for the header, other times for a list item. Separators are sometimes used to set off list items, other times to set off elements of text. Some text is one shade of blue, which sometimes indicates a link, while other links are styled in a darker blue and underlined. Confused yet? The subjects were, too.


Note how the subject was trying to click the “Lowest Fare” label, believing this was the button to choose the displayed flight. Besides the primary button being unclear, the list item is also very long. Combined, these two design choices are a surefire way to leave some users in doubt on how to even proceed.


On the left: This subject did not know what to click in order to proceed on United’s website. Presumably, this was caused by the single result. With no options to compare and choose between, it was not clear to the subject what to select. On the right: Many subjects did not pick up on the ticket icon and its meaning on Fandango’s website. Instead, they assumed that the movie was playing only in theaters where a “Buy” button was shown (which was not the case).

The images above show only some of the many instances where it was unclear to subjects what elements are clickable, what the differences are between the different hit areas and, most importantly, where to click in order to select an item in a list. The websites with the far fewest problems with hit areas embraced multiple of the following recommendations:

  • Make the entire element area clickable. In particular, the thumbnail, product header and price should be clickable and should lead to the product page.
  • Style the title as a link (using your primary style for text links).
  • Indicate the virtual space with an arrow or similar visual cue, showing that the entire list item will move the user to the next step in the process.
  • Consider separate “Buy Now” or select buttons for very long list items — i.e. when a list item could be easily mistaken as pieces of information, rather than a collective entity to be clicked.
  • Avoid multiple hit areas within the same visual element — in particular, links or buttons within a list item that lead to different pages.
Designing M-Commerce Websites

Aside from their practical use, these 10 recommendations have hopefully given you a glimpse of just how complex designing an m-commerce website really can be. It’s not simply a matter scaling and adding media queries; it’s an entirely new platform, and the balancing act is particularly difficult to get right due to the complex tasks involved, such as product finding and product comparison and multi-step processes such as checking out. In many ways, designing and optimizing an m-commerce website is much more difficult and often requires more “intelligent” website features than a traditional desktop e-commerce website. It comes as no surprise that IBM reports average m-commerce conversion rates that are roughly half of its desktop e-commerce conversion rates.

In general, the more complex a mobile website’s features, the more likely the experience should be significantly different from the desktop experience. The greater the difference between the two, the stronger the argument for having a standalone mobile website. Of course, maintaining two versions of the same website comes with many issues, especially with maintenance (of content, code and design). A responsive design is a better solution in some cases, but it depends very much on the size and complexity of the website, as well as on your organization’s strengths and weaknesses. It’s a nuanced issue, with many gray areas and with good arguments both for and against having a standalone mobile website.

If you can achieve this by designing for mobile first, then a responsive design could be truly great — not just in its maintainability, but also its user experience. Be clear, however, that if your existing website is complex, merely scaling it down to different devices won’t be enough to offer a great mobile experience. And if messing with the full website’s existing structure and content isn’t an option, then you might be forced to create a standalone mobile website in order to provide a decent experience — although maintaining content and code on the two separate platforms in parallel could turn out to be both expensive and messy.

Thus, getting an m-commerce website right tends to be very resource-demanding, as you account for all of the nuances. But the opportunities are great. This is a new world, and it will take time before best practices stabilize. Spending time and money on a mediocre m-commerce website is wasteful. Yes, making the website great will require significant investment, but the potential payoff is high, too. M-commerce is a window of opportunity; it enables you to distinguish yourself from competitors and to position yourself well to grab a share of this market, which is expected to reach $86 billion by 2016.

Note: Find out more about m-commerce usability guidelines in the (paid) report “M-Commerce Usability.”

(al) (il)

© Christian Holst for Smashing Magazine, 2013.

Categories: Web Design & Culture

The Design of Code: Organizing JavaScript

A List Apart - Tue, 05/21/2013 - 05:00

Great design is a product of care and attention applied to areas that matter, resulting in a useful, understandable, and hopefully beautiful user interface. But don’t be fooled into thinking that design is left only for designers.

There is a lot of design in code, and I don’t mean code that builds the user interface—I mean the design of code.

Well-designed code is much easier to maintain, optimize, and extend, making for more efficient developers. That means more focus and energy can be spent on building great things, which makes everyone happy—users, developers, and stakeholders.

There are three high-level, language-agnostic aspects to code design that are particularly important.

  1. System architecture—The basic layout of the codebase. Rules that govern how various components, such as models, views, and controllers, interact with each other.
  2. Maintainability—How well can the code be improved and extended?
  3. Reusability—How reusable are the application’s components? How easily can each implementation of a component be customized?

In looser languages, specifically JavaScript, it takes a bit of discipline to write well-designed code. The JavaScript environment is so forgiving that it’s easy to throw bits and pieces everywhere and still have things work. Establishing system architecture early (and sticking to it!) provides constraints to your codebase, ensuring consistency throughout.

One approach I’m fond of consists of a tried-and-true software design pattern, the module pattern, whose extensible structure lends itself to a solid system architecture and a maintainable codebase. I like building modules within a jQuery plugin, which makes for beautiful reusability, provides robust options, and exposes a well-crafted API.

Below, I’ll walk through how to craft your code into well-organized components that can be reused in projects to come.

The module pattern

There are a lot of design patterns out there, and equally as many resources on them. Addy Osmani wrote an amazing (free!) book on design patterns in JavaScript, which I highly recommend to developers of all levels.

The module pattern is a simple structural foundation that can help keep your code clean and organized. A “module” is just a standard object literal containing methods and properties, and that simplicity is the best thing about this pattern: even someone unfamiliar with traditional software design patterns would be able to look at the code and instantly understand how it works.

In applications that use this pattern, each component gets its own distinct module. For example, to build autocomplete functionality, you’d create a module for the textfield and a module for the results list. These two modules would work together, but the textfield code wouldn’t touch the results list code, and vice versa.

That decoupling of components is why the module pattern is great for building solid system architecture. Relationships within the application are well-defined; anything related to the textfield is managed by the textfield module, not strewn throughout the codebase—resulting in clear code.

Another benefit of module-based organization is that it is inherently maintainable. Modules can be improved and optimized independently without affecting any other part of the application.

I used the module pattern for the basic structure of jPanelMenu, the jQuery plugin I built for off-canvas menu systems. I’ll use that as an example to illustrate the process of building a module.

Building a module

To begin, I define three methods and a property that are used to manage the interactions of the menu system.

var jpm = { animated: true, openMenu: function( ) { … this.setMenuStyle( ); }, closeMenu: function( ) { … this.setMenuStyle( ); }, setMenuStyle: function( ) { … } };

The idea is to break down code into the smallest, most reusable bits possible. I could have written just one toggleMenu( ) method, but creating distinct openMenu( ) and closeMenu( ) methods provides more control and reusability within the module.

Notice that calls to module methods and properties from within the module itself (such as the calls to setMenuStyle( )) are prefixed with the this keyword—that’s how modules access their own members.

That’s the basic structure of a module. You can continue to add methods and properties as needed, but it doesn’t get any more complex than that. After the structural foundations are in place, the reusability layer—options and an exposed API—can be built on top.

jQuery plugins

The third aspect of well-designed code is probably the most crucial: reusability. This section comes with a caveat. While there are obviously ways to build and implement reusable components in raw JavaScript (we’re about 90 percent of the way there with our module above), I prefer to build jQuery plugins for more complex things, for a few reasons.

Most importantly, it’s a form of unobtrusive communication. If you used jQuery to build a component, you should make that obvious to those implementing it. Building the component as a jQuery plugin is a great way to say that jQuery is required.

In addition, the implementation code will be consistent with the rest of the jQuery-based project code. That’s good for aesthetic reasons, but it also means (to an extent) that developers can predict how to interact with the plugin without too much research. Just one more way to build a better developer interface.

Before you begin building a jQuery plugin, ensure that the plugin does not conflict with other JavaScript libraries using the $ notation. That’s a lot simpler than it sounds—just wrap your plugin code like so:

(function($) { // jQuery plugin code here })(jQuery);

Next, we set up our plugin and drop our previously built module code inside. A plugin is just a method defined on the jQuery ($) object.

(function($) { $.jPanelMenu = function( ) { var jpm = { animated: true, openMenu: function( ) { … this.setMenuStyle( ); }, closeMenu: function( ) { … this.setMenuStyle( ); }, setMenuStyle: function( ) { … } }; }; })(jQuery);

All it takes to use the plugin is a call to the function you just created.

var jpm = $.jPanelMenu( ); Options

Options are essential to any truly reusable plugin because they allow for customizations to each implementation. Every project brings with it a slew of design styles, interaction types, and content structures. Customizable options help ensure that you can adapt the plugin to fit within those project constraints.

It’s best practice to provide good default values for your options. The easiest way to do that is to use jQuery’s $.extend( ) method, which accepts (at least) two arguments.

As the first argument of $.extend( ), define an object with all available options and their default values. As the second argument, pass through the passed-in options. This will merge the two objects, overriding the defaults with any passed-in options.

(function($) { $.jPanelMenu = function(options) { var jpm = { options: $.extend({ 'animated': true, 'duration': 500, 'direction': 'left' }, options), openMenu: function( ) { … this.setMenuStyle( ); }, closeMenu: function( ) { … this.setMenuStyle( ); }, setMenuStyle: function( ) { … } }; }; })(jQuery);

Beyond providing good defaults, options become almost self-documenting—someone can look at the code and see all of the available options immediately.

Expose as many options as is feasible. The customization will help in future implementations, and flexibility never hurts.

API

Options are terrific ways to customize how a plugin works. An API, on the other hand, enables extensions to the plugin’s functionality by exposing methods and properties for the implementation code to take advantage of.

While it’s great to expose as much as possible through an API, the outside world shouldn’t have access to all internal methods and properties. Ideally, you should expose only the elements that will be used.

In our example, the exposed API should include calls to open and close the menu, but nothing else. The internal setMenuStyle( ) method runs when the menu opens and closes, but the public doesn’t need access to it.

To expose an API, return an object with any desired methods and properties at the end of the plugin code. You can even map returned methods and properties to those within the module code—this is where the beautiful organization of the module pattern really shines.

(function($) { $.jPanelMenu = function(options) { var jpm = { options: $.extend({ 'animated': true, 'duration': 500, 'direction': 'left' }, options), openMenu: function( ) { … this.setMenuStyle( ); }, closeMenu: function( ) { … this.setMenuStyle( ); }, setMenuStyle: function( ) { … } }; return { open: jpm.openMenu, close: jpm.closeMenu, someComplexMethod: function( ) { … } }; }; })(jQuery);

API methods and properties will be available through the object returned from the plugin initialization.

var jpm = $.jPanelMenu({ duration: 1000, … }); jpm.open( ); Polishing developer interfaces

With just a few simple constructs and guidelines, we’ve built ourselves a reusable, extensible plugin that will help make our lives easier. Like any part of what we do, experiment with this structure to see if it works for you, your team, and your workflow.

Whenever I find myself building something with a potential for reuse, I break it out into a module-based jQuery plugin. The best part about this approach is that it forces you to use—and test—the code you write. By using something as you build it, you’ll quickly identify strengths, discover shortcomings, and plan changes.

This process leads to battle-tested code ready for open-source contributions, or to be sold and distributed. I’ve released my (mostly) polished plugins as open-source projects on GitHub.

Even if you aren’t building something to be released in the wild, it’s still important to think about the design of your code. Your future self will thank you.

Categories: Web Design & Culture

Writing Testable JavaScript

A List Apart - Tue, 05/21/2013 - 05:00

We’ve all been there: that bit of JavaScript functionality that started out as just a handful of lines grows to a dozen, then two dozen, then more. Along the way, a function picks up a few more arguments; a conditional picks up a few more conditions. And then one day, the bug report comes in: something’s broken, and it’s up to us to untangle the mess.

As we ask our client-side code to take on more and more responsibilities—indeed, whole applications are living largely in the browser these days—two things are becoming clear. One, we can’t just point and click our way through testing that things are working as we expect; automated tests are key to having confidence in our code. Two, we’re probably going to have to change how we write our code in order to make it possible to write tests.

Really, we need to change how we code? Yes—because even if we know that automated tests are a good thing, most of us are probably only able to write integration tests right now. Integration tests are valuable because they focus on how the pieces of an application work together, but what they don’t do is tell us whether individual units of functionality are behaving as expected.

That’s where unit testing comes in. And we’ll have a very hard time writing unit tests until we start writing testable JavaScript.

Unit vs. integration: what’s the difference?

Writing integration tests is usually fairly straightforward: we simply write code that describes how a user interacts with our app, and what the user should expect to see as she does. Selenium is a popular tool for automating browsers. Capybara for Ruby makes it easy to talk to Selenium, and there are plenty of tools for other languages, too.

Here’s an integration test for a portion of a search app:

def test_search fill_in('q', :with => 'cat') find('.btn').click assert( find('#results li').has_content?('cat'), 'Search results are shown' ) assert( page.has_no_selector?('#results li.no-results'), 'No results is not shown' ) end

Whereas an integration test is interested in a user’s interaction with an app, a unit test is narrowly focused on a small piece of code:

When I call a function with a certain input, do I receive the expected output?

Apps that are written in a traditional procedural style can be very difficult to unit test—and difficult to maintain, debug, and extend, too. But if we write our code with our future unit testing needs in mind, we will not only find that writing the tests becomes more straightforward than we might have expected, but also that we’ll simply write better code, too.

To see what I’m talking about, let’s take a look at a simple search app:

When a user enters a search term, the app sends an XHR to the server for the corresponding data. When the server responds with the data, formatted as JSON, the app takes that data and displays it on the page, using client-side templating. A user can click on a search result to indicate that he “likes” it; when this happens, the name of the person he liked is added to the “Liked” list on the right-hand side.

A “traditional” JavaScript implementation of this app might look like this:

var tmplCache = {}; function loadTemplate (name) { if (!tmplCache[name]) { tmplCache[name] = $.get('/templates/' + name); } return tmplCache[name]; } $(function () { var resultsList = $('#results'); var liked = $('#liked'); var pending = false; $('#searchForm').on('submit', function (e) { e.preventDefault(); if (pending) { return; } var form = $(this); var query = $.trim( form.find('input[name="q"]').val() ); if (!query) { return; } pending = true; $.ajax('/data/search.json', { data : { q: query }, dataType : 'json', success : function (data) { loadTemplate('people-detailed.tmpl').then(function (t) { var tmpl = _.template(t); resultsList.html( tmpl({ people : data.results }) ); pending = false; }); } }); $('<li>', { 'class' : 'pending', html : 'Searching &hellip;' }).appendTo( resultsList.empty() ); }); resultsList.on('click', '.like', function (e) { e.preventDefault(); var name = $(this).closest('li').find('h2').text(); liked.find('.no-results').remove(); $('<li>', { text: name }).appendTo(liked); }); });

My friend Adam Sontag calls this Choose Your Own Adventure code—on any given line, we might be dealing with presentation, or data, or user interaction, or application state. Who knows! It’s easy enough to write integration tests for this kind of code, but it’s hard to test individual units of functionality.

What makes it hard? Four things:

  • A general lack of structure; almost everything happens in a $(document).ready() callback, and then in anonymous functions that can’t be tested because they aren’t exposed.
  • Complex functions; if a function is more than 10 lines, like the submit handler, it’s highly likely that it’s doing too much.
  • Hidden or shared state; for example, since pending is in a closure, there’s no way to test whether the pending state is set correctly.
  • Tight coupling; for example, a $.ajax success handler shouldn’t need direct access to the DOM.
Organizing our code

The first step toward solving this is to take a less tangled approach to our code, breaking it up into a few different areas of responsibility:

  • Presentation and interaction
  • Data management and persistence
  • Overall application state
  • Setup and glue code to make the pieces work together

In the “traditional” implementation shown above, these four categories are intermingled—on one line we’re dealing with presentation, and two lines later we might be communicating with the server.

While we can absolutely write integration tests for this code—and we should!—writing unit tests for it is pretty difficult. In our functional tests, we can make assertions such as “when a user searches for something, she should see the appropriate results,” but we can’t get much more specific. If something goes wrong, we’ll have to track down exactly where it went wrong, and our functional tests won’t help much with that.

If we rethink how we write our code, though, we can write unit tests that will give us better insight into where things went wrong, and also help us end up with code that’s easier to reuse, maintain, and extend.

Our new code will follow a few guiding principles:

  • Represent each distinct piece of behavior as a separate object that falls into one of the four areas of responsibility and doesn’t need to know about other objects. This will help us avoid creating tangled code.
  • Support configurability, rather than hard-coding things. This will prevent us from replicating our entire HTML environment in order to write our tests.
  • Keep our objects’ methods simple and brief. This will help us keep our tests simple and our code easy to read.
  • Use constructor functions to create instances of objects. This will make it possible to create “clean” copies of each piece of code for the sake of testing.

To start with, we need to figure out how we’ll break our application into different pieces. We’ll have three pieces dedicated to presentation and interaction: the Search Form, the Search Results, and the Likes Box.

We’ll also have a piece dedicated to fetching data from the server and a piece dedicated to gluing everything together.

Let’s start by looking at one of the simplest pieces of our application: the Likes Box. In the original version of the app, this code was responsible for updating the Likes Box:

var liked = $('#liked');
 var resultsList = $('#results');
 
 // ... 

 resultsList.on('click', '.like', function (e) { e.preventDefault();
 var name = $(this).closest('li').find('h2').text();
 liked.find( '.no-results' ).remove();
 $('<li>', { text: name }).appendTo(liked);
 });

The Search Results piece is completely intertwined with the Likes Box piece and needs to know a lot about its markup. A much better and more testable approach would be to create a Likes Box object that’s responsible for manipulating the DOM related to the Likes Box:

var Likes = function (el) { this.el = $(el); return this; }; Likes.prototype.add = function (name) { this.el.find('.no-results').remove(); $('<li>', { text: name }).appendTo(this.el); };

This code provides a constructor function that creates a new instance of a Likes Box. The instance that’s created has an .add() method, which we can use to add new results. We can write a couple of tests to prove that it works:

var ul; setup(function(){ ul = $('<ul><li class="no-results"></li></ul>'); }); test('constructor', function () { var l = new Likes(ul); assert(l); }); test('adding a name', function () { var l = new Likes(ul); l.add('Brendan Eich'); assert.equal(ul.find('li').length, 1); assert.equal(ul.find('li').first().html(), 'Brendan Eich'); assert.equal(ul.find('li.no-results').length, 0); });

Not so hard, is it? Here we’re using Mocha as the test framework, and Chai as the assertion library. Mocha provides the test and setup functions; Chai provides assert. There are plenty of other test frameworks and assertion libraries to choose from, but for the sake of an introduction, I find these two work well. You should find the one that works best for you and your project—aside from Mocha, QUnit is popular, and Intern is a new framework that shows a lot of promise.

Our test code starts out by creating an element that we’ll use as the container for our Likes Box. Then, it runs two tests: one is a sanity check to make sure we can make a Likes Box; the other is a test to ensure that our .add() method has the desired effect. With these tests in place, we can safely refactor the code for our Likes Box, and be confident that we’ll know if we break anything.

Our new application code can now look like this:

var liked = new Likes('#liked'); var resultsList = $('#results');
 
 // ... 

 resultsList.on('click', '.like', function (e) { e.preventDefault();
 var name = $(this).closest('li').find('h2').text();
 liked.add(name); });

The Search Results piece is more complex than the Likes Box, but let’s take a stab at refactoring that, too. Just as we created an .add() method on the Likes Box, we also want to create methods for interacting with the Search Results. We’ll want a way to add new results, as well as a way to “broadcast” to the rest of the app when things happen within the Search Results—for example, when someone likes a result.

var SearchResults = function (el) { this.el = $(el); this.el.on( 'click', '.btn.like', _.bind(this._handleClick, this) ); }; SearchResults.prototype.setResults = function (results) { var templateRequest = $.get('people-detailed.tmpl'); templateRequest.then( _.bind(this._populate, this, results) ); }; SearchResults.prototype._handleClick = function (evt) { var name = $(evt.target).closest('li.result').attr('data-name'); $(document).trigger('like', [ name ]); }; SearchResults.prototype._populate = function (results, tmpl) { var html = _.template(tmpl, { people: results }); this.el.html(html); };

Now, our old app code for managing the interaction between Search Results and the Likes Box could look like this:

var liked = new Likes('#liked'); var resultsList = new SearchResults('#results');
 
 // ... 

 $(document).on('like', function (evt, name) { liked.add(name); })

It’s much simpler and less entangled, because we’re using the document as a global message bus, and passing messages through it so individual components don’t need to know about each other. (Note that in a real app, we’d use something like Backbone or the RSVP library to manage events. We’re just triggering on document to keep things simple here.) We’re also hiding all the dirty work—such as finding the name of the person who was liked—inside the Search Results object, rather than having it muddy up our application code. The best part: we can now write tests to prove that our Search Results object works as we expect:

var ul; var data = [ /* fake data here */ ]; setup(function () { ul = $('<ul><li class="no-results"></li></ul>'); }); test('constructor', function () { var sr = new SearchResults(ul); assert(sr); }); test('display received results', function () { var sr = new SearchResults(ul); sr.setResults(data); assert.equal(ul.find('.no-results').length, 0); assert.equal(ul.find('li.result').length, data.length); assert.equal( ul.find('li.result').first().attr('data-name'), data[0].name ); }); test('announce likes', function() { var sr = new SearchResults(ul); var flag; var spy = function () { flag = [].slice.call(arguments); }; sr.setResults(data); $(document).on('like', spy); ul.find('li').first().find('.like.btn').click(); assert(flag, 'event handler called'); assert.equal(flag[1], data[0].name, 'event handler receives data' ); });

The interaction with the server is another interesting piece to consider. The original code included a direct $.ajax() request, and the callback interacted directly with the DOM:

$.ajax('/data/search.json', { data : { q: query }, dataType : 'json', success : function( data ) { loadTemplate('people-detailed.tmpl').then(function(t) { var tmpl = _.template( t ); resultsList.html( tmpl({ people : data.results }) ); pending = false; }); } });

Again, this is difficult to write a unit test for, because so many different things are happening in just a few lines of code. We can restructure the data portion of our application as an object of its own:

var SearchData = function () { }; SearchData.prototype.fetch = function (query) { var dfd; if (!query) { dfd = $.Deferred(); dfd.resolve([]); return dfd.promise(); } return $.ajax( '/data/search.json', { data : { q: query }, dataType : 'json' }).pipe(function( resp ) { return resp.results; }); };

Now, we can change our code for getting the results onto the page:

var resultsList = new SearchResults('#results');
 var searchData = new SearchData(); // ... searchData.fetch(query).then(resultsList.setResults);

Again, we’ve dramatically simplified our application code, and isolated the complexity within the Search Data object, rather than having it live in our main application code. We’ve also made our search interface testable, though there are a couple caveats to bear in mind when testing code that interacts with the server.

The first is that we don’t want to actually interact with the server—to do so would be to reenter the world of integration tests, and because we’re responsible developers, we already have tests that ensure the server does the right thing, right? Instead, we want to “mock” the interaction with the server, which we can do using the Sinon library. The second caveat is that we should also test non-ideal paths, such as an empty query.

test('constructor', function () { var sd = new SearchData(); assert(sd); }); suite('fetch', function () { var xhr, requests; setup(function () { requests = []; xhr = sinon.useFakeXMLHttpRequest(); xhr.onCreate = function (req) { requests.push(req); }; }); teardown(function () { xhr.restore(); }); test('fetches from correct URL', function () { var sd = new SearchData(); sd.fetch('cat'); assert.equal(requests[0].url, '/data/search.json?q=cat'); }); test('returns a promise', function () { var sd = new SearchData(); var req = sd.fetch('cat'); assert.isFunction(req.then); }); test('no request if no query', function () { var sd = new SearchData(); var req = sd.fetch(); assert.equal(requests.length, 0); }); test('return a promise even if no query', function () { var sd = new SearchData(); var req = sd.fetch(); assert.isFunction( req.then ); }); test('no query promise resolves with empty array', function () { var sd = new SearchData(); var req = sd.fetch(); var spy = sinon.spy(); req.then(spy); assert.deepEqual(spy.args[0][0], []); }); test('returns contents of results property of the response', function () { var sd = new SearchData(); var req = sd.fetch('cat'); var spy = sinon.spy(); requests[0].respond( 200, { 'Content-type': 'text/json' }, JSON.stringify({ results: [ 1, 2, 3 ] }) ); req.then(spy); assert.deepEqual(spy.args[0][0], [ 1, 2, 3 ]); }); });

For the sake of brevity, I’ve left out the refactoring of the Search Form, and also simplified some of the other refactorings and tests, but you can see a finished version of the app here if you’re interested.

When we’re done rewriting our application using testable JavaScript patterns, we end up with something much cleaner than what we started with:

$(function() { var pending = false; var searchForm = new SearchForm('#searchForm'); var searchResults = new SearchResults('#results'); var likes = new Likes('#liked'); var searchData = new SearchData(); $(document).on('search', function (event, query) { if (pending) { return; } pending = true; searchData.fetch(query).then(function (results) { searchResults.setResults(results); pending = false; }); searchResults.pending(); }); $(document).on('like', function (evt, name) { likes.add(name); }); });

Even more important than our much cleaner application code, though, is the fact that we end up with a codebase that is thoroughly tested. That means we can safely refactor it and add to it without the fear of breaking things. We can even write new tests as we find new issues, and then write the code that makes those tests pass.

Testing makes life easier in the long run

It’s easy to look at all of this and say, “Wait, you want me to write more code to do the same job?”

The thing is, there are a few inescapable facts of life about Making Things On The Internet. You will spend time designing an approach to a problem. You will test your solution, whether by clicking around in a browser, writing automated tests, or—shudder—letting your users do your testing for you in production. You will make changes to your code, and other people will use your code. Finally: there will be bugs, no matter how many tests you write.

The thing about testing is that while it might require a bit more time at the outset, it really does save time in the long run. You’ll be patting yourself on the back the first time a test you wrote catches a bug before it finds its way into production. You’ll be grateful, too, when you have a system in place that can prove that your bug fix really does fix a bug that slips through.

Additional resources

This article just scratches the surface of JavaScript testing, but if you’d like to learn more, check out:

  • My presentation from the 2012 Full Frontal conference in Brighton, UK.
  • Grunt, a tool that helps automate the testing process and lots of other things.
  • Test-Driven JavaScript Development by Christian Johansen, the creator of the Sinon library. It is a dense but informative examination of the practice of testing JavaScript.
Categories: Web Design & Culture

This week's sponsor: Igloo Software

A List Apart - Mon, 05/20/2013 - 10:00

If SharePoint and Facebook had a baby, it would look a lot like Igloo (without the recessive balding or oversharing tendencies). Hosted, managed and with a major release every 90 days, Igloo is a whitelabel content platform built for today’s needs. We also have Sandwich Video.

Categories: Web Design & Culture

Matt Mullenweg on Yahoo-Tumblr

A List Apart - Mon, 05/20/2013 - 05:30
» Matt Mullenweg on Yahoo-Tumblr

“We’re at the cusp of understanding the ultimate value of web publishing platforms, particularly ones that work cross-domain.”–Matt Mullenweg of WordPress.

Categories: Web Design & Culture
Subscribe to rothdigital aggregator - Web Design &amp;amp; Culture