Smashing Magazine
Adapting To A Responsive Design (Case Study)
This is the story of what we learned during a redesign for our most demanding client — ourselves! In this article, I will explain, from our own experience of refreshing our agency website, why we abandoned a separate mobile website and will review our process of creating a new responsive design.
At Cyber-Duck, we have been designing both responsive websites and adaptive mobile websites for several years now. Both options, of course, have their pros and cons. With a separate mobile website, you have the opportunity to tailor content and even interactions to the context of your users, whereas a responsive website means better content parity for users and a single website to maintain.
Why Adapt To A Responsive Design?Our redesign story starts in August 2012. Until then, our previous strategy of having separate mobile, tablet and desktop websites didn’t exactly perform badly; they drove conversions, and user engagement appeared to be good relative to our desktop website. I should mention that this strategy was borne purely out of the need to quickly tailor our ageing desktop website to the increasing number of tablet and mobile users at the time.
We used jQuery Mobile to create our previous mobile-optimized website as a quick fix for the increasing number of mobile users on our ageing desktop website.
We produced our tablet and mobile websites specifically with users of these devices in mind — performance was our top priority. We wanted to improve on the loading time of our “desktop” website dramatically; the desktop home page was 2.2 MB, with 84 HTTP requests, and the mobile home page was still quite large, at 700 KB, with 46 HTTP requests. We had also designed the interfaces specifically with touch in mind, using jQuery Mobile to enhance the user experience with touch gestures.
Changing Our ApproachDespite this, several factors led us to decide that this approach was no longer sustainable for our own website:
- having to support multiple code bases,
- content management,
- the emergence of new mini-tablets and “phablets.”
The first two were not ideal, but at least manageable. The third, however, was a deal-breaker. OK, so we could have designed a website optimized for mini-tablets, but with so many more Web-enabled devices of all shapes and sizes entering the market every day, it would have been only a matter of time before we needed to think about optimizing for new form factors.
We wanted our new website to be easier to maintain and more future-friendly for the inevitable influx of new form factors.
It was at this point that we decided to completely overhaul all three websites and create a responsive design that would provide the best possible experience to all of our users, regardless of how they accessed our website.
Setting Goals for the Responsive DesignAt the very start of this overhaul, we set ourselves some simple goals, or principles if you like, that we wanted to achieve with our responsive design:
- Speed
Performance affects everyone. - Accessibility
It should work with no styles, backgrounds or JavaScript. - Content parity
The same content and functionality should be on all platforms. - Device-agnostic
Leave no platform behind. - Future-friendly
Cut down on maintenance.
Based on these goals, our starting point for the design was to review our existing mobile website and to use it as a base for our responsive design. We explored how we could enhance for wider screens, rather than attempt to squeeze our previous desktop website down to mobile.
We started by speaking to some of our trusted customers about what they liked about our website, what they didn’t really like, and what was important to them when searching for a digital agency.
We also used analytics data from our previous website, using a mixture of Google Analytics, Lead Forensics and CrazyEgg to help us better understand what existing users wanted and needed from our website. As a result, we were able to streamline and prioritize a content strategy based on how our users actually interact with the website.
Our design team used card-sorting exercises to reorganize our existing content for the new website.
A potential pitfall of responsive Web design, which you don’t find with a separate mobile website, is that performance can suffer, especially if you are simply hiding content using display: none at certain screen widths. We wanted to avoid this issue by putting the speed of our website at the heart of all design and technology decisions. The advantage is that a better performing website would benefit all users, not just mobile users.
To achieve this, we set a performance budget — a set of targets to improve the speed and size of our new website. For mobile users, we wanted a website that performed at the very least comparably to our existing mobile website; so, we wanted to load no more than 40 HTTP requests and 500 KB of data for our mobile breakpoint. (This was just the start. Our next step was to reduce this to less than 100 KB.)
Third-Party ScriptsThe easiest way to trim the fat was to strip down third-party scripts as much as possible. According to Zurb, “to load the Facebook, Twitter and Google social media buttons for a total of 19 requests takes 246.7 KB in bandwidth.” As a result, we replaced heavy social-media plugins with lightweight social media links.
Replacing heavy third-party social buttons with simple social media links can significantly reduce HTTP requests and page-loading times.
While some essential tracking scripts had to stay, we ensured that they would load after the content by putting them at the bottom of the body element in the HTML document and in an external scripts file.
Did We Really Need A CMS?Early on in discussing the requirements for the new website, we considered whether we even needed a content management system (CMS). After all, as you’d expect in a digital agency, most of the team members are familiar with HTML, CSS and Git, so we could certainly manage our content without a CMS.
By using server-side performance-monitoring tools such as New Relic, we could see that our previous CMS was a key factor in the slow page-loading times. Thus, we took the fairly drastic decision to entirely remove the CMS from our website. We made an exception for our blog, which, due to the volume and frequency of content being published, still required a CMS to be managed effectively.
The previous home page queried the database server 1,459 times, for a total execution time of 2.34 seconds.
Our old website was built with a model-view-controller (MVC) architecture that connected with the WordPress CMS. To give you an example, a typical page with WordPress uses around 600 to 1,500 queries to load; the database server is queried hundreds of times, and by simply removing the CMS, we managed to reduce this to zero in one fell swoop.
The team developed early prototypes to see how we could improve performance and responsiveness.
By removing the CMS for static pages, we eliminated the need for a database and dynamic templates. Using the popular PHP framework Laravel, we implemented a custom “dynamic route and static template” system. This means that each time a URL is called on our website, the Laravel router knows exactly which template to load by matching the URL to the template’s name, and the template already has all of the content laid out statically in HTML.
As a result of this alone, we managed to improve the processing speed of the website by over 3,900%. Taking the home page as an example, we improved server processing speeds from 2.2 seconds to 56 milliseconds on average.
Server processing speed is now only 56 milliseconds, with zero database queries — approximately 40 times faster than before.
Naturally, this approach wouldn’t suit everyone (nor indeed many of our clients), but we should ask ourselves at the beginning of each project which CMS is most suitable, and whether one is necessary at all. Other options are out there, of course, including file-based CMS’ such as Kirby and Statamic, building or customizing a lightweight CMS such as Perch, or simply implementing better server-side caching such as with Varnish.
Ultimately, we decided to remove the CMS because even the most lightweight, highly optimized CMS with clever caching has overhead and cannot match the performance and server footprint of static files.
Avoiding Off-The-Shelf CSS FrameworksWhile CSS frameworks such as Twitter Bootstrap and Foundation are great for quickly building interactive prototypes, they are often far more complex than we need for most projects. The reason is that these frameworks need to be sensitive to and cater to a wide variety of use cases and are not tailored to the particular requirements of your project.
We reduced the size of our style sheets by creating a custom responsive grid system that was simple, fast and extremely flexible to our needs.
We designed from the content out, meaning that the content shaped the layout and grid, as opposed to having the layout define the content.
Clockwise from top: The layout is three columns on a desktop, becomes a single column stack on mobile, and takes advantage of the extra space on tablets by floating the image to the left of the content.
We used Sass for the front-end development to avoid any repetition of code, making sure every bit of CSS is actually being used. Sass can also minify the output to ensure that the CSS is a small as possible.
$sass --watch --style compressed scss:cssWe also made use of functions within Sass to build our custom grid. Here is the code for the desktop grid:
@import "vars"; // Grid system $wrap: $col * 12 + $gutter * 11; @for $i from 2 through 12 { .col#{$i} { width: $col * $i + $gutter * $i - $gutter; float: left; margin: 0 $gutter/2 $vgrid $gutter/2; } } @for $i from 1 through 11 { .pre#{$i} { padding-left: $col * $i + $gutter * $i; } } @for $i from 1 through 11 { .suf#{$i} { padding-right: $col * $i + $gutter * $i; } } .container { width: $wrap + $gutter; margin: 0 auto; padding-top: 1px; } .colr { float: right; margin: 0 $gutter; } .alpha { margin-left: 0; } .omega { margin-right: 0; }From here, we could customize the width of columns and gutters within the grid simply by editing the vars configuration file.
// Grid $vgrid: 20px; $col: 60px; $gutter: 20px;The grid basically calculates the width of a span of columns based on the number of columns in that span, making it flexible to any configuration of layout or grid. We’ve open-sourced this code on GitHub (we make no apologies for the duck puns), so please fork and adapt this flexible grid system to your own project’s requirements — and let us know how it goes!
Conditionally Loading JavaScriptTo further improve the speed of our new website, we wanted to load JavaScript only when it’s needed or supported. We achieved this by using RequireJS to ensure that JavaScript is loaded only after checking that JavaScript is available in the requesting browser and that the browser only loads scripts it can support. RequireJS also works as a module loader, ensuring that any JavaScript is called only if it’s needed on that page.
RequireJS also contains a handy optimization tool that combines related scripts and minifies them via UglifyJS to reduce the file size of the JavaScript.
The optimization reduced the JavaScript’s size from 411 KB to 106 KB.
In addition to JavaScript, images are among the heaviest assets to download for most websites. We particularly wanted to improve on this area because our website is fairly image-heavy, showing examples that showcase our work.
We manually optimized images throughout the website by selectively compressing areas of images using Adobe Fireworks’ selective quality options. We also reduced image file sizes through further granular control of compression, blur and desaturation.
By desaturating and blurring parts of images that are not essential, we significantly reduced image sizes.
We also used ImageOptim and TinyPNG to compress our images and sprites. These tools remove all unnecessary data without compromising the quality of an image. This reduced the weight of the main image sprite, for instance, from 111 KB to 40 KB.
For the slideshow banner on the home page, we optimized for different screen sizes by using media queries to ensure that only appropriate-sized images are loaded.
As you can see in the image above, on mobile, the slideshow items are far lighter.
The CSS:
@media only screen and (min-width: 120px) and (min-device-width: 120px) { .item-1 { background: $white url('carousel/dmd/background-optima-m.jpg') 50% 0 no-repeat; .computer, .tablet, .phone, .eiffel, .bigben, .train { display: none; } } /* Total loaded: 27 KB */ }
More assets are loaded on the desktop.
Meanwhile, on the desktop, we load more assets to make the most of the larger screen size available to us.
The CSS:
@media only screen and (min-width: 1024px) and (min-device-width: 1024px) { .item-1 { background: $white url('carousel/dmd/background.jpg') center -30px no-repeat; .computer { background: url('carousel/dmd/computer.png') center top no-repeat; div { background: url('carousel/dmd/sc-computer.jpg') center top no-repeat; } } .tablet { background: url('carousel/dmd/tablet.png') center top no-repeat; div { background: url('carousel/dmd/sc-tablet.jpg') center top no-repeat; } } .phone { background: url('carousel/dmd/phone.png') center top no-repeat; div { background: url('carousel/dmd/sc-mobile.jpg') center top no-repeat; } } .eiffel { background: url('#{$img}carousel/dmd/eiffel.png') center top no-repeat; } .bigben { background: url('#{$img}carousel/dmd/bigben.png') center top no-repeat; } .train { background: url('#{$img}carousel/dmd/train.png') center top no-repeat; } } /* Total loaded: 266 KB */ } Delivering Content FasterYahoo’s golden rule of performance states that “80-90% of the end-user response time is spent downloading all the components in the page: images, stylesheets, scripts, Flash, etc.” In short, each request takes time to process; therefore, each request (such as to serve a file from the server) will inevitably increase the loading time.
By using CloudFlare’s content delivery network (CDN), we have separated the file-serving task of the Web server from the processing of the website. This means that our Web server concentrates on the application, rather than on serving static files. We moved all static assets to a separate subdomain (in our case, static.cyber-duck.co.uk) to reduce the cookies being sent with each request for an asset to a minimum, which in turn reduces the bandwidth required for each asset.
The CDN also caches and ensures that files are delivered from the server nearest to the user’s location, minimizing network latency (because the data is transmitted over a shorter distance), further reducing loading times.
In addition to the CDN, we used the Gzip rules and expires headers in the .htaccess file of HTML5 Boilerplate. This uses Apache’s mod_deflate module to compress the output of files to the browser and also sets an expiration on headers far into the future, to ensure better caching of the website for returning visitors.
Creating A Truly Responsive DesignAs set out in our initial goals, we wanted our new website to have content parity and to provide accessibility to all users, regardless of how they access it.
In order to deliver a truly responsive design, we delegated all styling and display tasks to the CSS alone, using JavaScript to simply alter the “status” of elements by adding and removing CSS classes, as opposed to hiding and showing the elements with JavaScript directly.
The Right Code for the TaskUsing this method, we could make mobile-specific optimizations, such as transforming the top menu on mobile to have telephone and map buttons so that mobile visitors can call or find our office quickly.
We used this approach throughout the website to activate and deactivate dynamic elements, always ensuring that these elements are still present on the page when JavaScript is unavailable. This way, we can offer content parity to our users while avoiding duplicate markup for specific contextual enhancements, such as those for mobile. With this approach, we ensure that JavaScript is an enhancement to the user experience, rather than a necessity to view the website.
On the right side of the top GUI, you can see the map and phone buttons, accompanied by the standard control to access the rest of the pages.
Here is the JavaScript:
$('#menu').addClass('closed'); $('.btn-menu').click(function(e){ e.preventDefault(); $('#menu').toggleClass('closed'); });The CSS for desktops:
.nav { display: block; float: right; } .btn-menu, .btn-call, .btn-map { display: none; }The CSS for mobile:
.menu { display: block; height: auto; overflow: hidden; } .menu.closed { height: 0; } .btn-menu, .btn-call, .btn-map { display: block; } Animations as an EnhancementFor the animated slideshow of our projects on the home page, we used SequenceJS, a plugin that gave us the freedom to create the slideshow using only HTML and CSS for the content. This way, whenever JavaScript is unavailable or the screen size is too small, we don’t have to download all assets for the animation, only those necessary for a smaller, lighter version.
Elsewhere, we decided to use CSS3 for animations. These enhance the user experience for browsers that support CSS3 animations, while older browsers still get the functionality, if not the eye candy. For example, when a user is on a latest-generation smartphone and expands the menu or a portfolio item, it animates with CSS3 rather than with JavaScript.
This improves the performance of these animations by using hardware acceleration, offloading tasks of the central processing unit (CPU) to the graphics processing unit (GPU). For smartphone and tablet users, this can make a massive difference to performance by reducing consumption of their already limited CPU resources.
Delegating animation to the CSS enables us to make the most of hardware acceleration.
.menu { height: auto; transition: height 200ms linear; } .menu.closed { height: 0; transition: height 200ms linear; } Breakpoints Based on Content and Design, Not DeviceFor the breakpoints, we used multiple CSS media queries to responsively deliver the optimal presentation of content to screens both large and small.
This device-agnostic approach ensures that we do not need to optimize the code later when other devices come to market. We included (though did not limit) breakpoints at 120, 240, 600, 760, 980 and 1360 pixels, as well as targeted media queries for specific content on pages and also high-pixel-density screens.
The website responds fluidly between each breakpoint.
While we did not design breakpoints based on particular devices, in order to ensure further future-friendliness, we did test our website across as many devices and browsers as we could get our hands on, from the common (desktop browsers and a variety of phones and tablets) to the uncommon (Lynx, Playstation 3, Kindle Paperwhite, PSP Vita and others). We even tested the website on old Nokia devices, where the website still performed well.
Our designers and front-end team tested the new website on a wide variety of devices, including old models such as this Nokia X2.
Our responsibility as Web designers and developers is not only to make our websites more accessible, but also to educate our clients and colleagues about why they should care.
Below are a couple of quick wins for accessibility that we applied to our website.
Text- Text is legible against backgrounds, with a contrast ratio of 3:1 for headings and 4.5:1 for body text.
- The text is structured with appropriate headings and in a meaningful order, and it describes the topic or purpose of the content.
- Text can be resized without losing content or functionality.
- The purpose of all links is made clear with descriptive text and, when that isn’t practical, with alternative text.
- The first link on every page bypasses the navigation to move straight to the content. This is hidden by default in a standard browser but is accessible in appropriate scenarios.
- Page addresses (i.e. URLs) are human-readable and are permanent wherever possible.
- We implemented access keys for quick navigation to important pages and features.
Here is the HTML for the “skip” navigation link:
<a href="#content" title="Skip to content" accesskey="s" class="btn-skip">Skip navigation</a>And the CSS:
.btn-skip { position: absolute; left: -9999px; } Images- All content images have alternative text (with the alt attribute), which is shown where images are disabled or not supported.
- Content is accessible and understandable when images are disabled or not supported.
- All videos hosted on YouTube have captions (subtitles) if they include spoken words.
- All form controls and fields are properly and clearly labelled.
- Form inputs have been assigned types and attributes so that the correct keyboard is loaded on touchscreen devices.
- All crucial form fields are checked for errors when the form is submitted.
- Any error found is described to the user in text, along with suggestions on how to correct the error.
- All forms have an appropriate focus order so that they can be navigated with the Tab key on the keyboard.
- All forms can be submitted using the “Return” or “Enter” key.
Using the proper input types and attributes, such as required and placeholder, is easy and makes the form more accessible.
<input type="email" id="email" name="email" value="" required="" placeholder="Pop your email address in here"> Just Getting StartedSince we launched our new website a couple of weeks ago, the results have been impressive. Mobile traffic has increased by over 200% (with an 82% increase on average for all traffic); the average duration of a visit is up by 18%; and the exit rate on the home page for mobile users has decreased by over 4,000%. While statistics can tell us only so much, these indicate that the responsive website is performing better on mobile than our previous separate mobile website.
According to Google Analytics, server-response times have decreased from an average of 1.21 seconds to 170 milliseconds. Similarly, page-loading times have decreased from an average of 9.19 seconds to 1.82 seconds.
The important thing to remember here is that this is just the beginning. We know we can improve in some areas: pushing performance optimization much further, reducing file sizes, being more future-friendly with touch gestures across all breakpoints, using server-side solutions such as adaptive images for further contextual enhancement, conforming more closely to the Web Content Accessibility Guidelines’ “AA” standards.
Going responsive is just the first step for our website.
At 2012’s inaugural Smashing Conference, Brad Frost quoted Benjamin Franklin, who said, “When you are finished changing, you’re finished.” For anyone working in the Web industry, this statement will particularly ring true. We work in a medium that is both rapidly and constantly evolving. Keeping up to date with this ever-changing landscape is a challenge, but it’s what makes working with the Web so fantastic and exciting.
We see the launch of our new website as the first improvement of many in our quest for a truly responsive design — and we can’t wait to see where it takes us.
(al) (ea)
© Matt Gibson for Smashing Magazine, 2013.
Five Ways To Prevent Bad Microcopy
You’ve just created the best user experience ever. You had the idea. You sketched it out. You started to build it. Except you’re already in trouble, because you’ve forgotten something: the copy. Specifically, the microcopy.
Microcopy is the text we don’t talk about very often. It’s the label on a form field, a tiny piece of instructional text, or the words on a button. It’s the little text that can make or break your user experience.
If you think you’ve built the best user experience but didn’t make sure the microcopy was spot on, then you haven’t built the best user experience.
With the adoption of agile development and lean UX, we’re often concerned about racing through iterations and getting our products in front of customers. But we can’t forget that design is still about words.
Everyone frets about marketing copy — and they should — but communication doesn’t stop once you’ve sold the user. In some ways, you could argue that words become more important once the marketing experience is done. With most products, users have to be sold to only once — or once in a while — and then they’ll use the core product all the time.
If your microcopy isn’t getting the job done, you’ll lose users — and all the marketing in the world might not get you a second chance.
With that in mind, here are five ways to make sure your website’s microcopy doesn’t end up sinking your UX.
1. Get Out Of Your Own Head And Get To Know The User.I’m willing to bet that your experience is plastered with internal terminology, especially your labels and navigation. Every company has its own language, which often sneaks onto the website when we’re not careful.
Don’t let it happen. Never assume that what works for you will work for the user.
Here’s a simple way to check whether your microcopy is too internal — or confusing, for that matter.
Let’s assume that you’re running some form of usability testing. (If you’re not, there’s only about a thousand articles out there that will convince you you’re making a mistake, so you don’t need me for that.)
When you’re testing, you probably get caught up in watching how the user interacts with your website and their facial expressions. But instead of simply watching, make a point to really listen to — and take notes on — the actual words the user says during testing. Listen closely to the phrases they utter when describing their actions. After all, you’ve told them to think out loud.
Listen to the inflection in their voice as they read microcopy: Did they say that label or term with a question in their voice? Don’t hesitate to have your moderator follow up on copy. Have them go back and ask the user whether they’ve understood that label.
Take it a step further: Listen to what users say from the moment they walk in the building. Listen to their banter with the moderator, the jokes they make and the words they use to express their frustration or enjoyment.
You’d be surprised by what you can learn about a user and their language set from a comment they make about a cup of coffee. Everything someone says tells you something about them and can inform your copywriting process.
2. The User Is A Person. Talk To Them Like One.Because brevity is essential on the Web, most of us tend to truncate everything — particularly labels. Labels are great for design. They organize and keep tidy essential parts of a UI, such as navigation and forms.
Unfortunately, labels have an inherent problem: They’re easily subject to a user’s personal context because they don’t provide explanation. They’re on an island in the user’s mind.
Not too long ago, we encountered this problem with a label at TheLadders.
TheLadders is a job-matching service. Like any matching service, we required information to match a user with the right job.
We thought this form was very clear. “Job Goals” is the label we’ve used for our matching criteria for almost 10 years. It’s brief, which helped to keep the navigation neat. But in a recent redesign, we noticed that users kept stumbling when first arriving on the page.
Turns out that people who don’t work in the job-search industry think of job goals as accomplishments they hope to achieve at their job, not as the details of their next job.
(We also fell into the trap covered in the first point: internal terminology = bad.)
So, we made it more conversational: “What job do you want?” Instantly, we could see that users no longer hesitated. Why? Because taking this new line of copy out of context was impossible.
Instead of forcing a label on a form or field for the sake of the UI, use natural language. The experience should be a conversation with the user, not a filing cabinet for them to drudge through.
Most of all, the labels in the navigation shouldn’t be more important than the user’s interaction with the pages that the labels represent.
3. Use Copy As A Guide, Not A Crutch.“We can fix that with copy.”
I’ve heard this too many times when the UX falls short, and I hate it. If there’s a problem with the design, then fix the design. The best experiences have minimal copy because they’re intuitive. When designing the UX and you find yourself writing a sentence or two to help the user take an action, step back.
Tests have been conducted on readability and on the optimum length of content for understandability since the 1880s. With the rise of the Internet, this story became about line length. Most sources net out between 45 to 75 characters as the ideal line length.
To me, line length is moot, especially with responsive and mobile design. Besides, character counts seem tedious and not very lean.
Instead, I subscribe to the original readability tables of Rudolf Flesch (pictured below), in which sentences with eight words or fewer are regarded as “very easy” to read.
The readability tables of Rudolf Flesch.
It may be an old standard, but it still may be the best measuring stick we have, and it’s the easiest for lean teams to follow. On the Web, we’re shooting for “very easy to read” every time, and we want to be able to communicate with as many people (93%) as possible.
If you can’t explain what a user needs to do in eight words or fewer, then reconsider the design.
Once the user has gotten past the marketing portion of the experience, use copy as a guide to usher them through the product. The best copy on basic UI features, such as a form, will get read but not really noticed. The user absorbs the words and takes the desired action without a hiccup.
4. Treat Every Moment Like A Branding Moment, Even When It’s Not.There are multiple definitions of a “branding moment.” When we talk about copy in a UX, I define it as a moment when you purposefully inject your brand’s tone and voice into what would normally be a straightforward user interaction.
For example, Foursquare has a lot of great branding moments within its badging system. I unlocked the one below not too long ago. It’s fun and a bit edgy, on point with Foursquare’s brand.
A good job of a branding moment with Foursquare’s brand.
But getting carried away is easy. Think hard before using fun or quirky — or whatever your brand’s voice is — copy in a situation that the user wants and expects to be straightforward.
Your brand’s tone and voice are essential to consider when writing all of your copy, but it should not get in the way of a user who is trying to take action.
Avoid over-branding copy on:
- navigation,
- forms and field labels,
- instructional text,
- selection text (drop-downs, radio buttons),
- buttons.
Consider incorporating your brand’s voice in:
- confirmation messaging,
- rewards (badges, points),
- 404 pages,
- server errors,
- error messaging.
The difference between these lists is simple. In the first list, the user is attempting to take action; the second list is the results of actions.
In the first list, you don’t want to risk confusing users as they try to accomplish something and cause them to abandon. Clarity is essential.
In the second list, you have an opportunity to embrace the user’s success (Foursquare’s “You’re on fire!”) or mitigate a failure (TheLadders 404 page, below) by injecting your brand. You don’t need anything from the user at these points.
This isn’t to say that you can’t brand that first list. But if you’re going to do it, test it first. With branding moments, execution is paramount. If you’re unsure, don’t risk it.
By choosing not to brand parts of the experience to keep it simple and easy for the user, you’ll provide an enjoyable experience, which will make your brand stronger. So, every moment is a branding moment. Even when it’s not.
5. If Content Is King, Then Treat Context Like A Queen.The hot saying right now is “Content is king.” Native advertising, or the integration of relevant content into a natural experience for the purpose of acquisition, is becoming a core offering of many agencies and has spawned a few popular startups.
But without context, content is useless. (And if you’re big on Game of Thrones, then you’ll know that queens have all the real power!)
Whether you’re labeling a form or writing a blog post, you have to either understand the user’s existing context or provide context for them.
A user’s context will define how they interpret the copy on the page. That context could come from anywhere: an email they’ve just read, or something that happened to them when they were eight.
When a user doesn’t have proper context, they get confused. When a user gets confused, they abandon.
If you’re agile and iterative, accounting for a holistic experience adds an additional layer of complexity, in the form of consistency. A simple change to copy on one page could affect 10 other pages. One minute you’re calling something “Job Goals,” and the next you’re changing it to “What job do you want?” Well, where else have you used “Job Goals”?
To better understand the user’s context — and to check for consistency — sit down at least once per iteration and experience your “contextual flow” as the user sees it.
For example, if you have a subscription service, the flow might be something like this:
That’s at least 10 distinct steps in which a user’s context could be created, confirmed or altered.
Sit down, take a breath and wipe your mind of what you know is there. Then start with Google or your home page or wherever the first touch usually happens.
Does your onboarding experience deliver the same promise as your Google ad? Have you described a feature using the same language throughout? Are your labels so subjective that the context gets lost? These are questions to answer as you go through the flow.
Whatever Happens, Don’t Ignore Your Microcopy.Microcopy often falls victim to personal bias, internal terminology, poor branding, broken contextual flows, time crunches and other factors. Any of these can undermine even the most well-designed UX and the copy within.
Here’s the thing about mistakes with microcopy: They’re so easy to make yet so hard to identify after you’ve made them.
You have a much better chance of stopping the mistakes in advance than of identifying them after the fact. When you’re testing, how often do you think, “Hey, maybe we should change the label on the third field of this form?” You’re wrapped up in other UX mistakes that you know you’ve made. Unfortunately, a repeated pattern of noticeable failure is usually needed in order for microcopy to get updated or even tested.
So, the next time you’re creating or improving an experience, I hope you employ some of the tactics provided here so that you avoid these “easy” mistakes and do right by your microcopy — and by your user.
(al)
© Bill Beard for Smashing Magazine, 2013.
200 Foodie Pack: A Free Set Of Food Icons
Today we are pleased to feature a set of 200 useful and beautiful foodie icons. This freebie was created by the team behind Freepik, and at the time of writing it’s the largest set of food icons available on the web in one pack.
The 200 Foodie Pack includes 200 customized icons available in PNGs (32×32px, 64×64px, 128×128px), as well as in AI, EPS and vector format. Perfect for any projects around gourmet, food, restaurant, gastronomy and the like. Enjoy!
Download The Freebie!You may freely use it for both your private and commercial projects without any restrictions, including software, online services, templates and themes.
Behind The DesignHere are some insights from the design team:
“At Freepik we love to make freebies and to develop free icons sets for designers that make work easier. The pack was created to neutralize the growing demand for food icons.”
Many thanks to the creative minds behind Freepik! We really appreciate your efforts!
(ea)
© The Smashing Editorial for Smashing Magazine, 2013.
What Leap Motion And Google Glass Mean For Future User Experience
With the Leap Motion controller being released on June 27th and the Google Glass Explorer program already live, it is obvious that our reliance on the mouse or even the monitor to interact with the Web will eventually become obsolete.
The above statement seems like a given, considering that technology moves at such a rapid pace. Yet in 40 years of personal computing, our methods of controlling our machines haven’t evolved beyond using a mouse, keyboard and perhaps a stylus. Only in the last six years have we seen mainstream adoption of touchscreens.
Given that emerging control devices such as the Leap Controller are enabling us to interact with near pixel-perfect accuracy in 3-D space, our computers will be less like dynamic pages of a magazine and more like windows to another world. To make sure we’re on the same page, please take a minute to check out what the Leap Motion controller can do:
Thanks to monitors becoming portable with Google Glass (and the competitors that are sure to follow), it’s easy to see that the virtual world will no longer be bound to flat two-dimensional surfaces.
In this article, we’ll travel five to ten years into the future and explore a world where Google Glass, Leap Motion and a few other technologies are as much a part of our daily lives as our smartphones and desktops are now. We’ll be discussing a new paradigm of human-computer interface. The goal of this piece is to start a discussion with forward-thinking user experience designers, and to explore what’s possible when the mainstream starts to interact with computers in 3-D space.
Please note: We’re exploring an entirely hypothetical scenario, and these are opinions, some of which you may not agree with. However, the opinions are based on current trends, statistics and existing technology. If you’re the kind of designer who is interested in developing the future, I encourage you to read the sources that are linked throughout the article.
Setting The Stage: A Few Things To ConsiderPrior to the introduction of the iPhone in 2007, many considered the smartphone to be for techies and business folk. But in 2013, you’d be hard pressed to find someone in the developed world who isn’t checking their email or tweeting at random times.
So, it’s understandable to think that a conversation about motion control, 3-D interaction and portable monitors is premature. But if the mobile revolution has taught us anything, it’s that people crave connection without being tethered to a stationary device.
To really understand how user experience (UX) will change, we first have to consider the possibility that social and utilitarian UX will be taking place in different environments. In the future, people will use the desktop primarily for utilitarian purposes, while “social” UX will happen on a virtual layer, overlaying the real world (thanks to Glass). Early indicators of this are that Facebook anticipates its mobile growth to outpace its PC growth and that nearly one-seventh of the world’s population own smartphones.
The only barrier right now is that we lack the technology to truly merge the real and virtual worlds. But I’m getting ahead of myself. Let’s start with something more familiar.
The DesktopRight now, UX on the desktop cannot be truly immersive. Every interaction requires physically dragging a hunk of plastic across a flat surface, which approximates a position on screen. While this is accepted as commonplace, it’s quite unnatural. The desktop is the only environment where you interact with one pixel at a time.
Sure, you could create the illusion of three dimensions with drop shadows and parallax effects, but that doesn’t change the fact that the user may interact with only one portion of the screen at a time.
This is why the Leap Motion controller is revolutionary. It allows you to interact with the virtual environment using all 10 fingers and real-world tools in 3-D space. It is as important to computing as analog sticks were to video games.
The Shift In The Way We Interact With MachinesTo wrap our heads around just how game-changing this will be, let’s go back to basics. One basic UX and artificial intelligence test for any new platform is a simple game of chess.
(Image: Wikimedia Commons)
In the game of chess below, thanks to motion controllers and webcams, you’ll be able to “reach in” and grab a piece, as you watch your friend stress over which move to make next.
Now you can watch your opponent sweat. (Image: Algernon D’Ammassa)
In a game of The Sims, you’ll be able to rearrange furniture by moving it with your hands. CAD designers will use their hands to “physically” manipulate components (and then send their design to the 3-D printer they bought from Staples for prototyping.)
While the lack of tactile feedback might deter mainstream adoption early on, research into haptics is already enabling developers to simulate physical feedback in the real world to correspond with the actions of a user’s virtual counterpart. Keep this in mind as you continue reading.
Over time, this level of 3-D interactivity will fundamentally change the way we use our desktops and laptops altogether.
Think about it: The desktop is a perfect, quiet, isolated place to do more involved work like writing, photo editing or “hands-on” training to learn something new. However, a 3-D experience like those mentioned above doesn’t make sense for social interactions such as on Facebook or even reading the news, which are more becoming of mobile.
With immersive, interactive experiences being available primarily via the desktop, it’s hard to imagine users wanting these two experiences to share the same screen.
So, what would a typical desktop experience look like?
Imagine A Cooking Website For People Who Can’t CookWith this cooking website for people who can’t cook, we’re not just talking about video tutorials or recipes with unsympathetic instructions, but rather immersive simulations in which an instructor leads you through making a virtual meal from prep to presentation.
Interactions in this environment would be so natural that the real design challenge is to put the user in a kitchen that’s believable as their own.
You wouldn’t click and drag the icon that represents sugar; you would reach out with your virtual five-fingered hand and grab the life-sized “box” of Domino-branded sugar. You wouldn’t click to grease the pan; you’d mimic pushing the aerosol nozzle of a bottle of Pam.
The Tokyo Institute of Technology has already built such a simulation in the real world. So, transferring the experience to the desktop is only a matter of time.
“Cooking simulator will help you cook a perfect steak every time”
UX on the future desktop will be about simulating physics and creating realistic environments, as well as tracking head, body and eyes to create intuitive 3-D interfaces, based on HTML5 and WebGL.
Aside from the obvious hands-on applications, such as CAD and art programs, the technology will shift the paradigm of UX and user interface (UI) design in ways that are currently difficult to fathom.
The problem right now is that we currently lack a set of clearly defined 3-D gestures to interact with a 3-D UI. Designing UIs will be hard without knowing what our bodies will have to do to interact.
The closest we have right now to defined gestures are those created by Kinect hackers and John Underkoffler of Oblong Technology (the team behind Minority Report’s UI).
In his TED talk from 2010, Underkoffler demonstrates probably the most advanced example of 3-D computer interaction that you’re going to see for a while. If you’ve got 15 minutes to spare, I highly recommend watching it:
John Underkoffler’s talk “Pointing to the Future of UI”
Now, before you start arguing, “Minority Report isn’t practical — humans aren’t designed for that!” consider two things:
- We won’t likely be interacting with 60-inch room-wrapping screens the way Tom Cruise does in Minority Report; therefore, our gestures won’t need to be nearly as big.
- The human body rapidly adapts to its environment. Between the years 2000 and 2010, a period when home computers really went mainstream, reports of Carpal Tunnel Syndrome dropped by nearly 8%.
(Image: Minnesota Department of Health)
However, because the Leap Motion controller is less than $80 and will be available at Best Buy, this technology isn’t just hypothetical, sitting in a lab somewhere, with a bunch of geeks saying “Wouldn’t it be cool if…”
It’s real and it’s cheap, which really means we’re about to enter the Wild West of true 3-D design.
Social Gets Back To The Real WorldSo, where does that leave social UX? Enter Glass.
It’s easy to think that head-mounted augmented reality (AR) displays, such as Google Glass, will not be adopted by the public, and in 2013 that might be true.
But remember that we resisted the telephone when it came out, for many of the same privacy concerns. The same goes for mobile phones and for smartphones around 2007.
So, while first-generation Glass won’t likely be met with widespread adoption, it’s the introduction of a new phase. ABI Research predicts that the wearable device market will exceed 485 million annual shipments by 2018.
According to Steve Lee, Glass’ product director, the goal is to “allow people to have more human interactions” and to “get technology out of the way.”
First-generation Glass performs Google searches, tells time, gives turn-by-turn directions, reports the weather, snaps pictures, records video and does Hangouts — which are many of the reasons why our phones are in front of our faces now.
Moving these interactions to a heads-up display, while moving important and more heavy-duty social interactions to a wrist-mounted display, like the Pebble smartwatch, eliminates the phone entirely and enables you to truly see what’s in front of you.
(Image: Pebble)
Now, consider the possibility that something like the Leap Motion controller could become small enough to integrate into a wrist-mounted smartwatch. This, combined with a head-mounted display, would essentially give us the ability to create an interactive virtual layer that overlays the real world.
Add haptic wristband technology and a Bluetooth connection to the smartwatch, and you’ll be able to “feel” virtual objects as you physically manipulate them in both the real world and on the desktop. While this might still sound like science fiction, with Glass reportedly to be priced between $299 and $499 and Leap Motion at $80 and Pebble being $150, widespread affordability of these technologies isn’t entirely impossible.
Social UX In The Future: A Use CasePicture yourself walking out of the mall, and your close friend Jon updates his status. A red icon appears in the top right of your field of vision. Your watch displays Jon’s avatar, which says, “Sooo hungry right now.”
You say, “OK, Glass. Update status: How about lunch? What do you want?” and keep walking.
“Tacos.”
You say, “OK, Glass. Where can I get good Mexican food?” 40 friends have favorably rated Rosa’s Cafe. Would you like directions? “Yes.” The navigation starts, and you’re en route.
You reach the cafe, but Jon is 10 minutes away. Would you like an audiobook while you wait? “No, play music.” A smart playlist compiles exactly 10 minutes of music that perfectly fits your mood.
“OK, Glass. Play Angry Birds 4.”
Across the table, 3-D versions of the little green piggies and their towers materialize.
In front of you are a red bird, a yellow bird, two blue birds and a slingshot. The red bird jumps up, you pull back on the slingshot, the trajectory beam shows you a path across the table, you let go and knock down a row of bad piggies.
Suddenly, an idea comes to you. “OK, Glass. Switch to Evernote.”
A piece of paper and a pen are projected onto the table in front of you, and a bulletin board appears to the left.
You pick up the AR pen, jot down your note, move the paper to the appropriate bulletin, and return to Angry Birds.
You could make your game visible to other Glass wearers. That way, others could play with you — or, at the very least, would know you’re not some crazy person pretending to do… whatever you’re doing across the table.
When Jon arrives, notifications are disabled. You push the menu icon on the table and select your meal. Your meal arrives; you take photos of your food; eat; publish to Instagram 7.
Before you leave, the restaurant gives a polite notification, letting you know that a coupon for 10% off will be sent to your phone if you write a review.
How Wearable Technology Interacts With DesktopsLater, having finished the cooking tutorial on the desktop, you decide it’s time to make the meal for real. You put on Glass and go to the store. The headset guides you directly to the brands that were advertised “in game.” After picking out your ingredients, you receive a notification that a manufacturer’s coupon has been sent to your phone and can be used at the check-out.
When you get home, you lay a carrot on the cutting board and an overlay projects guidelines on where to cut. You lay out the meat, and a POW graphic is overlaid, showing you where to hit for optimal tenderness:
Image source?
You put the meat in the oven; Glass starts the timer. You put the veggies in the pan; Glass overlays a pattern to show where and when to stir.
While you were at the store, Glass helped you to pick out the perfect bottle of wine to pair with your meal (based on reviews, of course). So, you pour yourself a glass and relax while you wait for the timer to go off.
In the future, augmented real-world UX experiences will be turned into real business. The more you enhance real life, the more successful your business will be. After all, is it really difficult to imagine this cooking experience being turned into a game?
What Can We Do About This Today?If you’re the kind of UI designer who seeks to push boundaries, then the best thing you can do right now is think. Because the technology isn’t 100% available, the best you can do is open your imagination to what will be possible when the average person has evolved beyond the keyboard and mouse.
Draw inspiration from websites and software that simulate depth to create dynamic, layered experiences that can be easily operated without a mouse. The website of agency Black Negative is a good example of future-inspired “flat” interaction. It’s easy to imagine interacting with this website without needing a mouse. The new Myspace is another.
To go really deep, look at the different Chrome Experiments, and find a skilled HTML5 and WebGL developer to discuss what’s in store for the future. The software and interactions that come from your mind will determine whether these technologies will be useful.
ConclusionWhile everything I’ve talked about here is conceptual, I’m curious to hear what you think about how (or even if) these devices will affect UIs. I’d also love to hear your vision of future UIs.
To get started, let me ask you two questions:
- How will the ability to reach into the screen and interact with the virtual world shape our expectations of computing?
- How will untethering content from flat surfaces fundamentally change the medium?
I look forward to your feedback. Please share this article if you’ve enjoyed this trip into the future.
(il) (al)
© Tommy Walker for Smashing Magazine, 2013.
Building An App In 45 Minutes With Meteor
The other day, I finally accomplished one of my long-standing goals: to go from one of those “Wouldn’t it be cool…” ideas to a working, live app in less than 1 hour. 45 minutes, actually.
It all started with a design meet-up in San Francisco. I can honestly say this was the best meet-up I’ve ever been to: Even though it was announced only two days in advance, more than 200 people RSVPed, and a good number of them showed up. It was a great chance to put faces to familiar names, as well as to make new friends.
But I got to talking with so many people that I didn’t have a chance to get contact info for everybody. So, the next day, I asked the organizers about it and they suggested that everyone who attended leave a link to their Twitter account in a shared Google Doc.
That would work, but I was afraid it would prove to be too much effort. If I’ve learned one thing in my years as a designer, it’s that people are lazy. Instead, what if I built an app that lets the user add their Twitter account to a list in a single click?
The app would work something like this:
- The user signs into Twitter,
- A link to their Twitter profile appears on the page,
- That’s pretty much it!
With my list of requirements complete, I set to work to see how fast I could build this, and I thought it’d be interesting to walk you through the process.
At first, take a peek at how the final app looked like:
Our final bare-bones (but working!) app.
You can also see a demo of the finished product, and find the code on GitHub. (Note: Give it some time to load. Apps hosted on Meteor’s free hosting service often slow down under a lot of traffic.)
A word of warning: This won’t be a traditional tutorial. Instead, it will be a play-by-play walkthrough of how I coded the app in one hour, including the usual dumb mistakes and wrong turns.
Introducing MeteorI decided to build the app with Meteor. Meteor is a fairly young JavaScript framework that works on top of Node and has a few interesting characteristics.
First, it’s all JavaScript, so you don’t need to deal with one language in the browser and another on the server. That’s right: the same language you use to set up jQuery slider plugins can also be used to query your app’s database! The added benefit of this is that your app now has only a single code base — meaning you can make the same code accessible from both the client and server if you need to.
Meteor is also reactive, meaning that any change to your data is automatically reflected everywhere throughout the app (including the user interface) without the need for callbacks. This is a powerful feature. Imagine adding a task to a to-do list. With reactivity, you don’t need a callback to insert the new HTML element into the list. As soon as Meteor receives the new item, it automatically propagates the change to the user interface, without any intervention on your part!
What’s more, Meteor is real time, so both your changes and the changes made by other users are instantly reflected in the UI.
Like many other modern frameworks, Meteor also speeds up your Web app by transforming it into a single-page Web app. This means that instead of refreshing the whole browser window every time the user changes the page or performs an action, Meteor modifies only the part of the app that actually changes without reloading the rest, and then it uses the HTML5 pushState API to change the URL appropriately and make the back button work.
Not having to update the whole page enables another very powerful feature. Instead of sending HTML code over the network, Meteor sends the raw data and lets the client decide how to render it.
Finally, one of my favorite features of Meteor is simply that it automates a lot of boring tasks, such as linking up and minifying style sheets and JavaScript code. It also takes care of routine stuff for you on the back end, letting you add user accounts to the app with a single line of code.
I’ve been experimenting with Meteor for the past six months, using it first to build Telescope (an open-source social news app), and then in turn using Telescope as a base to create Sidebar (a design links website), and I’ve just released a book about it. I believe that, more than any other framework, Meteor helps you get from idea to app in the shortest possible amount of time. So, if all of this has made you curious, I recommend you give it a try and follow along this short walkthrough.
Step 0: Install Meteor (5 Minutes)First, let’s install Meteor. If you’re on Mac or Linux, simply open a Terminal window and type:
curl https://install.meteor.com | /bin/shInstalling Meteor on Windows is a little trickier; you can refer to this handy guide to get started.
Step 1: Create The App (1 Minute)Creating a Meteor app is pretty easy. Once you’ve installed Meteor, all you need to do is go back to the Terminal and type this:
meteor create myAppYou’ll then be able to run your brand new app locally with this:
cd myApp meteor myAppIn my case, I decided to call my app twitterList, but you can call yours whatever you want!
Once you run the app, it will be accessible at http://localhost:3000/ in your browser.
Step 2: Add Packages (1 Minute)Because I want users to be able to log in with Twitter, the first step is to set up user accounts. Thankfully, Meteor makes this trivially easy as well. First, add the required Meteor packages, accounts-ui and (since we want users to log in with Twitter) accounts-twitter.
Open up a new Terminal window (since your app is already running in the first one) and enter:
meteor add accounts-ui meteor add accounts-twitterYou’ll now be able to display a log-in button just by inserting {{loginButtons}} anywhere in your Handlebars code.
A more complex version of the accounts-ui widget, as seen in Telescope.
I didn’t want to have to bother with styling, so I decided to also include Twitter Bootstrap with my app.
I went to the Twitter Bootstrap website, downloaded the framework, extracted the ZIP file, copied it to my app’s Meteor directory, and then hooked up the required CSS files in the head of my app’s main file.
Ha ha, not really. What is this, 2012? That’s not how it works with Meteor. Instead, we just go back to the Terminal and type:
meteor add bootstrap Client Vs. ServerI guess at this point I should briefly tell you more about how Meteor apps work. First, we’ve already established that a Meteor app’s code is all JavaScript. This JavaScript can be executed in the browser like regular JavaScript code (think a jQuery plugin or an alert() message), but can additionally be executed on the server (like PHP or Ruby code). What’s more, the same code can even be executed in both environments!
So, how do you keep track of all this? It turns out Meteor has two mechanisms to keep client and server code separate: the Meteor.isClient and Meteor.isServer booleans, and the /client and /server directories.
I like to keep things clean; so, unlike the default Meteor app that gets generated with meteor create (which uses the booleans), I’d rather use separate directories.
Also, note that anything that isn’t in the /client or /server directories will be executed in both environments by default.
Step 3: Create the Markup (10 Minutes)I like to start from a static template and then fill in the holes with dynamic data, so that’s what I did. Just write your template as if it were static HTML, except replace every “moving part” with Handlebars tags. So, something like this…
<a href="http://twitter.com/SachaGreif">Sacha Greif</a></p>… becomes this:
<a href="http://twitter.com/{{userName}}">{{fullName}}</a>Of course, those tags won’t do anything yet and will appear blank. But we’ll match them up with real data pretty soon. Next, I deleted the contents of twitterlist.html and got to work on my HTML. This is the code I had after this step:
<head> <title>Who Was There?</title> </head> <body> <div class="container"> <div class="row"> <div class="span6"> <div class="well"> <h4>Did you go to the <a href="http://www.meetup.com/Meteor-SFBay/events/115875132/">Designer Potluck</a>? Sign in with Twitter to add your name.</h4> {{loginButtons}} </div> <table class="table"> <tr> <td> <a target="_blank" href="http://twitter.com/{{userName}}"><img src="{{image}}"/> {{fullName}}</a> </td> </tr> </table> </div> </div> </div> </body> Step 4: Configure Twitter Sign-In (3 Minutes)You’ll have noticed the {{loginButtons}} Handlebars tag, which inserts a log-in button on your page. If you try to click it right now, it won’t work, and Meteor will ask you for additional information.
You’ll need to fill in your app’s Twitter credentials. Larger view.
To get this information, we first need to tell Twitter about our app. Follow the steps on the screen and create a new Twitter app; once you’re done, try logging in. If everything has worked right, you should now have a user account in the app!
Creating a new Twitter app. Larger view.
To test this out, open your browser’s console (in the WebKit inspector or in Firebug) and type this:
Meteor.user()This will retrieve the currently logged-in user, and, if everything has gone right, it will give you your own user object in return (something like Object {_id: "8ijhgK5icGrLjYTS7", profile: Object, services: Object}).
Step 5: Split It Into Templates (5 Minutes)You’ll have noticed that our HTML has room to display only a single user. We’ll need some kind of loop to iterate over the whole list. Thankfully, Handlebars provides us with the {{#each xyz}} … {{/each}} helper (where xyz are the objects you want to iterate on, usually an array), which does just that.
We’ll also split the code into a few templates to keep things organized. The result is something like this:
<head> <title>Who Was There?</title> </head> <body> <div class="container"> {{> content}} </div> </div> </body> <template name="content"> <div class="row"> <div class="span6"> <div class="well"> {{loginButtons}} </div> <table class="table"> {{#each users}} {{> user}} {{/each}} </table> </div> </template> <template name="user"> <tr> <td> <a target="_blank" href="http://twitter.com/{{userName}}"><img src="{{image}}"/> {{fullName}}</a> </td> </tr> </template> Step 6: Hook Up Our Template (5 Minutes)Our template is all set up, but it’s iterating over empty air. We need to tell it what exactly this users variable in the {{#each users}} block is. This block is contained in the content template, so we’ll give that template a template helper.
Delete the contents of twitterlist.js, and write this instead:
Template.content.users = function () { return Meteor.users.find(); };What we’re doing here is defining Template.content.users as a function that returns Meteor.users.find().
Meteor.users is a special collection created for us by Meteor. Collections are Meteor’s equivalent of MySQL tables. In other words, they’re a list of items of the same type (such as users, blog posts or invoices). And find() simply returns all documents in the collection.
We’ve now told Meteor where to find that list of users, but nothing’s happening yet. What’s going on?
Step 7: Fix Our Tags (5 Minutes)Remember when we typed this?
<a target="_blank" href="http://twitter.com/{{userName}}"><img src="{{image}}"/> {{fullName}}</a>The {{userName}}, {{image}} and {{fullName}} are just random placeholders that I picked for the sake of convenience. We’d be pretty lucky if they corresponded to actual properties of our user object! (Hint: they don’t.)
Let’s find out the “real” properties with the help of our friend, the browser console. Open it up, and once more type this:
Meteor.user()The object returned has all of the fields we need. By exploring it, we can quickly find out that the real properties are actually these:
- {{services.twitter.screenName}}
- {{services.twitter.profile_image_url}}
- {{profile.name}}
Let’s make the substitutions in our template and see what happens.
It works! Our first and only user (you!) should now appear in the list. We’re still missing some fields, though, and only the user’s full name appears. We need to dig deeper into Meteor to understand why.
A Database On The ClientWe haven’t really touched on what Meteor does behind the scenes yet. Unlike, say, PHP and MySQL, with which your data lives only on the server (and stays there unless you extract it from the database), Meteor replicates your server-side data in the client and automatically syncs both copies.
This accomplishes two things. First, reading data becomes very fast because you’re reading from the browser’s own memory, and not from a database somewhere in a data center.
Secondly, modifying data is extremely fast as well, because you can just modify the local copy of the data, and Meteor will replicate the changes for you server-side in the background. But this new paradigm comes with a caveat: We have to be more careful with data security.
Step 8: Make the App Secure (1 Minute)We’ll address data security in terms of both writing and reading. First, let’s prevent people from writing whatever they want to our database. This is simple enough because all we need to do is remove Meteor’s insecure package:
meteor remove insecureThis package comes bundled with every new Meteor app to speed up development (letting you insert data client-side without having to set up all of the necessary checks and balances first), but it is obviously not meant for production. And because our app won’t need to write to the database at all (except for creating new users — but that’s a special case that Meteor already takes care of), we’re pretty much done!
More On SecurityWhile we’re on the topic of security, Meteor apps also come with a second default package, autopublish, which takes care of sending all of the data contained in your server-side collections to the client.
Of course, for a larger app, you probably won’t want to do that. After all, some of the information in your database is supposed to remain private, and even if all your data is public, sending all of it to the client might not be good for performance.
In our case, this doesn’t really matter because we do want to “publish” (i.e. send from the server to the client) all of our users. Don’t worry, though — Meteor is still smart enough not to publish sensitive information, such as passwords and authentication tokens, even with autopublish on.
Step 9: Add Follow Buttons (8 Minutes)While visitors can now click on a name to go to their Twitter profile, simply displaying follow buttons for each user would be much better. This step took a little tinkering to get right. It turns out that Twitter’s default follow button code doesn’t play nice with Meteor.
After 15 minutes of unsuccessful attempts, I turned to the Google and quickly found that for single-page apps, Twitter suggests using an iframe instead.
This worked great:
<iframe style="width: 300px; height: 20px;" src="//platform.twitter.com/widgets/follow_button.html?screen_name={{services.twitter.screenName}}" height="240" width="320" frameborder="0" scrolling="no"></iframe> Step 10: Deploy (1 Minute)The last step is to deploy our app and test it in production. Once again, Meteor makes this easy. No need to find a hosting service, register, launch an instance, and do a Git push. All you need to do is go back to the Terminal and type this:
meteor deploy myAppHere, myApp is a unique subdomain that you pick (it doesn’t have to be the same as the app’s name). Once you’ve deployed, your app will live at http://myapp.meteor.com. Go ahead and ask a few people to register: You’ll see their Twitter profiles added to the list in real time!
Going FurtherOf course, I had to gloss over a lot of key Meteor concepts to keep this tutorial light. I barely mentioned collections and publications, and I didn’t even really talk about Meteor’s most important concept, reactivity. To learn more about Meteor, here are a few good resources:
- Documentation, Meteor
This is a required reference for any Meteor developer. And it’s cached, meaning you can even access it offline. - EventedMind
Chris Mather puts out two Meteor screencasts every Friday. They’re a great help when you want to tackle Meteor’s more advanced features. - Discover Meteor
I’m obviously biased, but I think our book is one of the best resources to get started with Meteor. It takes you through building a real-time social news app (think Reddit or Hacker News) step by step. - Blog, Discover Meteor
We also make a lot of information available for free on our blog. We suggest looking at “Getting Started With Meteor” and “Useful Meteor Resources.” - “Prototyping With Meteor”
A tutorial we wrote for NetTuts that takes you through building a simple chat app.
I truly believe Meteor is one of the best frameworks out there for quickly building apps, and it’s only going to get better. Personally, I’m really excited to see how the framework evolves in the next couple of months. I hope this short tutorial has given you a taste of what Meteor’s all about and has made you curious to learn more!
(il) (ea) (al)
© Sacha G for Smashing Magazine, 2013.
Facing The Challenge: Building A Responsive Web Application
We are talking and reading a lot about responsive Web design (RWD) these days, but very little attention is given to Web applications. Admittedly, RWD still has to be ironed out. But many of us believe it to be a strong concept, and it is here to stay. So, why don’t we extend this topic to HTML5-powered applications? Because responsive Web applications (RWAs) are both a huge opportunity and a big challenge, I wanted to dive in.
Building a RWA is more feasible than you might think. In this article, we will explore ideas and solutions. In the first part, we will set up some important concepts. We will build on these in the second part to actually develop a RWA, and then explore how scalable and portable this approach is.
Part 1: Becoming Responsible Some Lessons LearnedIt’s not easy to admit, but recently it has become more and more apparent that we don’t know many things about users of our websites. Varying screen sizes, device features and input mechanisms are pretty much RWD’s reasons for existence.
From the lessons we’ve learned so far, we mustn’t assume too much. For instance, a small screen is not necessarily a touch device. A mobile device could be over 1280 pixels wide. And a desktop could have a slow connection. We just don’t know. And that’s fine. This means we can focus on these things separately without making assumptions: that’s what responsiveness is all about.
Progressive EnhancementThe “JavaScript-enabled” debate is so ’90s. We need to optimize for accessibility and indexability (i.e. SEO) anyway. Claiming that JavaScript is required for Web apps and, thus, that there is no real need to pre-render HTML is fair (because SEO is usually not or less important for apps). But because we are going responsive, we will inherently pay a lot attention to mobile and, thus, to performance as well. This is why we are betting heavily on progressive enhancement.
Responsive Web DesignRWD has mostly to do with not knowing the screen’s width. We have multiple tools to work with, such as media queries, relative units and responsive images. No matter how wonderful RWD is conceptually, some technical issues still need to be solved.
Not many big websites have gone truly responsive since The Boston Globe. (Image credits: Antoine Lefeuvre)
In the end, RWD is mostly about client-side solutions. Assuming that the server basically sends the same initial document and resources (images, CSS and JavaScript) to every device, any responsive measures will be taken on the client, such as:
- applying specific styles through media queries;
- using (i.e. polyfilling) <picture> or @srcset to get responsive images;
- loading additional content.
Some of the issues surrounding RWD today are the following:
- Responsive images haven’t been standardized.
- Devices still load the CSS behind media queries that they never use.
- We lack (browser-supported) responsive layout systems (think flexbox, grid, regions, template).
- We lack element queries.
Imagine that these challenges (such as images not being responsive and CSS loading unnecessarily) were solved on all devices and in all browsers, and that we didn’t have to resort to hacks or polyfills in the client. This would transfer some of the load from the client to the server (for instance, the CMS would have more control over responsive images).
But we would still face the issue of responsive content. Although many believe that the constraints of mobile help us to focus, to write better content and to build better designs, sometimes it’s simply not enough. This is where server-side solutions such as RESS and HTTP Client Hints come in. Basically, by knowing the device’s constraints and features up front, we can serve a different and optimized template to it.
Assuming we want to COPE, DRY and KISS and stuff, I think it comes down to where you want to draw the line here: the more important that performance and content tailored to each device is, the more necessary server-side assistance becomes. But we also have to bet on user-agent detection and on content negation. I’d say that this is a big threshold, but your mileage may vary. In any case, I can see content-focused websites getting there sooner than Web apps.
Having said that, I am focusing on RWAs in this article without resorting to server-side solutions.
Responsive BehaviorRWD is clearly about layout and design, but we will also have to focus on responsive behavior. It is what makes applications different from websites. Fluid grids and responsive images are great, but once we start talking about Web applications, we also have to be responsive in loading modules according to screen size or device capability (i.e. pretty much media queries for JavaScript).
For instance, an application might require GPS to be usable. Or it might contain a large interactive table that just doesn’t cut it on a small screen. And we simply can’t set display: none on all of these things, nor can we build everything twice.
We clearly need more.
Part 2: Building RWAsTo quickly recap, our fundamental concepts are:
- progressive enhancement,
- responsive design,
- responsive behavior.
Fully armed, we will now look into a way to build responsive, context-aware applications. We’ll do this by declaratively specifying modules, conditions for loading modules, and extended modules or variants, based on feature detection and media queries. Then, we’ll dig deeper into the mechanics of dependency injection to see how all of this can be implemented.
Declarative Module InjectionWe’ll start off by applying the concepts of progressive enhancement and mobile first, and create a common set of HTML, CSS and JavaScript for all devices. Later, we’ll progressively enhance the application based on content, screen size, device features, etc. The foundation is always plain HTML. Consider this fragment:
<div data-module="myModule"> <p>Pre-rendered content</p> </div>Let’s assume we have some logic to query the data-module attribute in our document, to load up the referenced application module (myModule) and then to attach it to that element. Basically, we would be adding behavior that targets a particular fragment in the document.
This is our first step in making a Web application responsive: progressive module injection. Also, note that we could easily attach multiple modules to a single page in this way.
Conditional Module InjectionSometimes we want to load a module only if a certain condition is met — for instance, when the device has a particular feature, such as touch or GPS:
<div data-module="find/my/dog" data-condition="gps"> <p>Pre-rendered fallback content if GPS is unavailable.</p> </div>This will load the find/my/dog module only if the geolocation API is available.
Note: For the smallest footprint possible, we’ll simply use our own feature detection for now. (Really, we’re just checking for 'geolocation' in navigator.) Later, we might need more robust detection and so delegate this task to a tool such as Modernizr or Has.js (and possibly PhoneGap in hybrid mode).
Extended Module InjectionWhat if we want to load variants of a module based on media queries? Take this syntax:
<div data-module="myModule" data-variant="large"> <p>Pre-rendered content</p> </div>This will load myModule on small screens and myModule/large on large screens.
For brevity, this single attribute contains the condition and the location of the variant (by convention). Programmatically, you could go mobile first and have the latter extend from the former (or separated modules, or even the other way around). This can be decided case by case.
Media QueriesOf course, we couldn’t call this responsive if it wasn’t actually driven by media queries. Consider this CSS:
@media all and (min-width: 45em) { body:after { content: 'large'; display: none; } }Then, from JavaScript this value can be read:
var size = window.getComputedStyle(document.body,':after').getPropertyValue('content');And this is why we can decide to load the myModule/large module from the last example if size === "large", and load myModule otherwise. Being able to conditionally not load a module at all is useful, too:
<div data-module="myModule" data-condition="!small"> <p>Pre-rendered content</p> </div>There might be cases for media queries inside module declarations:
<div data-module="myModule" data-matchMedia="min-width: 800px"> <p>Pre-rendered content</p> </div>Here we can use the window.matchMedia() API (a polyfill is available). I normally wouldn’t recommend doing this because it’s not very maintainable. Following breakpoints as set in CSS seems logical (because page layout probably dictates which modules to show or hide anyway). But obviously it depends on the situation. Targeted element queries may also prove useful:
<div data-module="myModule" data-matchMediaElement="(min-width: 600px)"></div>Please note that the names of the attributes used here represent only an example, a basic implementation. They’re supposed to clarify the idea. In a real-world scenario, it might be wise to, for example, namespace the attributes, to allow for multiple modules and/or conditions, and so on.
Device OrientationTake special care with device orientation. We don’t want to load a different module when the device is rotated. So, the module itself should be responsive, and the page’s layout might need to accommodate for this.
Connecting The DotsThe concept of responsive behavior allows for a great deal of flexibility in how applications are designed and built. We will now look into where those “modules” come in, how they relate to application structure, and how this module injection might actually work.
Applications and ModulesWe can think of a client-side application as a group of application modules that are built with low-level modules. As an example, we might have User and Message models and a MessageDetail view to compose an Inbox application module, which is part of an entire email client application. The details of implementation, such as the module format to be used (for example, AMD, CommonJS or the “revealing module” pattern), are not important here. Also, defining things this way doesn’t mean we can’t have a bunch of mini-apps on a single page. On the other hand, I have found this approach to scale well to applications of any size.
A Common ScenarioAn approach I see a lot is to put something like <div id="container"> in the HTML, and then load a bunch of JavaScript that uses that element as a hook to append layouts or views. For a single application on a single page, this works fine, but in my experience it doesn’t scale well:
- Application modules are not very reusable because they rely on a particular element to be present.
- When multiple applications or application modules are to be instantiated on a single page, they all need their own particular element, further increasing complexity.
To solve these issues, instead of letting application modules control themselves, what about making them more reusable by providing the element they should attach to? Additionally, we don’t need to know which modules must be loaded up front; we will do that dynamically. Let’s see how things come together using powerful patterns such as Dependency Injection (DI) and Inversion of Control (IOC).
Dependency InjectionYou might have wondered how myModule actually gets loaded and instantiated.
Loading the dependency is pretty easy. For instance, take the string from the data-module attribute (myModule), and have a module loader fetch the myModule.js script.
Let’s assume we are using AMD or CommonJS (either of which I highly recommended) and that the module exports something (say, its public API). Let’s also assume that this is some kind of constructor that can be instantiated. We don’t know how to instantiate it because we don’t know exactly what it is up front. Should we instantiate it using new? What arguments should be passed? Is it a native JavaScript constructor function or a Backbone view or something completely different? Can we make sure the module attaches itself to the DOM element that we provide it with?
We have a couple of possible approaches here. A simple one is to always expect the same exported value — such as a Backbone view. It’s simple but might be enough. It would come down to this (using AMD and a Backbone view):
var moduleNode = document.querySelector('[data-module]'), moduleName = node.getAttribute('data-module'); require([moduleName], function(MyBackBoneView) { new MyBackBoneView({ el: moduleNode }); })That’s the gist of it. It works fine, but there are even better ways to apply this pattern of dependency injection.
IOC ContainersLet’s take a library such as the excellent wire.js library by cujoJS. An important concept in wire.js is “wire specs,” which essentially are IOC containers. It performs the actual instantiation of the application modules based on a declarative specification. Going this route, the data-module should reference a wire spec (instead of a module) that describes what module to load and how to instantiate it, allowing for practically any type of module. Now, all we need to do is pass the reference to the spec and the viewNode to wire.js. We can simply define this:
wire([specName, { viewNode: moduleNode }]);Much better. We let wire.js do all of the hard work. Besides, wire has a ton of other features.
In summary, we can say that our declarative composition in HTML (<div data-module="">) is parsed by the composer, and consults the advisor about whether the module should be loaded (data-condition) and which module to load (data-module or data-variant), so that the dependency injector (DI, wire.js) can load and apply the correct spec and application module:
Detections for screen size and device features that are used to build responsive applications are sometimes implemented deep inside application logic. This responsibility should be laid elsewhere, decoupled more from the particular applications. We are already doing our (responsive) layout composition with HTML and CSS, so responsive applications fit in naturally. You could think of the HTML as an IOC container to compose applications.
You might not like to put (even) more information in the HTML. And honestly, I don’t like it at all. But it’s the price to pay for optimized performance when scaling up. Otherwise, we would have to make another request to find out whether and which module to load, which defeats the purpose.
Wrapping UpI think the combination of declarative application composition, responsive module loading and module extension opens up a boatload of options. It gives you a lot of freedom to implement application modules the way you want, while supporting a high level of performance, maintainability and software design.
Performance and BuildSometimes RWD actually decreases the performance of a website when implemented superficially (such as by simply adding some media queries or extra JavaScript). But for RWA, performance is actually what drives the responsive injection of modules or variants of modules. In the spirit of mobile first, load only what is required (and enhance from there).
Looking at the build process to minify and optimize applications, we can see that the challenge lies in finding the right approach to optimize either for a single application or for reusable application modules across multiple pages or contexts. In the former case, concatenating all resources into a single JavaScript file is probably best. In the latter case, concatenating resources into a separate shared core file and then packaging application modules into separate files is a sound approach.
A Scalable ApproachResponsive behavior and complete RWAs are powerful in a lot of scenarios, and they can be implemented using various patterns. We have only scratched the surface. But technically and conceptually, the approach is highly scalable. Let’s look at some example scenarios and patterns:
- Sprinkle bits of behavior onto static content websites.
- Serve widgets in a portal-like environment (think a dashboard, iGoogle or Netvibes). Load a single widget on a small screen, and enable more as screen resolution allows.
- Compose context-aware applications in HTML using reusable and responsive application modules.
In general, the point is to maximize portability and reach by building on proven concepts to run applications on multiple platforms and environments.
Future-Proof and PortableSome of the major advantages of building applications in HTML5 is that they’re future-proof and portable. Write HTML5 today and your efforts won’t be obsolete tomorrow. The list of platforms and environments where HTML5-powered applications run keeps growing rapidly:
- As regular Web applications in browsers;
- As hybrid applications on mobile platforms, powered by Apache Cordova (see note below):
- iOS,
- Android,
- Windows Phone,
- BlackBerry;
- As Open Web Apps (OWA), currently only in Firefox OS;
- As desktop applications (such as those packaged by the Sencha Desktop Packager):
- Windows,
- OS X,
- Linux.
Note: Tools such as Adobe PhoneGap Build, IBM Worklight and Telerik’s Icenium all use Apache Cordova APIs to access native device functionality.
DemoYou might want to dive into some code or see things in action. That’s why I created a responsive Web apps repository on GitHub, which also serves as a working demo.
ConclusionHonestly, not many big websites (let alone true Web applications) have gone truly responsive since The Boston Globe. However, looking at deciding factors such as cost, distribution, reach, portability and auto-updating, RWAs are both a huge opportunity and a big challenge. It’s only a matter of time before they become much more mainstream.
We are still looking for ways to get there, and we’ve covered just one approach to building RWAs here. In any case, declarative composition for responsive applications is quite powerful and could serve as a solid starting point.
(al) (ea)
© Lars Kappert for Smashing Magazine, 2013.
