Building Mobile Websites

  • 5/15/2012

Development Aspects of a Mobile Site

Based on the discussion in Chapter 3, the most important task when planning a mobile site planning is selecting use-cases. This doesn’t mean, however, that use-case selection is unimportant when developing full sites or other types of applications. It’s just that a mobile application and site are structurally built around a few (and well-chosen) use-cases.

Even when you’re simply picking up a use-case from the root site, the way in which you implement it for a mobile audience may require significant changes—possibly a different user interface and perhaps even a different workflow.

At this point, let’s assume that you have a well-defined (and hopefully well-chosen) set of use-cases; and let’s also suppose that you have everything required for the back end already in place. You are now ready to start producing markup. But, first and foremost, how do you reach the mobile site?

Reaching the Mobile Site

A mobile site can be a stand-alone site located at its own unique URL, or it can result from the application logic serving appropriate content to desktop and mobile browsers. In the former case, you just create a new ASP.NET project, design your pages for the mobile devices that you intend to support, give your images and style sheet the size and properties they need, and go. In the latter case, you have a single project where you just handle the desktop full-web case as a special case of a mobile site. Let’s investigate the two options.

One Site, One Experience

Maybe partly influenced by the One Web vision, I initially approached mobile development with the idea of offering my users just one endpoint and host name. The plan was to hard-code the server with the ability to detect device capabilities and serve the most appropriate content. So my first mobile project was a mere extension of an existing site: I just released a new version of the desktop site with the additional ability to detect mobile browsers and serve ad hoc markup. I had just one ASP.NET project with two distinct sets of pages/views for desktop and mobile.

Honestly, this didn’t take much effort to design and implement. It took only a little extra engineering to set up a page/view router to distinguish between and serve both mobile and desktop requests. However, testing the site was painful. The only reliable source of information was to use a real mobile device; switching the user agent string on desktop browsers just didn’t work effectively. We’ll return to these test issues later in this chapter, and also demonstrate this one-site, one-experience approach while presenting a demonstration of device capability detection.

The noteworthy point is that when you have just one site that can handle both mobile and desktop browsers, you actually have one set of pages for full browsers and then multiple sets of pages for each class of mobile devices that you support. Really, the desktop becomes the special case!

What about different use-cases? This isn’t a big issue. You always have a home page in both mobile and desktop environments, so your mobile home page will just offer a different set of links and start a different type of navigation. You only need some logic that, when a new browser session starts, the home page request for http://www.yoursite.com produces the output of default.aspx, default.mobile.aspx, or perhaps default.iphone.aspx

Two Sites, One Experience

Mostly for ease of development and testing, I soon switched to a different model: two sites, one experience. The mobile site is a neatly separated entity and has its own URL. You have a stand-alone mobile site reachable as a /mobile virtual directory of the main site or as a subdomain, such as http://m.yoursite.com. Sometimes, the site takes its own extension, such as http://www.yoursite.mobi. Any option that you choose here is equally good, in my opinion, and mostly depends on other aspects of the mobile strategy. In any case, it is always a good advice to provide users (at least on smartphones and tablets) with a link to browse the full site.

Because the mobile site is isolated from the principal site, you can test it much more easily—and you can use desktop browsers or mobile generic emulators (such as Opera Mobile Emulator) to perform quick tests aimed primarily at evaluating the user interface and experience. Obviously, it’s crucial to test on real devices, but for quick tests on markup, colors, position, and flow, using a desktop program makes the process seamless.

Because you now have two distinct sites, you need an automatic mechanism to switch users to the right site based on the capabilities of the requesting device.

Routing Users to the Right Site

It’s a mistake to assume a one-to-one correspondence between desktop and mobile pages. This may happen but should not be considered a common occurrence. Note that by saying “page correspondence,” I simply mean that both applications can serve the same URL; I’m not saying anything about what each page actually will serve.

All in all, we can safely consider only the host name of any requested URL. If the host name belongs to the desktop site and the requesting browser is detected to be a desktop browser, then everything works as expected. Otherwise, the user should be displayed a landing page, where she will be informed that she’s trying to access a desktop site with a mobile device. The user is given a chance to save her preference for future similar situations. The preference is stored to a cookie and checked next.

If the request refers to a URL in the mobile site and the user seems to have a desktop browser, consider showing another landing page rather than simply letting the request occur as usual. Finally, if a request is placed from a mobile device to the mobile site, it will be served as expected; namely, by looking into the device capabilities and figuring the most appropriate view. Figure 4-1 presents a diagram of the algorithm.

Figure 4-1

Figure 4-1 The desktop/mobile view switcher algorithm.

How would you implement this algorithm?

In ASP.NET, the natural tool to implement this routing algorithm is an HTTP module that is active on both sites and capturing the BeginRequest event. The module will use plain redirection or, if possible, URL rewriting to change the target page as appropriate.

Here’s some code that implements the aforementioned algorithm in the desktop site:

public class MobileRouter : IHttpModule
{
    private const String FullSiteModeCookie = "FullSiteMode";
    public void Dispose()
    {
    }
    public void Init(HttpApplication context)
    {
        context.BeginRequest += OnBeginRequest;
    }

    private static void OnBeginRequest(Object sender, EventArgs e)
    {
        var app = sender as HttpApplication;
        if (app == null)
            throw new ArgumentNullException("sender");

        var isMobileDevice = IsRequestingBrowserMobile(app);

        // Mobile on desktop site, but FULL-SITE flag on the query string
        if (isMobileDevice && HasFullSiteFlag(app))
        {
            app.Response.AppendCookie(new HttpCookie(FullSiteModeCookie));
            return;
        }

        // Mobile on desktop site, but FULL-SITE cookie
        if (isMobileDevice && HasFullSiteCookie(app))
            return;

        // Mobile on desktop site => landing page
        if (isMobileDevice)
            ToMobileLandingPage(app);
    }

    #region Helpers
    private static Boolean IsRequestingBrowserMobile(HttpApplication app)
    {
        return app.Context.Request.IsMobileDevice();
    }

    private static Boolean HasFullSiteFlag(HttpApplication app)
    {
        var fullSiteFlag = app.Context.Request.QueryString["m"];
        if (!String.IsNullOrEmpty(fullSiteFlag))
            return String.Equals(fullSiteFlag, "f";
        return false;
    }

    private static Boolean HasFullSiteCookie(HttpApplication app)
    {
        var cookie = app.Context.Request.Cookies[FullSiteModeCookie];
        return cookie != null;
    }

    private static void ToMobileLandingPage(HttpApplication app)
    {
        var landingPage = ConfigurationManager.AppSettings["MobileLandingPage"];
        if (!String.IsNullOrEmpty(landingPage))
            app.Context.Response.Redirect(landingPage);
    }
    #endregion
}

Once installed in the desktop site, the HTTP module captures every request and checks the requesting browser. If the browser runs within a mobile device, the module redirects to the specified landing page. The landing page will be a mobile optimized page that basically offers a couple of links: one to the home of the desktop site and one to the home of the mobile site. Figure 4-2 shows a sample landing page viewed with an Android 2.2 device.

If the user insists on viewing the full site, then you can’t simply redirect to the plain home page. For its nature, the HTTP module will intercept the new request and redirect again to the mobile landing page. From the landing page, you can simply add a specific query string parameter that the HTTP module will detect on the successive request. Here’s the actual link that results in Figure 4-2:

<a href="http://www.easycourt.net/contosoen?m=f">Full site</a>

You are responsible for defining the query string syntax; in this case, m stands for mode and f for full. The task is not finished yet, though. At this point, users navigate to the home page of the site. What about any other requests? Those requests, in fact, will be intercepted by the HTTP module. By adding a cookie, you can provide additional information to the HTTP module about requests deliberately sent to the desktop site from a mobile device.

Figure 4-2

Figure 4-2 The landing page of the EasyCourt demo site.

How can the user switch back to the mobile site? Ideally, any desktop site with a sister mobile site should offer a clearly visible link to switch to the mobile version (and vice versa when the full site is viewed on a mobile device). If not, the user won’t be offered a chance to choose the full or mobile site until the cookie expires or is cleared. To clear cookies, users deal with the Settings page of the mobile browser.

Adding Mobile Support to an Existing Site

Where do you place the landing page? Is it on the desktop or on the mobile site? In general, it doesn’t matter; however, if you put it on the mobile site, then you really can enable a scenario in which you deploy a mobile site with all the required routing logic without touching codebase of the existing desktop site.

In the demo site of EasyCourt, a commercial booking system for tennis courts, which I introduced in Chapter 3, I just edited the Web.config file of the desktop site and deployed a library with the HTTP module in the Bin folder. No changes were made to the source code. Here’s the configuration script to add a router HTTP module to the desktop site:

<system.webServer>
     <modules>
         <add name="MobileRouter" type="..." />
     </modules>
     ...
</system.webServer>

The Welcome page was defined on the mobile site. Note that the Welcome page always should be visible, and it never should need authentication. Depending on how you deploy the mobile site—a distinct root site/application or a child application/directory—you may need to tweak the Web.config file of the mobile site to disable the HTTP module. If the mobile site is a distinct application, then it needs its own Web.config file that has been fully configured with the HTTP module. If the mobile site is, instead, hosted as a child directory in the desktop site, then it inherits the configuration settings of the parent site (the desktop site), including the HTTP module. To speed up requests, you might want to disable the HTTP module in the mobile site.

Here’s the configuration script that you need in the mobile site’s Web.config file. The script clears the list of HTTP modules required by the mobile site:

<system.webServer>
     <modules>
         <clear />
     </modules>
     ...
</system.webServer>

In addition, you need to instruct the parent application/site explicitly to stop the default inheritance chain of settings. Here’s what you need:

<location path="." inheritInChildApplications="false">
<system.webServer>
     <modules>
         <add name="MobileRouter" type="..." />
     </modules>
     ...
</system.webServer>
</location>

Also, notice that when the mobile site is a child application/directory, then it inherits a bunch of settings (for the section where inheritance is not disabled) that don’t need to be repeated (for example, connection strings and membership providers).

Design of the Mobile Views

Mobile websites normally show a subset of the content offered by a desktop site. For example, if you have a three-column layout in a desktop site, you probably want to remove (or move to additional pages) content displayed in two of the three columns. Reducing the amount of information improves the load time of the site and makes better use of the available space. “Shrink-and-fit” is a popular slogan.

An ideal layout for pages of a mobile site is based on a single column. The font size is large enough to allow easy reading without zoom. The search bar (if any) ideally will go at the top, and navigation links are commonly placed at the bottom. You might want to place a link to the desktop version of the site somewhere on the mobile site.

Scrolling is accepted, especially vertical scrolling, but endless lists are annoying. Let’s briefly review some common scenarios now.

Input Elements

On a typical mobile site, most of the functionality is read-only. This fact seems to suggest that you are not going to have that many chances to write input forms, and perhaps even that input forms are not an aspect of development you want to invest much time in.

This is just wrong.

Exactly because most of the functionality is read-only and a mobile device is tiny and not as powerful as a laptop, providing specific and restricted parameters is key. To type query parameters, or to specify settings, input forms are a common presence on mobile pages anyway. Some typical web and Windows controls need fixes, though, especially in light of the touch capabilities of many devices.

Typing text on mobile devices is hard and should be minimized. As we’ll see in later chapters, this is easier to achieve with native applications, where you can control the input scope of soft keyboards and attempt to display an optimized subset of keys to the user. In mobile sites, all is left to the browser, although developers can use forms of auto-completion via AJAX.

If the browser understands HTML5, then you can just use the most appropriate type attribute on the <input> element and let the browser do the rest. To be honest, what you get may differ quite a bit, even on smartphones. For example, numbers and ranges are well supported on both iPhone and Android at present, but the date type produces just the plain text box on Android. In iOS5, however, the browser recognizes your intentions and displays the compelling iPhone date picker element (see Figure 4-3).

On the other hand, iOS still lacks the ability to upload files from the browser, which is a feature available in Android mobile browsers.

In general, data entry should be redesigned and even rethought case by case. For example, when it comes to booking a tennis court in EasyCourt, the site offers a drop-down list with ready-made dates, as shown in Figure 4-4. It should be noted, however, that this particular screen is not mobile-specific but simply represents the plain transposition of a desktop page. You always should wonder if there may be an innovative way of letting users enter their choices. Don’t stop at the classic, desktop-oriented way of building input forms. Mobile is different and user-centered.

Figure 4-3

Figure 4-3 Entering dates in iOS5.

Figure 4-4

Figure 4-4 Setting parameters for a query on available courts.

And finally, here’s a quick tip related to passwords. Strong passwords typically require mixing lowercase and uppercase letters and numbers and symbols, but that’s too much work in a mobile website. If possible, consider using numeric personal identification numbers (PINs).

Radio Buttons and Check Boxes

A common presence in many input forms, radio buttons and check boxes have just one problem in mobile forms: they tend to be too small and hard to select with a touch. It is recommended that you style these elements accordingly using padding and the companion label element. Don’t place such elements too close to other elements, including other possibly related buttons.

It is worth noting that jQuery Mobile completely rewrites the canonical markup for such input elements, as follows:

<input type="checkbox" name="rememberme" id="rememberme" data-theme="d" />
<label for="rememberme">Keep me logged</label>

The output produced by the preceding markup is shown in Figure 4-5.

Figure 4-5

Figure 4-5 A check box that looks like a button and is really easy to tap.

In particular, jQuery Mobile surrounds the base HTML markup with padded DIVs to make it easier for the user to tap. Compare the experience of tapping this with a regular check box that may even need zooming to be read and selected (see Figure 4-6).

Figure 4-6

Figure 4-6 A regular HTML check box, but zoomed.

When the user’s choice is a yes/no or on/off choice, it is common in mobile to use flip-switch artifacts that are larger and more comfortable to use and easier to see. Although differently styled, flip-switches are available in iOS, Android, and Windows Phone.

Scrollable and Drop-Down Lists

Radio buttons are a valid solution if you need only one selection out of just a few options. When the number of options gets closer to 10, or more, you might want to consider a combo box or a plain scrollable list.

One of the original Windows controls, the combo box provides the same experience on desktop applications and websites. The same points previously discussed for radio buttons and check boxes apply to combo boxes too—they’re usually too small to be touch-enabled effectively. You can play with style sheets and use a larger font, but you manage to improve the result only a little bit—it remains far from ideal. Figure 4-7 compares native and adjusted combo boxes.

Figure 4-7

Figure 4-7 Native and adjusted combo boxes.

Figure 4-7 shows the results that you get when you use jQuery Mobile. The bottom line, though, is that you hardly want to use plain <select> elements on a mobile page without some graphical adjustments for size and touchability. On the other hand, <select> elements are more important than ever in mobile pages because they can save users from typing free text.

Scrolling vertically is quite a natural gesture in a mobile scenario. However, the more you can group related items, the better the final experience for the user is. Once again, focus is king. Figure 4-8 shows a couple of mobile views featuring grouped items and collapsible elements that effectively save valuable screen real estate while providing optional information to users. Grids are effectively rendered on mobile only rarely; smartly built vertical lists are a much more common and preferable choice.

Figure 4-8

Figure 4-8 Collapsible and grouped elements.

In Figure 4-8, a collapsible element is the block that shows messages. As the icon suggests, it is an area of the screen that can be collapsed. Other blocks are tables with one or multiple sections (to use a terminology popular to iOS and Android developers). Some of the items serve as dividers of the sections and are styled differently, communicating the idea of grouped items.

If the list of items is particularly long, you might want to introduce some pagination. Essentially, pagination works by first loading a fixed number of items and then displaying a link at the end to get more. Alternatively, more items can be loaded automatically when the user reaches the bottom of the list. It is up to you to ensure that the DOM doesn’t end up containing too many items after a few click requests for more items. If this happens, you might want to remove older items and move them to another page that the user can request if needed.

Free Text and Auto-Completion

No matter your efforts to save free text typing, sometimes users are just requested to enter a name or a comment. There’s not much you can do to reduce the hassle of typing on a mobile soft keyboard if you can’t figure out ways to allow the browser to offer a close-enough input scope. With native applications, it’s slightly better, but text typing remains a very sore point for mobile developers.

Auto-completion does help, but it costs you quite a bit of script code, which in turn increases the payload for the page. Auto-completion must be coded through a plug-in—the jQuery UI auto-complete plug-in works well with mobile pages. A plug-in that downloads data from an external source is the most viable option when the potential number of options is in the order of hundreds. For a smaller number of items, you can also consider the jQuery Mobile filter bar. The base markup is the following:

<ul>
  <li> ... </li>
  <li> ... </li>
  <li> ... </li>
</ul>

Additional attributes will give the final markup a strong auto-completion flavor, as in Figure 4-9. Auto-completion also is sometimes a way to avoid long lists of hundreds of items that are very boring to scroll through.

Figure 4-9

Figure 4-9 A jQuery Mobile filter bar selecting list items with “n.”

Testing the Mobile Site

Testing a mobile site is not an easy task. You may use a mobile emulator (possibly more than one to better simulate the various scenarios), but emulators are not enough. Testing on real devices is what really matters and gives you the real perception of the application performance and user experience.

However, before you deploy to a few test devices (at least one per device class), you might want to check user interface and logic on a more comfortable desktop machine. Emulators and user-agent switchers can do some of the work for you.

Desktop Emulators

An emulator is a desktop application typically running on Windows that aims to mimic the behavior and functions of a specific browser. In mobile development, emulators are time-saving tools for first-pass software testing.

Device/OS emulators are more specific than browser emulators. Device/OS emulators (i.e., the Windows Phone emulator) are created by device manufacturers and are generally really close to the device.

Browser emulators are generally written by third-party companies and serve mostly for verifying the look and feel of the site at a given size and resolution. You should not consider a browser emulator for verifying the rendering of pages that have been optimized for certain classes of devices.

In general, emulators are a first-aid device, and they can be used to test the behavior of the application on types of devices that you have no access to.

User Agent Switching

Most desktop browsers come with tools to switch the user agent (UA) string. By changing the default UA string to that of a mobile device, you allow the browser to present the website with the credentials of a particular mobile browser. Subsequently, the website will serve the mobile content that it has in store. UA switchers are a special case of browser emulators.

The Firefox browser was the first to offer such a powerful add-on. Today, you find the same tool for Google Chrome and Internet Explorer 9, as shown in Figure 4-10.

Figure 4-10

Figure 4-10 The User Agent Switcher tool in Internet Explorer 9.

Opera Mobile Emulator is another interesting tool through which you can experience your site as if you are visiting it through a number of specified devices. Compared to the User Agent Switcher Tool, the Opera Mobile Emulator is more flexible; more important, it is a single tool that can serve multiple scenarios. In Figure 4-11, you see the emulator configured to give the site being tested the appearance of running on a tablet.

Figure 4-11

Figure 4-11 Selecting an emulator.

With all this said, it is worth making this point even clearer: you should test your mobile site on a variety of mobile devices. In particular, don’t trust too much the apparent magic of UA switchers.

Let me illustrate a specific scenario. The UA switcher forces the browser to send a particular UA string and, subsequently, your server-side code recognizes the requesting browser as mobile. This is the only certain fact.

At this point, your server-side code may inject some JavaScript that checks the browser’s capabilities and adapts the markup. Your JavaScript code, however, will be querying the desktop browser, not the mobile browser! Furthermore, a generic emulator like the Opera Browser Emulator may not be able to imitate the real browser perfectly, which makes the test experience significantly less valuable.

The bottom line is that you should use switchers for quick testing, then move to device emulators, and finally test on a selection of actual sample devices—the only source of truth.

In addition to buying or renting as many devices as you can, you can use a device-testing service such as Keynote Device Anywhere (http://www.deviceanywhere.com). Another tool that is great for remote debugging is Weinre.