How Mail.Ru Reduced Email Storage From 50 To 32 PB

case studyHow Mail.Ru Reduced Email Storage From 50 To 32 PB

When the Russian ruble’s exchange rate slumped two years ago, it drove us to think of cutting hardware and hosting costs for the Mail.Ru email service. To look at ways to save money, let’s first take a look at what email consists of.

1

Indexes and bodies account for only 15% of the storage size, whereas 85% is taken up by files. So, optimization of files (that is, attachments) is worth exploring in more detail. At the time, we didn’t have file deduplication in place, but we estimated that it could shrink the total storage size by 36%, because many users receive the same messages, such as price lists from online stores and newsletters from social networks that contain images2 and so on. In this article, I’ll describe how we implemented a deduplication system under the guidance of PSIAlt3.

Further Reading on SmashingMag: Link

Meta Data Storage Link

We’re dealing with a stream of files. When we receive a message, we must deliver it to the user as soon as possible. We need to be able to quickly recognize duplicates. An easy solution would be to name files based on their contents. We’re using SHA-1 for this purpose. The initial name of the file is stored in the email itself, so we don’t need to worry about it.

Once a new email arrives, we retrieve the files, compute their hashes and add the result to the email. It’s a necessary step to be able to easily locate the files belonging to a particular email in our future storage when this email is being sent.

Now, let’s upload a file to our storage and find out whether another file with the same hash already exists there. This means we’ll need to store all hashes in memory. Let’s call this storage for hashes “FileDB.”

8

A single file can be attached to different emails, so we’ll need a counter that keeps track of all emails containing this file.

9

The counter increments with every new file uploaded. About 40% of all files are deleted, so if a user deletes an email containing files uploaded to the cloud, the counter must be decremented. If the counter reaches zero, the file can be deleted.

Here we face the first issue: Information about an email (indexes) is stored in one system, whereas information about a file is stored in another. This could lead to an error. For example, consider the following workflow:

  1. The system receives a request to delete an email.
  2. The system checks the email indexes.
  3. The system can see there’s an attachment (SHA-1).
  4. The system sends a request to delete a file.
  5. A crash occurs, so the email doesn’t get deleted.
10

In this case, the email stays in the system, but the counter gets decremented by 1. When the system receives a second request to delete this email, the counter gets decremented again — and we could encounter a situation in which the file is still attached to an email but the counter is already at 0.

11

Not losing data is critical. We can’t have a situation in which a user opens an email and discovers no attachment there. That being said, storing some redundant files on disks is no big deal. All we need is a mechanism to unambiguously determine whether the counter is correctly set to 0. That’s why we have one more field — magic.

12

The algorithm is simple. Along with the hash of a file, we store a randomly generated number in an email. All requests to upload or delete a file take this random number into account: In case of an upload request, this number is added to the current value of the magic number; if it’s a delete request, this random number is subtracted from the current value of the magic number.

Thus, if all emails have incremented and decremented the counter the correct number of times, then the magic number will also equal 0. Otherwise, the file must not be deleted.

Let’s consider an example. We have a file named sha1. It’s uploaded once, and the email generates a random (magic) number for it, which is equal to 345.

13

Then a new email arrives with the same file. It generates its own magic number (123) and uploads the file. The new magic number is added to the current value of the magic number (345), and the counter gets incremented by 1. As a result, what we have in FileDB is the magic number with the value of 468 and the counter set to 2.

14

After the user deletes the second email, the magic number generated for this email is subtracted from the current value of the magic number (468), and the counter gets decremented by 1.

15

Let’s first look at the normal course of events. The user deletes the first email, and the magic number and the counter both become 0. This means the data is consistent and the file can be deleted.

16

Now, suppose something goes wrong: The second email sends two delete requests. The counter being equal to 0 means there are no more links to the file, but the magic number, which equals 222, signals a problem: The file can’t be deleted until the data is consistent.

17

Let’s develop the situation a little more. Suppose the first email also gets deleted. In this case, the magic number (-123) still signals an inconsistency.

18

As a safety measure, once the counter reaches 0 but the magic number doesn’t (in our case, the magic number is 222 and the counter is 0), the file is assigned a “Do not delete” flag. This way, even if — after a series of deletions and uploads — both the magic number and the counter somehow become 0, we’ll still know that this file is problematic and must not be deleted. The system isn’t allowed to generate a magic peer 0. If you send 0 as the magic number, you’ll receive an error.

Back to FileDB. Every entity has a set of flags. Whether you plan to use them or not, you’re going to need them (if, say, a file needs to be marked as undeletable).

19

We have all of the file attributes, except for where the file is physically located. This place is identified by a server (IP) and a disk. There should be two such servers and two such disks. We store two copies of each file.

20

But one disk stores a lot of files (in our case, about 1 million), which means these records will be identified by the same disk pair in FileDB, so storing this information in FileDB would be wasteful. Let’s put it in a separate table, PairDB, linked to FileDB via a disk pair ID.

21

I guess it goes without saying that, apart from a disk pair ID, we’ll also need a flags field. I’ll jump ahead a bit and mention that this field signals whether the disks are locked (say, one disk has crashed and the other is being copied, so no new data can be written to either of them).

22

Also, we need to know how much free space each disk has — hence, the corresponding fields.

23

To make sure everything works fast, both FileDB and PairDB must be RAM-resident. We were using Tarantool 1.5, but now the latest version should be used. FileDB has five fields (20, 4, 4, 4 and 4 bytes long), which add up to 36 bytes. Also, each record has a 16-byte header, plus a 1-byte length pointer per field, which brings the total record size to 57 bytes.

24

Tarantool allows you to specify the minimum allocation size, so memory-associated overhead can be kept close to zero. We’ll be allocating the exact amount of memory needed for one record. We have 12 billion files.

(57 * 12 * 10^9) / (1024^3) = 637 GB

But that’s not all, we’ll also need an index on the sha1 field, which adds 12 more bytes to the total record size.

(12 * 12 * 10^9) / (1024^3) = 179 GB

All in all, 800 GB of RAM are needed. And let’s not forget about replication, which doubles the amount of RAM required.

25

If we buy machines with 256 GB of RAM on board, we’d need eight of them.

We can assess the size of PairDB. The average file size is 1 MB and disk capacity is 1 TB, which allows storage of about 1 million files on a single disk; so, we’d need some 28,000 disks. One PairDB record describes two disks. Therefore, PairDB contains 14,000 records — negligible compared to FileDB.

File Upload Link

Now that we’ve got the database structure out of the way, let’s turn to the API for interacting with the system. At first glance, we need the upload and delete methods. But don’t forget about deduplication: Chances are good that the file we’re trying to upload is already in storage, and uploading it a second time wouldn’t make sense. So, the following methods are necessary:

  • inc(sha1, magic) increments the counter. If a file doesn’t exist, it returns an error. Recall that we also need a magic number that helps to prevent incorrect file deletion.
  • upload(sha1, magic) should be called if inc has returned an error, which means this file doesn’t exist and must be uploaded.
  • dec(sha1, magic) should be called if a user deletes an email. The counter is decremented first.
  • GET /sha1 downloads a file via HTTP.

Let’s take a closer look at what happens during uploading. For the daemon that implements this interface, we chose the IProto protocol. Daemons must scale well to any number of machines, so they don’t store states. Suppose we receive a request via a socket:

26

The command name tells us the header’s length, so we read the header first. Now, we need to know the length of the origin-len file. It’s necessary to choose a couple of servers to upload it. We just retrieve all of the records (a few thousand) from PairDB and use the standard algorithm to find the needed pair: Take a segment with the length equal to the sum of free spaces on all pairs, randomly pick a point on this segment, and choose whatever pair this point belongs to.

27

However, choosing a pair this way is risky. Suppose all of our disks are 90% full — and then we add a new empty disk. It’s highly likely that all new files will be uploaded to this disk. To avoid this problem, we should sum not the free space of a disk pair, but the nth root of this free space.

So, we’ve chosen a pair, but our daemon is a streaming one, and if we start uploading a file to storage, there’s no turning back. That being said, before uploading a real file, we’ll upload a small test file first. If the test upload is successful, we’ll read filecontent from the socket and upload it to storage; otherwise, another pair is chosen. SHA-1 hash can be read on the fly, so it is also checked during uploading.

Let’s now examine a file upload from a loader to a chosen disk pair. On machines that contain the disks, we set up nginx and use the WebDAV protocol. An email arrives. FileDB doesn’t have this file yet, so it needs to be uploaded to a disk pair via a loader.

28

But nothing prevents another user from receiving the same email — suppose two recipients are specified. Remember that FileDB doesn’t have this file yet, so one more loader will be uploading this very file and might pick the same disk pair for uploading.

29

Nginx would likely resolve this situation correctly, but we need to control the whole process, so we’ll save the file with a complex name.

30

The part of the name in red is where each loader puts a random number. Thus, the two PUT methods won’t overlap and upload two different files. Once nginx responds with 201 (OK), the first loader performs an atomic MOVE operation, which specifies the final name of the file.

31

When the second loader is done uploading the file and also performs MOVE, the file will get overwritten, but it’s no big deal because the file is one and the same. Once the file is on the disks, a new record needs to be added to FileDB. Our version of Tarantool is divided into two spaces. We’ve only been using space0 so far.

32

However, instead of simply adding a new record to FileDB, we’re using a stored procedure that either increments the file counter or adds a new record to FileDB. Why? In the time that has passed since the loader made sure the file doesn’t exist in FileDB, uploaded it and proceeded to add a new record to FileDB, someone else could have uploaded this file and added the corresponding record. We’ve considered this very case: Two recipients are specified for one email, so two loaders start uploading the file; once the second loader finishes the upload, it also proceeds to add a new record to FileDB.

33

In this case, the second loader just increments the file counter.

Let’s now look at the dec method. Our system has two high-priority tasks: to reliably write a file to disk and to quickly give it back to a client from this disk. Physically deleting a file generates a certain workload and slows down these two tasks. That’s why we perform deletions offline. The dec method itself decrements the counter. If the latter becomes 0, just like the magic number, then it means nobody needs the file anymore, so we move the corresponding record from space0 to space1 in Tarantool.

decrement (sha1, magic){ counter-- current_magic –= magic if (counter == 0 && current_magic == 0){ move(sha1, space1) } } 

Valkyrie Link

Each storage has a Valkyrie daemon that monitors data integrity and consistency — and it works with space1. There’s one daemon instance per disk. The daemon iterates over all of the files on a disk and checks whether space1 contains a record corresponding to a particular file, which would mean that this file should be deleted.

34

But after the dec method is called and a file is moved to space1, Valkyrie might take a while to find this file. This means that, in the time between these two events, the file may be reuploaded and, thus, moved to space0 again.

35

That’s why Valkyrie also checks whether a file exists in space0. If this is the case and the pair_id of the corresponding record points to a pair of disks that this Valkyrie instance is running on, then the record is deleted from space1.

36

If no record is found in space0, then the file is a potential candidate for deletion. However, between a request to space0 and the physical deletion of a file, there’s still a window of time in which a new record corresponding to this file might appear in space0. To deal with this, we put the file in quarantine.

37

Instead of deleting the file, we append deleted and a timestamp to its name. This means we’ll physically delete the file at timestamp plus some time specified in the config file. If a crash occurs and the file is deleted by mistake, the user will come to reclaim it. We’ll be able to restore it and resolve the issue without losing any data.

Now, recall that there are two disks, with a Valkyrie instance running on each. The two instances are not synced. Hence the question: When should the record be deleted from space1?

38

We’ll do two things. First, for the file in question, let’s make one of the Valkyrie instances the master. This is easily done by using the first bit of the file name: If it equals zero, then disk0 is the master; otherwise, disk1 is the master.

39

Let’s introduce a processing delay. Recall that when a record sits in space0, it contains the magic field for checking consistency. When the record is moved to space1, this field is not used, so we’ll put there a timestamp corresponding to the time that this record appeared in space1. This way, the master Valkyrie instance will start processing records in space1 at once, whereas the slave will add some delay to the timestamp and will process and delete records from space1 a little later.

40

This approach has one more advantage. If a file was mistakenly put in quarantine on the master, it’ll be evident from the log once we query the master. Meanwhile, the client that requested the file will fall back to the slave — and the user will receive the needed file.

So, we have considered the situation in which the Valkyrie daemon locates a file named sha1, and this file (being a potential candidate for deletion) has a corresponding record in space1. What other variants are possible?

Suppose a file is on a disk, but FileDB doesn’t have any corresponding record. If, in the case considered above, the master Valkyrie instance, for some reason, hasn’t been working for some time, it would mean the slave’s had enough time to put the file in quarantine and to delete the corresponding record from space1. In this case, we would also put the file in quarantine by using sha1.deleted.timestamp.

Another situation: A record exists but points to a different disk pair. This could happen during uploading if two recipients are specified for one email. Recall this scheme:

41

What happens if the second loader uploads the file to a different pair than the first one? It will increment the counter in space0, but the disk pair where the file was uploaded would contain some junk files. What we need to do is make sure these files can be read and that they match sha1. If everything’s fine, such files can be deleted at once.

Also, Valkyrie might encounter a file that has been put in quarantine. If the quarantine is over, this file will get deleted.

Now, imagine that Valkyrie encounters a good file. It needs to be read from disk, checked for integrity and compared to sha1. Then, Valkyrie needs to query the second disk to see if it has this same file. A simple HEAD method is enough here: The daemon running on the second disk will itself check the file’s integrity. If the file is corrupt on the first disk, it’s immediately copied over from the second disk. If the second disk doesn’t have the file, its copy is uploaded from the first disk.

We’re left with the last situation, which has to do with disk problems. If any problem with a disk is identified in the course of system monitoring, the problematic disk is put in service (read-only) mode, while on the second disk, the UNMOVE operation is run. This effectively distributes all of the files on the second disk among other disk pairs.

Result Link

Let’s get back to where we started. Our email storage used to look like this:

42

We’ve managed to reduce the total size by 18 PB after implementing the new system:

43

Emails now occupy 32 PB (25% for indexes, 75% for files). Thanks to the 18-PB cut, we didn’t have to buy new hardware for quite some time.

About SHA-1 Link

As of now, there are no known examples of SHA-1 collisions. There exist collision examples for its internal compression function (SHA-1 freestart collision), though. Given 12 billion files, the probability of a hash collision is less than 10^-38.

But let’s assume it’s possible. In this case, when a file is requested by its hash value, we check whether it has the correct size and CRC32 checksum that were saved in the indexes of the corresponding email during upload. That is to say, the requested file will be provided if and only if it was uploaded along with this email.

(vf, yk, il, al)

Footnotes Link

  1. 1 https://www.smashingmagazine.com/wp-content/uploads/2017/01/01-preview-opt.png
  2. 2 https://www.smashingmagazine.com/2013/12/imageoptim-cli-batch-compression-tool/
  3. 3 https://www.facebook.com/psialt
  4. 4 https://www.smashingmagazine.com/2014/08/improve-your-email-workflow-with-modular-design/
  5. 5 https://www.smashingmagazine.com/2017/01/making-responsive-html-email-coding-easy-with-mjml/
  6. 6 https://www.smashingmagazine.com/2013/06/email-templates-web-designers-developers-pdf-odt-txt/
  7. 7 https://shop.smashingmagazine.com/products/designing-for-email
  8. 8 https://www.smashingmagazine.com/wp-content/uploads/2017/01/02-preview-opt.png
  9. 9 https://www.smashingmagazine.com/wp-content/uploads/2017/01/03-preview-opt.png
  10. 10 https://www.smashingmagazine.com/wp-content/uploads/2017/01/04-preview-opt.png
  11. 11 https://www.smashingmagazine.com/wp-content/uploads/2017/01/05-preview-opt.png
  12. 12 https://www.smashingmagazine.com/wp-content/uploads/2017/01/06-preview-opt.png
  13. 13 https://www.smashingmagazine.com/wp-content/uploads/2017/01/07-preview-opt.png
  14. 14 https://www.smashingmagazine.com/wp-content/uploads/2017/01/08-preview-opt.png
  15. 15 https://www.smashingmagazine.com/wp-content/uploads/2017/01/09-preview-opt.png
  16. 16 https://www.smashingmagazine.com/wp-content/uploads/2017/01/10-preview-opt-1.png
  17. 17 https://www.smashingmagazine.com/wp-content/uploads/2017/01/11-preview-opt-1.png
  18. 18 https://www.smashingmagazine.com/wp-content/uploads/2017/01/12-preview-opt-2.png
  19. 19 https://www.smashingmagazine.com/wp-content/uploads/2017/01/13-preview-opt-2.png
  20. 20 https://www.smashingmagazine.com/wp-content/uploads/2017/01/14-preview-opt-2.png
  21. 21 https://www.smashingmagazine.com/wp-content/uploads/2017/01/15-preview-opt-2.png
  22. 22 https://www.smashingmagazine.com/wp-content/uploads/2017/01/16-preview-opt-2.png
  23. 23 https://www.smashingmagazine.com/wp-content/uploads/2017/01/17-preview-opt-2.png
  24. 24 https://www.smashingmagazine.com/wp-content/uploads/2017/01/18-preview-opt-1.png
  25. 25 https://www.smashingmagazine.com/wp-content/uploads/2017/01/19-preview-opt-1.png
  26. 26 https://www.smashingmagazine.com/wp-content/uploads/2017/01/20-preview-opt-1.png
  27. 27 https://www.smashingmagazine.com/wp-content/uploads/2017/01/21-preview-opt-1.png
  28. 28 https://www.smashingmagazine.com/wp-content/uploads/2017/01/22-preview-opt-1.png
  29. 29 https://www.smashingmagazine.com/wp-content/uploads/2017/01/23-preview-opt.png
  30. 30 https://www.smashingmagazine.com/wp-content/uploads/2017/01/24-preview-opt-1.png
  31. 31 https://www.smashingmagazine.com/wp-content/uploads/2017/01/25-preview-opt.png
  32. 32 https://www.smashingmagazine.com/wp-content/uploads/2017/01/26-preview-opt.png
  33. 33 https://www.smashingmagazine.com/wp-content/uploads/2017/01/27-preview-opt.png
  34. 34 https://www.smashingmagazine.com/wp-content/uploads/2017/01/28-preview-opt.png
  35. 35 https://www.smashingmagazine.com/wp-content/uploads/2017/01/29-preview-opt.png
  36. 36 https://www.smashingmagazine.com/wp-content/uploads/2017/01/30-preview-opt.png
  37. 37 https://www.smashingmagazine.com/wp-content/uploads/2017/01/31-preview-opt.png
  38. 38 https://www.smashingmagazine.com/wp-content/uploads/2017/01/32-preview-opt.png
  39. 39 https://www.smashingmagazine.com/wp-content/uploads/2017/01/33-preview-opt.png
  40. 40 https://www.smashingmagazine.com/wp-content/uploads/2017/01/34-preview-opt.png
  41. 41 https://www.smashingmagazine.com/wp-content/uploads/2017/01/35-preview-opt.png
  42. 42 https://www.smashingmagazine.com/wp-content/uploads/2017/01/36-preview-opt.png
  43. 43 https://www.smashingmagazine.com/wp-content/uploads/2017/01/37-preview-opt.png

↑ Back to topTweet itShare on Facebook

The Underestimated Power Of Color In Mobile App Design

Sponsored ArticleThe Underestimated Power Of Color In Mobile App Design

Color is arguably the second most important aspect of your app, after functionality. The human to computer interaction is heavily based on interacting with graphical UI elements, and color plays a critical role in this interaction. It helps users see and interpret your app’s content, interact with the correct elements, and understand actions. Every app has a color scheme, and it uses the primary colors for its main areas.

When designing a new app, it’s often difficult to decide on a color scheme that works well, as there are an infinite number of possible color combinations out there. In this article, we’ll go over the most important points related to color in apps. We’ll cover traditional color scheme patterns (monochrome, analogous, complementary), custom color combinations that aren’t based strictly on any one pattern, and we’ll also learn how to choose colors and contrasts for your app that support usability. If you’d like to hone your own color usage skills, you can download and test Adobe XD1for free, and get started right away.

Further Reading on SmashingMag: Link

How To Select An Effective Color Scheme Link

When creating a color scheme there are many factors to consider, including brand colors and color associations for your region.

How Many Colors?Link

Keeping your color combinations simple will help you improve the user experience6. A simple color scheme isn’t overwhelming to the eye and makes your content easier to understand. Conversely, having too many colors in too many places is an easy way to mess up a design.

A University of Toronto study7 on how people used Adobe Color CC8 revealed that most people preferred simple color combinations that relied on only two to three colors.

How To Create a SchemeLink

So, how do you choose those two or three colors? The color wheel can help.

9
The twelve-spoke color wheel is an important tool in creating color schemes. (Large preview10)

There are a number of predefined color scheme standards that make creating new schemes easier, especially for beginners.

MonochromaticLink

Monochromatic schemes are the simplest color schemes to create, as each color is taken from the same base color. Monochromatic colors go well together, producing a soothing effect.

11
Monochromatic colors are a single color, and its tints, shades, and tones. (Large preview12)

The monochromatic scheme is very easy on the eyes, especially with blue or green hues.

13
Image credit: Adobe Color CC36282314. (Large preview15)
16
Image credit: Louis Saville17

As you can see, the scheme looks clean and elegant.

AnalogousLink

Analogous color schemes are created from related colors that don’t stand out from one another; one color is used as a dominant color while others are used to enrich the scheme.

18
Analogous schemes are created by using three colors that are next to each other on the 12-spoke color wheel. (Large preview19)

While this scheme is relatively easy to pull off, the trick is in deciding which vibrancy of color to use, as it will be exaggerated. For example, Clear20, a gesture-driven21 to-do app, uses the analogous colors to visually prioritize current set of tasks.

22
Image credit: Adobe Color CC36282314. (Large preview24)
25
The default color scheme in Clear is reminiscent of a heat map, where the hotter items are displayed in bright red.

While Calm26, a meditation app, uses the analogous colors blue and green to help users feel relaxed and peaceful.

27
Image credit: Adobe Color CC36282314. (Large preview29)
30
Calm 31uses analogous colors to establish an overall mood.

ComplementaryLink

Colors aren’t always at odds with each other; complementary colors are opposite colors.

32
Complementary colors are opposite of each other on the color wheel. (Large preview33)

They contrast strongly, and they can be used to attract the viewer’s attention. When using a complementary scheme, it is important to choose a dominant color and use its complementary color for accents. For example, when the human eye sees an object full of different hues of greens, a bit of red is going to stand out very well.

34
Using complementary colors is the easiest way to make something to stand out.

However, you have to use complementary colors carefully to keep your content from being visually jarring.

Custom Color SchemeLink

Creating your own color schemes is not as complicated as many people think. Adding a bright accent color into an otherwise neutral palette is one of the easiest color schemes to create, and it’s also one of the most visually striking.

35
Adding one color to a grayscale design draws the eye simply and effectively. Image credit: Adobe Color CC36282314. (Large preview37)

White canvases and cool gray copy, splashed with accents of blue, make up the Dropbox color scheme.

38
Image credit: Dropbox39 (Large preview40)

Adobe Color CC Makes Your Life Easier Link

Adobe Color CC41, previously known as Kuler, makes color selection extremely easy. Every color on the palette can be individually modified or chosen as the base color with a few simple clicks.

42
Under each color, the export codes are provided (including hexadecimal). (Large preview43)
44

Palettes can be saved and added directly to a library. In addition, there are a number of great color schemes created by the community available on the site.

45
Large preview46

Check it out, so you don’t need to start from scratch.

The Impact Of Color Contrast Link

Typically, a colored object or area on a UI is not displayed in isolation, but is adjacent to or superimposed on another colored object or area. This creates contrast effects. Contrast is how one color stands apart from another. Properly used, it reduces eyestrain and focuses user attention by clearly dividing elements on a screen.

47
High contrast is when colors easily stand apart from each other. Low contrast is when they don’t. (Large preview48)

Contrast and Text ReadabilityLink

Color contrast is one area where color theory is crucial to the usability of a design. Designers often like to use low contrast techniques because low contrast makes things look beautiful and harmonious. However, beautiful isn’t always the best for readability. When you’re using colors in text, be aware that placing two colors with low-value contrast next to each other can make your copy very difficult to read. This is especially true on mobile screens, where users are often on devices outdoors or in bright places that cause screen glare.

49
These lines of text are difficult to read against their background colors.

Make sure you have a fair amount of contrast between elements. It’s really not that hard — all you need to do is to check the contrast ratio. Contrast ratios represent how different a color is from another color (commonly written as 1:1 or 21:1). The higher the difference between the two numbers in the ratio, the greater the difference in relative luminance between the colors. The W3C50 recommends51 the following contrast ratios for body text and image text:

  • Small text should have a contrast ratio of at least 4.5:1 against its background.
  • Large text (at 14 pt bold/18 pt regular and up) should have a contrast ratio of at least 3:1 against its background.

This guideline also helps users with low vision, color blindness, or worsening vision see and read the text on your screen.

52
These lines of text follow the color contrast ratio recommendations and are legible against their background colors.

Icons or other critical elements should also use the above-recommended contrast ratios.

53
Left: Icons don’t follow the color contrast ratio recommendations. Right: Icons follow the color contrast ratio recommendations and are legible against their backgrounds. Image credit: Material Design54. (Large preview55)

There are several free tools available to give you meaningful feedback about the levels of contrast in your chosen palette. One of them is WebAIM’s Color Contrast Checker56 which let you test colors you have already chosen.

Contrast and User’s Attention Link

Along with establishing readable text, contrast can also draw the user’s attention towards specific elements on a screen. Generally, high-contrast is the best choice for important content or key elements. So, if you want users to see or click something, make it stand out! For example, users are much more likely to click a call-to-action button that strongly contrasts with its background.

57
Contrast makes the area look different than the rest of the screen.

Designing For Color Blindness Link

Have you thought about your app appears to users who have visual impairments?

When people talk about color blindness58, they usually refer to the inability of perceiving certain colors. Approximately 8% of men and 0.5% of women are affected by some form of color blindness. Red and green colors are a common problematic combination.

59
Colors, as seen with normal vision, and same colors, as seen with red-green color deficiency (Deuteranopia and Protanopia) (Large preview60)

Since colorblindness takes different forms (including red-green, blue-yellow, and monochromatic), it’s important to use multiple visual cues to communicate important states in your app. Never rely on a color solely to indicates system status. Instead, use elements such as strokes, indicators, patterns, texture, or text to describe actions and content.

Avocode lets you visually compare revisions of designs.

Also, Photoshop61 has really useful tools to help, and can simulate color blindness. This feature allows the designer to see what the app’s screen will look like to people with different types of color blindness.

62
Airbnb app login screen Image credit: Pinterest63. (Large preview64)

Conclusion Link

We’ve barely covered the fundamentals of how color theory can enhance your app UI design. Honing your color usage skills is an ongoing endeavor. If you want to learn how to create beautiful, functional color schemes, all it takes is practice, determination, and lots of user testing.

This article is part of the UX design series sponsored by Adobe. The newly introduced Experience Design app65 is made for a fast and fluid UX design process, creating interactive navigation prototypes, as well as testing and sharing them — all in one place.

You can check out more inspiring projects created with Adobe XD on Behance66, and also visit the Adobe XD blog to stay updated and informed. Adobe XD is being updated with new features frequently, and since it’s in public Beta, you can download and test it for free67.

(ms, aa, il)

Footnotes Link

  1. 1 https://adobe.ly/2iHmxQr
  2. 2 https://www.smashingmagazine.com/2017/01/how-functional-animation-helps-improve-user-experience/
  3. 3 https://www.smashingmagazine.com/2016/10/in-app-gestures-and-mobile-app-user-experience/
  4. 4 https://www.smashingmagazine.com/2016/12/best-practices-for-animated-progress-indicators/
  5. 5 https://www.smashingmagazine.com/2016/08/experience-design-essentials-animated-microinteractions-in-mobile-apps/
  6. 6 https://www.smashingmagazine.com/2010/10/what-is-user-experience-design-overview-tools-and-resources/
  7. 7 http://www.dgp.toronto.edu/~donovan/color/colorcomp.pdf
  8. 8 https://color.adobe.com/create/color-wheel/
  9. 9 https://www.smashingmagazine.com/wp-content/uploads/2017/01/1-large-opt.png
  10. 10 https://www.smashingmagazine.com/wp-content/uploads/2017/01/1-large-opt.png
  11. 11 https://www.smashingmagazine.com/wp-content/uploads/2017/01/2-large-opt.png
  12. 12 https://www.smashingmagazine.com/wp-content/uploads/2017/01/2-large-opt.png
  13. 13 https://www.smashingmagazine.com/wp-content/uploads/2017/01/3-large-opt.png
  14. 14 https://color.adobe.com/
  15. 15 https://www.smashingmagazine.com/wp-content/uploads/2017/01/3-large-opt.png
  16. 16 https://www.smashingmagazine.com/wp-content/uploads/2017/01/4-preview-opt.jpg
  17. 17 https://twitter.com/louis_saville
  18. 18 https://www.smashingmagazine.com/wp-content/uploads/2017/01/5-large-opt.png
  19. 19 https://www.smashingmagazine.com/wp-content/uploads/2017/01/5-large-opt.png
  20. 20 https://itunes.apple.com/en/app/clear-tasks-reminders-to-do/id493136154?mt=8
  21. 21 https://blogs.adobe.com/creativecloud/in-app-gestures-and-mobile-app-user-experience/
  22. 22 https://www.smashingmagazine.com/wp-content/uploads/2017/01/6-large-opt.png
  23. 23 https://color.adobe.com/
  24. 24 https://www.smashingmagazine.com/wp-content/uploads/2017/01/6-large-opt.png
  25. 25 https://www.smashingmagazine.com/wp-content/uploads/2017/01/7-preview-opt.jpg
  26. 26 http://www.calm.com/
  27. 27 https://www.smashingmagazine.com/wp-content/uploads/2017/01/8-large-opt.png
  28. 28 https://color.adobe.com/
  29. 29 https://www.smashingmagazine.com/wp-content/uploads/2017/01/8-large-opt.png
  30. 30 https://www.smashingmagazine.com/wp-content/uploads/2017/01/9-preview-opt.png
  31. 31 https://blogs.adobe.com/creativecloud/how-the-calm-app-uses-empathy-and-simplicity-to-connect-with-users/
  32. 32 https://www.smashingmagazine.com/wp-content/uploads/2017/01/10-large-opt.png
  33. 33 https://www.smashingmagazine.com/wp-content/uploads/2017/01/10-large-opt.png
  34. 34 https://www.smashingmagazine.com/wp-content/uploads/2017/01/11-preview-opt.png
  35. 35 https://www.smashingmagazine.com/wp-content/uploads/2017/01/12-large-opt-1.png
  36. 36 https://color.adobe.com/
  37. 37 https://www.smashingmagazine.com/wp-content/uploads/2017/01/12-large-opt-1.png
  38. 38 https://www.smashingmagazine.com/wp-content/uploads/2017/01/13-large-opt-1.png
  39. 39 https://blogs.dropbox.com/
  40. 40 https://www.smashingmagazine.com/wp-content/uploads/2017/01/13-large-opt-1.png
  41. 41 https://color.adobe.com/
  42. 42 https://www.smashingmagazine.com/wp-content/uploads/2017/01/14-large-opt-1.png
  43. 43 https://www.smashingmagazine.com/wp-content/uploads/2017/01/14-large-opt-1.png
  44. 44 https://www.smashingmagazine.com/wp-content/uploads/2017/01/15-preview-opt-1.png
  45. 45 https://www.smashingmagazine.com/wp-content/uploads/2017/01/16-large-opt.png
  46. 46 https://www.smashingmagazine.com/wp-content/uploads/2017/01/16-large-opt.png
  47. 47 https://www.smashingmagazine.com/wp-content/uploads/2017/01/17-large-opt-1.png
  48. 48 https://www.smashingmagazine.com/wp-content/uploads/2017/01/17-large-opt-1.png
  49. 49 https://www.smashingmagazine.com/wp-content/uploads/2017/01/18-preview-opt.jpg
  50. 50 http://www.w3.org/TR/UNDERSTANDING-WCAG20/visual-audio-contrast-contrast.html
  51. 51 http://www.w3.org/TR/UNDERSTANDING-WCAG20/visual-audio-contrast-contrast.html
  52. 52 https://www.smashingmagazine.com/wp-content/uploads/2017/01/19-preview-opt.jpg
  53. 53 https://www.smashingmagazine.com/wp-content/uploads/2017/01/20-large-opt.png
  54. 54 http://material.google.com/
  55. 55 https://www.smashingmagazine.com/wp-content/uploads/2017/01/20-large-opt.png
  56. 56 http://webaim.org/resources/contrastchecker/
  57. 57 https://www.smashingmagazine.com/wp-content/uploads/2017/01/21-preview-opt.png
  58. 58 https://en.wikipedia.org/wiki/Color_blindness#Dichromacy
  59. 59 https://www.smashingmagazine.com/wp-content/uploads/2017/01/22-large-opt.png
  60. 60 https://www.smashingmagazine.com/wp-content/uploads/2017/01/22-large-opt.png
  61. 61 http://www.adobe.com/accessibility/products/photoshop.html
  62. 62 https://www.smashingmagazine.com/wp-content/uploads/2017/01/24-preview-opt.png
  63. 63 https://ru.pinterest.com/pin/396457573423276783/
  64. 64 https://www.smashingmagazine.com/wp-content/uploads/2017/01/24-preview-opt.png
  65. 65 https://adobe.ly/2iHmxQr
  66. 66 http://adobe.ly/1U9LS0E
  67. 67 https://adobe.ly/2iHmxQr

↑ Back to topTweet itShare on Facebook

Making Responsive HTML Email Coding Easy With MJML

Making Responsive HTML Email Coding Easy With MJML

Email is one of the best ways to engage with your users, especially during the holiday season. However, if you want to stand out, no matter how beautiful your emails are, you need to make sure they render correctly in your reader’s inbox, regardless of what email client they’re using. Creating responsive email is not an easy task, and there are various reasons for that.

First, there is no standard in the way email clients render HTML. This is true for email clients from different companies, such as Outlook and Apple Mail, but not only. Even different versions of Outlook, such as Outlook 2003, Outlook 2013 and Outlook.com, render HTML differently.

Then, while email clients render HTML, many of them have very limited support of it. Some email clients will just strip the head of your HTML file, including media queries, which is why inline styles are heavily recommended. On a good note, this is moving in the right direction with the Gmail update1.

Now, there are a few techniques out there to help email developers. You might be familiar with some of them, such as the hybrid approach2, the mobile-first approach3 or even the Fab Four technique4 by HTeuMeuLeu5. But because of the reasons stated earlier, and especially the lack of a standard, none of these techniques will enable you to tame all email clients at once.

Abstracting Away The Complexity Of Responsive Email With MJML Link

MJML is an open-source framework that abstracts away the complexity of responsive email. The idea behind it is pretty simple. Just as jQuery normalizes the DOM and abstracts low-level interactions and animations, MJML abstracts the low-level hacks for responsive emails with an easy syntax. MJML is responsive by design. This means you can forget about nested tables and conditional comments and, more generally, about making your email responsive. MJML does it for you.

Leveraging a semantic syntax and high-level components such as the carousel6 (yes, you can display an interactive image gallery within an email!), MJML is really easy to learn for anyone. Responsive emails are no longer only accessible to a handful of experts anymore.

7
Example of an MJML component: carousel

Being easy to use doesn’t mean that MJML is not powerful. It just enables experts to streamline their development workflow, while still giving them the flexibility they need with lower-level components such as tables8.

For instance, our example email9 was coded in 788 lines of HTML10 and reproduced in fewer than 240 lines of MJML11.

The Approach Link

MJML is built in React12, a JavaScript library developed and maintained by Facebook, and it leverages the power of React’s components. The component names are semantic, starting with mj-, so that they are straightforward as well as easy to recognize and understand: mj-text, mj-image, mj-button, etc.

MJML will transpile to responsive HTML, following a mix of the mobile-first and hybrid coding approaches. Going mobile-first enables you to make sure that the most readable version is displayed by default in email clients that do not change the layout according to the device used.

For example, in Outlook.com, the mobile version will be displayed on both desktop and mobile (which is far more readable than a desktop version being displayed on mobile). The hybrid approach then enables the layout to change according to the device’s size wherever possible, using a mix of fallbacks, conditional comments, nested tables and media queries to target as many clients as possible. The layout degrades nicely, with multi-column layouts on desktop turning into single-column layouts on mobile.

2-column layout - desktop view.13
Two-column layout, desktop view
2-column layout - mobile view.14
Two-column layout, mobile view

Coding In MJML Link

Before we start the tutorial, let’s get ready to code in MJML. We have different ways to use MJML, such as running it locally15 or using the online editor2316. By choosing the online editor, you’ll be able to start immediately, but running it locally enables you to use MJML with your favorite code editor (with plugins for Atom17, Sublime Text18 and Vim19), task runners such as gulp-mjml20 and grunt-mjml21 and a lot more22.

For this tutorial, the online editor2316 is recommended because it doesn’t require any setup.

If you still want to use it locally, open your terminal and run npm install mjml -g (requires to have Node.js and npm24 installed).

Once MJML is installed, create a file named example.mjml (or any name you like) with some MJML and run mjml -r example.mjml in your terminal (make sure to be in the same folder as the file you’re rendering). It will render your MJML file in a file named example.html, with the responsive HTML inside. You can find all available options for the command line in the documentation25.

Creating Your First Newsletter With MJML Link

Now that you’re all set up, we can start creating a responsive newsletter together. To find inspiration, one of the best places around is ReallyGoodEmails26. I found a great example of a newsletter27 by Thrive Market28. Let’s recreate it with MJML!

(Brand names, logos and trademarks used herein remain the property of their respective owners, and their use does not imply any endorsement by or affiliation with Thrive Market.)

Thrive Market newsletter29
Thrive Market newsletter

First, here is what the basic layout30 of an MJML document looks like:

 <mjml> <mj-head> <!-- Head components go here: https://mjml.io/documentation/#standard-head-components --> </mj-head> <!-- All of the content of our email will go in mj-body --> <mj-body> <!-- mj-container defines the default styling of our email, including the default width, set to 600px but overwritable --> <mj-container> <!-- Body components go here (https://mjml.io/documentation/#standard-body-components) --> </mj-container> </mj-body> </mjml> 

Streamlining The Style Link

While inlining is the norm in HTML to ensure responsiveness, MJML also allows you to create custom MJML classes and MJML styles, which will then automatically be inlined from the head of your MJML file31. In MJML, styles come as component attributes.

<mj-text font-size="20px" color="#F45E43" font-family="helvetica"> Hello World </mj-text>

To start, we’ll set a default sans-serif font family for text components, because sans-serif is used for most text here. Then, we’ll create classes for elements used repeatedly, so that we don’t have to manually set styles over and over again. We could have created more custom classes and styles, but the most useful styles will be for:

  • buttons,
  • image descriptions,
  • text below the six icons in the footer.

Here, we’ll be leveraging head components32 in three ways:

  • Set a default padding of 0 for every component, using <mj-all />. This default padding can be overridden by manually specifying a padding directly on the components we are using.
  • Override the default font family of <mj-text>, using <mj-text /> in the head. Each time we use <mj-text>, the default font family will be sans-serif. We can still manually override this new default font by specifying a new one directly on the component.
  • Create classes using <mj-class /> and, more specifically, using the following mj-classes:
    • pill

      This is to design a nice button. Attributes worth noting are the background-color set to transparent and the inner-padding, used to size the button as we want.
    • desc

      This is to style the descriptions of the images in the two-column layout.
    • ico

      This is to style the text below the six icons just before the footer.
<mj-head> <mj-title>Discover the latest trends</mj-title> <mj-attributes> <mj-all padding="0" /> <mj-text font-family="sans-serif" color="#8e8b85" /> <mj-class name="pill" font-weight="700" color="#d5ad4b" border-radius="50" border="2px solid #d5ad4b" font-size="16px" line-height="16px" padding="8 20 20 20" inner-padding="10 75 10 75" background-color="transparent" /> <mj-class name="desc" font-family="Georgia" font-size="20px" color="#45495d" padding="25 5 10 10" /> <mj-class name="ico" font-family="Helvetica" font-size="14px" align="center" padding="0 0"/> </mj-attributes> </mj-head> 

(As you may have noticed, we have omitted the units on some attributes, such as padding. If you do so, MJML will output the attributes with px by default.)

Adding Content Link

Now that the styles are defined in the head (you can see here33 what your code should look like now), let’s start adding content to our email! MJML layouts are based on <mj-section>34 to create rows and <mj-column>3835 to create columns inside rows, which is very practical for email design. Note that, except for high-level components such as <mj-hero>36 and <mj-navbar>37, content should always be wrapped in a <mj-column>3835, which itself should go in a <mj-section>39, even when there is only one column in a section.

Let’s see this with two examples, the preheader and the header of the email.

Preheader Link

There’s nothing very fancy here. We’re just creating a text preheader using the <mj-text>40 component, wrapped in a column, and giving it some MJML styles.

Hack: <mj-text> enables you to use HTML directly inside MJML, granting you full control over the content and allowing you to use the <span> and <a> tags you’re used to, for example.

 <mj-section padding="0" background-color="#eeebe7"> <mj-column> <mj-text padding="0 2" align="center" font-size="10px"> The latest tips, trends, recipes, and more </mj-text> </mj-column> </mj-section> 

Header Link

Header of the email41
Header of the email

Three-Column Layout for Blog, Logo and Referral Link Link

The header is a bit fancier but very easy to achieve with MJML. All we have to do is create a section that we’ll split into three equal columns (because columns are equal, we don’t even have to manually set the width). We’ll use images as in the original email, leveraging the explicit component <mj-image>42, which comes with the common attributes you would expect, including src, padding and border.

By default, columns will stack in the mobile version of our email. Here, because we want those three columns to stay side by side even on mobile, we’ll wrap them in an <mj-group>43 component, which will prevent the columns from stacking.

Hack: As noted in the documentation, due to a bug in iOS, you might have to use a minifier, or else the columns could stack on iPhone even if they’re wrapped in <mj-group>. The MJML command-line interface44 comes with a built-in minifier45 that you can use to run the -m option when rendering MJML.

<mj-section padding="0" background-color="#ffffff"> <mj-group> <mj-column> <mj-image align="right" padding="40 0 0 0" width="100" href="https://thrivemarket.com/blog?uid=5019850&uaexptime=1778637862&uatoken=1462b977c1fa70b09b585f3a8943d79a7079ab314393fe89852fd83fd05b631e&ccode=KG6OCD3H&utm_content=lead_welcome&utm_medium=lifecycle&utm_campaign=day8&utm_source=sailthru" src="http://i1044.photobucket.com/albums/b447/ngarnier/Thrive%20Market/blog_zpscedcgvla.jpg" alt="blog" title="blog" /> </mj-column> <mj-column> <mj-image padding="15 0 0 0" href="https://thrivemarket.com/?uid=5019850&uaexptime=1778637862&uatoken=1462b977c1fa70b09b585f3a8943d79a7079ab314393fe89852fd83fd05b631e&ccode=KG6OCD3H&utm_content=lead_welcome&utm_medium=lifecycle&utm_campaign=day8&utm_source=sailthru" src="http://i1044.photobucket.com/albums/b447/ngarnier/Thrive%20Market/thrive-logo-250_zps4lonavha.jpg" title="logo" alt="logo" /> </mj-column> <mj-column> <mj-image align="left" padding="40 0 0 0" width="100" href="https://thrivemarket.com/customer/account/login/referer/aHR0cHM6Ly90aHJpdmVtYXJrZXQuY29tL2ludml0ZT9jY29kZT1LRzZPQ0QzSCZ1YWV4cHRpbWU9MTc3ODYzNzg2MiZ1YXRva2VuPTE0NjJiOTc3YzFmYTcwYjA5YjU4NWYzYTg5NDNkNzlhNzA3OWFiMzE0MzkzZmU4OTg1MmZkODNmZDA1YjYzMWUmdWlkPTUwMTk4NTAmdXRtX2NhbXBhaWduPWRheTgmdXRtX2NvbnRlbnQ9bGVhZF93ZWxjb21lJnV0bV9tZWRpdW09bGlmZWN5Y2xlJnV0bV9zb3VyY2U9c2FpbHRocnU,/" src="http://i1044.photobucket.com/albums/b447/ngarnier/Thrive%20Market/refer_zpsnoo1uzvu.jpg" title="refer and win" alt="refer and win" /> </mj-column> </mj-group> </mj-section> 

One-Column Layout for the GIF and CTA Link

We’ll create another section in which we’ll simply add an image, some text and a button. The only new component here is <mj-button>46, which should be clear enough and which comes with the standard attributes. Please note that you must specify an href, or else the text of the button might not display in some email clients.

<mj-section padding="20"> <mj-column> <mj-image padding="5 0 23 0" width="200px" src="http://i1044.photobucket.com/albums/b447/ngarnier/Thrive%20Market/566f6a67e871e_zpskalhjefi.gif" /> <mj-text align="center" font-size="16px"> Your daily destination for healthy living </mj-text> <mj-button padding="20 0 10 0" mj-class="pill" href="https://thrivemarket.com/blog?uid=5019850&uaexptime=1778637862&uatoken=1462b977c1fa70b09b585f3a8943d79a7079ab314393fe89852fd83fd05b631e&utm_content=lead_welcome&utm_medium=lifecycle&utm_campaign=day8&utm_source=sailthru"> Read more </mj-button> </mj-column> </mj-section> 

Divider Between Body and Header Link

Yes, there’s a component for that, too! It’s a good practice to split different rows into different sections, instead of dumping everything into the same section, because that gives you more control over styling (especially through padding), and it also makes it easier to isolate any problems that occur.

<mj-section padding="0 0 20 0"> <mj-column> <mj-divider border-width="5px" border-color="#EEEBE7" /> </mj-column> </mj-section> 

We’ll use the same divider between the body and footer later.

Body Link

Now that we have a beautiful header47, let’s start with what seems to be the complex part of this email.

Two-Column Layout That Stacks on Mobile Link

Two-column layout48
Two-column layout

Here, we’ll create a section for each two-column row. Each column will consist of an image, a piece of text and a button. The good news is that, thanks to MJML’s hybrid approach, we don’t have to do anything to make the images stack on mobile. It’s responsive by default!

Regarding the styling, we don’t have much to do because we’re leveraging the mj-classes pill and desc, which we created earlier. All we need to do is add some padding to match the style of the original email.

Hack: Due to an issue with Outlook 2000, 2002 and 2003 ignoring the set width, it’s a good practice in MJML to set images to the sizes you want them to display at in those clients.

<mj-section padding="20 10 0 10"> <mj-column> <mj-image width="280px" href="https://thrivemarket.com/blog/foods-for-happiness?uaexptime=1778637862&uatoken=1462b977c1fa70b09b585f3a8943d79a7079ab314393fe89852fd83fd05b631e&uid=5019850&utm_campaign=day8&utm_content=lead_welcome&utm_medium=lifecycle&utm_source=sailthru" src="http://i1044.photobucket.com/albums/b447/ngarnier/Thrive%20Market/5-foods_zps9escvg7g.jpg" /> <mj-text mj-class="desc"> <a href="https://thrivemarket.com/blog/foods-for-happiness?uaexptime=1778637862&uatoken=1462b977c1fa70b09b585f3a8943d79a7079ab314393fe89852fd83fd05b631e&uid=5019850&utm_campaign=day8&utm_content=lead_welcome&utm_medium=lifecycle&utm_source=sailthru"> 5 Foods to Boost Your Happiness </a> </mj-text> <mj-button mj-class="pill" href="https://thrivemarket.com/blog/foods-for-happiness?uaexptime=1778637862&uatoken=1462b977c1fa70b09b585f3a8943d79a7079ab314393fe89852fd83fd05b631e&uid=5019850&utm_campaign=day8&utm_content=lead_welcome&utm_medium=lifecycle&utm_source=sailthru"> Read more </mj-button> </mj-column> <mj-column> <mj-image width="280px" href="https://thrivemarket.com/blog/whiten-teeth-instantly-activated-charcoal?uaexptime=1778637862&uatoken=1462b977c1fa70b09b585f3a8943d79a7079ab314393fe89852fd83fd05b631e&uid=5019850&utm_campaign=day8&utm_content=lead_welcome&utm_medium=lifecycle&utm_source=sailthru" src="http://i1044.photobucket.com/albums/b447/ngarnier/Thrive%20Market/teeth_zpsr1sycjxi.jpg" /> <mj-text mj-class="desc"> <a href="https://thrivemarket.com/blog/whiten-teeth-instantly-activated-charcoal?uaexptime=1778637862&uatoken=1462b977c1fa70b09b585f3a8943d79a7079ab314393fe89852fd83fd05b631e&uid=5019850&utm_campaign=day8&utm_content=lead_welcome&utm_medium=lifecycle&utm_source=sailthru"> Whiten Teeth Instantly with Activated Charcoal </a> </mj-text> <mj-button mj-class="pill" href="https://thrivemarket.com/blog/whiten-teeth-instantly-activated-charcoal?uaexptime=1778637862&uatoken=1462b977c1fa70b09b585f3a8943d79a7079ab314393fe89852fd83fd05b631e&uid=5019850&utm_campaign=day8&utm_content=lead_welcome&utm_medium=lifecycle&utm_source=sailthru"> Read more </mj-button> </mj-column> </mj-section> 

Here, we can see that the default HTML style for links is applied. In addition to <mj-attributes>, you can also inline CSS right into MJML using <mj-style>49. Let’s do just that by updating the head to overwrite the default style of links once and for all. We’ll also create a CSS class to apply to the <a> tags to give them the right color (we’re creating a class because the links in the email shouldn’t all have the same color).

 <mj-head> <mj-title>Discover the latest trends</mj-title> <mj-attributes> <mj-all padding="0" /> <mj-text font-family="sans-serif" color="#8e8b85" /> <mj-class name="pill" font-weight="700" color="#d5ad4b" border-radius="50" border="2px solid #d5ad4b" font-size="16px" line-height="16px" padding="8 20 20 20" inner-padding="10 75 10 75" background-color="transparent" /> <mj-class name="desc" font-family="Georgia" font-size="20px" color="#45495d" padding="25 5 10 10" /> <mj-class name="ico" font-family="Helvetica" font-size="14px" align="center" padding="0 0"/> </mj-attributes> <mj-style> a { text-decoration:none; } .desc { color: #45495d; } </mj-style> </mj-head> 

Follow the same steps with the other two-column sections.

Blue Section With CTA Link

Blue section50
Blue section

To create this section, we’ll use the components that we’re getting familiar with: <mj-section>, <mj-column> and <mj-button>.

First, we’ll add a background-color to our section and some padding so that it looks as expected. Then, we just have to create two columns, one wider than the other, leveraging the width attribute with percentages. As usual, columns will stack on mobile. Because the button is different from the others here, we won’t use the pill class, but rather will manually create a new style.

Hack: Because of poor support for shorthand HEX colors in Internet Explorer, we recommend using six-digit HEX colors. This is a hack that we’ll reintegrate in MJML at some point to make sure that three-digit HEX codes are turned into six-digit codes.

<mj-section background-color="#6d8be1" padding="15 40 10 40"> <mj-column width="60%"> <mj-text font-weight="bold" color="#ffffff" font-size="16px" padding="0 0 10 0"> Get all your healthy groceries at Thrive Market! </mj-text> </mj-column> <mj-column width="40%"> <mj-button background-color="#ffffff" color="#45495d" font-weight="800" font-family="sans-serif" font-size="16px" border-radius="2px" inner-padding="15 60"> Shop Now </mj-button> </mj-column> </mj-section> 

Last Section Of The Body Link

Last section of the body51
Last section of the body

To design the title, we’ll create a three-column layout. The columns will consist of the following, respectively:

  • the dark blue line to the left of the title,
  • the title "Want More Tips, Tricks, and Delicious Recipes?",
  • the dark blue line to the right of the title.

Then, we will wrap the three columns in an <mj-group> so that it doesn’t stack on mobile.

We’ll start creating the lines, leveraging the <mj-divider> component, setting its border-width to 2px and adding some padding so that it looks the way we want. By default, the divider will fill the column it’s contained in, so that it looks consistent across devices. Therefore, we don’t need to explicitly set the width of the divider.

Then, we’re just using <mj-text> to add our title, leveraging the desc mj-class (because we want to inherit some of the styles set in this class) and overriding the font-family and align properties that are different from this class. We could have also manually set the style without using the desc mj-class.

Finally, we just have to use our button with the pill mj-class as we did before. We’re overriding the inner-padding because, according to the original design, this button is not as wide as the others.

<mj-section padding="40px 0 0 0"> <mj-group> <mj-column width="12%"> <mj-divider border-width="2px" padding="10 0 0 10" /> </mj-column> <mj-column width="75%"> <mj-text padding="0 0 20 0" mj-class="desc" font-family="Helvetica" align="center"> <a href="https://thrivemarket.com/blog?utm_content=lead_welcome&utm_medium=lifecycle&utm_campaign=day8&utm_source=sailthru"> Want More Tips, Tricks, and Delicious Recipes? </a> </mj-text> </mj-column> <mj-column width="13%"> <mj-divider border-width="2px" padding="10 10 0 0" /> </mj-column> </mj-group> </mj-section> <mj-section padding="5px"> <mj-column> <mj-image src="https://img.thrivemarket.com/emails/images/img-18.jpg" href="https://thrivemarket.com/blog?utm_content=lead_welcome&utm_medium=lifecycle&utm_campaign=day8&utm_source=sailthru" /> </mj-column> </mj-section> <mj-section padding="15px"> <mj-column> <mj-button mj-class="pill" inner-padding="12 25" href="https://thrivemarket.com/blog?uid=5019850&uaexptime=1778637862&uatoken=1462b977c1fa70b09b585f3a8943d79a7079ab314393fe89852fd83fd05b631e&utm_content=lead_welcome&utm_medium=lifecycle&utm_campaign=day8&utm_source=sailthru"> Read our Blog </mj-button> </mj-column> </mj-section> 

You can see52 what our MJML template should look like so far.

Footer Link

Footer of the email53
Footer of the email

Title Link

We’re wrapping our title in a section and a column, as we’ve seen before, and we’re using the desc style that we created earlier. We need to alter only a few styles by manually setting a different align, font-size and font-style from our mj-class.

<mj-section background-color="#EEEBE7" padding="25"> <mj-column> <mj-text padding-top="20px" mj-class="desc" align="center" font-size="28px" font-style="italic"> Stay Connected </mj-text> </mj-column> </mj-section> 

Six-Icon Section Link

This section is made up of six icons, with accompanying text below. The icons display side by side on desktop and wrap to two lines of three icons on mobile. By now, you probably know that creating such layouts is easy if we leverage the <mj-column> component. To make the icons stack onto two lines, all we have to do is wrap the columns in two groups of three columns in an <mj-group>.

To design the text below the icons, we just have to use the ico mj-class that we created before. We’ll also create a CSS class named ico to apply to the a tags, like we did in the two-column layout section.

<mj-section padding="40 0"> <mj-group> <mj-column> <mj-image padding="10" src="http://i1044.photobucket.com/albums/b447/ngarnier/Thrive%20Market/img-01_zpssvjtmopj.png" /> <mj-text mj-class="ico"><a href="https://thrivemarket.com/paleo?uid=5019850&uaexptime=1778637862&uatoken=1462b977c1fa70b09b585f3a8943d79a7079ab314393fe89852fd83fd05b631e&ccode=KG6OCD3H&utm_content=lead_welcome&utm_medium=lifecycle&utm_campaign=day8&utm_source=sailthru">Paleo</a></mj-text> </mj-column> <mj-column> <mj-image padding="10" src="http://i1044.photobucket.com/albums/b447/ngarnier/Thrive%20Market/img-02_zpshj3vgh1w.png" href="https://thrivemarket.com/gluten-free?uid=5019850&uaexptime=1778637862&uatoken=1462b977c1fa70b09b585f3a8943d79a7079ab314393fe89852fd83fd05b631e&ccode=KG6OCD3H&utm_content=lead_welcome&utm_medium=lifecycle&utm_campaign=day8&utm_source=sailthru"/> <mj-text mj-class="ico"><a href="https://thrivemarket.com/gluten-free?uid=5019850&uaexptime=1778637862&uatoken=1462b977c1fa70b09b585f3a8943d79a7079ab314393fe89852fd83fd05b631e&ccode=KG6OCD3H&utm_content=lead_welcome&utm_medium=lifecycle&utm_campaign=day8&utm_source=sailthru">Gluten Free</a></mj-text> </mj-column> <mj-column> <mj-image padding="10" src="http://i1044.photobucket.com/albums/b447/ngarnier/Thrive%20Market/img-03_zpshvwomzpo.png" href="https://thrivemarket.com/vegan?uid=5019850&uaexptime=1778637862&uatoken=1462b977c1fa70b09b585f3a8943d79a7079ab314393fe89852fd83fd05b631e&ccode=KG6OCD3H&utm_content=lead_welcome&utm_medium=lifecycle&utm_campaign=day8&utm_source=sailthru"/> <mj-text mj-class="ico"><a href="https://thrivemarket.com/vegan?uid=5019850&uaexptime=1778637862&uatoken=1462b977c1fa70b09b585f3a8943d79a7079ab314393fe89852fd83fd05b631e&ccode=KG6OCD3H&utm_content=lead_welcome&utm_medium=lifecycle&utm_campaign=day8&utm_source=sailthru">Vegan</a></mj-text> </mj-column> </mj-group> <mj-group> <mj-column> <mj-image padding="10" src="http://i1044.photobucket.com/albums/b447/ngarnier/Thrive%20Market/img-04_zpsyeczb1sp.png" href="https://thrivemarket.com/ingredients/gmo-free?uid=5019850&uaexptime=1778637862&uatoken=1462b977c1fa70b09b585f3a8943d79a7079ab314393fe89852fd83fd05b631e&ccode=KG6OCD3H&utm_content=lead_welcome&utm_medium=lifecycle&utm_campaign=day8&utm_source=sailthru" /> <mj-text mj-class="ico"><a href="https://thrivemarket.com/ingredients/gmo-free?uid=5019850&uaexptime=1778637862&uatoken=1462b977c1fa70b09b585f3a8943d79a7079ab314393fe89852fd83fd05b631e&ccode=KG6OCD3H&utm_content=lead_welcome&utm_medium=lifecycle&utm_campaign=day8&utm_source=sailthru">Non-GMO</a></mj-text> </mj-column> <mj-column> <mj-image padding="10" src="http://i1044.photobucket.com/albums/b447/ngarnier/Thrive%20Market/img-05_zpsryppwpok.png" href="https://thrivemarket.com/certifications/certified-organic?uid=5019850&uaexptime=1778637862&uatoken=1462b977c1fa70b09b585f3a8943d79a7079ab314393fe89852fd83fd05b631e&ccode=KG6OCD3H&utm_content=lead_welcome&utm_medium=lifecycle&utm_campaign=day8&utm_source=sailthru" /> <mj-text mj-class="ico"><a href="https://thrivemarket.com/certifications/certified-organic?uid=5019850&uaexptime=1778637862&uatoken=1462b977c1fa70b09b585f3a8943d79a7079ab314393fe89852fd83fd05b631e&ccode=KG6OCD3H&utm_content=lead_welcome&utm_medium=lifecycle&utm_campaign=day8&utm_source=sailthru">Organic</a></mj-text> </mj-column> <mj-column> <mj-image padding="10" src="http://i1044.photobucket.com/albums/b447/ngarnier/Thrive%20Market/img-06_zpsoq4ulmbq.png" href="https://thrivemarket.com/raw?uid=5019850&uaexptime=1778637862&uatoken=1462b977c1fa70b09b585f3a8943d79a7079ab314393fe89852fd83fd05b631e&ccode=KG6OCD3H&utm_content=lead_welcome&utm_medium=lifecycle&utm_campaign=day8&utm_source=sailthru" /> <mj-text mj-class="ico"><a href="https://thrivemarket.com/raw?uid=5019850&uaexptime=1778637862&uatoken=1462b977c1fa70b09b585f3a8943d79a7079ab314393fe89852fd83fd05b631e&ccode=KG6OCD3H&utm_content=lead_welcome&utm_medium=lifecycle&utm_campaign=day8&utm_source=sailthru">Raw</a></mj-text> </mj-column> </mj-group> </mj-section> 

Social Networks Link

Once again, this section is easy to achieve by leveraging the <mj-column> component, using one column per social network icon and wrapping all of the icons in an <mj-group> so that they don’t stack on mobile. The only trick here is to fine-tune the width of the images and the padding so that the result is consistent with the original design.

Divider and Text Link

Because this part is pretty simple, it’s OK to wrap the divider and the text in the same column and section, even though we could have separated the divider from the text. As we did before when styling the links, we’ll create a footer class so that our links have the proper color.

<mj-section background-color="#EEEBE7" padding="25 40"> <mj-column> <mj-divider /> <mj-text padding="30 0 0 0" align="center" font-size="14"><a href="https://thrivemarket.com/blog?uid=5019850&uaexptime=1778637862&uatoken=1462b977c1fa70b09b585f3a8943d79a7079ab314393fe89852fd83fd05b631e&ccode=KG6OCD3H&utm_content=lead_welcome&utm_medium=lifecycle&utm_campaign=day8&utm_source=sailthru">Read Our Blog</a> <a href="https://thrivemarket.com/">View Email Online</a></mj-text> <mj-text align="center" color="#45495d" font-size="10px" line-height="14px"> <p>Please don't hit 'reply' to this email—we won't be able to email you back from this address and help you thrive! If you need anything, visit our <a href="https://thrivemarket.com/faq?uid=5019850&uaexptime=1778637862&uatoken=1462b977c1fa70b09b585f3a8943d79a7079ab314393fe89852fd83fd05b631e&ccode=KG6OCD3H&utm_content=lead_welcome&utm_medium=lifecycle&utm_campaign=day8&utm_source=sailthru">FAQ</a> or contact <a href="https://thrivemarket.com/faq/contact?uid=5019850&uaexptime=1778637862&uatoken=1462b977c1fa70b09b585f3a8943d79a7079ab314393fe89852fd83fd05b631e&ccode=KG6OCD3H&utm_content=lead_welcome&utm_medium=lifecycle&utm_campaign=day8&utm_source=sailthru">Member Services</a> anytime, and we'll be happy to help!</p> <p>We don't want to see you go, but if you no longer wish to receive promotional emails from us, you can <a href="https://thrivemarket.com/">unsubscribe here</a> or <a href="https://thrivemarket.com/">change your email preferences</a> anytime.</p> <p>4509 Glencoe Ave, Marina Del Rey, CA 90292 <br />@2016 Thrive Market All Rights Reserved</p> </mj-text> </mj-column> </mj-section> 

Rendering the HTML File and Testing Link

You should now have fewer than 240 lines of MJML (you can check the full code54), whereas the original file was a bit less than 800 lines of HTML. Congrats! You’ve just created your first responsive email using MJML! How easy was that?

Testing how an email renders in different email clients is always a good practice, so let’s do just that using Litmus55 (Email on Acid56 is another great platform for email testing).

Go to Litmus57 (create an account if you don’t have one already), create a new project, and paste the HTML that we generated earlier in the code area. You’ll be able to see the results in various email clients by clicking “Instant Previews” in the right pane. You can see58 the results for major email clients, from Outlook 2003 to Inbox by Gmail.

Going Further Link

Now that you know how to use MJML to easily create a responsive email, why not try to create your own component? My tutorial59 will guide you through this step by step.

What did you think about your first experience with MJML? Feel free to reach out on Twitter60 and join the MJML community now by signing up to the Slack61 channel. You can also subscribe to the newsletter62 to keep up to date on the latest news.

(rb, vf, yk, al, il)

Footnotes Link

  1. 1 https://www.mailjet.com/blog/gmail-responsive-email-design
  2. 2 https://litmus.com/blog/understanding-responsive-and-hybrid-email-design
  3. 3 https://getflywheel.com/layout/design-emails-for-mobile/
  4. 4 https://medium.freecodecamp.com/the-fab-four-technique-to-create-responsive-emails-without-media-queries-baf11fdfa848#.86y5xm2q7
  5. 5 https://twitter.com/hteumeuleu
  6. 6 https://mjml.io/documentation/#mjml-carousel
  7. 7 https://www.smashingmagazine.com/wp-content/uploads/2016/12/mj-carousel-gmail-preview-opt.gif
  8. 8 https://mjml.io/documentation/#mjml-table
  9. 9 http://reallygoodemails.com/wp-content/uploads/discover-the-latest-trends.html
  10. 10 http://codepen.io/mjml/pen/woeNwp
  11. 11 https://mjml.io/try-it-live/templates/thrive_email
  12. 12 https://facebook.github.io/react/
  13. 13 https://www.smashingmagazine.com/wp-content/uploads/2016/12/desktop-view2-preview-opt.png
  14. 14 https://www.smashingmagazine.com/wp-content/uploads/2016/12/mobile-view2-preview-opt.png
  15. 15 https://mjml.io/download
  16. 16 https://mjml.io/try-it-live
  17. 17 https://atom.io/users/mjmlio
  18. 18 https://packagecontrol.io/packages/MJML-syntax
  19. 19 https://github.com/amadeus/vim-mjml
  20. 20 https://github.com/mjmlio/gulp-mjml
  21. 21 https://github.com/smbeiragh/grunt-mjml
  22. 22 https://mjml.io/community
  23. 23 https://mjml.io/try-it-live
  24. 24 https://nodejs.org/en/
  25. 25 https://mjml.io/documentation/#command-line-interface
  26. 26 http://reallygoodemails.com/
  27. 27 http://reallygoodemails.com/wp-content/uploads/discover-the-latest-trends.html
  28. 28 https://thrivemarket.com/
  29. 29 https://www.smashingmagazine.com/wp-content/uploads/2016/12/thrive-market-newsletter-large-opt.png
  30. 30 https://mjml.io/documentation/#overview
  31. 31 https://mjml.io/documentation/#standard-head-components
  32. 32 https://mjml.io/documentation/#standard-head-components
  33. 33 https://mjml.io/try-it-live/templates/thrive_head
  34. 34 https://mjml.io/documentation/mjml-section
  35. 35 https://mjml.io/documentation/#mjml-column
  36. 36 https://mjml.io/documentation/#mjml-hero
  37. 37 https://mjml.io/documentation/#mjml-navbar
  38. 38 https://mjml.io/documentation/#mjml-column
  39. 39 https://mjml.io/documentation/#mjml-section
  40. 40 https://mjml.io/documentation/mjml-text
  41. 41 https://www.smashingmagazine.com/wp-content/uploads/2016/12/header-preview-opt.png
  42. 42 https://mjml.io/documentation/#mjml-image
  43. 43 https://mjml.io/documentation/#mjml-group
  44. 44 https://mjml.io/documentation/#command-line-interface
  45. 45 https://github.com/mjmlio/mjml/blob/master/packages/mjml-cli/README.md#render-and-minify-the-output-html
  46. 46 https://mjml.io/documentation/#mjml-button
  47. 47 https://mjml.io/try-it-live/templates/thrive_header
  48. 48 https://www.smashingmagazine.com/wp-content/uploads/2016/12/2-column-layout-preview-opt.png
  49. 49 https://mjml.io/documentation/#mjml-style
  50. 50 https://www.smashingmagazine.com/wp-content/uploads/2016/12/blue-section-preview-opt.png
  51. 51 https://www.smashingmagazine.com/wp-content/uploads/2016/12/last-part-preview-opt.png
  52. 52 https://mjml.io/try-it-live/templates/thrive_body
  53. 53 https://www.smashingmagazine.com/wp-content/uploads/2016/12/footer-preview-opt.png
  54. 54 https://mjml.io/try-it-live/templates/thrive_email
  55. 55 https://litmus.com/builder/
  56. 56 https://www.emailonacid.com/
  57. 57 https://litmus.com/builder/
  58. 58 http://imgur.com/a/l3xHE
  59. 59 https://medium.com/mjml-making-responsive-email-easy/tutorial-creating-your-own-mjml-component-d3a236ab7093#.d1ji1oheq
  60. 60 https://twitter.com/mjmlio
  61. 61 https://slack.mjml.io/
  62. 62 http://mjml.io/

↑ Back to topTweet itShare on Facebook

A Case Study: Is App Indexing For Google Worth The Effort?

A Case Study: Is App Indexing For Google Worth The Effort?

Will the resources spent implementing app indexing for Google search be a boon or a bust for your app’s traffic? In this article, I’ll take you through a case study for app indexing at our company, the results of which may surprise you.

App indexing is one of the hottest topics in SEO right now, and in some sense for good reason. Google has only been indexing apps for everyone1 for a little more than two years, and with only 30% of apps being indexed2 there is huge potential for websites to draw additional search traffic to their apps.

What’s more, Google has given not one but two ranking boosts3 to websites that use app indexing and the app indexing API4; so, implementing app indexing for your website is likely to increase your search traffic.

However, when we did it, it was a bust. We got a lot more app traffic from Google search when we implemented app indexing, but it was so little traffic compared to web search at that point that it was almost not worth the effort. Read on to learn more about what we did and what effect it had on our overall traffic.

What Is App Indexing? Link

If you’re not familiar with app indexing5, it is basically the process by which your app appears in Google search results alongside relevant web results. By supporting HTTP URLs in your app and adding the App Indexing SDK, you allow Google to crawl and index your app as it would a web page, and you enable users to install or launch your app from search results when they search with relevant keywords.

If the app is already installed, you’ll see a button to launch it in the relevant search results:

6
View of an indexed app on a Nexus 6P running Android 7.0 when the app is installed on the device. (Image: Bryson Meunier) (View large version7)

If the searcher doesn’t have the app installed yet, they will see an “Install” button in search results:

View of an indexed app on a Nexus 6P running Android 7.0 when the app is not installed on the device.8
View of an indexed app on a Nexus 6P running Android 7.0 when the app is not installed on the device. (Image: Bryson Meunier) (View large version9)

Theoretically, this is great for users because they can find relevant authoritative content in Google regardless of whether they prefer websites or apps, and it’s great for app developers and marketers because it allows apps to be exposed to a whole new audience outside of the app store, potentially increasing app usage and downloads. But “theoretically” doesn’t necessarily mean that app indexing brings a lot of real traffic from search.

While I have seen a lot of great info on how10 and why11 to implement app indexing, I haven’t yet seen a case study on the benefits of app indexing in terms of traffic (though Google does highlight several other benefits12). So, I looked at our app indexing traffic at Vivid Seats so that marketers, developers and webmasters can get a better sense of how much traffic, realistically, they can expect from getting their app indexed.

I want to start the case study with a small caveat: Vivid Seats13 is the largest independent ticket marketplace, and the number-three resale marketplace behind StubHub and Ticketmaster, according to Bloomberg14. As such, we get a lot of web traffic. A website that doesn’t get as much web traffic as we do or an app that has no equivalent website will probably have different results than ours — especially if it’s in a different industry. That said, a lot of large websites might see similar results and might want to adjust their strategy accordingly.

This is also an Android-only case study, because we haven’t yet been given access to the iOS app-indexing beta in Google’s Search Console15, and we don’t have the same kind of visibility into our iOS app’s indexing and ranking.

Background Link

Vivid Seats has had an Android app16 indexed since September of 2015. However, Google had a difficult time finding the equivalent app URI for our web pages at first, and in February of this year we had about 18 app URIs indexed and more than 35,000 pages with the “Intent URI not supported” error17. We had had different URIs for our app than for our website at the time, which was making it difficult for Google to find equivalent pages.

Solution Link

Initially, we tried to add alternate tags to our web pages pointing to the equivalent app URIs, as instructed by Google’s help section on the subject18.

For example, Adele’s Vivid Seats page19http://www.vividseats.com/concerts/adele-tickets.html — had the following rel="alternate" tag, which was dynamically served to mobile user agents and which pointed to the equivalent app URI:

<link rel="alternate" href="android-app://com.vividseats.android/vividseats/performer/15313">
Mobile view of Adele's tickets page.20
Mobile view of Adele’s tickets page. (Image: Fawaad Ahmad)
View of the code for the same page with the alternate tag highlighted.21
View of the code for the same page with the alternate tag highlighted. (Image: Fawaad Ahmad)

We were initially hopeful that this solution would be all that was necessary, because Google recommended it in its help section as a solution to this problem. Unfortunately, weeks after implementation, it was clear that Google was still having a difficult time figuring it out, and it didn’t index many more app URIs.

And the crawl errors persisted because Google was assuming that a lot of web pages on our website had equivalent app views, which at the time wasn’t the case.

We supported universal links22 in our iOS app and HTTP URLs in Android23 in April, which reduced the number of errors from 40,000 at its apex to about 85 today. As a result, we have seen the number of app URIs indexed go from 18 in February to about 35,000 today.

Screenshot of Search Console Crawl Status report from 5/31/2016 which shows the effect of implementing HTTP URLs in Android on pages with errors and pages indexed.24
Screenshot of Search Console’s “Crawl Status” report from 31 May 2016, which shows the effect of implementing HTTP URLs in Android on pages with errors and pages indexed. (Image: Bryson Meunier) (View large version25)

To do this, we simply followed the procedure outlined in the Firebase documentation26:

  • We made sure that each type of link on our website had an equivalent view and corresponding URI in our Android app. To do this, we designed templates for page types that were not included in our app previously, and we built them in our Android app. The unique information on each page is dynamically served from our RESTful endpoint, so it’s only necessary to design and code the templates, not individual pages.
  • We verified our website in Search Console and associated it with our website, since our website isn’t in SSL, as required by Digital Asset Links.
  • We added an intent filter27 in our Android manifest file.
  • We called getIntent in the onCreate code and deployed the app to the Play store.

Results Link

Predictably, clicks and impressions grew exponentially from December, when 18 app URIs were indexed, to September, when 40,000 app URIs were indexed. Overall, clicks grew 919%, with clicks from non-brand queries (i.e. informational queries that don’t mention Vivid Seats, like “packers tickets”) growing 5,500%. The clickthrough rate (CTR) went down, predictably, as a result of the increase in impressions, specifically non-brand ones.

Clicks to app from Google search grew 919% after getting additional URLs indexed, with non-brand traffic growing 5500%.28
Traffic to the app from Google search grew 919% after getting additional URLs indexed, with non-brand traffic growing 5500%. (Image: Bryson Meunier) (View large version29)

While app traffic (defined in Search Console as “clicks”) grew exponentially as a result of the increase in app URIs getting indexed, relative to the website traffic, app traffic has been underwhelming to date.

Even with an additional 40,000 app URIs indexed, 99.82% of our traffic from search currently goes to web pages, with just 0.23% of total search traffic going to our app URIs.

A few reasons why this might be so low:

  • Android traffic is a lower percentage of our mobile traffic than iOS, which isn’t included in this study.
  • We also have fewer app pages indexed than web pages — more than three times fewer, in fact. Because we grew traffic exponentially by having more app URIs indexed, there’s probably more traffic out there to be had that we will see when Google finally indexes all of our app URIs.
  • But the biggest reason is that CTRs vary dramatically for app listings and web listings. Our brand term, which we usually rank in position 1 and for which we usually get around a 40% CTR on the web, has a CTR of less than 1% for the app equivalent. This suggests that, though the app buttons are prominent in Google for navigational terms, most people still prefer to click through to the website.

This last point could just be a matter of this being fairly new technology and searchers not fully understanding the new layout, and we could imagine this trend reversing sometime in the future. For now, however, it’s important that this point is understood by all who are looking to index their app pages in search results. It’s tempting to think that the presence of a large colorful button in search results will increase the CTR and traffic, but our research hasn’t found any evidence to support this.

In fact, we found just the opposite: The CTR to app content is less than half of what it is to web content, with our Android app pages getting a CTR of 1.55%, at an average position of 5.1, compared to our web content CTR of 4.67%, two positions below our app content, at 7.6.

Breakdown of the CTR across all content types, as reported by Search Console.30
Breakdown of the CTR across all content types, as reported by Search Console. (Image: Bryson Meunier) (View large version31)

Though app content in general has a lower CTR than web content, we found that navigational (or branded) search terms actually have a lower CTR for us than informational terms, which is the opposite of how it works for web content.

Branded navigational terms drove much less traffic to apps than web pages.32
Branded navigational terms drove much less traffic to apps than to web pages. (Image: Bryson Meunier)

56% of the app traffic we received came from branded queries, compared to just 40% of our web traffic.

The CTR varies significantly for web and app traffic by query type.33
The CTR varies significantly for web and app traffic by query type. (Image: Bryson Meunier) (View large version34)

Looking deeper into query type, we broke down queries into two distinct types: first, navigational queries that mention our brand (for example, “vivid seats”) and informational queries that don’t (for example, “packer tickets”), and secondly, queries that indicate the searcher is looking for a website (for example, “www.vividseats.com”) or an app (for example, “download vivid seats app”) specifically.

If the searcher hadn’t indicated in their query that they were looking for an app or a website, we recorded that the query was branded or not, and that the website or app preference was “Not Specified.”

In this chart of app and web impressions and traffic to Vivid Seats from Google search, 93% of web impressions came from non-brand queries that didn't specify an app or website preference, compared to just 12% for the same category in app impressions.35
In this chart of app and web impressions and traffic to Vivid Seats from Google search, 93% of web impressions came from non-brand queries that didn’t specify an app or website preference, compared to just 12% for the same category in app impressions. (Image: Bryson Meunier) (View large version36)

4% of total app traffic specified that they’re looking for an app, compared to less than 1% for web traffic. This is important traffic to be aware of, because it doesn’t have an equivalent on the desktop, and it could be a new query type to optimize for, but it’s not representative of app traffic. The great majority of queries for both web (99%) and app (96%) do not use qualifiers to describe whether the searchers are looking for an app or website specifically.

The traffic to app content from search has so far been underwhelming, but the real reason most developers would index their app content would be to drive downloads.

Fortunately, with Search Console, we can see installations from search as well. It’s kind of hidden in the Search Console reports; to see it, go to “Search analytics” → “Search appearance” → “Filter search appearance” → “Install app button.”

View of Install App Button filter within Google Search Console's Search Analytics Report.37
View of “Install app button” filter in Search Console’s “Search Analytics” report. (Image: Bryson Meunier) (View large version38)

When we did that, we found that just 0.03% of our total search traffic led to an app installation from search in the last 90 days.

But when you take the total number of installations from the last 90 days and compare it to the installations we’ve gotten from search, it’s clear that about 2% of our total Android downloads came from users installing the downloads in search results. This isn’t terribly impressive, but when you consider that this represents many app installations from search that we may not have had otherwise, it justifies for us the little bit of work it took to implement it.

Summary Link

If your resources are limited and you’re wondering if app indexing would deliver enough traffic and installations to justify the effort, our experience would suggest you should focus on web content instead. Even after growing our traffic from app indexing by 919%, web content still brings in more than 99.8% of the total traffic from search to our website. If you’re considering other high-value projects, you might want to do those instead.

Still, if you only have an app to index, or if you have resources on your team, then app indexing does bring traffic that you wouldn’t get otherwise, and it might be worth the long-term benefits to your website and to Google users.

Have you implemented app indexing with similar (or dissimilar) results? I’d love to hear about it in the comments.

Many thanks to the UX design and development group at Vivid Seats, including Fawaad Ahmad, who made a lot of this happen.

(da, vf, il, yk, al)

Front page image credits: Introducing Firebase App Indexing39

Footnotes Link

  1. 1 https://webmasters.googleblog.com/2014/06/android-app-indexing-is-now-open-for.html
  2. 2 http://searchengineland.com/searchmetrics-study-shows-most-apps-not-utilizing-google-app-indexing-api-244432
  3. 3 http://searchengineland.com/google-adds-additional-ranking-boost-for-using-app-indexing-api-232018
  4. 4 https://firebase.google.com/docs/app-indexing/android/activity
  5. 5 https://firebase.google.com/docs/app-indexing/
  6. 6 https://www.smashingmagazine.com/wp-content/uploads/2016/11/View-of-an-indexed-app-on-a-Nexus-6P-running-Android-7.0-large-opt.png
  7. 7 https://www.smashingmagazine.com/wp-content/uploads/2016/11/View-of-an-indexed-app-on-a-Nexus-6P-running-Android-7.0-large-opt.png
  8. 8 https://www.smashingmagazine.com/wp-content/uploads/2016/11/View-of-an-indexed-app-on-a-Nexus-6P-running-Android-7.0-when-the-app-is-not-installed-on-the-device-large-opt.png
  9. 9 https://www.smashingmagazine.com/wp-content/uploads/2016/11/View-of-an-indexed-app-on-a-Nexus-6P-running-Android-7.0-when-the-app-is-not-installed-on-the-device-large-opt.png
  10. 10 http://searchengineland.com/smx-advanced-recap-advanced-google-app-deep-linking-253134
  11. 11 http://searchengineland.com/app-indexing-new-frontier-seo-app-packs-app-store-search-242319
  12. 12 https://firebase.google.com/docs/app-indexing/partners/case-study-one-pager.pdf
  13. 13 http://www.vividseats.com/
  14. 14 https://www.bloomberg.com/gadfly/articles/2016-06-22/stubhub-ebay-s-next-ticket-to-ride
  15. 15 https://www.google.com/webmasters/
  16. 16 http://www.vividseats.com/app
  17. 17 https://support.google.com/webmasters/answer/6216428?hl=en
  18. 18 https://developer.android.com/training/app-indexing/enabling-app-indexing.html
  19. 19 http://www.vividseats.com/concerts/adele-tickets.html
  20. 20 https://www.smashingmagazine.com/wp-content/uploads/2016/11/adele-tickets-alternate-tag-app-uri-preview-opt.png
  21. 21 https://www.smashingmagazine.com/wp-content/uploads/2016/11/adele-tickets-alternate-tag-code-view-preview-opt.png
  22. 22 https://developer.apple.com/library/content/documentation/General/Conceptual/AppSearch/UniversalLinks.html
  23. 23 https://firebase.google.com/docs/app-indexing/android/app
  24. 24 https://www.smashingmagazine.com/wp-content/uploads/2016/11/universal-links-large-opt.jpg
  25. 25 https://www.smashingmagazine.com/wp-content/uploads/2016/11/universal-links-large-opt.jpg
  26. 26 https://firebase.google.com/docs/app-indexing/android/app
  27. 27 https://developer.android.com/studio/write/app-link-indexing.html#intent
  28. 28 https://www.smashingmagazine.com/wp-content/uploads/2016/11/traffic-growth-post-app-indexing-vivid-seats-large-opt.png
  29. 29 https://www.smashingmagazine.com/wp-content/uploads/2016/11/traffic-growth-post-app-indexing-vivid-seats-large-opt.png
  30. 30 https://www.smashingmagazine.com/wp-content/uploads/2016/11/overall-ctr-by-content-type-web-and-apps-search-console-large-opt.png
  31. 31 https://www.smashingmagazine.com/wp-content/uploads/2016/11/overall-ctr-by-content-type-web-and-apps-search-console-large-opt.png
  32. 32 https://www.smashingmagazine.com/wp-content/uploads/2016/11/brand-vs-non-brand-ctr-apps-web-preview-opt.png
  33. 33 https://www.smashingmagazine.com/wp-content/uploads/2016/11/brand-non-brand-traffic-apps-web-large-opt.png
  34. 34 https://www.smashingmagazine.com/wp-content/uploads/2016/11/brand-non-brand-traffic-apps-web-large-opt.png
  35. 35 https://www.smashingmagazine.com/wp-content/uploads/2016/11/brand-device-breakdown-app-web-queries-large-opt.jpg
  36. 36 https://www.smashingmagazine.com/wp-content/uploads/2016/11/brand-device-breakdown-app-web-queries-large-opt.jpg
  37. 37 https://www.smashingmagazine.com/wp-content/uploads/2016/11/search-analytics-google-search-performance-large-opt.png
  38. 38 https://www.smashingmagazine.com/wp-content/uploads/2016/11/search-analytics-google-search-performance-large-opt.png
  39. 39 https://www.youtube.com/watch?v=C35OSHlTNwA

↑ Back to topTweet itShare on Facebook

Web Development Reading List #166: Efficient Docker, CSP Learnings, And JavaScript’s Global Object

Web Development Reading List #166: Efficient Docker, CSP Learnings, And JavaScript’s Global Object

What fuels your work? What fuels your mind? What do you do on a non-productive day or when you’re sad? Nowadays, I try to embrace these times. I try to relax and not be angry at myself for not being productive.

And the fun fact about it? Well, most of the times when I could convince my mind that not being productive is nothing to feel bad about, things take a sudden turn: I get my ideas back, my productivity rises and, in effect, I even achieve more work than on an average day. It’s important to try to be human.

News Link

General Link

Tools & Workflows Link

Security Link

Web Performance Link

11
With its modernized progressive enhancement delivery12 in place, the Filament Group website can even be deemed a bonified Progressive Web App.

Accessibility Link

JavaScript Link

  • Chart.js15 is a nice library that uses subtle animations to draw canvas charts on a page. Mixed chart types are available.
  • Stefan Judis wrote about the global object in JavaScript16, variables and the issues around it. This is not only useful for people with beginner or intermediate JavaScript knowledge but also for advanced users who want to understand the topic better.
  • Todd Motto published an “Angular 2+ Fundamentals17” video course in which he explains Angular, Typescript, component architecture, and other modern programming concepts.
The Global Object In JavaScript18
Stefan Judis takes a new look at the global object in JavaScript19. (Image credit20)

Work & Life Link

Going Beyond… Link

  • This visual introduction to machine learning22 explains how computers apply statistical learning techniques to automatically identify patterns in data. If you’re not familiar with how machine learning works, this will give you a rough idea.
  • As we’ve seen in statistics and data from the NASA before, this is, unfortunately, the truth: 2016 was the hottest year on record23. The consequences: Nearly a quarter of the Great Barrier Reef died, Canada had to deal with the costliest wildfires ever, and the Arctic sea ice has been at its smallest winter maximum for two years now. And do you remember Hurricane Matthew? Such weather events are mostly driven by the climate change that we’re facing right now, with no trend of change over the upcoming years. Fortunately, there’s something everyone of us can do: The UN shows how we can take action, even from the couch at home24.

And with that, I’ll close for this week. If you like what I write each week, please support me with a donation25 or share this resource with other people. You can learn more about the costs of the project here26. It’s available via email, RSS and online.

— Anselm

Footnotes Link

  1. 1 https://ma.ttias.be/despite-revoked-cas-startcom-wosign-continue-sell-certificates/
  2. 2 https://www.rachelandrew.co.uk/archives/2017/01/12/browser-support-for-evergreen-websites/
  3. 3 http://csswizardry.com/2017/01/ack-for-css-developers/
  4. 4 http://bitjudo.com/blog/2014/03/13/building-efficient-dockerfiles-node-dot-js/
  5. 5 https://tobiastom.name/explains/docker
  6. 6 http://githubengineering.com/githubs-csp-journey/
  7. 7 https://githubengineering.com/githubs-post-csp-journey/
  8. 8 http://www.japantimes.co.jp/news/2017/01/11/national/crime-legal/researchers-warn-fingerprint-theft-peace-sign/
  9. 9 https://www.ccc.de/en/updates/2014/ursel
  10. 10 https://www.filamentgroup.com/lab/modernizing-delivery.html
  11. 11 https://www.filamentgroup.com/lab/modernizing-delivery.html
  12. 12 https://www.filamentgroup.com/lab/modernizing-delivery.html
  13. 13 http://www.ssbbartgroup.com/blog/differences-aria-1-0-1-1-additions-role/
  14. 14 https://allyjs.io/tutorials/focusing-in-svg.html
  15. 15 http://www.chartjs.org/
  16. 16 https://www.contentful.com/blog/2017/01/17/the-global-object-in-javascript/
  17. 17 https://ultimateangular.com/angular-2-fundamentals
  18. 18 https://www.contentful.com/blog/2017/01/17/the-global-object-in-javascript/
  19. 19 https://www.contentful.com/blog/2017/01/17/the-global-object-in-javascript/
  20. 20 https://www.contentful.com/blog/2017/01/17/the-global-object-in-javascript/
  21. 21 https://superyesmore.com/rockbots-6-tricks-to-leading-a-healthy-productive-life-8b553b6c4ac1112787d2d52d3804ea64
  22. 22 http://www.r2d3.us/visual-intro-to-machine-learning-part-1/
  23. 23 https://www.bloomberg.com/graphics/hottest-year-on-record/
  24. 24 http://www.un.org/sustainabledevelopment/takeaction/
  25. 25 https://wdrl.info/donate
  26. 26 https://wdrl.info/costs/

↑ Back to topTweet itShare on Facebook

Internationalizing React Apps

Internationalizing React Apps

First of all, let’s define some vocabulary. “Internationalization” is a long word, and there are at least two widely used abbreviations: “intl,” “i18n”. “Localization” can be shortened to “l10n”.

Internationalization can be generally broken down into the following challenges:

  • detecting the user’s locale;
  • translating UI elements, titles and hints;
  • serving locale-specific content such as dates, currencies and numbers.

Note: In this article, I am going to focus only on front-end part. We’ll develop a simple universal React application with full internationalization support.

Let’s use my boilerplate repository1 as a starting point. Here we have the Express web server for server-side rendering, webpack for building client-side JavaScript, Babel for translating modern JavaScript to ES5, and React for the UI implementation. We’ll use better-npm-run to write OS-agnostic scripts, nodemon to run a web server in the development environment and webpack-dev-server to serve assets.

Our entry point to the server application is server.js. Here, we are loading Babel and babel-polyfill to write the rest of the server code in modern JavaScript. Server-side business logic is implemented in src/server.jsx. Here, we are setting up an Express web server, which is listening to port 3001. For rendering, we are using a very simple component from components/App.jsx, which is also a universal application part entry point.

Our entry point to the client-side JavaScript is src/client.jsx. Here, we mount the root component component/App.jsx to the placeholder react-view in the HTML markup provided by the Express web server.

So, clone the repository, run npm install and execute nodemon and webpack-dev-server in two console tabs simultaneously.

In the first console tab:

 git clone https://github.com/yury-dymov/smashing-react-i18n.git cd smashing-react-i18n npm install npm run nodemon

And in the second console tab:

 cd smashing-react-i18n npm run webpack-devserver 

A website should become available at localhost:30012. Open your favorite browser and try it out.

We are ready to roll!

1. Detecting The User’s Locale Link

There are two possible solutions to this requirement. For some reason, most popular websites, including Skype’s and the NBA’s, use Geo IP to find the user’s location and, based on that, to guess the user’s language. This approach is not only expensive in terms of implementation, but also not really accurate. Nowadays, people travel a lot, which means that a location doesn’t necessarily represent the user’s desired locale. Instead, we’ll use the second solution and process the HTTP header Accept-Language on the server side and extract the user’s language preferences based on their system’s language settings. This header is sent by every modern browser within a page request.

Accept-Language Request Header Link

The Accept-Language request header provides the set of natural languages that are preferred as a response to the request. Each language range may be given an associated “quality” value, which represents an estimate of the user’s preference for the languages specified by that range. The quality value defaults to q=1. For example, Accept-Language: da, en-gb;q=0.8, en;q=0.7 would mean, “I prefer Danish, but will accept British English and other types of English.” A language range matches a language tag if it exactly equals the tag or if it exactly equals a prefix of the tag such that the first tag character following the prefix is -.

(It is worth mentioning that this method is still imperfect. For example, a user might visit your website from an Internet cafe or a public computer. To resolve this, always implement a widget with which the user can change the language intuitively and that they can easily locate within a few seconds.)

Implementing Detection of User’s Locale Link

Here is a code example for a Node.js Express web server. We are using the accept-language package, which extracts locales from HTTP headers and finds the most relevant among the ones supported by your website. If none are found, then you’d fall back to the website’s default locale. For returning users, we will check the cookie’s value instead.

Let’s start by installing the packages:

 npm install --save accept-language npm install --save cookie-parser js-cookie 

And in src/server.jsx, we’d have this:

import cookieParser from 'cookie-parser'; import acceptLanguage from 'accept-language'; acceptLanguage.languages(['en', 'ru']); const app = express(); app.use(cookieParser()); function detectLocale(req) { const cookieLocale = req.cookies.locale; return acceptLanguage.get(cookieLocale || req.headers['accept-language']) || 'en'; } … app.use((req, res) => { const locale = detectLocale(req); const componentHTML = ReactDom.renderToString(<App />); res.cookie('locale', locale, { maxAge: (new Date() * 0.001) + (365 * 24 * 3600) }); return res.end(renderHTML(componentHTML)); }); 

Here, we are importing the accept-language package and setting up English and Russian locales as supported. We are also implementing the detectLocale function, which fetches a locale value from a cookie; if none is found, then the HTTP Accept-Language header is processed. Finally, we are falling back to the default locale (en in our example). After the request is processed, we add the HTTP header Set-Cookie for the locale detected in the response. This value will be used for all subsequent requests.

2. Translating UI Elements, Titles And Hints Link

I am going to use the React Intl3 package for this task. It is the most popular and battle-tested i18n implementation of React apps. However, all libraries use the same approach: They provide “higher-order components” (from the functional programming design pattern4, widely used in React), which injects internationalization functions for handling messages, dates, numbers and currencies via React’s context features.

First, we have to set up the internationalization provider. To do so, we will slightly change the src/server.jsx and src/client.jsx files.

 npm install --save react-intl 

Here is src/server.jsx:

import { IntlProvider } from 'react-intl'; … --- const componentHTML = ReactDom.renderToString(<App />); const componentHTML = ReactDom.renderToString( <IntlProvider locale={locale}> <App /> </IntlProvider> ); … 

And here is src/client.jsx:

import { IntlProvider } from 'react-intl'; import Cookie from 'js-cookie'; const locale = Cookie.get('locale') || 'en'; … --- ReactDOM.render(<App />, document.getElementById('react-view')); ReactDOM.render( <IntlProvider locale={locale}> <App /> </IntlProvider>, document.getElementById('react-view') ); 

So, now all IntlProvider child components will have access to internationalization functions. Let’s add some translated text to our application and a button to change the locale (for testing purposes). We have two options: either the FormattedMessage component or the formatMessage function. The difference is that the component will be wrapped in a span tag, which is fine for text but not suitable for HTML attribute values such as alt and title. Let’s try them both!

Here is our src/components/App.jsx file:

import { FormattedMessage } from 'react-intl'; … --- <h1>Hello World!</h1> <h1><FormattedMessage defaultMessage="Hello World!" description="Hello world header greeting" /></h1> 

Please note that the id attribute should be unique for the whole application, so it makes sense to develop some rules for naming your messages. I prefer to follow the format componentName.someUniqueIdWithInComponent. The defaultMessage value will be used for your application’s default locale, and the description attribute gives some context to the translator.

Restart nodemon and refresh the page in your browser. You should still see the “Hello World” message. But if you open the page in the developer tools, you will see that text is now inside the span tags. In this case, it isn’t an issue, but sometimes we would prefer to get just the text, without any additional tags. To do so, we need direct access to the internationalization object provided by React Intl.

Let’s go back to src/components/App.jsx:

 --- import { FormattedMessage } from 'react-intl'; import { FormattedMessage, intlShape, injectIntl, defineMessages } from 'react-intl'; const propTypes = { intl: intlShape.isRequired, }; const messages = defineMessages({ helloWorld2: { id: 'app.hello_world2', defaultMessage: 'Hello World 2!', }, }); --- export default class extends Component { class App extends Component { render() { return ( <div className="App"> <h1> <FormattedMessage defaultMessage="Hello World!" description="Hello world header greeting" /> </h1> <h1>{this.props.intl.formatMessage(messages.helloWorld2)}</h1> </div> ); } } App.propTypes = propTypes; export default injectIntl(App); 

We’ve had to write a lot more code. First, we had to use injectIntl, which wraps our app component and injects the intl object. To get the translated message, we had to call the formatMessage method and pass a message object as a parameter. This message object must have unique id and defaultValue attributes. We use defineMessages from React Intl to define such objects.

The best thing about React Intl is its ecosystem. Let’s add babel-plugin-react-intl to our project, which will extract FormattedMessages from our components and build a translation dictionary. We will pass this dictionary to the translators, who won’t need any programming skills to do their job.

 npm install --save-dev babel-plugin-react-intl 

Here is .babelrc:

{ "presets": [ "es2015", "react", "stage-0" ], "env": { "development": { "plugins":[ ["react-intl", { "messagesDir": "./build/messages/" }] ] } } } 

Restart nodemon and you should see that a build/messages folder has been created in the project’s root, with some folders and files inside that mirror your JavaScript project’s directory structure. We need to merge all of these files into one JSON. Feel free to use my script5. Save it as scripts/translate.js.

Now, we need to add a new script to package.json:

"scripts": { … "build:langs": "babel scripts/translate.js | node", … } 

Let’s try it out!

 npm run build:langs 

You should see an en.json file in the build/lang folder with the following content:

{ "app.hello_world": "Hello World!", "app.hello_world2": "Hello World 2!" } 

It works! Now comes interesting part. On the server side, we can load all translations into memory and serve each request accordingly. However, for the client side, this approach is not applicable. Instead, we will send the JSON file with translations once, and a client will automatically apply the provided text for all of our components, so the client gets only what it needs.

Let’s copy the output to the public/assets folder and also provide some translation.

 ln -s ../../build/lang/en.json public/assets/en.json 

Note: If you are a Windows user, symlinks are not available to you, which means you have to manually copy the command below every time you rebuild your translations:

cp ../../build/lang/en.json public/assets/en.json 

In public/assets/ru.json, we need the following:

{ "app.hello_world": "Привет мир!", "app.hello_world2": "Привет мир 2!" } 

Now we need to adjust the server and client code.

For the server side, our src/server.jsx file should look like this:

--- import { IntlProvider } from 'react-intl'; import { addLocaleData, IntlProvider } from 'react-intl'; import fs from 'fs'; import path from 'path'; import en from 'react-intl/locale-data/en'; import ru from 'react-intl/locale-data/ru'; addLocaleData([…ru, …en]); const messages = {}; const localeData = {}; ['en', 'ru'].forEach((locale) => { localeData[locale] = fs.readFileSync(path.join(__dirname, `../node_modules/react-intl/locale-data/${locale}.js`)).toString(); messages[locale] = require(`../public/assets/${locale}.json`); }); --- function renderHTML(componentHTML) { function renderHTML(componentHTML, locale) { … <script type="application/javascript" src="${assetUrl}/public/assets/bundle.js"></script> <script type="application/javascript">${localeData[locale]}</script> … --- <IntlProvider locale={locale}> <IntlProvider locale={locale} messages={messages[locale]}> … --- return res.end(renderHTML(componentHTML)); return res.end(renderHTML(componentHTML, locale)); ``` 

Here we are doing the following:

  • caching messages and locale-specific JavaScript for the currency, DateTime and Number formatting during startup (to ensure good performance);
  • extending the renderHTML method so that we can insert locale-specific JavaScript into the generated HTML markup;
  • providing the translated messages to IntlProvider (all of those messages are now available to child components).

For the client side, first we need to install a library to perform AJAX requests. I prefer to use isomorphic-fetch because we will very likely also need to request data from third-party APIs, and isomorphic-fetch can do that very well in both client and server environments.

 npm install --save isomorphic-fetch 

Here is src/client.jsx:

--- import { IntlProvider } from 'react-intl'; import { addLocaleData, IntlProvider } from 'react-intl'; import fetch from 'isomorphic-fetch'; const locale = Cookie.get('locale') || 'en'; fetch(`/public/assets/${locale}.json`) .then((res) => { if (res.status >= 400) { throw new Error('Bad response from server'); } return res.json(); }) .then((localeData) => { addLocaleData(window.ReactIntlLocaleData[locale]); ReactDOM.render( --- <IntlProvider locale={locale}> <IntlProvider locale={locale} messages={localeData}> … ); }).catch((error) => { console.error(error); }); 

We also need to tweak src/server.jsx, so that Express serves the translation JSON files for us. Note that in production, you would use something like nginx instead.

app.use(cookieParser()); app.use('/public/assets', express.static('public/assets')); 

After the JavaScript is initialized, client.jsx will grab the locale from the cookie and request the JSON file with the translations. Afterwards, our single-page application will work as before.

Time to check that everything works fine in the browser. Open the “Network” tab in the developer tools, and check that JSON has been successfully fetched by our client.

6
AJAX request (View large version7)

To finish this part, let’s add a simple widget to change the locale, in src/components/LocaleButton.jsx:

import React, { Component, PropTypes } from 'react'; import Cookie from 'js-cookie'; const propTypes = { locale: PropTypes.string.isRequired, }; class LocaleButton extends Component { constructor() { super(); this.handleClick = this.handleClick.bind(this); } handleClick() { Cookie.set('locale', this.props.locale === 'en' ? 'ru' : 'en'); window.location.reload(); } render() { return <button onClick={this.handleClick}>{this.props.locale === 'en' ? 'Russian' : 'English'}; } } LocaleButton.propTypes = propTypes; export default LocaleButton; 

Add the following to src/components/App.jsx:

import LocaleButton from './LocaleButton'; … <h1>{this.props.intl.formatMessage(messages.helloWorld2)}</h1> <LocaleButton locale={this.props.intl.locale} /> 

Note that once the user changes their locale, we’ll reload the page to ensure that the new JSON file with the translations is fetched.

High time to test! OK, so we’ve learned how to detect the user’s locale and how to show translated messages. Before moving to the last part, let’s discuss two other important topics.

Pluralization And Templates Link

In English, most words take one of two possible forms: “one apple,” “many apples.” In other languages, things are a lot more complicated. For example, Russian has four different forms. Hopefully, React Intl will help us to handle pluralization accordingly. It also supports templates, so you can provide variables that will be inserted into the template during rendering. Here’s how it works.

In src/components/App.jsx, we have the following:

const messages = defineMessages({ counting: { id: 'app.counting', defaultMessage: 'I need to buy {count, number} {count, plural, one {apple} other {apples}}' }, … <LocaleButton locale={this.props.intl.locale} /> <div>{this.props.intl.formatMessage(messages.counting, { count: 1 })}</div> <div>{this.props.intl.formatMessage(messages.counting, { count: 2 })}</div> <div>{this.props.intl.formatMessage(messages.counting, { count: 5 })}</div> 

Here, we are defining a template with the variable count. We will print either “1 apple” if count is equal to 1, 21, etc. or “2 apples” otherwise. We have to pass all variables within formatMessage‘s values option.

Let’s rebuild our translation file and add the Russian translations to check that we can provide more than two variants for languages other than English.

npm run build:langs 

Here is our public/assets/ru.json file:

{ … "app.counting": "Мне нужно купить {count, number} {count, plural, one {яблоко} few {яблока} many {яблок}}" } 

All use cases are covered now. Let’s move forward!

3. Serving Locale-Specific Content Such As Dates, Currencies And Numbers Link

Your data will be represented differently depending on the locale. For example, Russian would show 500,00 $ and 10.12.2016, whereas US English would show $500.00 and 12/10/2016.

React Intl provides React components for such kinds of data and also for the relative rendering of time, which will automatically be updated each 10 seconds if you do not override the default value.

Add this to src/components/App.jsx:

--- import { FormattedMessage, intlShape, injectIntl, defineMessages } from 'react-intl'; import { FormattedDate, FormattedRelative, FormattedNumber, FormattedMessage, intlShape, injectIntl, defineMessages, } from 'react-intl'; … <div>{this.props.intl.formatMessage(messages.counting, { count: 5 })}</div> <div><FormattedDate value={Date.now()} /></div> <div><FormattedNumber value="1000" currency="USD" currencyDisplay="symbol" /></div> <div><FormattedRelative value={Date.now()} /></div> 

Refresh the browser and check the page. You’ll need to wait for 10 seconds to see that the FormattedRelative component has been updated.

You’ll find a lot more examples in the official wiki8.

Cool, right? Well, now we might face another problem, which affects universal rendering.

Universal rendering is broken9
Universal rendering is broken. (View large version10)

On average, two seconds will elapse between when the server provides markup to the client and the client initializes client-side JavaScript. This means that all DateTimes rendered on the page might have different values on the server and client sides, which, by definition, breaks universal rendering. To resolve this, React Intl provides a special attribute, initialNow. This provides a server timestamp that will initially be used by client-side JavaScript as a timestamp; this way, the server and client checksums will be equal. After all components have been mounted, they will use the browser’s current timestamp, and everything will work properly. So, this trick is used only to initialize client-side JavaScript, in order to preserve universal rendering.

Here is src/server.jsx:

--- function renderHTML(componentHTML, locale) { function renderHTML(componentHTML, locale, initialNow) { return ` <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Hello React</title> </head> <body> <div>${componentHTML}</div> <script type="application/javascript" src="${assetUrl}/public/assets/bundle.js"></script> <script type="application/javascript">${localeData[locale]}</script> <script type="application/javascript">window.INITIAL_NOW=${JSON.stringify(initialNow)}</script> </body> </html> `; } const initialNow = Date.now(); const componentHTML = ReactDom.renderToString( --- <IntlProvider locale={locale} messages={messages[locale]}> <IntlProvider initialNow={initialNow} locale={locale} messages={messages[locale]}> <App /> </IntlProvider> ); res.cookie('locale', locale, { maxAge: (new Date() * 0.001) + (365 * 24 * 3600) }); --- return res.end(renderHTML(componentHTML, locale)); return res.end(renderHTML(componentHTML, locale, initialNow)); 

And here is src/client.jsx:

--- <IntlProvider locale={locale} messages={localeData}> <IntlProvider initialNow={parseInt(window.INITIAL_NOW, 10)} locale={locale} messages={localeData}> 

Restart nodemon, and the issue will almost be gone! It might persist because we are using Date.now(), instead of some timestamp provided by the database. To make the example more realistic, in app.jsx replace Date.now() with a recent timestamp, like 1480187019228.

(You might face another issue when the server is not able to render the DateTime in the proper format, which will also break universal rendering. This is because version 4 of Node.js is not built with Intl support by default. To resolve this, follow one of the solutions described in the official wiki11.)

4. A Problem Link

It sounds too good to be true so far, doesn’t it? We as front-end developers always have to be very cautious about anything, given the variety of browsers and platforms. React Intl uses the native Intl browser API for handling the DateTime and Number formats. Despite the fact that it was introduced in 2012, it is still not supported by all modern browsers. Even Safari supports it partially only since iOS 10. Here is the whole table from CanIUse for reference.

Internationalization browser support12
Intl browser support (View large version13)

This means that if you are willing to cover a minority of browsers that don’t support the Intl API natively, then you’ll need a polyfill. Thankfully, there is one, Intl.js14. It might sound like a perfect solution once again, but from my experience, it has its own drawbacks. First of all, you’ll need to add it to the JavaScript bundle, and it is quite heavy. You’ll also want to deliver the polyfill only to browsers that don’t support the Intl API natively, to reduce your bundle size. All of these techniques are well known, and you might find them, along with how to do it with webpack, in Intl.js’ documentation15. However, the biggest issue is that Intl.js is not 100% accurate, which means that the DataTime and Number representations might differ between the server and client, which will break server-side rendering once again. Please refer to the relevant GitHub issue16 for more details.

I’ve come up with another solution, which certainly has its own drawbacks, but it works fine for me. I implemented a very shallow polyfill17, which has only one piece of functionality. While it is certainly unusable for many cases, it adds only 2 KB to the bundle’s size, so there is not even any need to implement dynamic code-loading for outdated browsers, which makes the overall solution simpler. Feel free to fork and extend it if you think this approach would work for you.

Conclusion Link

Well, now you might feel that things are becoming too complicated, and you might be tempted to implement everything yourself. I did that once; I wouldn’t recommend it. Eventually, you will arrive at the same ideas behind React Intl’s implementation, or, worse, you might think there are not many options to make certain things better or to do things differently. You might think you can solve the Intl API support issue by relying on Moment.js18 instead (I won’t mention other libraries with the same functionality because they are either unsupported or unusable). Fortunately, I tried that, so I can save you a lot of time. I’ve learned that Moment.js is a monolith and very heavy, so while it might work for some folks, I wouldn’t recommend it. Developing your own polyfill doesn’t sound great because you will surely have to fight with bugs and support the solution for quite some time. The bottom line is that there is no perfect solution at the moment, so choose the one that suits you best.

(If you feel lost at some point or something doesn’t work as expected, check the “solution” branch of my repository19.)

Hopefully, this article has given you all of the knowledge needed to build an internationalized React front-end application. You should now know how to detect the user’s locale, save it in the cookie, let the user change their locale, translate the user interface, and render currencies, DateTimes and Numbers in the appropriate formats! You should also now be aware of some traps and issues you might face, so choose the option that fits your requirements, bundle-size budget and number of languages to support.

(rb, al, il, vf)

Footnotes Link

  1. 1 https://github.com/yury-dymov/smashing-react-i18n
  2. 2 http://localhost:3001
  3. 3 https://github.com/yahoo/react-intl
  4. 4 https://medium.com/@franleplant/react-higher-order-components-in-depth-cf9032ee6c3e#.zb3t19yyx
  5. 5 https://github.com/yury-dymov/smashing-react-i18n/blob/solution/scripts/translate.js
  6. 6 https://www.smashingmagazine.com/wp-content/uploads/2017/01/AJAX-request-large-opt.png
  7. 7 https://www.smashingmagazine.com/wp-content/uploads/2017/01/AJAX-request-large-opt.png
  8. 8 https://github.com/yahoo/react-intl/wiki/Components
  9. 9 https://www.smashingmagazine.com/wp-content/uploads/2017/01/universal-rendering-is-broken-large-opt.png
  10. 10 https://www.smashingmagazine.com/wp-content/uploads/2017/01/universal-rendering-is-broken-large-opt.png
  11. 11 https://github.com/nodejs/node/wiki/Intl
  12. 12 https://www.smashingmagazine.com/wp-content/uploads/2017/01/intl-browser-support-large-opt.png
  13. 13 https://www.smashingmagazine.com/wp-content/uploads/2017/01/intl-browser-support-large-opt.png
  14. 14 https://github.com/andyearnshaw/Intl.js
  15. 15 https://github.com/andyearnshaw/Intl.js/
  16. 16 https://github.com/andyearnshaw/Intl.js/issues/124
  17. 17 https://github.com/yury-dymov/intl-polyfill
  18. 18 http://momentjs.com/
  19. 19 https://github.com/yury-dymov/smashing-react-i18n/tree/solution

↑ Back to topTweet itShare on Facebook

More Than Just Pretty: How Imagery Drives User Experience

Sponsored ArticleMore Than Just Pretty: How Imagery Drives User Experience

As the saying goes, “A picture is worth a thousand words.” Human beings are highly visual creatures who are able to process visual information almost instantly; 90 percent1 of all information that we perceive and that gets transmitted to our brains is visual. Images can be a powerful way to capture users’ attention and differentiate your product. A single image can convey more to the observer than an elaborate block of text. Furthermore, images can cross language barriers in a way text simply can’t.

Images are more than just decoration; they have the power to make or break a user’s experience. In this article, we’ll cover a good number of useful principles and best practices that will help you successfully integrate imagery into your designs. If you’d like to bring your app or website to life with little effort, you can download and test Adobe XD2for free.

Further Reading on SmashingMag: Link

Only Use Relevant Images Link

Every image has a story to tell. Just like it is with writing, it’s better if you know what you want to say before you begin. Compelling images have a unique ability to inspire and engage your audience, but not all images improve the experience. Some of them just take up space or, in the worst case, confuse the user. One of the most dangerous elements in any design is imagery that conveys the wrong message.

6
Images that aren’t related to the topic often cause confusion. (Image credit7) (Large preview8)

Users react to visuals faster than text, so make sure your content matches the supporting visuals. You should select images that have a strong relationship with your product goals and ensure that they are context-relevant.

Images Shouldn’t Create A Visual Noise Link

The principle “more is better” doesn’t apply to images. Don’t put a lot of effort in creating purely decorative images because people usually ignore such images. Instead, choose images that showcase the purpose of your product. Use limited number of striking visuals in your designs — the ones that really capture users’ attention.

Use High-Quality Assets Without Distortion Link

Make sure your images are appropriately sized for displays across all platforms. Images shouldn’t appear pixelated, so be sure to test appropriate resolution sizes for specific ratios and devices. Display photos and graphics in their original aspect ratio, and don’t scale them greater than 100%. You don’t want the artwork or graphics in your product to look skewed, too small or too large.

psdistort9
Left: Degraded imagery. Right: Correct resolution. (Image credit10) (Large preview11)

Responsive websites and mobile apps often struggle with selecting image resolutions that best match the various user devices. It’s quite clear that one image for all screen resolutions and different devices is not enough. However, an image per pixel is too much; cropping images one at a time can be overwhelming especially if you have a ton of images.

So, how can someone automatically choose the optimal responsive image sizes? Hopefully, there are online tools that allow you to manage multiple sizes for an entire folder of images. One of them is Cloudinary1412 which enables you to interactively generate responsive image breakpoints. This tool uses advanced algorithms to easily generate best matching breakpoints for each uploaded image; images are analyzed to find the best breakpoints on an image by image basis, rather than creating all possible image resolutions.

13
Cloudinary1412 is a cloud-based service which is used to batch, crop and resize images. (Large preview15)

Image-Focussed Design Isn’t For Every Page Link

Getting people’s attention with aesthetically pleasing images certainly has value, but it comes at the price of making other elements harder to see and use.

Putting too much focus on images in your designs may create a visual overkill that can seriously distract users from meaningful engagement with your content. You can see this effect in SoundCloud’s app in which the image takes all the attention and you barely notice the two buttons.

16
Screen buttons are overshadowed by the image in Soundcloud’17s home view.

Although image-focused design is appropriate in some cases (e.g. Apple’s homepage), the vast majority of apps and sites should follow a balanced approach — images that are used in user interfaces should support the product, but not obscure other important content or overshadow functionality.

Use Multiple Mediums Link

Both illustration and photography can be used within the same product.

  • Photography is ideal to showcase specific entities and stories. For example, if we need to show not just any flower, but in particular a rose:
  • redrose18
    For specific entities, use photographic representations. (Image credit3528252219) (Large preview20)
  • Illustration is effective for representing concepts and metaphors, where photography might be alienating.
  • flower21
    Illustration conveys an approximation of content to aid comprehension when total specificity isn’t required. (Image credit3528252219) (Large preview23)

Have A Point Of Focus Link

Imagery is a visual communication tool that conveys your message. A clear focus communicates the concept at a glance, whereas a lack of focus makes the image meaningless.

When the point of focus is obscured, the iconic quality of the image is lost:

planesinsun24
Don’t. A lack of focus makes the image meaningless. (Image credit3528252219) (Large preview26)

Avoid making the user hunt for the meaning in the image and ensure that a clear concept is conveyed to the user in a memorable way.

airplane27
Do. A clear focus communicates the concept at a glance. (Image credit3528252219) (Large preview29)

Try to minimize distraction and focus on meaningful elements in your images.

Show Real People Link

Human images are a very effective way to get your users engaged. When we see faces of other humans, it makes us feel like we are actually connecting with them, and not just using a product. However, many corporate sites are notorious for the overuse of insincere photography which is employed to “build trust.”

family30
Don’t. Inauthentic images leaves the user with a sense of shallow, false pretense. (Image credit31)

U32sability tests33 show that purelydecorative photos rarely add value to the design and more often harm than improve the user experience. Users usually overlook such images and might even get frustrated by them.

A very simple rule of thumb is to use high-quality photographs of people who match your app’s or website’s character. Imagery you use should be an authentic representation of your product, company or culture.

fatherdaughter34
Do. Show real, down-to earth people and make sure that they really match your product’s characters. (Image credit3528252219) (Large preview36)

Tips: Link

  • Try to avoid crowd shots; use photos that have a single main subject instead.
  • Strive for images that represent genuine stories. Take photos of your people doing interesting things. If you have a product, consider ways they can interact with that product.

Blend Images With Designs Link

When using images in your design, ask yourself if the images you’re taking will match the aesthetic of your app or website. The homepage for Squarespace37 is a good example of focus on imagery. It’s elegant, clean and uses a huge amount of white space and large, full-screen images to create a bold design that grabs your attention.

38
It’s important to choose pictures that fit the theme of the experiences we create. (Large preview39)

Improve Your E-Commerce Design Link

The product image sells the item. Users often rely on the product image to assess product and it’s features. Regardless of your product, whether it be headphones or toys, product photography is the most important element of any e-commerce website. Ultimately, the more attractive your products look to visitors, the more confident they’ll feel about purchasing from you, and the better your conversion rate will be.

40
The image should be used to get a feel for the product. (Image credit41) (Large preview42)

Make product images beautiful. A good image does all the hard work for you: It captures users’ attention and differentiates your product. However, good product photography requires work. Consider reading the article “Improve Your E-Commerce Design With Brilliant Product Photos43” on how to take quality photographs of your products.

Let products sell themselves. Consider the Gorilla Pod44 example shown below. The photo demonstrates brilliantly the benefits of the product.

45
Large preview46

Display the primary image above the fold. Don’t make users scroll in order to see the main image for a product. The main product image should be anchored in a prominent position in order to merchandise your priority offerings.

For the image to be effective it needs to be big — as big as you can make it. Then, when you’ve maxed out the size of your image, you need to integrate the ability to zoom in on specific details of the product. This is especially important for products like apparel where users are more concerned with detail. The zoomed-in images also need to maintain high quality.

47
Don’t. Zoomed-in view forces the user to look at a specific part. (Image credit5048)
49
Do. Put users in control by allowing them to zoom in as they prefer (both depth and area of zoom is controlled by the user). (Image credit5048)

Express Personality And Trigger User Emotions Link

Imagery can convey the essence of a product or service, but it can surprise and delight, too. Images have the capacity to entertain as much as to inform. If you already have a satisfying customer experience, adding delight to your product helps create an emotional connection with your users. Emotionally powerful imagery is a factor in ensuring that users continue to delve into your experience.

51
Imagery is able to evoke emotional responses in the viewer. A dash of humor can ease the burden and your users might love it. (Image credit52) (Large preview53)

The emotional brain is affected by photos and illustrations, especially of people, and by stories. Speaking about illustrations, even sites or apps that don’t incorporate the drawn style throughout still can use cartoons for these purposes. For example, illustrations can be used for instructions, tutorials and empty states.

54
Choose striking images that capture attention and express personal relevance. (Image credit55) (Large preview56)

Real-Life Scenario: How To Pick Images For Landing Page That Serves A Purpose Well Link

Landing pages are essentially your shop window and in most cases you have only one chance to impress the user. When it comes to landing pages, you want your visitors to have just one task on your page: to convert. Great landing pages are built around solid user experiences and imagery plays important role in building this experience. When users come to your page, they’ll have some kind of reaction. Whether it’s positive or negative, in large part, is determined by what they see.

Following the advice “show, don’t tell” and:

  1. Choose imagery that fits your message.

    It’s important to choose images that can simply explain the concept of the product or service. That doesn’t mean that the image needs to say everything — the image seen alone might not even seem to be clear, but it should logically fit when it’s connected to everything else on the page. It should visually reinforce the message you try to deliver to visitors.
  2. Show images in the right place.

    If the image supports a high priority goal, it should have more visual emphasis; conversely, images related to secondary goals should have less emphasis. The most important images should be anchored in a prominent position (i.e. above the fold), and should be a primary point of focus.
  3. Choose striking visuals that capture attention.

    Focus on selecting the most compelling images you can find. As Steven Snell mentioned, “A vivid, striking image will last in the minds of visitors. Text may be read and forgotten, but a strong image will be remembered.”
  4. Use emotionally powerful imagery.

    Your images should be emotionally persuasive — have an emotional impact and reinforce the feelings you are trying to create. After all, emotion often overrides logic when it comes to decision making.

Below is an example of landing page by Intercom57, a service that allows you to communicate with your customers more efficiently. The landing page takes a reasonably complex idea and makes it easy to understand how the product works, and why it might be beneficial.

58
Intercom uses illustration to compare the the old way of working, versus a simple approach. (Large preview59)

Conclusion Link

Thinking about images in terms of their usability is important. All visual communication in your design leaves a cumulative impression on the user.

Compelling images have a unique ability to inspire and engage your audience to provide useful information. Take the time to make every image in your app or site reinforce user experience.

Recommended Reading Link

This article is part of the UX design series sponsored by Adobe. The newly introduced Experience Design app63 is made for a fast and fluid UX design process, creating interactive navigation prototypes, as well as testing and sharing them — all in one place.

You can check out more inspiring projects created with Adobe XD on Behance64, and also visit the Adobe XD blog to stay updated and informed. Adobe XD is being updated with new features frequently, and since it’s in public Beta, you can download and test it for free65.

(ms, vf, yk, il)

Footnotes Link

  1. 1 https://www.smashingmagazine.com/2011/10/the-dos-and-donts-of-infographic-design/
  2. 2 https://adobe.ly/2iHiSBS
  3. 3 https://www.smashingmagazine.com/2016/10/in-app-gestures-and-mobile-app-user-experience/
  4. 4 https://www.smashingmagazine.com/2016/12/best-practices-for-animated-progress-indicators/
  5. 5 https://www.smashingmagazine.com/2016/10/designing-card-based-user-interfaces/
  6. 6 https://www.smashingmagazine.com/wp-content/uploads/2017/01/1-large-opt.jpg
  7. 7 http://hubpages.com/business/11-Vintage-Food-Ads-Featuring-Creepy-Soulless-Children
  8. 8 https://www.smashingmagazine.com/wp-content/uploads/2017/01/1-large-opt.jpg
  9. 9 https://www.smashingmagazine.com/wp-content/uploads/2016/12/psdistort-large-opt.png
  10. 10 https://www.adobe.com/products/photoshop.html?promoid=KLXLS
  11. 11 https://www.smashingmagazine.com/wp-content/uploads/2016/12/psdistort-large-opt.png
  12. 12 http://www.responsivebreakpoints.com/
  13. 13 https://www.smashingmagazine.com/wp-content/uploads/2017/01/4-large-opt.png
  14. 14 http://www.responsivebreakpoints.com/
  15. 15 https://www.smashingmagazine.com/wp-content/uploads/2017/01/4-large-opt.png
  16. 16 https://www.smashingmagazine.com/wp-content/uploads/2017/01/5-preview-opt.png
  17. 17 https://soundcloud.com/
  18. 18 https://www.smashingmagazine.com/wp-content/uploads/2016/12/redrose-large-opt.png
  19. 19 https://stock.adobe.com/
  20. 20 https://www.smashingmagazine.com/wp-content/uploads/2016/12/redrose-large-opt.png
  21. 21 https://www.smashingmagazine.com/wp-content/uploads/2016/12/flower-large-opt.png
  22. 22 https://stock.adobe.com/
  23. 23 https://www.smashingmagazine.com/wp-content/uploads/2016/12/flower-large-opt.png
  24. 24 https://www.smashingmagazine.com/wp-content/uploads/2016/12/planesinsun-large-opt.png
  25. 25 https://stock.adobe.com/
  26. 26 https://www.smashingmagazine.com/wp-content/uploads/2016/12/planesinsun-large-opt.png
  27. 27 https://www.smashingmagazine.com/wp-content/uploads/2016/12/airplane-large-opt.png
  28. 28 https://stock.adobe.com/
  29. 29 https://www.smashingmagazine.com/wp-content/uploads/2016/12/airplane-large-opt.png
  30. 30 https://www.smashingmagazine.com/wp-content/uploads/2016/12/family-preview-opt.png
  31. 31 https://material.google.com/
  32. 32 https://articles.uie.com/deciding_when_graphics_help/
  33. 33 https://articles.uie.com/deciding_when_graphics_help/
  34. 34 https://www.smashingmagazine.com/wp-content/uploads/2016/12/fatherdaughter-large-opt.png
  35. 35 https://stock.adobe.com/
  36. 36 https://www.smashingmagazine.com/wp-content/uploads/2016/12/fatherdaughter-large-opt.png
  37. 37 https://www.squarespace.com/
  38. 38 https://www.smashingmagazine.com/wp-content/uploads/2017/01/12-large-opt.png
  39. 39 https://www.smashingmagazine.com/wp-content/uploads/2017/01/12-large-opt.png
  40. 40 https://www.smashingmagazine.com/wp-content/uploads/2017/01/13-large-opt.png
  41. 41 https://dribbble.com/mutlu82
  42. 42 https://www.smashingmagazine.com/wp-content/uploads/2017/01/13-large-opt.png
  43. 43 https://www.smashingmagazine.com/2010/08/improve-your-e-commerce-design-with-brilliant-product-photos/
  44. 44 http://joby.com/gorillapod
  45. 45 https://www.smashingmagazine.com/wp-content/uploads/2017/01/14-large-opt.png
  46. 46 https://www.smashingmagazine.com/wp-content/uploads/2017/01/14-large-opt.png
  47. 47 https://www.smashingmagazine.com/wp-content/uploads/2017/01/15-preview-opt.png
  48. 48 https://www.thinkwithgoogle.com/
  49. 49 https://www.smashingmagazine.com/wp-content/uploads/2017/01/16-preview-opt.png
  50. 50 https://www.thinkwithgoogle.com/
  51. 51 https://www.smashingmagazine.com/wp-content/uploads/2017/01/17-large-opt.png
  52. 52 https://basecamp.com/
  53. 53 https://www.smashingmagazine.com/wp-content/uploads/2017/01/17-large-opt.png
  54. 54 https://www.smashingmagazine.com/wp-content/uploads/2017/01/18-large-opt.png
  55. 55 http://emptystat.es/
  56. 56 https://www.smashingmagazine.com/wp-content/uploads/2017/01/18-large-opt.png
  57. 57 http://intercom.com
  58. 58 https://www.smashingmagazine.com/wp-content/uploads/2017/01/19-large-opt.png
  59. 59 https://www.smashingmagazine.com/wp-content/uploads/2017/01/19-large-opt.png
  60. 60 https://articles.uie.com/deciding_when_graphics_help/
  61. 61 https://www.smashingmagazine.com/2010/06/how-to-use-photos-to-sell-more-online/
  62. 62 https://www.nngroup.com/articles/image-focused-design/
  63. 63 https://adobe.ly/2iHiSBS
  64. 64 http://adobe.ly/1U9LS0E
  65. 65 https://adobe.ly/2iHiSBS

↑ Back to topTweet itShare on Facebook

How To Design Eye-Catching App Icons

How To Design Eye-Catching App Icons

Creating that singular piece of graphic design1 that users will first interact with each time they encounter your product can be intimidating. A beautiful, identifiable and memorable app icon can have a huge impact on the popularity and success of the app. But how exactly does one make a “good” app icon? What does that even mean? Fear not, I’ve put together some tips and advice to help answer these questions and to guide you on your way to designing great app icons.

I’ve been designing2, making resources3 and giving talks4 about icon design for the past couple of years. In this article, and in the video at the end, I’ll sum up what I’ve learned about this amazing craft.

Further Reading on SmashingMag: Link

What Is An App Icon? Link

The first things you need to understand when setting out to create an icon is what exactly an app icon is and what job it performs. An app icon is a visual anchor for your product. Think of it as a tiny piece of branding that not only needs to look attractive and stand out, but ideally also communicates the essence of your application.

The word “logo” is thrown around carelessly these days. App icons are not logos. While they certainly share branding-like qualities, they’re under a lot of different restrictions. It’s an important distinction for a designer to make: Logos are scalable vector pieces of branding designed for letterheads and billboards. Icons are most often raster-based outputs customized to look good within a square canvas, at specific sizes and in specific contexts. The approach, the tools, the job and, therefore, the criteria for success are different.

9
App icon packages consist of a range of sizes. Get this template from Apply Pixels211210. (View large version11)

From a practical standpoint, when you’re making an app icon, you are creating a set of PNG files in multiple sizes — ranging from small sizes like 29 × 29 pixels all the way up to 1024 × 1024 pixels — that need to be bundled with your app. This set of carefully crafted designs will be used in the many contexts of the operating system where users will encounter your application — including the iOS App Store and Google Play, the settings panel, the search results and the home screen.

App icons can essentially be made in any application capable of producing raster files, but common choices are Photoshop, Illustrator and Sketch. Tools like the ones found on Apply Pixels211210 offer clever PSD templates that can help you get off the ground quickly.

A short video demonstrating how to use one of the templates on Apply Pixels

The Five Core Aspects Link

Now, let’s look at some of the best practices in designing app icons. I’ll discuss each of my five core aspects of app icon design, give tips on how to improve each aspect and show off some examples of how I’ve worked with that quality. A lot of these examples will be based on my own work. That’s not because I feel like it is the best or only way to illustrate these things, but it has the added benefit of my knowing what thoughts went into the process. When going through the aspects, try to imagine icons that you like and how the individual aspects take shape in the icons on your home screen. Let’s get started.

1. Scalability Link

One of the most important aspects of an icon is scalability. Because the icon is going to be shown in several places throughout the platform, and at several sizes, it’s important that your creation maintains its legibility and uniqueness. It needs to look good in the App Store, on “Retina” devices and even in the settings panel.

13
An app icon needs to work at multiple resolutions, retaining the legibility of the concept across the range of sizes.

Overly complicated icons that cram too much into the canvas often fall victim to bad scalability. A very big part of the conceptual stage of app icon design should be dedicated to thinking about whether a given design will scale gracefully.

How to Improve Scalability Link

  • Working on a 1024 × 1024-pixel canvas can be deceptive. Try out the design on the device and in multiple contexts and sizes.
  • Embrace simplicity and focus on a single object, preferably a unique shape or element that retains its contours and qualities when scaled.
  • Make sure the icon looks good against a variety of backgrounds.
14
A few icons I’ve made with scalability in mind.

2. Recognizability Link

An app icon is like a little song, and being able to identify it easily amidst the noise of the store and the home screen is a key component in great icon design. Just as the verse of a song needs to resonate with the listener, so do the shapes, colors and ideas of an app icon. The design needs to instill a memory and sense of connection on both a functional and an emotional level.

15
An icon can be detailed or simple; just make sure it’s creative and interesting and accurately conveys your intentions.

Your icon will be vying for attention among thousands of other icons, all of which have the same 1024-pixel canvas to make their impact and secure their connection with the viewer. While scalability is a huge part of recognizability, so is novelty. The search for balance between these qualities is the very crux of the discipline.

How to Improve Recognizability Link

  • Bland, overly complicated icons are the enemy of recognizability. Try removing details from your icon until the concept starts to deteriorate. Does this improve recognizability?
  • Try out several variations of your design. Line them up on a grid and glance over them, seeing which aspects of the designs catch your eye.
  • Deconstruct your favourite app icons and figure out why you like them and what methods were used to make them stand out.

3. Consistency Link

There’s something to be said for creating consistency between the experience of interacting with an app icon and interacting with the app it represents. I feel like good icon design is an extension of what the app is all about. Making sure the two support each other will create a more memorable encounter.

16
Consistency between icon and interface is important to strengthening the visual narrative.

Shaping a sleek, unified image of your app in the user’s mind increases product satisfaction, retention and virality. In short, getting your icon to work harmoniously with the essence, functionality and design of your application is a big win.

How to Improve Consistency Link

  • One way to ensure consistency between app and icon is to align their color palettes and to use a similar and consistent design language — a green interface reinforced by a green app icon, for example.
  • Although it’s not always possible, one way to tighten the connection between an app and its icon is to tie the symbolism of the icon directly to the functionality of the app.
17
Icons can also be made consistent across a suite of related apps.

4. Uniqueness Link

This almost goes without saying, but try to make something unique. Mimicking a style or a trend is perfectly fine, but make it your own. Your icon will be constantly competing with other icons for the user’s attention, and standing out can be a perfectly valid argument for a design.

18
The “Productivity” category in the iOS App Store is a great example of how uniqueness hasn’t entered the design process.

Uniqueness is a tricky part of design, because it relies not only on your skill but also on the choices of others who are tackling a similar task.

How to Improve Uniqueness Link

  • Consider what everyone else is doing in your space and go in a different direction. Always do your research — the world doesn’t need another checkmark icon.
  • A single glyph on a one-color background can be a tricky route to go down if you want to be unique. Play around with different colors and compositions, and challenge yourself to find new and clever metaphors.
  • Color is a great and often overlooked way to reframe a concept.
19
Whatever your design style, uniqueness is often an exercise in finding a novel idea.
20
Game icon design can be a great source of inspiration because there’s usually a broader range of ideas on display, free of convention.

5. Don’t Use Words Link

This is one of my all-time top pet peeves. Only on the rarest of occasions is it OK to use words in an app icon. If you have to retreat to another tool of abstraction — the written word — then I’d say you’re not using the full force of your pictorial arsenal.

Words and pictures are separate representational tools, and mixing them in what is supposed to be a graphical representation usually leads to an experience that is cluttered, unfocused and harder to decode. Is there really no better way to visualize the application than with dry words? Whenever I see words in an app icon, I feel like the designer missed an opportunity to clearly convey their intention.

What to Think About When You’re Considering Words in Icons Link

  • There’s no need to include the app’s name in the icon — it will usually accompany the icon in the interface. Instead, spend your time coming up with a cool pictorial concept.
  • “But Facebook has the ‘f’ in its app icon,” I hear you say. If you’re using a single letter and it’s a good (and unique) fit, then the letter will lose its “wordy” quality and become iconic. However, this is more often the exception than the rule.
  • Your company logo and name in a square is never a good solution. Do you have a mark or a glyph that works well within the constraints? If not, then you’d probably be best off coming up with something new. Remember that an icon is not the same as a logo and shouldn’t be forced into the same context.

Making Your Mark Link

The App Store and Google Play have many examples of bland and unopinionated icon design. Your icon is the strongest connection you’ll have with the user. It is what they’ll see first when they meet you in the App Store. It’s what they’ll interact with every single time they use your app. It is what they’ll think of when they think of the app. Anything short of a well-thought-out, fitting and attractive solution will be a failure of your greatest visual asset. Your app icon should not be an afterthought; it should be a working part of the process.

App icons are tiny little pieces of concentrated design, and the qualities of good iconography are universal: scalability, recognizability, consistency and uniqueness. Mastering these will spill over to other areas of your design. Becoming an iconist will make you a better designer.

Whether they’re detailed or simple, conventional or creative, good icons have one unifying property: They all grab people’s attention in the same limited amount of space, on a completely level playing field. It’s a specific challenge, and the answer is always within that same canvas.

Crowning your application with a singular piece of graphic design is no doubt intimidating, but I hope the tips outlined above will make you more confident in taking on the challenge. Now go forth and make a fantastic app icon!

Resources Link

In this article, I’ve used icon tools available to subscribing members of Apply Pixels211210, but many icon tools are out there, both free and paid. Icon design is one of my great passions, and if you’re hungry for more, I’ve made several videos and given a lot of talks on the subject. Below are two that elaborate on the theories behind this article.

In the video above, in roughly 10 minutes, I go through the five major aspects of app icon design and give real working examples of how I’ve worked on them. It’s packed full of stories, advice and pixels, and I hope there’s something in it for everybody — whether you’re about to make your first app icon or are a seasoned veteran.
In this one-hour neon-infused video, I go over some of my work and the concepts outlined in this article, and finally I give a demo on stage on improving an existing app icon.

(da, yk, al, il)

Footnotes Link

  1. 1 https://www.smashingmagazine.com/2016/03/inspiring-graphic-design/
  2. 2 http://pixelresort.com
  3. 3 https://applypixels.com
  4. 4 https://www.youtube.com/playlist?list=PLxpqfOFALZU8rKlftjcG42SOhhfIB33it
  5. 5 https://www.smashingmagazine.com/2016/05/easy-steps-to-better-logo-design/
  6. 6 https://www.smashingmagazine.com/2009/03/how-to-use-icons-to-support-content-in-web-design/
  7. 7 https://www.smashingmagazine.com/2016/10/icons-as-part-of-a-great-user-experience/
  8. 8 https://www.smashingmagazine.com/2009/06/50-fresh-useful-icon-sets-for-your-next-design/
  9. 9 https://www.smashingmagazine.com/wp-content/uploads/2016/12/appicontemplate-large-opt.jpg
  10. 10 https://applypixels.com
  11. 11 https://www.smashingmagazine.com/wp-content/uploads/2016/12/appicontemplate-large-opt.jpg
  12. 12 https://applypixels.com
  13. 13 https://www.smashingmagazine.com/wp-content/uploads/2016/12/scalability-preview-opt.jpg
  14. 14 https://www.smashingmagazine.com/wp-content/uploads/2016/12/scalability-examples-preview-opt.png
  15. 15 https://www.smashingmagazine.com/wp-content/uploads/2016/12/recognisability-preview-opt.jpg
  16. 16 https://www.smashingmagazine.com/wp-content/uploads/2016/12/consistency-preview-opt.jpg
  17. 17 https://www.smashingmagazine.com/wp-content/uploads/2016/12/photocookbook-preview-opt.png
  18. 18 https://www.smashingmagazine.com/wp-content/uploads/2016/12/uniqueness-preview-opt.png
  19. 19 https://www.smashingmagazine.com/wp-content/uploads/2016/12/unique1-preview-opt.png
  20. 20 https://www.smashingmagazine.com/wp-content/uploads/2016/12/unique2-preview-opt.png
  21. 21 https://applypixels.com

↑ Back to topTweet itShare on Facebook

Algorithm-Driven Design: How Artificial Intelligence Is Changing Design

Algorithm-Driven Design: How Artificial Intelligence Is Changing Design

I’ve been following the idea of algorithm-driven design for several years now and have collected some practical examples. The tools of the approach can help us to construct a UI, prepare assets and content, and personalize the user experience. The information, though, has always been scarce and hasn’t been systematic.

However, in 2016, the technological foundations of these tools became easily accessible, and the design community got interested in algorithms, neural networks and artificial intelligence (AI). Now is the time to rethink the modern role of the designer.

1
Album covers processed through Prisma and Glitché (View large version2)

Will Robots Replace Designers? Link

One of the most impressive promises of algorithm-driven design was given by the infamous CMS The Grid3. It chooses templates and content-presentation styles, and it retouches and crops photos — all by itself. Moreover, the system runs A/B tests to choose the most suitable pattern. However, the product is still in private beta, so we can judge it only by its publications and ads.

The Designer News community found real-world examples of websites created with The Grid, and they had a mixed reaction4 — people criticized the design and code quality. Many skeptics opened a champagne bottle on that day.

5
The Grid CMS (View large version6)

The idea to fully replace a designer with an algorithm sounds futuristic, but the whole point is wrong. Product designers help to translate a raw product idea into a well-thought-out user interface, with solid interaction principles and a sound information architecture and visual style, while helping a company to achieve its business goals and strengthen its brand.

Designers make a lot of big and small decisions; many of them are hardly described by clear processes. Moreover, incoming requirements are not 100% clear and consistent, so designers help product managers solve these collisions — making for a better product. It’s much more than about choosing a suitable template and filling it with content.

However, if we talk about creative collaboration, when designers work “in pair” with algorithms to solve product tasks, we see a lot of good examples and clear potential. It’s especially interesting how algorithms can improve our day-to-day work on websites and mobile apps.

Creative Collaboration With Algorithms Link

Designers have learned to juggle many tools and skills to near perfection, and as a result, a new term emerged, “product designer7.” Product designers are proactive members of a product team; they understand how user research works, they can do interaction design and information architecture, they can create a visual style, enliven it with motion design, and make simple changes in the code for it. These people are invaluable to any product team.

However, balancing so many skills is hard — you can’t dedicate enough time to every aspect of product work. Of course, a recent boon of new design tools has shortened the time we need to create deliverables and has expanded our capabilities. However, it’s still not enough. There is still too much routine, and new responsibilities eat up all of the time we’ve saved. We need to automate and simplify our work processes even more. I see three key directions for this:

  • constructing a UI,
  • preparing assets and content,
  • personalizing the UX.

I’ll show you some examples and propose a new approach for this future work process.

Constructing A UI Link

Publishing tools such as Medium, Readymag and Squarespace have already simplified the author’s work — countless high-quality templates will give the author a pretty design without having to pay for a designer. There is an opportunity to make these templates smarter, so that the barrier to entry gets even lower.

For example, while The Grid is still in beta, a hugely successful website constructor, Wix, has started including algorithm-driven features. The company announced Advanced Design Intelligence8, which looks similar to The Grid’s semi-automated way of enabling non-professionals to create a website. Wix teaches the algorithm by feeding it many examples of high-quality modern websites. Moreover, it tries to make style suggestions relevant to the client’s industry. It’s not easy for non-professionals to choose a suitable template, and products like Wix and The Grid could serve as a design expert.

 

Introducing Wix Artificial Design Intelligence
Surely, as in the case of The Grid, rejecting designers from the creative process leads to clichéd and mediocre results (even if it improves overall quality). However, if we consider this process more like “paired design” with a computer, then we can offload many routine tasks; for example, designers could create a moodboard on Dribbble or Pinterest, then an algorithm could quickly apply these styles to mockups and propose a suitable template. Designers would become art directors to their new apprentices, computers.

Of course, we can’t create a revolutionary product in this way, but we could free some time to create one. Moreover, many everyday tasks are utilitarian and don’t require a revolution. If a company is mature enough and has a design system9, then algorithms could make it more powerful.

For example, the designer and developer could define the logic that considers content, context and user data; then, a platform would compile a design using principles and patterns. This would allow us to fine-tune the tiniest details for specific usage scenarios, without drawing and coding dozens of screen states by hand. Florian Schulz shows how you can use the idea of interpolation10 to create many states of components.

11
Florian Schultz Interpolation (Large preview12)

My interest in algorithm-driven design sprung up around 2012, when my design team at Mail.Ru Group required an automated magazine layout. Existing content had a poor semantic structure, and updating it by hand was too expensive. How could we get modern designs, especially when the editors weren’t designers?

Well, a special script would parse an article. Then, depending on the article’s content (the number of paragraphs and words in each, the number of photos and their formats, the presence of inserts with quotes and tables, etc.), the script would choose the most suitable pattern to present this part of the article. The script also tried to mix patterns, so that the final design had variety. It would save the editors time in reworking old content, and the designer would just have to add new presentation modules. Flipboard launched a very similar model13 a few years ago.

Vox Media made a home page generator14 using similar ideas. The algorithm finds every possible layout that is valid, combining different examples from a pattern library. Next, each layout is examined and scored based on certain traits. Finally, the generator selects the “best” layout — basically, the one with the highest score. It’s more efficient than picking the best links by hand, as proven by recommendation engines such as Relap.io15.

16
Vox’s home page generator (View large version17)

Preparing Assets And Content Link

Creating cookie-cutter graphic assets in many variations is one of the most boring parts of a designer’s work. It takes so much time and is demotivating, when designers could be spending this time on more valuable product work.

Algorithms could take on simple tasks such as color matching. For example, Yandex.Launcher uses an algorithm to automatically set up colors for app cards, based on app icons18. Other variables could be automatically set, such as changing text color according to the background color19, highlighting eyes in a photo to emphasize emotion20, and implementing parametric typography21.

22
Yandex.Launcher (View large version23)

Algorithms can create an entire composition. Yandex.Market uses a promotional image generator for e-commerce product lists (in Russian24). A marketer fills a simple form with a title and an image, and then the generator proposes an endless number of variations, all of which conform to design guidelines. Netflix went even further25 — its script crops movie characters for posters, then applies a stylized and localized movie title, then runs automatic experiments on a subset of users. Real magic! Engadget has nurtured a robot apprentice to write simple news articles about new gadgets26. Whew!

27
Netflix movie ads (View large version28)

Truly dark magic happens in neural networks. A fresh example, the Prisma app29, stylizes photos to look like works of famous artists. Artisto30 can process video in a similar way (even streaming video).

31
Prisma (View large version32)

 

Aristo app: example
However, all of this is still at an early stage. Sure, you could download an app on your phone and get a result in a couple of seconds, rather than struggle with some library on GitHub (as we had to last year); but it’s still impossible to upload your own reference style and get a good result without teaching a neural network. However, when that happens at last, will it make illustrators obsolete? I doubt it will for those artists with a solid and unique style. But it will lower the barrier to entry when you need decent illustrations for an article or website but don’t need a unique approach. No more boring stock photos!

For a really unique style, it might help to have a quick stylized sketch based on a question like, “What if we did an illustration of a building in our unified style?” For example, the Pixar artists of the animated movie Ratatouille tried to apply several different styles to the movie’s scenes and characters; what if a neural network made these sketches? We could also create storyboards and describe scenarios with comics (photos can be easily converted to sketches). The list can get very long.

Finally, there is live identity, too. Animation has become hugely popular in branding recently, but some companies are going even further. For example, Wolff Olins presented a live identity for Brazilian telecom Oi33, which reacts to sound. You just can’t create crazy stuff like this without some creative collaboration with algorithms.

 

Oi — Logo loop fundo cinza

Personalizing UX Link

One way to get a clear and well-developed strategy is to personalize a product for a narrow audience segment or even specific users. We see it every day in Facebook newsfeeds, Google search results, Netflix and Spotify recommendations, and many other products. Besides the fact that it relieves the burden of filtering information from users, the users’ connection to the brand becomes more emotional when the product seems to care so much about them.

However, the key question here is about the role of designer in these solutions. We rarely have the skill to create algorithms like these — engineers and big data analysts are the ones to do it. Giles Colborne of CX Partners sees a great example in Spotify’s Discover Weekly feature: The only element of classic UX design here is the track list, whereas the distinctive work is done by a recommendation system that fills this design template with valuable music.

34
Spotify’s Discover Weekly feature (a slide from Giles Colborne’s presentation)

Colborne offers advice to designers35 about how to continue being useful in this new era and how to use various data sources to build and teach algorithms. It’s important to learn how to work with big data and to cluster it into actionable insights. For example, Airbnb learned how to answer the question, “What will the booked price of a listing be on any given day in the future?” so that its hosts could set competitive prices36. There are also endless stories about Netflix’s recommendation engine.

 

“Interaction designers vs. algorithms” by Giles Colborne (Source37)
A relatively new term, “anticipatory design38” takes a broader view of UX personalization and anticipation of user wishes. We already have these types of things on our phones: Google Now automatically proposes a way home from work using location history data; Siri proposes similar ideas. However, the key factor here is trust. To execute anticipatory experiences, people have to give large companies permission to gather personal usage data in the background.

I already mentioned some examples of automatic testing of design variations used by Netflix, Vox Media and The Grid. This is one more way to personalize UX that could be put onto the shoulders of algorithms. Liam Spradlin describes the interesting concept of mutative design39; it’s a well-though-out model of adaptive interfaces that considers many variables to fit particular users.

An Exoskeleton For Designers Link

I’ve covered several examples of algorithm-driven design in practice. What tools do modern designers need for this? If we look back to the middle of the last century, computers were envisioned as a way to extend human capabilities. Roelof Pieters and Samim Winiger have analyzed computing history and the idea of augmentation of human ability40 in detail. They see three levels of maturity for design tools:

  1. First-generation systems mimic analogue tools with digital means.
  2. The second generation is assisted creation systems, where humans and machines negotiate the creative process through tight action-feedback loops.
  3. The third generation is assisted creation systems 3.0, which negotiate the creative process in fine-grained conversations, augment creative capabilities and accelerate the acquisition of skills from novice to expert.
CreativeAI41
CreativeAI (Large preview42)

Algorithm-driven design should be something like an exoskeleton for product designers — increasing the number and depth of decisions we can get through. How might designers and computers collaborate?

The working process of digital product designers could potentially look like this:

  1. Explore a problem space, and pick the most valuable problem for the business and users to solve (analysis).
  2. Explore a solution space, and pick the best solution to fix the problem (analysis).
  3. Develop, launch and market a product that solves this problem (synthesis).
  4. Evaluate how the product works for real users, and optimize it (analysis and synthesis).
  5. Connect and unify the solution with other products and solutions of the company (synthesis).

These tasks are of two types: the analysis of implicitly expressed information and already working solutions, and the synthesis of requirements and solutions for them. Which tools and working methods do we need for each of them?

Analysis Link

Analysis of implicitly expressed information about users that can be studied with qualitative research is hard to automate. However, exploring the usage patterns of users of existing products is a suitable task. We could extract behavioral patterns and audience segments, and then optimize the UX for them. It’s already happening in ad targeting, where algorithms can cluster a user using implicit and explicit behavior patterns (within either a particular product or an ad network).

To train algorithms to optimize interfaces and content for these user clusters, designers should look into machine learning43. Jon Bruner gives44 a good example: A genetic algorithm starts with a fundamental description of the desired outcome — say, an airline’s timetable that is optimized for fuel savings and passenger convenience. It adds in the various constraints: the number of planes the airline owns, the airports it operates in, and the number of seats on each plane. It loads what you might think of as independent variables: details on thousands of flights from an existing timetable, or perhaps randomly generated dummy information. Over thousands, millions or billions of iterations, the timetable gradually improves to become more efficient and more convenient. The algorithm also gains an understanding of how each element of the timetable — the take-off time of Flight 37 from O’Hare, for instance — affects the dependent variables of fuel efficiency and passenger convenience.

In this scenario, humans curate an algorithm and can add or remove limitations and variables. The results can be tested and refined with experiments on real users. With a constant feedback loop, the algorithm improves the UX, too. Although the complexity of this work suggests that analysts will be doing it, designers should be aware of the basic principles of machine learning. O’Reilly published45 a great mini-book on the topic recently.

Synthesis Link

Two years ago, a tool for industrial designers named Autodesk Dreamcatcher46 made a lot of noise and prompted several publications from UX gurus47. It’s based on the idea of generative design, which has been used in performance, industrial design, fashion and architecture for many years now. Many of you know Zaha Hadid Architects; its office calls this approach “parametric design48.”

49
Autodesk Dreamcatcher (View large version50)

Logojoy51 is a product to replace freelancers for a simple logo design. You choose favorite styles, pick a color and voila, Logojoy generates endless ideas. You can refine a particular logo, see an example of a corporate style based on it, and order a branding package with business cards, envelopes, etc. It’s the perfect example of an algorithm-driven design tool in the real world! Dawson Whitfield, the founder, described machine learning principles behind it52.

53
Logojoy (Large preview54)

However, it’s not yet established in digital product design, because it doesn’t help to solve utilitarian tasks. Of course, the work of architects and industrial designers has enough limitations and specificities of its own, but user interfaces aren’t static — their usage patterns, content and features change over time, often many times. However, if we consider the overall generative process — a designer defines rules, which are used by an algorithm to create the final object — there’s a lot of inspiration. The working process of digital product designers could potentially look like this:

  1. An algorithm generates many variations of a design using predefined rules and patterns.
  2. The results are filtered based on design quality and task requirements.
  3. Designers and managers choose the most interesting and adequate variations, polishing them if needed.
  4. A design system runs A/B tests for one or several variations, and then humans choose the most effective of them.

It’s yet unknown how can we filter a huge number of concepts in digital product design, in which usage scenarios are so varied. If algorithms could also help to filter generated objects, our job would be even more productive and creative. However, as product designers, we use generative design every day in brainstorming sessions where we propose dozens of ideas, or when we iterate on screen mockups and prototypes. Why can’t we offload a part of these activities to algorithms?

Experiment by Jon Gold Link

The experimental tool Rene55 by Jon Gold, who worked at The Grid, is an example of this approach in action. Gold taught a computer to make meaningful typographic decisions56. Gold thinks that it’s not far from how human designers are taught, so he broke this learning process into several steps:

  1. Analyze glyphs to understand similarities in typefaces.
  2. Formulate basic guidelines for combining typefaces.
  3. Identify the best examples of type combinations to understand trends.
  4. Create algorithms to observe how great designers work.

His idea is similar to what Roelof and Samim say: Tools should be creative partners for designers, not just dumb executants.

57
Generative design by Jon Gold: Plausible combinations

Gold’s experimental tool Rene is built on these principles58. He also talks about imperative and declarative approaches to programming and says that modern design tools should choose the latter — focusing on what we want to calculate, not how. Jon uses vivid formulas to show how this applies to design and has already made a couple of low-level demos. You can try out the tool59 for yourself. It’s a very early concept but enough to give you the idea.

 

Rene — A Product Design Tool
While Jon jokingly calls this approach “brute-force design” and “multiplicative design,” he emphasizes the importance of a professional being in control. Notably, he left The Grid team earlier this year.

Do Tools Already Exist? Link

Unfortunately, there are no tools for product design for web and mobile that could help with analysis and synthesis on the same level as Autodesk Dreamcatcher does. However, The Grid and Wix could be considered more or less mass-level and straightforward solutions. Adobe is constantly adding features that could be considered intelligent: The latest release of Photoshop has a content-aware feature60 that intelligently fills in the gaps when you use the cropping tool to rotate an image or expand the canvas beyond the image’s original size.

 

Introducing Content-Aware Crop
There is another experiment by Adobe and University of Toronto. DesignScape61 automatically refines a design layout for you. It can also propose an entirely new composition.

 

DesignScape: Design with Interactive Layout Suggestions
You should definitely follow Adobe in its developments, because the company announced a smart platform named Sensei62 at the MAX 2016 conference. Sensei uses Adobe’s deep expertise in AI and machine learning, and it will be the foundation for future algorithm-driven design features in Adobe’s consumer and enterprise products. In its announcement63, the company refers to things such as semantic image segmentation (showing each region in an image, labeled by type — for example, building or sky), font recognition (i.e. recognizing a font from a creative asset and recommending similar fonts, even from handwriting), and intelligent audience segmentation.

However, as John McCarthy, the late computer scientist who coined the term “artificial intelligence,” famously said, “As soon as it works, no one calls it AI anymore.” What was once cutting-edge AI is now considered standard behavior for computers. Here are a couple of experimental ideas and tools64 that could become a part of the digital product designer’s day-to-day toolkit:

But these are rare and patchy glimpses of the future. Right now, it’s more about individual companies building custom solutions for their own tasks. One of the best approaches is to integrate these algorithms into a company’s design system. The goals are similar: to automate a significant number of tasks in support of the product line; to achieve and sustain a unified design; to simplify launches; and to support current products more easily.

Modern design systems started as front-end style guidelines, but that’s just a first step (integrating design into code used by developers). The developers are still creating pages by hand. The next step is half-automatic page creation and testing using predefined rules.

 

“Platform Thinking” by Yury Vetrov (Source67)

Pros And Cons Link

Should your company follow this approach?

Pros Link

If we look in the near term, the value of this approach is more or less clear:

  • Remove the routine of preparing assets and content, which is more or less mechanical work.
  • Broaden creative exploration, where a computer makes combinations of variables, while the designer filters results to find the best variations.
  • Optimize a user interface for narrow audience segments or even specific users.
  • Quickly adapt a design to various platforms and devices, though in a primitive way.
  • Experiment with different parts of a user interface or particular patterns — ideally, automatically.

Altogether, this frees the designer from the routines of both development support and the creative process, but core decisions are still made by them. A neat side effect is that we will better understand our work, because we will be analyzing it in an attempt to automate parts of it. It will make us more productive and will enable us to better explain the essence of our work to non-designers. As a result, the overall design culture within a company will grow.

Cons Link

However, all of these benefits are not so easy to implement or have limitations:

  • We can only talk about a company’s custom solutions in the context of the company’s own tasks. The work requires constant investment into development, support and enhancement.
  • As The Grid’s CMS shows, a tool alone can’t do miracles. Without a designer at the helm, its results will usually be mediocre. On the other hand, that’s true of most professional tools.
  • Breaking past existing styles and solutions becomes harder. Algorithm-driven design is based on existing patterns and rules.
  • Copying another designer’s work becomes easier if a generative design tool can dig through Dribbble.

There are also ethical questions: Is design produced by an algorithm valuable and distinct? Who is the author of the design? Wouldn’t generative results be limited by a local maximum? Oliver Roeder says68 that “computer art” isn’t any more provocative than “paint art” or “piano art.” The algorithmic software is written by humans, after all, using theories thought up by humans, using a computer built by humans, using specifications written by humans, using materials gathered by humans, in a company staffed by humans, using tools built by humans, and so on. Computer art is human art — a subset, rather than a distinction. The revolution is already happening, so why don’t we lead it?

Conclusion Link

This is a story of a beautiful future, but we should remember the limits of algorithms — they’re built on rules defined by humans, even if the rules are being supercharged now with machine learning. The power of the designer is that they can make and break rules; so, in a year from now, we might define “beautiful” as something totally different. Our industry has both high- and low-skilled designers, and it will be easy for algorithms to replace the latter. However, those who can follow and break rules when necessary will find magical new tools and possibilities.

Moreover, digital products are getting more and more complex: We need to support more platforms, tweak usage scenarios for more user segments, and hypothesize more. As Frog’s Harry West says, human-centered design has expanded from the design of objects (industrial design) to the design of experiences (encompassing interaction design, visual design and the design of spaces). The next step will be the design of system behavior: the design of the algorithms that determine the behavior of automated or intelligent systems. Rather than hire more and more designers, offload routine tasks to a computer. Let it play with the fonts.

(vf, il, al)

Footnotes Link

  1. 1 https://www.smashingmagazine.com/wp-content/uploads/2016/11/Cover-large-opt.jpg
  2. 2 https://www.smashingmagazine.com/wp-content/uploads/2016/11/Cover-large-opt.jpg
  3. 3 https://thegrid.io/
  4. 4 https://www.designernews.co/stories/65265-the-first-gridio-sites-have-surfaced-and-theyre-kinda-terrible
  5. 5 https://www.smashingmagazine.com/wp-content/uploads/2016/11/TheGrid-large-opt.png
  6. 6 https://www.smashingmagazine.com/wp-content/uploads/2016/11/TheGrid-large-opt.png
  7. 7 http://www.uxmatters.com/mt/archives/2015/02/applied-ux-strategy-part-2-the-product-designer.php
  8. 8 http://www.fastcodesign.com/3060934/can-you-teach-ai-to-design-wix-is-trying
  9. 9 http://www.uxmatters.com/mt/archives/2015/08/applied-ux-strategy-part-3-platform-thinking.php
  10. 10 https://medium.com/@getflourish/designing-with-intent-be6664b10ac
  11. 11 https://www.smashingmagazine.com/wp-content/uploads/2016/11/FlorianSchultzInterpolation.gif
  12. 12 https://www.smashingmagazine.com/wp-content/uploads/2016/11/FlorianSchultzInterpolation.gif
  13. 13 http://techcrunch.com/2014/03/23/layout-in-flipboard-for-web-and-windows/
  14. 14 http://product.voxmedia.com/2014/12/17/7405131/algorithmic-design-how-vox-picks-a-winning-layout-out-of-thousands
  15. 15 https://relap.io/en
  16. 16 https://www.smashingmagazine.com/wp-content/uploads/2016/11/VoxChorus-large-opt.png
  17. 17 https://www.smashingmagazine.com/wp-content/uploads/2016/11/VoxChorus-large-opt.png
  18. 18 https://translate.google.com/translate?hl=en&sl=ru&tl=en&u=https%3A%2F%2Fmedium.com%2F%40mishanikin%2F%25D0%25BE%25D1%2587%25D0%25B5%25D0%25BD%25D1%258C-%25D0%25BF%25D1%2580%25D0%25BE%25D1%2581%25D1%2582%25D0%25BE%25D0%25B9-%25D0%25B0%25D0%25BB%25D0%25B3%25D0%25BE%25D1%2580%25D0%25B8%25D1%2582%25D0%25BC-%25D0%25BF%25D0%25BE%25D0%25B4%25D0%25B1%25D0%25BE%25D1%2580%25D0%25B0-%25D1%2586%25D0%25B2%25D0%25B5%25D1%2582%25D0%25B0-%25D0%25BA%25D0%25BE%25D1%2582%25D0%25BE%25D1%2580%25D1%258B%25D0%25B9-%25D1%2580%25D0%25B0%25D0%25B1%25D0%25BE%25D1%2582%25D0%25B0%25D0%25B5%25D1%2582-98b8f0dcfdc5
  19. 19 http://thesassway.com/intermediate/dynamically-change-text-color-based-on-its-background-with-sass
  20. 20 http://berglondon.com/blog/2012/08/01/headliner/
  21. 21 http://alistapart.com/blog/post/variable-fonts-for-responsive-design
  22. 22 https://www.smashingmagazine.com/wp-content/uploads/2016/11/YandexLauncherColor-large-opt.png
  23. 23 https://www.smashingmagazine.com/wp-content/uploads/2016/11/YandexLauncherColor-large-opt.png
  24. 24 https://translate.google.com/translate?hl=en&sl=ru&tl=en&u=https%3A%2F%2Fevents.yandex.ru%2Flib%2Ftalks%2F3532%2F&sandbox=1
  25. 25 http://techblog.netflix.com/2016/03/extracting-image-metadata-at-scale.html
  26. 26 https://www.engadget.com/2016/08/15/robot-journalism-wordsmith-writer/
  27. 27 https://www.smashingmagazine.com/wp-content/uploads/2016/11/Netflix-large-opt.png
  28. 28 https://www.smashingmagazine.com/wp-content/uploads/2016/11/Netflix-large-opt.png
  29. 29 http://prisma-ai.com/
  30. 30 http://artisto.my.com/
  31. 31 https://www.smashingmagazine.com/wp-content/uploads/2016/11/PrismaAI-large-opt.png
  32. 32 https://www.smashingmagazine.com/wp-content/uploads/2016/11/PrismaAI-large-opt.png
  33. 33 http://www.fastcodesign.com/3059059/the-ultimate-responsive-logo-reacts-to-the-sound-of-your-voice
  34. 34 https://www.smashingmagazine.com/wp-content/uploads/2016/11/SpotifyDiscoverWeekly-opt.png
  35. 35 https://www.cxpartners.co.uk/our-thinking/interaction-design-in-the-age-of-algorithms/
  36. 36 http://airbnb.design/invisible-design/
  37. 37 http://www.slideshare.net/cxpartners/algorithms-slideshare
  38. 38 https://www.smashingmagazine.com/2015/09/anticipatory-design/
  39. 39 https://medium.com/project-phoebe
  40. 40 https://medium.com/@ArtificialExperience/creativeai-9d4b2346faf3
  41. 41 https://www.smashingmagazine.com/wp-content/uploads/2016/11/CreativeAI.gif
  42. 42 https://www.smashingmagazine.com/wp-content/uploads/2016/11/CreativeAI.gif
  43. 43 http://www.r2d3.us/visual-intro-to-machine-learning-part-1/
  44. 44 https://www.oreilly.com/ideas/artificial-intelligence-and-the-future-of-design
  45. 45 http://www.oreilly.com/design/free/machine-learning-for-designers.csp
  46. 46 https://autodeskresearch.com/projects/dreamcatcher
  47. 47 http://radar.oreilly.com/2014/05/the-automation-of-design.html
  48. 48 http://www.patrikschumacher.com/Texts/Parametricism%20-%20A%20New%20Global%20Style%20for%20Architecture%20and%20Urban%20Design.html
  49. 49 https://www.smashingmagazine.com/wp-content/uploads/2016/11/AutodeskDreamcatcher-large-opt.png
  50. 50 https://www.smashingmagazine.com/wp-content/uploads/2016/11/AutodeskDreamcatcher-large-opt.png
  51. 51 http://logojoy.com/
  52. 52 https://www.indiehackers.com/businesses/logojoy
  53. 53 https://www.smashingmagazine.com/wp-content/uploads/2016/12/logojoy-large-opt.png
  54. 54 https://www.smashingmagazine.com/wp-content/uploads/2016/12/logojoy-large-opt.png
  55. 55 http://rene.jon.gold/
  56. 56 http://www.jon.gold/2016/05/robot-design-school/
  57. 57 https://www.smashingmagazine.com/wp-content/uploads/2016/11/robot-design-school-selection-opt.png
  58. 58 http://www.jon.gold/2016/06/declarative-design-tools/
  59. 59 http://rene.jon.gold/
  60. 60 https://www.youtube.com/watch?v=1DoCQMelAMM
  61. 61 http://www.dgp.toronto.edu/~donovan/design/index.html
  62. 62 http://www.adobe.com/ru/sensei.html
  63. 63 https://blogs.adobe.com/conversations/2016/11/adobe-sensei.html
  64. 64 http://www.creativeai.net/
  65. 65 https://www.subtraction.com/2016/06/17/hand-drawn-rendering-of-3d-objects-and-animation/
  66. 66 http://www.fastcodesign.com/3052463/microsoft-research-debuts-autocomplete-for-animation-and-its-incredible
  67. 67 http://www.slideshare.net/jvetrau/amuse-ux-2015-yvetrov-platform-thinking
  68. 68 https://aeon.co/ideas/there-is-no-such-thing-as-computer-art-it-s-all-just-art

↑ Back to topTweet itShare on Facebook

Illustrating Animals With 13 Circles: A Tutorial And Drawing Challenge

Illustrating Animals With 13 Circles: A Tutorial And Drawing Challenge

Editor’s Note: New year, new challenges! You might have set up your New Year’s resolutions already, but if not, how about designing something… different for a change? Today, we’re happy to introduce Dorota1, an artist who created a fun little project last year that was inspired by Twitter’s new logo based on 13 circles2. Below you’ll find the lessons Dorota has learned along the process, so maybe you’d like to embark on a similar journey as well?

If you can make a bird out of circles, then you can probably make all sorts of animals. I wanted to add something more design-based to my portfolio, so I made that my personal challenge. The idea was to draw animals from exactly 13 circles, and I decided to match that number by making 13 animals. This makes for a nicer title for the project, and it helps to get others to share it around the web, too. Knowing what you want to create early on helps, because then all you have to do is figure out ways to make it happen.

The project mostly consisted of three Adobe applications: Photoshop, Illustrator and After Effects.

Getting Started: Sketching Link

I prefer to sketch things on paper first, but you can do so digitally as well. First, I chose some animals that I didn’t think would be extremely difficult to draw. Then, I chose prominent features of those animals to focus on. I also Googled logos, designs and illustrations of the animals to see what features other people emphasize. When limited to 13 circles, you can’t fit everything! For example, with the monkey, all I could fit were the ears, the long tail and the outline around the eyes, leaving me with few circles to play with, but that’s OK.

While sketching, I kept track of the number of circles I was using, counting one for every curve. If I had too many circles, I would examine them to see if two curves could somehow come from one circle. For example, in the part of the giraffe below, the orange circle serves as both the top of the left horn and the bottom of the ear:

3
(View large version4)

Illustrator Link

After I had a sketch I was happy with, I photographed it or scanned it to my computer.

Before I began, I decided on a size for the project. This is important for consistency and to keep things moving quickly in Photoshop and After Effects. I chose 8 × 10 inches at 300 DPI (or PPI), just in case I decided to print them after, because that’s a common print size. I also felt the ratio would be good to turn them into animated GIFs later.

Here are the first steps to take in Illustrator:

  1. Open your sketch, or drag or paste it into your sized document. Select the sketch, and click Ctrl + 2 to lock it in place.
  2. Draw circles using the Ellipse tool (L); to make perfect circles, hold Shift while dragging. You can find the ellipses by holding or right-clicking the Rectangle tool. Select your circle(s), and set the fill to none, and choose a small stroke to work with. Hide the sketch layer once you’ve finished by clicking the eye.
  3. Select all of your circles by enabling the Selection tool (V) and dragging from one corner over the entire screen. Resize them to the size you want the animal to be in the document. This is important if you want to save time later.
  4. With the circles still selected, we’re going to make a backup by clicking Ctrl + C, then clicking “New Layer,” then clicking Ctrl + F. This pastes in the exact same location. Hide the backup layer.
  5. Click the Shape Builder tool (Shift + M), choose a fill color (removing the stroke), and click in the parts of the circles that you want to fill in.
  6. Once you’re happy with the shape, isolate all the filled shapes from the circles by clicking on one and then going to menu “Select” → “Same” → “Fill Color”. Once they’re selected, you can simply copy them, select & delete everything in the document (we backed up the circles), and press Ctrl + F to bring back just the filled shapes.

Instead of the Shape Builder tool in step 4, you could also use the Live Paint Bucket tool (K), which allows you to move the circles safely while keeping your area filled in, and then you would expand at the very end.

Sometimes the curves I sketched didn’t perfectly form a circle, so I’d have to go back and move a few curves around or change their sizes. If you merely want to suggest some shapes in your animal (rather than being explicit), you may have to add more circles. For example, sometimes I would want an area to be cut out, such as the inside of the fox tail. Other times, I would want an area to be a different color from the rest of the shape, such as the toucan’s beak. There are many ways to create separation.

At this point, I had the animal (still in pieces), a hidden layer with the circles, and a hidden layer with the sketch.

5
Steps 1, 2, 5 and 6 (View large version6)

Sometimes, at this point, I would turn the animal into one solid shape. To do this, select the animal, open the Pathfinder panel (in the menu, “Window” → Pathfinder, or Ctrl/Cmd + Shift + F9) and click the “Unite” option. The paths might have small flaws, but you can usually fix those using the Direct Selection tool (A), which allows you to click individual anchors and paths to easily move, modify or delete them.

Often, however, rather than turning an animal into a solid shape, I would add a bit of shading using gradients. I would often add these to one section of the animal, and I would use the same method as above to select a couple of pieces of an animal and merge those pieces into one (often, my animals would be in two or three pieces by the end).

In this example, you can see that I used different shading methods on different parts of the monkey. Above the monkey’s eyes, I used the Mesh tool (U) to get a gradient that follows the curves. A fast way to add a mesh is to click an object and go to “Object” → “Create Gradient Mesh.” I’m not an expert with this tool yet, so my attempt is more of an experiment.

Underneath the monkey’s face, I simply used a regular gradient. A fast way to apply a gradient to an object is to click the object and press the period key (.). Then, in the menu, go to “Window” → “Gradient” to open the Gradient panel and change the settings of that gradient.

7
(View large version8)

Because I knew I would be bringing the animals into Photoshop after, I simply shaded them with shades of gray. This way, if I wanted to use different blending modes with colors and textures, the hues that I chose would be retained.

9
(View large version10)

Photoshop Link

Create a document in Photoshop of the exact size as your Illustrator document (this is to make things easy and is not a requirement). I also stayed with the RGB color space because my focus is the web, but I can always convert to CMYK later if I want to print. Before bringing in the animals, I would create the background first.

I started with the colors. There are many ways to create gradients. I started with a white background and then simply stacked a few transparent layers of lightly brushed colors. Sometimes I would further tweak the colors using an Adjustment Layer such as “Curves” (experiment to find what works best for you).

Once you’ve got the color gradients down, it’s time to add some texture! I experimented with many different textures that I downloaded online — you can find many by searching for terms like “free paper texture.” There are also some nice textures on Subtle Patterns11, but they’re usually small image tiles meant to be repeated, and I personally don’t like repeating ones.

I often used a subtle paper texture as a base and then used other textures to bring out more light and dark speckles. It’s easy to bring out speckles from a texture using Curves or Levels. All of my textures are overlaid using different blending modes, as well as by experimenting with opacity.

12
(View large version13)

Below are the noise layer and the texture image that I used for the background above:

14
(View large version15)

And below are the layers for the background, along with my settings for each Curves layer. The really crazy curves were the ones I used to bring out different parts of the textures, such as the speckles.

16
(View large version17)

As I said, experiment with Photoshop’s functionality until you’re happy. Here are the layers for this background, starting from the bottom:

  1. a blank white background;
  2. lightly painted colors at a small opacity using the brush;
  3. noise (“Filter” → “Noise” → “Add Noise”) at a 41% “Overlay” blending mode, sometimes enlarged or blurred;
  4. a texture layer with “Color Burn”;
  5. a Curves adjustment layer clipped to the texture layer, to create a high contrast for the speckles in the texture;
  6. a texture layer again, rotated to a different position and a “Color Burn” of 40%;
  7. a Curves layer clipped to the texture, this time bringing out the textures in a different way;
  8. a blue layer set to “Divide” at 37%;
  9. an overall Curves layer to brighten the entire image (including the monkey).

Once my background was ready, I brought in the animal as a smart object. Use smart objects18 whenever possible. I simply copied and pasted the animal from Illustrator. Because the documents are the same size, the animal should be pasted into Photoshop at the same size. I didn’t resize the animal in Photoshop, so that I could easily align the circles in a further step.

19
(View large version20)

Here are the layers I used for the monkey:

  1. a monkey smart object;
  2. a stamp of only the background (Ctrl + Alt + Shift + E), clipped to the monkey, at “Multiply”;
  3. another stamp of background, clipped to monkey, with a “Hard Light” of 34%;
  4. another stamp of background, clipped to the monkey, with “Multiply” set to 34%;
  5. a Curves layer, clipped to the monkey, to brighten it up;
  6. a “Hue/Saturation” layer, clipped to the monkey, to make the hue a more blueish-purple.

Here are a few points in the evolution of the monkey:

21
(View large version22)

Illustrator Again Link

It’s almost time to animate! I animated in After Effects, although many programs will do it (Photoshop has some basic animation capability, too).

Use “File” → “Place” (Shift + Ctrl + P) to place the Photoshop file in Illustrator as a linked object; this way, if you need to make any changes in the Photoshop file, it will automatically update in Illustrator. Placing the file in the top-left corner anchor works best, from what I’ve seen. Next, bring back your circles by unhiding the backup layer we created. You may have to drag and change the order of the layers to stack the circles on top, and you might have to realign them to your animal if it has moved.

I decided to stoke the circles with a dashed line. I did this by selecting the circles, clicking “Stroke,” checking “Dashed line” and specifying the size of the dash and the size of the gap. I used 5 points for the dash and 3 points for the gap.

In case you need to slightly resize the circles, select them and use the width (“W”) and height (“H”) boxes on top to change the size in small increments. Make sure the chain in the middle is activated, to maintain the proportions.

I had to put each circle on a separate layer so that I could animate them in After Effects. I simply created 13 new layers, then dragged a circle into each one. Your file will look like this:

23
(View large version24)

After Effects Link

First, download and install Ease & Wizz25, which will make the movement of our circles a bit more interesting — moving in slow, speeding up quickly, and ending slow again. This is a “name your price” script, so you could technically download it for $0.

26
Without the script (left), and with (right). (View large version27)

Start a new project, go to “Import” → “File” (Ctrl + I), and select your Illustrator file. But make sure where it says “Import as Footage,” you change it to “Composition — Retain layer sizes.”

If the composition doesn’t open up right away, double-click it in the “Project” tab. If you’re planning to resize the composition, make sure to click the little gear icon to the right of it.

It might also be a good idea to choose an animation frame rate before starting (“Composition” → “Composition Settings”). I chose 20 frames per second because I knew my animation would be quite short and would loop. If you’re working with a longer animation, you should lower it, because animated GIFs with a high number of frames can end up being too big in size.

Select all of the layers except for the layer with the background; right-click and choose “Create shapes from vector layer.” These are the shapes we’ll be animating. The original Illustrator layers should still be there, but their visibility should now be off.

Choose a shape layer, and click its contents; to the right of it, where it says “Add,” select “Trim Paths.” First, I set “End” to 0%. Clicking the stopwatch near “Start” or “End” will activate the keyframes for that action and turn blue. A keyframe will be created at that point, depending on where your indicator is placed. It’ll be a small diamond. I set mine to “Start 0%,” which made my circle invisible, and I moved it down the timeline to where I wanted my circles to start animating. Move your indicator down the timeline, and then change “Start” to 100%; you’ll see a new keyframe appear automatically.

Depending on which direction you want the path to disappear (clockwise versus counterclockwise), you might have to start with “Start” or “End.” Below is an example of what I did to make the circle be invisible at first for a moment, appear into the frame, pause, and then disappear in the direction that it appeared. The timing isn’t what I used for my project — it’s just an example.

28
(View large version29)

Here is the breakdown of my keyframes:

  1. Start 0%
  2. Start 100%
  3. Start 100% and End 0%
  4. End 100%

Then, I added the Ease & Wizz effect. Open the plugin by going to “Window” → “Ease and Wizz” (.jsx). Then, highlight and select all of the keyframes, and click “Apply” (I used the plugin’s default settings). The percentage text should now be in red. You could also drag the plugin window into your toolbar, so that it’s not floating around.

Also, I used the Rotation tool (W) on the circles to rotate them, so that the animation starts at a different point, such as the end of the tail, rather than right in the middle of it.

You can also copy and paste your keyframes into the “Trim Paths” folder of another circle if that animation is going in the same direction that you want this circle to go in. I created a clockwise animation and then a counterclockwise one (renaming the layer folders to not lose my place), and I would copy and paste those keyframes into the rest of the circles according to how I wanted; for example, the monkey’s tail would be counterclockwise, whereas the ears would be clockwise.

Once all of the circles are done, you can go to “File” → “Export” → “Add to Render Queue” (or Ctrl + Shift + /) and render it as an AVI file (or any video format of your choice).

Turning the video into an animated GIF

Back To Photoshop Link

To turn the video into an animated GIF, I opened Photoshop and went to “File” → “Import” → “Video Frames to Layers.” Once it opens up, I went to “Windows” → “Timeline” (or “Animation”) to open the “Animation” tab. In newer versions of Photoshop, you have the option of a video timeline or a frame animation. I chose frame animation.

Because there were pauses in my animation, each pause rendered as its own frame, so I had to delete all of the duplicate frames from each pause in the animation and keep only one frame, but then set the timing of that one frame to a higher duration. You can avoid this by removing all gaps in your After Effects animation and then adding the pauses back in Photoshop; however, not being able to see the entire thing at once might make it a little harder to decide on the duration of the animation. Also, don’t forget to set the looping option to “forever.”

30
Frames 1, 28 and 53 are consolidated in my example (you could further combine 1 and 53). (View large version31)

Once that’s done, go to “File” → “Export” → “Save for Web” and choose “GIF.” Here is where it gets experimental, because I had to play around with the settings to get a good balance of quality and file size. Choosing the best quality will often make the file size way too big (I try never to exceed 1 MB for a GIF).

I also found that when resizing the image to be smaller, the color table would change and would often look much worse (or even vice versa). Here’s a trick: Change the animated GIF to various sizes until the colors look as best as possible, then save that color table, resize it to your desired size, and then load that color table:

32
(View large version33)

All done!

Some Reflections Link

  • When I initially created the animals, I didn’t make sure that all of my document sizes were the same, and so I had to resize and realign all of the circles for each animal! Pay close attention to document size.
  • I haven’t figured out why an image loads in After Effects at narrower than 600 pixels, even when the original document is much larger! I have a lot to learn about After Effects.
  • I haven’t yet figured out a way to quickly remove extra frames in a Photoshop animation. Maybe better applications for creating GIFs are out there?

I also gained some knowledge while working on this:

  • I’ve never really drawn so many animals before. I realized with this project that you’re not really drawing the animal — you’re mainly just drawing its features! That takes a lot of the pressure off.
  • I also realized that experimenting with textures can be extremely difficult and sometimes hit or miss. Start building your texture collection folder early on! I wish I had started years ago.
  • I discovered the color table trick only after getting extremely annoyed when some of the GIFs would suddenly look horrible when I’d change their size by a slight amount (for example, 50 pixels in width). Always be open to discovering tricks, even in the applications most familiar to you!
  • This was probably my third time making something in After Effects, so there was a lot of tedious trial and error here, as well as some help from a friend. It helps having friends who share your passion.

I did many things that could probably have been done more quickly or easily. This was a learning experience. If you have any tips for making these types of animations faster, better or easier, feel free to share in the comments!

Hope you enjoyed the animations!

Full Preview Of All 13 Illustrated Animals Link

Owl made from circles34
Owl made from circles (Large preview35)
Rabbit made from circles36
Rabbit made from circles (Large preview37)
Monkey made from circles38
Monkey made from circles (Large preview39)
Elephant made from circles40
Elephant made from circles (Large preview41)
Toucan made from circles42
(Large preview43)
Giraffe made from circles44
Giraffe made from circles (Large preview45)
Mouse made from circles46
Mouse made from circles (Large preview47)
Dog made from circles48
Dog made from circles (Large preview49)
Owl made from circles50
Cat made from circles (Large preview51)
Fox made from circles52
Fox made from circles (Large preview53)
Whale made from circles54
Whale made from circles (Large preview55)
Frog made from circles56
Frog made from circles (Large preview57)
Walrus made from circles58
Walrus made from circles (Large preview59)

(vf, il, al)

Footnotes Link

  1. 1 http://dorotapankowska.com
  2. 2 http://dorotapankowska.com/13-animals-13-circles.html
  3. 3 https://www.smashingmagazine.com/wp-content/uploads/2016/11/13-animals-13-circles-img3-large-opt.jpg
  4. 4 https://www.smashingmagazine.com/wp-content/uploads/2016/11/13-animals-13-circles-img3-large-opt.jpg
  5. 5 https://www.smashingmagazine.com/wp-content/uploads/2016/11/13-animals-13-circles-img4-large-opt.jpg
  6. 6 https://www.smashingmagazine.com/wp-content/uploads/2016/11/13-animals-13-circles-img4-large-opt.jpg
  7. 7 https://www.smashingmagazine.com/wp-content/uploads/2016/11/13-animals-13-circles-img5-large-opt.jpg
  8. 8 https://www.smashingmagazine.com/wp-content/uploads/2016/11/13-animals-13-circles-img5-large-opt.jpg
  9. 9 https://www.smashingmagazine.com/wp-content/uploads/2016/11/13-animals-13-circles-img6-large-opt.jpg
  10. 10 https://www.smashingmagazine.com/wp-content/uploads/2016/11/13-animals-13-circles-img6-large-opt.jpg
  11. 11 http://subtlepatterns.com/
  12. 12 https://www.smashingmagazine.com/wp-content/uploads/2016/11/13-animals-13-circles-img7-large-opt.jpg
  13. 13 https://www.smashingmagazine.com/wp-content/uploads/2016/11/13-animals-13-circles-img7-large-opt.jpg
  14. 14 https://www.smashingmagazine.com/wp-content/uploads/2016/11/13-animals-13-circles-img8-large-opt.jpg
  15. 15 https://www.smashingmagazine.com/wp-content/uploads/2016/11/13-animals-13-circles-img8-large-opt.jpg
  16. 16 https://www.smashingmagazine.com/wp-content/uploads/2016/11/13-animals-13-circles-img9-large-opt.jpg
  17. 17 https://www.smashingmagazine.com/wp-content/uploads/2016/11/13-animals-13-circles-img9-large-opt.jpg
  18. 18 https://helpx.adobe.com/photoshop/using/create-smart-objects.html
  19. 19 https://www.smashingmagazine.com/wp-content/uploads/2016/11/13-animals-13-circles-img10-large-opt.jpg
  20. 20 https://www.smashingmagazine.com/wp-content/uploads/2016/11/13-animals-13-circles-img10-large-opt.jpg
  21. 21 https://www.smashingmagazine.com/wp-content/uploads/2016/11/13-animals-13-circles-img11-large-opt.jpg
  22. 22 https://www.smashingmagazine.com/wp-content/uploads/2016/11/13-animals-13-circles-img11-large-opt.jpg
  23. 23 https://www.smashingmagazine.com/wp-content/uploads/2016/11/13-animals-13-circles-img12-large-opt.jpg
  24. 24 https://www.smashingmagazine.com/wp-content/uploads/2016/11/13-animals-13-circles-img12-large-opt.jpg
  25. 25 http://aescripts.com/ease-and-wizz/
  26. 26 https://www.smashingmagazine.com/wp-content/uploads/2016/11/13-animals-13-circles-img13-large-opt.gif
  27. 27 https://www.smashingmagazine.com/wp-content/uploads/2016/11/13-animals-13-circles-img13-large-opt.gif
  28. 28 https://www.smashingmagazine.com/wp-content/uploads/2016/11/13-animals-13-circles-img14-large-opt.jpg
  29. 29 https://www.smashingmagazine.com/wp-content/uploads/2016/11/13-animals-13-circles-img14-large-opt.jpg
  30. 30 https://www.smashingmagazine.com/wp-content/uploads/2016/11/13-animals-13-circles-img15-large-opt.jpg
  31. 31 https://www.smashingmagazine.com/wp-content/uploads/2016/11/13-animals-13-circles-img15-large-opt.jpg
  32. 32 https://www.smashingmagazine.com/wp-content/uploads/2016/11/13-animals-13-circles-img16-large-opt.jpg
  33. 33 https://www.smashingmagazine.com/wp-content/uploads/2016/11/13-animals-13-circles-img16-large-opt.jpg
  34. 34 https://www.smashingmagazine.com/wp-content/uploads/2016/12/poster-owl.gif
  35. 35 https://www.smashingmagazine.com/wp-content/uploads/2016/12/poster-owl.gif
  36. 36 https://www.smashingmagazine.com/wp-content/uploads/2016/12/poster-rabbit.gif
  37. 37 https://www.smashingmagazine.com/wp-content/uploads/2016/12/poster-rabbit.gif
  38. 38 https://www.smashingmagazine.com/wp-content/uploads/2016/12/poster-monkey.gif
  39. 39 https://www.smashingmagazine.com/wp-content/uploads/2016/12/poster-monkey.gif
  40. 40 https://www.smashingmagazine.com/wp-content/uploads/2016/12/poster-elephant.gif
  41. 41 https://www.smashingmagazine.com/wp-content/uploads/2016/12/poster-elephant.gif
  42. 42 https://www.smashingmagazine.com/wp-content/uploads/2016/12/poster-toucan.gif
  43. 43 https://www.smashingmagazine.com/wp-content/uploads/2016/12/poster-toucan.gif
  44. 44 https://www.smashingmagazine.com/wp-content/uploads/2016/12/poster-giraffe.gif
  45. 45 https://www.smashingmagazine.com/wp-content/uploads/2016/12/poster-giraffe.gif
  46. 46 https://www.smashingmagazine.com/wp-content/uploads/2016/12/poster-mouse.gif
  47. 47 https://www.smashingmagazine.com/wp-content/uploads/2016/12/poster-mouse.gif
  48. 48 https://www.smashingmagazine.com/wp-content/uploads/2016/12/poster-dog.gif
  49. 49 https://www.smashingmagazine.com/wp-content/uploads/2016/12/poster-dog.gif
  50. 50 https://www.smashingmagazine.com/wp-content/uploads/2016/12/poster-cat.gif
  51. 51 https://www.smashingmagazine.com/wp-content/uploads/2016/12/poster-cat.gif
  52. 52 https://www.smashingmagazine.com/wp-content/uploads/2016/12/poster-fox.gif
  53. 53 https://www.smashingmagazine.com/wp-content/uploads/2016/12/poster-fox.gif
  54. 54 https://www.smashingmagazine.com/wp-content/uploads/2016/12/poster-whale.gif
  55. 55 https://www.smashingmagazine.com/wp-content/uploads/2016/12/poster-whale.gif
  56. 56 https://www.smashingmagazine.com/wp-content/uploads/2016/12/poster-frog.gif
  57. 57 https://www.smashingmagazine.com/wp-content/uploads/2016/12/poster-frog.gif
  58. 58 https://www.smashingmagazine.com/wp-content/uploads/2016/12/poster-walrus.gif
  59. 59 https://www.smashingmagazine.com/wp-content/uploads/2016/12/poster-walrus.gif

↑ Back to topTweet itShare on Facebook

Desktop Wallpaper Calendars: January 2017

Desktop Wallpaper Calendars: January 2017

New year, new beginnings! To cater for a fresh start into 2017 and all the challenges, endeavors and adventures it might bring along, artists and designers from across the globe put their creative skills to the test and created unique desktop wallpapers for you to indulge in.

This monthly wallpapers mission has been going on for eight years1 now, and we are very thankful to all the creative minds who contribute to it tirelessly each month anew. Today’s wallpapers all come in versions with and without a calendar and can be downloaded for free. Happy New Year!

Please note that:

  • All images can be clicked on and lead to the preview of the wallpaper,
  • You can feature your work in our magazine2 by taking part in our Desktop Wallpaper Calendars series. We are regularly looking for creative designers and artists to be featured on Smashing Magazine. Are you one of them?
  • Looking for more winter-related wallpapers3 dedicated to snow, ice and frost? We’ve got you covered with only the best ones since 2008.

Angel In Snow

Designed by Brainer4 from Ukraine.

5

Colorful 2017

“As 2016 ends, we head to a new beginning where hopefully the best is yet to come. Happy 2017!” — Designed by Maria Keller31 from Mexico.

Colorful 201732

A New Start

“The new year brings hope, festivity, lots and lots of resolutions, and many more goals that need to be achieved. This wallpaper is based on the idea of ‘A New Start’.” — Designed by Damn Perfect84 from India.

A New Start85

Happy Hot Tea Month

“You wake me up to a beautiful day; lift my spirit when I’m feeling blue. When I’m home you relieve me of the long day’s stress. You help me have a good time with my loved ones; give me company when I’m all alone. You’re none other than my favourite cup of hot tea.” — Designed by Acodez IT Solutions129 from India.

Happy Hot Tea Month!130

Love Makes You Warm

“Following the busy Christmas season, the cold and boring January comes, love is one thing, what can make us warm for sure!” — Designed by Barbara Dörnyei172 from Hungary.

Love makes you warm!173

Hello Summer In Australia

Designed by Tazi Designs191 from Australia.

Hello Summer in Australia!192

Summer Celebration

“Summer in Australia is about sun and the beach – which inspired the colours I have used. It is a wonderful celebration of the ending on one year and the beginning of another. I hope my illustration inspires this feeling of the celebration of rebirth and growth.” — Designed by Katherine Appleby216 from Australia.

Summer Celebration217

The Year Of The Rooster

“2017 is the year of the rooster according to the Chinese horoscope, which begins January 28, 2017. The rooster being the sign of dawn and awakening, triumph and success can only be achieved at the price of hard work and patience in 2017.” — Designed by Lucas Debelder259 from Belgium.

2017 - The Year Of The Rooster260

New Beginnings

“2016 was an exciting year, many things happened and changed our world. In the coming year of 2017, we wish all to be more successful, to love and be loved, and to look into the future holding hands with your better half. Let every day in January be smashing for you. Happy New Year, everybody!” — Designed by PopArt Studio304 from Serbia.

New Beginnings305

Fire Rooster

“Inspired by the upcoming year of the Fire Rooster.” — Designed by Lia Pantazi345 from Greece.

Year of the Rooster.346

Reindeer

Designed by Ana Masnikosa380 from Belgrade, Serbia.

Reindeer381

Travel And Explore

“For once you have tasted flight you will walk the earth with your eyes turned skywards, for there you have been and there you will long to return. (Leonardo da Vinci)” — Designed by Dipanjan Karmakar421 from India.

Travel & Explore422

The Rooster Wishes You A Happy New Year

“2017 is the year of the rooster, so I made a wallpaper with a rooster on it. I myself have 8 chickens at home but no rooster, so maybe we could buy one this year to celebrate the year of the rooster. Happy New Year to everyone!” — Designed by Melissa Bogemans450 from Belgium.

The rooster wishes you a happy New Year!451

Happy Birthday A. A. Milne

“I love Winnie the Pooh! January 18th marks A.A. Milne’s 135th birthday, the creator of Winnie the Pooh. I have included one of my favourite quotes to symbolize what an inspiration his stories have been to both kids and adults.” — Designed by Safia Begum491 from United Kingdom.

Happy Birthday A. A. Milne!492

Ice Crime

Designed by Doud – Elise Vanoorbeek534 from Belgium.

Ice Crime535

The Worried Weighing Scales

“Most of us have over-indulged a little over the holiday period – spare a thought for our bathroom scales, who will have much heavier people standing on them for the next few months!” — Designed by James Mitchell559 from United Kingdom.

The Worried Weighing Scales560

Wake Up, It Is Time To Study

“Sitting on a chair before my desk playing video games when a friend called me to ask something about the exams. Then I realized that I have one more week to study before the first exam begins. So wake up guys! It is time to study!” — Designed by Robert Vaida580 from Belgium.

Wake up! It is time to study581

Angels Of Heaven

“January is a month of cold winter days. Whenever I hear ‘January’, the first thing that comes to my mind are long sleepy winter nights, cause these days are the most comfortable for sleeping. It gives me the feeling of a baby from heaven sleeping comfortably.” — Designed by Swapnil Chavan599 from India.

Angels Of Heaven600

The Tree

“Before reaching the spring it is necessary to go through the intense cold of winter.” — Designed by Ana Travassos614 from Portugal.

The tree615

Let’s Do Great Things Together

“I choose a typographic wallpaper for the mont January to clearly emphasize my message to the world. We need to make this upcoming year a better year than 2016 and and we can only achieve that if we stand together and try making the best of it.” — Designed by Thomas Debelder637 from Belgium.

Let's do great things together!638

Observing Cat

“I took a shot of this cat while she was observing the world on a chilly sunny day.” — Designed by Marija Zaric656 from Belgrade, Serbia.

Observing Cat657

It Shines

“January represents a new beginning, a new chance to start over. This wallpaper is made to charge everyone with energy and to remember that smiling everyday does make the difference.” — Designed by Rodrigo Flores675 from Costa Rica.

It shines!676

Join In Next Month! Link

Please note that we respect and carefully consider the ideas and motivation behind each and every artist’s work. This is why we give all artists the full freedom to explore their creativity and express emotions and experience throughout their works. This is also why the themes of the wallpapers weren’t anyhow influenced by us, but rather designed from scratch by the artists themselves.

A big thank you to all designers for their participation. Join in next month694!

What’s Your Favorite? Link

What’s your favorite theme or wallpaper for this month? Please let us know in the comment section below.

(cm, il)

Footnotes Link

  1. 1 https://www.smashingmagazine.com/tag/wallpapers/
  2. 2 https://www.smashingmagazine.com/desktop-wallpaper-calendars-join-in/
  3. 3 https://www.smashingmagazine.com/winter-wallpaper/
  4. 4 https://www.behance.net/DesignStudioBrainer
  5. 5 http://files.smashingmagazine.com/wallpapers/jan-17/angel-in-snow/jan-17-angel-in-snow-full.jpg
  6. 6 http://files.smashingmagazine.com/wallpapers/jan-17/angel-in-snow/jan-17-angel-in-snow-preview.jpg
  7. 7 http://files.smashingmagazine.com/wallpapers/jan-17/angel-in-snow/cal/jan-17-angel-in-snow-cal-800×600.jpg
  8. 8 http://files.smashingmagazine.com/wallpapers/jan-17/angel-in-snow/cal/jan-17-angel-in-snow-cal-1024×768.jpg
  9. 9 http://files.smashingmagazine.com/wallpapers/jan-17/angel-in-snow/cal/jan-17-angel-in-snow-cal-1152×864.jpg
  10. 10 http://files.smashingmagazine.com/wallpapers/jan-17/angel-in-snow/cal/jan-17-angel-in-snow-cal-1280×800.jpg
  11. 11 http://files.smashingmagazine.com/wallpapers/jan-17/angel-in-snow/cal/jan-17-angel-in-snow-cal-1280×960.jpg
  12. 12 http://files.smashingmagazine.com/wallpapers/jan-17/angel-in-snow/cal/jan-17-angel-in-snow-cal-1400×1050.jpg
  13. 13 http://files.smashingmagazine.com/wallpapers/jan-17/angel-in-snow/cal/jan-17-angel-in-snow-cal-1440×900.jpg
  14. 14 http://files.smashingmagazine.com/wallpapers/jan-17/angel-in-snow/cal/jan-17-angel-in-snow-cal-1600×1200.jpg
  15. 15 http://files.smashingmagazine.com/wallpapers/jan-17/angel-in-snow/cal/jan-17-angel-in-snow-cal-1680×1050.jpg
  16. 16 http://files.smashingmagazine.com/wallpapers/jan-17/angel-in-snow/cal/jan-17-angel-in-snow-cal-1680×1260.jpg
  17. 17 http://files.smashingmagazine.com/wallpapers/jan-17/angel-in-snow/cal/jan-17-angel-in-snow-cal-1920×1200.jpg
  18. 18 http://files.smashingmagazine.com/wallpapers/jan-17/angel-in-snow/cal/jan-17-angel-in-snow-cal-1920×1440.jpg
  19. 19 http://files.smashingmagazine.com/wallpapers/jan-17/angel-in-snow/nocal/jan-17-angel-in-snow-nocal-800×600.jpg
  20. 20 http://files.smashingmagazine.com/wallpapers/jan-17/angel-in-snow/nocal/jan-17-angel-in-snow-nocal-1024×768.jpg
  21. 21 http://files.smashingmagazine.com/wallpapers/jan-17/angel-in-snow/nocal/jan-17-angel-in-snow-nocal-1152×864.jpg
  22. 22 http://files.smashingmagazine.com/wallpapers/jan-17/angel-in-snow/nocal/jan-17-angel-in-snow-nocal-1280×800.jpg
  23. 23 http://files.smashingmagazine.com/wallpapers/jan-17/angel-in-snow/nocal/jan-17-angel-in-snow-nocal-1280×960.jpg
  24. 24 http://files.smashingmagazine.com/wallpapers/jan-17/angel-in-snow/nocal/jan-17-angel-in-snow-nocal-1400×1050.jpg
  25. 25 http://files.smashingmagazine.com/wallpapers/jan-17/angel-in-snow/nocal/jan-17-angel-in-snow-nocal-1440×900.jpg
  26. 26 http://files.smashingmagazine.com/wallpapers/jan-17/angel-in-snow/nocal/jan-17-angel-in-snow-nocal-1600×1200.jpg
  27. 27 http://files.smashingmagazine.com/wallpapers/jan-17/angel-in-snow/nocal/jan-17-angel-in-snow-nocal-1680×1050.jpg
  28. 28 http://files.smashingmagazine.com/wallpapers/jan-17/angel-in-snow/nocal/jan-17-angel-in-snow-nocal-1680×1260.jpg
  29. 29 http://files.smashingmagazine.com/wallpapers/jan-17/angel-in-snow/nocal/jan-17-angel-in-snow-nocal-1920×1200.jpg
  30. 30 http://files.smashingmagazine.com/wallpapers/jan-17/angel-in-snow/nocal/jan-17-angel-in-snow-nocal-1920×1440.jpg
  31. 31 http://www.mariakellerac.com
  32. 32 http://files.smashingmagazine.com/wallpapers/jan-17/colorful-2017/jan-17-colorful-2017-full.png
  33. 33 http://files.smashingmagazine.com/wallpapers/jan-17/colorful-2017/jan-17-colorful-2017-preview.png
  34. 34 http://files.smashingmagazine.com/wallpapers/jan-17/colorful-2017/cal/jan-17-colorful-2017-cal-320×480.png
  35. 35 http://files.smashingmagazine.com/wallpapers/jan-17/colorful-2017/cal/jan-17-colorful-2017-cal-640×480.png
  36. 36 http://files.smashingmagazine.com/wallpapers/jan-17/colorful-2017/cal/jan-17-colorful-2017-cal-640×1136.png
  37. 37 http://files.smashingmagazine.com/wallpapers/jan-17/colorful-2017/cal/jan-17-colorful-2017-cal-750×1334.png
  38. 38 http://files.smashingmagazine.com/wallpapers/jan-17/colorful-2017/cal/jan-17-colorful-2017-cal-800×480.png
  39. 39 http://files.smashingmagazine.com/wallpapers/jan-17/colorful-2017/cal/jan-17-colorful-2017-cal-800×600.png
  40. 40 http://files.smashingmagazine.com/wallpapers/jan-17/colorful-2017/cal/jan-17-colorful-2017-cal-1024×768.png
  41. 41 http://files.smashingmagazine.com/wallpapers/jan-17/colorful-2017/cal/jan-17-colorful-2017-cal-1024×1024.png
  42. 42 http://files.smashingmagazine.com/wallpapers/jan-17/colorful-2017/cal/jan-17-colorful-2017-cal-1152×864.png
  43. 43 http://files.smashingmagazine.com/wallpapers/jan-17/colorful-2017/cal/jan-17-colorful-2017-cal-1242×2208.png
  44. 44 http://files.smashingmagazine.com/wallpapers/jan-17/colorful-2017/cal/jan-17-colorful-2017-cal-1280×720.png
  45. 45 http://files.smashingmagazine.com/wallpapers/jan-17/colorful-2017/cal/jan-17-colorful-2017-cal-1280×800.png
  46. 46 http://files.smashingmagazine.com/wallpapers/jan-17/colorful-2017/cal/jan-17-colorful-2017-cal-1280×960.png
  47. 47 http://files.smashingmagazine.com/wallpapers/jan-17/colorful-2017/cal/jan-17-colorful-2017-cal-1280×1024.png
  48. 48 http://files.smashingmagazine.com/wallpapers/jan-17/colorful-2017/cal/jan-17-colorful-2017-cal-1366×768.png
  49. 49 http://files.smashingmagazine.com/wallpapers/jan-17/colorful-2017/cal/jan-17-colorful-2017-cal-1400×1050.png
  50. 50 http://files.smashingmagazine.com/wallpapers/jan-17/colorful-2017/cal/jan-17-colorful-2017-cal-1440×900.png
  51. 51 http://files.smashingmagazine.com/wallpapers/jan-17/colorful-2017/cal/jan-17-colorful-2017-cal-1600×1200.png
  52. 52 http://files.smashingmagazine.com/wallpapers/jan-17/colorful-2017/cal/jan-17-colorful-2017-cal-1680×1050.png
  53. 53 http://files.smashingmagazine.com/wallpapers/jan-17/colorful-2017/cal/jan-17-colorful-2017-cal-1680×1200.png
  54. 54 http://files.smashingmagazine.com/wallpapers/jan-17/colorful-2017/cal/jan-17-colorful-2017-cal-1920×1080.png
  55. 55 http://files.smashingmagazine.com/wallpapers/jan-17/colorful-2017/cal/jan-17-colorful-2017-cal-1920×1200.png
  56. 56 http://files.smashingmagazine.com/wallpapers/jan-17/colorful-2017/cal/jan-17-colorful-2017-cal-1920×1440.png
  57. 57 http://files.smashingmagazine.com/wallpapers/jan-17/colorful-2017/cal/jan-17-colorful-2017-cal-2560×1440.png
  58. 58 http://files.smashingmagazine.com/wallpapers/jan-17/colorful-2017/cal/jan-17-colorful-2017-cal-2880×1800.png
  59. 59 http://files.smashingmagazine.com/wallpapers/jan-17/colorful-2017/nocal/jan-17-colorful-2017-nocal-320×480.png
  60. 60 http://files.smashingmagazine.com/wallpapers/jan-17/colorful-2017/nocal/jan-17-colorful-2017-nocal-640×480.png
  61. 61 http://files.smashingmagazine.com/wallpapers/jan-17/colorful-2017/nocal/jan-17-colorful-2017-nocal-640×1136.png
  62. 62 http://files.smashingmagazine.com/wallpapers/jan-17/colorful-2017/nocal/jan-17-colorful-2017-nocal-750×1334.png
  63. 63 http://files.smashingmagazine.com/wallpapers/jan-17/colorful-2017/nocal/jan-17-colorful-2017-nocal-800×480.png
  64. 64 http://files.smashingmagazine.com/wallpapers/jan-17/colorful-2017/nocal/jan-17-colorful-2017-nocal-800×600.png
  65. 65 http://files.smashingmagazine.com/wallpapers/jan-17/colorful-2017/nocal/jan-17-colorful-2017-nocal-1024×768.png
  66. 66 http://files.smashingmagazine.com/wallpapers/jan-17/colorful-2017/nocal/jan-17-colorful-2017-nocal-1024×1024.png
  67. 67 http://files.smashingmagazine.com/wallpapers/jan-17/colorful-2017/nocal/jan-17-colorful-2017-nocal-1152×864.png
  68. 68 http://files.smashingmagazine.com/wallpapers/jan-17/colorful-2017/nocal/jan-17-colorful-2017-nocal-1242×2208.png
  69. 69 http://files.smashingmagazine.com/wallpapers/jan-17/colorful-2017/nocal/jan-17-colorful-2017-nocal-1280×720.png
  70. 70 http://files.smashingmagazine.com/wallpapers/jan-17/colorful-2017/nocal/jan-17-colorful-2017-nocal-1280×800.png
  71. 71 http://files.smashingmagazine.com/wallpapers/jan-17/colorful-2017/nocal/jan-17-colorful-2017-nocal-1280×960.png
  72. 72 http://files.smashingmagazine.com/wallpapers/jan-17/colorful-2017/nocal/jan-17-colorful-2017-nocal-1280×1024.png
  73. 73 http://files.smashingmagazine.com/wallpapers/jan-17/colorful-2017/nocal/jan-17-colorful-2017-nocal-1366×768.png
  74. 74 http://files.smashingmagazine.com/wallpapers/jan-17/colorful-2017/nocal/jan-17-colorful-2017-nocal-1400×1050.png
  75. 75 http://files.smashingmagazine.com/wallpapers/jan-17/colorful-2017/nocal/jan-17-colorful-2017-nocal-1440×900.png
  76. 76 http://files.smashingmagazine.com/wallpapers/jan-17/colorful-2017/nocal/jan-17-colorful-2017-nocal-1600×1200.png
  77. 77 http://files.smashingmagazine.com/wallpapers/jan-17/colorful-2017/nocal/jan-17-colorful-2017-nocal-1680×1050.png
  78. 78 http://files.smashingmagazine.com/wallpapers/jan-17/colorful-2017/nocal/jan-17-colorful-2017-nocal-1680×1200.png
  79. 79 http://files.smashingmagazine.com/wallpapers/jan-17/colorful-2017/nocal/jan-17-colorful-2017-nocal-1920×1080.png
  80. 80 http://files.smashingmagazine.com/wallpapers/jan-17/colorful-2017/nocal/jan-17-colorful-2017-nocal-1920×1200.png
  81. 81 http://files.smashingmagazine.com/wallpapers/jan-17/colorful-2017/nocal/jan-17-colorful-2017-nocal-1920×1440.png
  82. 82 http://files.smashingmagazine.com/wallpapers/jan-17/colorful-2017/nocal/jan-17-colorful-2017-nocal-2560×1440.png
  83. 83 http://files.smashingmagazine.com/wallpapers/jan-17/colorful-2017/nocal/jan-17-colorful-2017-nocal-2880×1800.png
  84. 84 http://www.damnperfect.com
  85. 85 http://files.smashingmagazine.com/wallpapers/jan-17/a-new-start/jan-17-a-new-start-full.jpg
  86. 86 http://files.smashingmagazine.com/wallpapers/jan-17/a-new-start/jan-17-a-new-start-preview.jpg
  87. 87 http://files.smashingmagazine.com/wallpapers/jan-17/a-new-start/cal/jan-17-a-new-start-cal-320×480.jpg
  88. 88 http://files.smashingmagazine.com/wallpapers/jan-17/a-new-start/cal/jan-17-a-new-start-cal-640×480.jpg
  89. 89 http://files.smashingmagazine.com/wallpapers/jan-17/a-new-start/cal/jan-17-a-new-start-cal-800×480.jpg
  90. 90 http://files.smashingmagazine.com/wallpapers/jan-17/a-new-start/cal/jan-17-a-new-start-cal-800×600.jpg
  91. 91 http://files.smashingmagazine.com/wallpapers/jan-17/a-new-start/cal/jan-17-a-new-start-cal-1024×768.jpg
  92. 92 http://files.smashingmagazine.com/wallpapers/jan-17/a-new-start/cal/jan-17-a-new-start-cal-1024×1024.jpg
  93. 93 http://files.smashingmagazine.com/wallpapers/jan-17/a-new-start/cal/jan-17-a-new-start-cal-1152×864.jpg
  94. 94 http://files.smashingmagazine.com/wallpapers/jan-17/a-new-start/cal/jan-17-a-new-start-cal-1280×720.jpg
  95. 95 http://files.smashingmagazine.com/wallpapers/jan-17/a-new-start/cal/jan-17-a-new-start-cal-1280×800.jpg
  96. 96 http://files.smashingmagazine.com/wallpapers/jan-17/a-new-start/cal/jan-17-a-new-start-cal-1280×960.jpg
  97. 97 http://files.smashingmagazine.com/wallpapers/jan-17/a-new-start/cal/jan-17-a-new-start-cal-1280×1024.jpg
  98. 98 http://files.smashingmagazine.com/wallpapers/jan-17/a-new-start/cal/jan-17-a-new-start-cal-1366×768.jpg
  99. 99 http://files.smashingmagazine.com/wallpapers/jan-17/a-new-start/cal/jan-17-a-new-start-cal-1400×1050.jpg
  100. 100 http://files.smashingmagazine.com/wallpapers/jan-17/a-new-start/cal/jan-17-a-new-start-cal-1440×900.jpg
  101. 101 http://files.smashingmagazine.com/wallpapers/jan-17/a-new-start/cal/jan-17-a-new-start-cal-1600×1200.jpg
  102. 102 http://files.smashingmagazine.com/wallpapers/jan-17/a-new-start/cal/jan-17-a-new-start-cal-1680×1050.jpg
  103. 103 http://files.smashingmagazine.com/wallpapers/jan-17/a-new-start/cal/jan-17-a-new-start-cal-1680×1200.jpg
  104. 104 http://files.smashingmagazine.com/wallpapers/jan-17/a-new-start/cal/jan-17-a-new-start-cal-1920×1080.jpg
  105. 105 http://files.smashingmagazine.com/wallpapers/jan-17/a-new-start/cal/jan-17-a-new-start-cal-1920×1200.jpg
  106. 106 http://files.smashingmagazine.com/wallpapers/jan-17/a-new-start/cal/jan-17-a-new-start-cal-1920×1440.jpg
  107. 107 http://files.smashingmagazine.com/wallpapers/jan-17/a-new-start/cal/jan-17-a-new-start-cal-2560×1440.jpg
  108. 108 http://files.smashingmagazine.com/wallpapers/jan-17/a-new-start/nocal/jan-17-a-new-start-nocal-320×480.jpg
  109. 109 http://files.smashingmagazine.com/wallpapers/jan-17/a-new-start/nocal/jan-17-a-new-start-nocal-640×480.jpg
  110. 110 http://files.smashingmagazine.com/wallpapers/jan-17/a-new-start/nocal/jan-17-a-new-start-nocal-800×480.jpg
  111. 111 http://files.smashingmagazine.com/wallpapers/jan-17/a-new-start/nocal/jan-17-a-new-start-nocal-800×600.jpg
  112. 112 http://files.smashingmagazine.com/wallpapers/jan-17/a-new-start/nocal/jan-17-a-new-start-nocal-1024×768.jpg
  113. 113 http://files.smashingmagazine.com/wallpapers/jan-17/a-new-start/nocal/jan-17-a-new-start-nocal-1024×1024.jpg
  114. 114 http://files.smashingmagazine.com/wallpapers/jan-17/a-new-start/nocal/jan-17-a-new-start-nocal-1152×864.jpg
  115. 115 http://files.smashingmagazine.com/wallpapers/jan-17/a-new-start/nocal/jan-17-a-new-start-nocal-1280×720.jpg
  116. 116 http://files.smashingmagazine.com/wallpapers/jan-17/a-new-start/nocal/jan-17-a-new-start-nocal-1280×800.jpg
  117. 117 http://files.smashingmagazine.com/wallpapers/jan-17/a-new-start/nocal/jan-17-a-new-start-nocal-1280×960.jpg
  118. 118 http://files.smashingmagazine.com/wallpapers/jan-17/a-new-start/nocal/jan-17-a-new-start-nocal-1280×1024.jpg
  119. 119 http://files.smashingmagazine.com/wallpapers/jan-17/a-new-start/nocal/jan-17-a-new-start-nocal-1366×768.jpg
  120. 120 http://files.smashingmagazine.com/wallpapers/jan-17/a-new-start/nocal/jan-17-a-new-start-nocal-1400×1050.jpg
  121. 121 http://files.smashingmagazine.com/wallpapers/jan-17/a-new-start/nocal/jan-17-a-new-start-nocal-1440×900.jpg
  122. 122 http://files.smashingmagazine.com/wallpapers/jan-17/a-new-start/nocal/jan-17-a-new-start-nocal-1600×1200.jpg
  123. 123 http://files.smashingmagazine.com/wallpapers/jan-17/a-new-start/nocal/jan-17-a-new-start-nocal-1680×1050.jpg
  124. 124 http://files.smashingmagazine.com/wallpapers/jan-17/a-new-start/nocal/jan-17-a-new-start-nocal-1680×1200.jpg
  125. 125 http://files.smashingmagazine.com/wallpapers/jan-17/a-new-start/nocal/jan-17-a-new-start-nocal-1920×1080.jpg
  126. 126 http://files.smashingmagazine.com/wallpapers/jan-17/a-new-start/nocal/jan-17-a-new-start-nocal-1920×1200.jpg
  127. 127 http://files.smashingmagazine.com/wallpapers/jan-17/a-new-start/nocal/jan-17-a-new-start-nocal-1920×1440.jpg
  128. 128 http://files.smashingmagazine.com/wallpapers/jan-17/a-new-start/nocal/jan-17-a-new-start-nocal-2560×1440.jpg
  129. 129 http://acodez.in/
  130. 130 http://files.smashingmagazine.com/wallpapers/jan-17/happy-hot-tea-month/jan-17-happy-hot-tea-month-full.png
  131. 131 http://files.smashingmagazine.com/wallpapers/jan-17/happy-hot-tea-month/jan-17-happy-hot-tea-month-preview.png
  132. 132 http://files.smashingmagazine.com/wallpapers/jan-17/happy-hot-tea-month/cal/jan-17-happy-hot-tea-month-cal-320×480.png
  133. 133 http://files.smashingmagazine.com/wallpapers/jan-17/happy-hot-tea-month/cal/jan-17-happy-hot-tea-month-cal-640×480.png
  134. 134 http://files.smashingmagazine.com/wallpapers/jan-17/happy-hot-tea-month/cal/jan-17-happy-hot-tea-month-cal-800×480.png
  135. 135 http://files.smashingmagazine.com/wallpapers/jan-17/happy-hot-tea-month/cal/jan-17-happy-hot-tea-month-cal-800×600.png
  136. 136 http://files.smashingmagazine.com/wallpapers/jan-17/happy-hot-tea-month/cal/jan-17-happy-hot-tea-month-cal-1024×768.png
  137. 137 http://files.smashingmagazine.com/wallpapers/jan-17/happy-hot-tea-month/cal/jan-17-happy-hot-tea-month-cal-1024×1024.png
  138. 138 http://files.smashingmagazine.com/wallpapers/jan-17/happy-hot-tea-month/cal/jan-17-happy-hot-tea-month-cal-1152×864.png
  139. 139 http://files.smashingmagazine.com/wallpapers/jan-17/happy-hot-tea-month/cal/jan-17-happy-hot-tea-month-cal-1280×720.png
  140. 140 http://files.smashingmagazine.com/wallpapers/jan-17/happy-hot-tea-month/cal/jan-17-happy-hot-tea-month-cal-1280×960.png
  141. 141 http://files.smashingmagazine.com/wallpapers/jan-17/happy-hot-tea-month/cal/jan-17-happy-hot-tea-month-cal-1280×1024.png
  142. 142 http://files.smashingmagazine.com/wallpapers/jan-17/happy-hot-tea-month/cal/jan-17-happy-hot-tea-month-cal-1366×768.png
  143. 143 http://files.smashingmagazine.com/wallpapers/jan-17/happy-hot-tea-month/cal/jan-17-happy-hot-tea-month-cal-1400×1050.png
  144. 144 http://files.smashingmagazine.com/wallpapers/jan-17/happy-hot-tea-month/cal/jan-17-happy-hot-tea-month-cal-1440×900.png
  145. 145 http://files.smashingmagazine.com/wallpapers/jan-17/happy-hot-tea-month/cal/jan-17-happy-hot-tea-month-cal-1600×1200.png
  146. 146 http://files.smashingmagazine.com/wallpapers/jan-17/happy-hot-tea-month/cal/jan-17-happy-hot-tea-month-cal-1680×1050.png
  147. 147 http://files.smashingmagazine.com/wallpapers/jan-17/happy-hot-tea-month/cal/jan-17-happy-hot-tea-month-cal-1680×1200.png
  148. 148 http://files.smashingmagazine.com/wallpapers/jan-17/happy-hot-tea-month/cal/jan-17-happy-hot-tea-month-cal-1920×1080.png
  149. 149 http://files.smashingmagazine.com/wallpapers/jan-17/happy-hot-tea-month/cal/jan-17-happy-hot-tea-month-cal-1920×1200.png
  150. 150 http://files.smashingmagazine.com/wallpapers/jan-17/happy-hot-tea-month/cal/jan-17-happy-hot-tea-month-cal-1920×1440.png
  151. 151 http://files.smashingmagazine.com/wallpapers/jan-17/happy-hot-tea-month/cal/jan-17-happy-hot-tea-month-cal-2560×1440.png
  152. 152 http://files.smashingmagazine.com/wallpapers/jan-17/happy-hot-tea-month/nocal/jan-17-happy-hot-tea-month-nocal-320×480.png
  153. 153 http://files.smashingmagazine.com/wallpapers/jan-17/happy-hot-tea-month/nocal/jan-17-happy-hot-tea-month-nocal-640×480.png
  154. 154 http://files.smashingmagazine.com/wallpapers/jan-17/happy-hot-tea-month/nocal/jan-17-happy-hot-tea-month-nocal-800×480.png
  155. 155 http://files.smashingmagazine.com/wallpapers/jan-17/happy-hot-tea-month/nocal/jan-17-happy-hot-tea-month-nocal-800×600.png
  156. 156 http://files.smashingmagazine.com/wallpapers/jan-17/happy-hot-tea-month/nocal/jan-17-happy-hot-tea-month-nocal-1024×768.png
  157. 157 http://files.smashingmagazine.com/wallpapers/jan-17/happy-hot-tea-month/nocal/jan-17-happy-hot-tea-month-nocal-1024×1024.png
  158. 158 http://files.smashingmagazine.com/wallpapers/jan-17/happy-hot-tea-month/nocal/jan-17-happy-hot-tea-month-nocal-1152×864.png
  159. 159 http://files.smashingmagazine.com/wallpapers/jan-17/happy-hot-tea-month/nocal/jan-17-happy-hot-tea-month-nocal-1280×720.png
  160. 160 http://files.smashingmagazine.com/wallpapers/jan-17/happy-hot-tea-month/nocal/jan-17-happy-hot-tea-month-nocal-1280×960.png
  161. 161 http://files.smashingmagazine.com/wallpapers/jan-17/happy-hot-tea-month/nocal/jan-17-happy-hot-tea-month-nocal-1280×1024.png
  162. 162 http://files.smashingmagazine.com/wallpapers/jan-17/happy-hot-tea-month/nocal/jan-17-happy-hot-tea-month-nocal-1366×768.png
  163. 163 http://files.smashingmagazine.com/wallpapers/jan-17/happy-hot-tea-month/nocal/jan-17-happy-hot-tea-month-nocal-1400×1050.png
  164. 164 http://files.smashingmagazine.com/wallpapers/jan-17/happy-hot-tea-month/nocal/jan-17-happy-hot-tea-month-nocal-1440×900.png
  165. 165 http://files.smashingmagazine.com/wallpapers/jan-17/happy-hot-tea-month/nocal/jan-17-happy-hot-tea-month-nocal-1600×1200.png
  166. 166 http://files.smashingmagazine.com/wallpapers/jan-17/happy-hot-tea-month/nocal/jan-17-happy-hot-tea-month-nocal-1680×1050.png
  167. 167 http://files.smashingmagazine.com/wallpapers/jan-17/happy-hot-tea-month/nocal/jan-17-happy-hot-tea-month-nocal-1680×1200.png
  168. 168 http://files.smashingmagazine.com/wallpapers/jan-17/happy-hot-tea-month/nocal/jan-17-happy-hot-tea-month-nocal-1920×1080.png
  169. 169 http://files.smashingmagazine.com/wallpapers/jan-17/happy-hot-tea-month/nocal/jan-17-happy-hot-tea-month-nocal-1920×1200.png
  170. 170 http://files.smashingmagazine.com/wallpapers/jan-17/happy-hot-tea-month/nocal/jan-17-happy-hot-tea-month-nocal-1920×1440.png
  171. 171 http://files.smashingmagazine.com/wallpapers/jan-17/happy-hot-tea-month/nocal/jan-17-happy-hot-tea-month-nocal-2560×1440.png
  172. 172 https://www.facebook.com/Barberrydesign/
  173. 173 http://files.smashingmagazine.com/wallpapers/jan-17/love-makes-you-warm/jan-17-love-makes-you-warm-full.png
  174. 174 http://files.smashingmagazine.com/wallpapers/jan-17/love-makes-you-warm/jan-17-love-makes-you-warm-preview.png
  175. 175 http://files.smashingmagazine.com/wallpapers/jan-17/love-makes-you-warm/cal/jan-17-love-makes-you-warm-cal-320×480.png
  176. 176 http://files.smashingmagazine.com/wallpapers/jan-17/love-makes-you-warm/cal/jan-17-love-makes-you-warm-cal-640×480.png
  177. 177 http://files.smashingmagazine.com/wallpapers/jan-17/love-makes-you-warm/cal/jan-17-love-makes-you-warm-cal-1024×768.png
  178. 178 http://files.smashingmagazine.com/wallpapers/jan-17/love-makes-you-warm/cal/jan-17-love-makes-you-warm-cal-1280×720.png
  179. 179 http://files.smashingmagazine.com/wallpapers/jan-17/love-makes-you-warm/cal/jan-17-love-makes-you-warm-cal-1280×800.png
  180. 180 http://files.smashingmagazine.com/wallpapers/jan-17/love-makes-you-warm/cal/jan-17-love-makes-you-warm-cal-1680×1050.png
  181. 181 http://files.smashingmagazine.com/wallpapers/jan-17/love-makes-you-warm/cal/jan-17-love-makes-you-warm-cal-1920×1200.png
  182. 182 http://files.smashingmagazine.com/wallpapers/jan-17/love-makes-you-warm/cal/jan-17-love-makes-you-warm-cal-2560×1440.png
  183. 183 http://files.smashingmagazine.com/wallpapers/jan-17/love-makes-you-warm/nocal/jan-17-love-makes-you-warm-nocal-320×480.png
  184. 184 http://files.smashingmagazine.com/wallpapers/jan-17/love-makes-you-warm/nocal/jan-17-love-makes-you-warm-nocal-640×480.png
  185. 185 http://files.smashingmagazine.com/wallpapers/jan-17/love-makes-you-warm/nocal/jan-17-love-makes-you-warm-nocal-1024×768.png
  186. 186 http://files.smashingmagazine.com/wallpapers/jan-17/love-makes-you-warm/nocal/jan-17-love-makes-you-warm-nocal-1280×720.png
  187. 187 http://files.smashingmagazine.com/wallpapers/jan-17/love-makes-you-warm/nocal/jan-17-love-makes-you-warm-nocal-1280×800.png
  188. 188 http://files.smashingmagazine.com/wallpapers/jan-17/love-makes-you-warm/nocal/jan-17-love-makes-you-warm-nocal-1680×1050.png
  189. 189 http://files.smashingmagazine.com/wallpapers/jan-17/love-makes-you-warm/nocal/jan-17-love-makes-you-warm-nocal-1920×1200.png
  190. 190 http://files.smashingmagazine.com/wallpapers/jan-17/love-makes-you-warm/nocal/jan-17-love-makes-you-warm-nocal-2560×1440.png
  191. 191 http://www.tazi.com.au
  192. 192 http://files.smashingmagazine.com/wallpapers/jan-17/hello-summer-in-australia/jan-17-hello-summer-in-australia-full.png
  193. 193 http://files.smashingmagazine.com/wallpapers/jan-17/hello-summer-in-australia/jan-17-hello-summer-in-australia-preview.png
  194. 194 http://files.smashingmagazine.com/wallpapers/jan-17/hello-summer-in-australia/cal/jan-17-hello-summer-in-australia-cal-320×480.png
  195. 195 http://files.smashingmagazine.com/wallpapers/jan-17/hello-summer-in-australia/cal/jan-17-hello-summer-in-australia-cal-640×480.png
  196. 196 http://files.smashingmagazine.com/wallpapers/jan-17/hello-summer-in-australia/cal/jan-17-hello-summer-in-australia-cal-800×600.png
  197. 197 http://files.smashingmagazine.com/wallpapers/jan-17/hello-summer-in-australia/cal/jan-17-hello-summer-in-australia-cal-1024×768.png
  198. 198 http://files.smashingmagazine.com/wallpapers/jan-17/hello-summer-in-australia/cal/jan-17-hello-summer-in-australia-cal-1152×864.png
  199. 199 http://files.smashingmagazine.com/wallpapers/jan-17/hello-summer-in-australia/cal/jan-17-hello-summer-in-australia-cal-1280×720.png
  200. 200 http://files.smashingmagazine.com/wallpapers/jan-17/hello-summer-in-australia/cal/jan-17-hello-summer-in-australia-cal-1280×960.png
  201. 201 http://files.smashingmagazine.com/wallpapers/jan-17/hello-summer-in-australia/cal/jan-17-hello-summer-in-australia-cal-1600×1200.png
  202. 202 http://files.smashingmagazine.com/wallpapers/jan-17/hello-summer-in-australia/cal/jan-17-hello-summer-in-australia-cal-1920×1080.png
  203. 203 http://files.smashingmagazine.com/wallpapers/jan-17/hello-summer-in-australia/cal/jan-17-hello-summer-in-australia-cal-1920×1440.png
  204. 204 http://files.smashingmagazine.com/wallpapers/jan-17/hello-summer-in-australia/cal/jan-17-hello-summer-in-australia-cal-2560×1440.png
  205. 205 http://files.smashingmagazine.com/wallpapers/jan-17/hello-summer-in-australia/nocal/jan-17-hello-summer-in-australia-nocal-320×480.png
  206. 206 http://files.smashingmagazine.com/wallpapers/jan-17/hello-summer-in-australia/nocal/jan-17-hello-summer-in-australia-nocal-640×480.png
  207. 207 http://files.smashingmagazine.com/wallpapers/jan-17/hello-summer-in-australia/nocal/jan-17-hello-summer-in-australia-nocal-800×600.png
  208. 208 http://files.smashingmagazine.com/wallpapers/jan-17/hello-summer-in-australia/nocal/jan-17-hello-summer-in-australia-nocal-1024×768.png
  209. 209 http://files.smashingmagazine.com/wallpapers/jan-17/hello-summer-in-australia/nocal/jan-17-hello-summer-in-australia-nocal-1152×864.png
  210. 210 http://files.smashingmagazine.com/wallpapers/jan-17/hello-summer-in-australia/nocal/jan-17-hello-summer-in-australia-nocal-1280×720.png
  211. 211 http://files.smashingmagazine.com/wallpapers/jan-17/hello-summer-in-australia/nocal/jan-17-hello-summer-in-australia-nocal-1280×960.png
  212. 212 http://files.smashingmagazine.com/wallpapers/jan-17/hello-summer-in-australia/nocal/jan-17-hello-summer-in-australia-nocal-1600×1200.png
  213. 213 http://files.smashingmagazine.com/wallpapers/jan-17/hello-summer-in-australia/nocal/jan-17-hello-summer-in-australia-nocal-1920×1080.png
  214. 214 http://files.smashingmagazine.com/wallpapers/jan-17/hello-summer-in-australia/nocal/jan-17-hello-summer-in-australia-nocal-1920×1440.png
  215. 215 http://files.smashingmagazine.com/wallpapers/jan-17/hello-summer-in-australia/nocal/jan-17-hello-summer-in-australia-nocal-2560×1440.png
  216. 216 http://www.katherine-appleby.com
  217. 217 http://files.smashingmagazine.com/wallpapers/jan-17/summer-celebration/jan-17-summer-celebration-full.png
  218. 218 http://files.smashingmagazine.com/wallpapers/jan-17/summer-celebration/jan-17-summer-celebration-preview.png
  219. 219 http://files.smashingmagazine.com/wallpapers/jan-17/summer-celebration/cal/jan-17-summer-celebration-cal-320×480.png
  220. 220 http://files.smashingmagazine.com/wallpapers/jan-17/summer-celebration/cal/jan-17-summer-celebration-cal-640×480.png
  221. 221 http://files.smashingmagazine.com/wallpapers/jan-17/summer-celebration/cal/jan-17-summer-celebration-cal-800×480.png
  222. 222 http://files.smashingmagazine.com/wallpapers/jan-17/summer-celebration/cal/jan-17-summer-celebration-cal-800×600.png
  223. 223 http://files.smashingmagazine.com/wallpapers/jan-17/summer-celebration/cal/jan-17-summer-celebration-cal-1024×768.png
  224. 224 http://files.smashingmagazine.com/wallpapers/jan-17/summer-celebration/cal/jan-17-summer-celebration-cal-1024×1024.png
  225. 225 http://files.smashingmagazine.com/wallpapers/jan-17/summer-celebration/cal/jan-17-summer-celebration-cal-1152×864.png
  226. 226 http://files.smashingmagazine.com/wallpapers/jan-17/summer-celebration/cal/jan-17-summer-celebration-cal-1280×720.png
  227. 227 http://files.smashingmagazine.com/wallpapers/jan-17/summer-celebration/cal/jan-17-summer-celebration-cal-1280×800.png
  228. 228 http://files.smashingmagazine.com/wallpapers/jan-17/summer-celebration/cal/jan-17-summer-celebration-cal-1280×960.png
  229. 229 http://files.smashingmagazine.com/wallpapers/jan-17/summer-celebration/cal/jan-17-summer-celebration-cal-1280×1024.png
  230. 230 http://files.smashingmagazine.com/wallpapers/jan-17/summer-celebration/cal/jan-17-summer-celebration-cal-1400×1050.png
  231. 231 http://files.smashingmagazine.com/wallpapers/jan-17/summer-celebration/cal/jan-17-summer-celebration-cal-1440×900.png
  232. 232 http://files.smashingmagazine.com/wallpapers/jan-17/summer-celebration/cal/jan-17-summer-celebration-cal-1600×1200.png
  233. 233 http://files.smashingmagazine.com/wallpapers/jan-17/summer-celebration/cal/jan-17-summer-celebration-cal-1680×1050.png
  234. 234 http://files.smashingmagazine.com/wallpapers/jan-17/summer-celebration/cal/jan-17-summer-celebration-cal-1680×1200.png
  235. 235 http://files.smashingmagazine.com/wallpapers/jan-17/summer-celebration/cal/jan-17-summer-celebration-cal-1920×1080.png
  236. 236 http://files.smashingmagazine.com/wallpapers/jan-17/summer-celebration/cal/jan-17-summer-celebration-cal-1920×1200.png
  237. 237 http://files.smashingmagazine.com/wallpapers/jan-17/summer-celebration/cal/jan-17-summer-celebration-cal-1920×1440.png
  238. 238 http://files.smashingmagazine.com/wallpapers/jan-17/summer-celebration/cal/jan-17-summer-celebration-cal-2560×1440.png
  239. 239 http://files.smashingmagazine.com/wallpapers/jan-17/summer-celebration/nocal/jan-17-summer-celebration-nocal-320×480.png
  240. 240 http://files.smashingmagazine.com/wallpapers/jan-17/summer-celebration/nocal/jan-17-summer-celebration-nocal-640×480.png
  241. 241 http://files.smashingmagazine.com/wallpapers/jan-17/summer-celebration/nocal/jan-17-summer-celebration-nocal-800×480.png
  242. 242 http://files.smashingmagazine.com/wallpapers/jan-17/summer-celebration/nocal/jan-17-summer-celebration-nocal-800×600.png
  243. 243 http://files.smashingmagazine.com/wallpapers/jan-17/summer-celebration/nocal/jan-17-summer-celebration-nocal-1024×768.png
  244. 244 http://files.smashingmagazine.com/wallpapers/jan-17/summer-celebration/nocal/jan-17-summer-celebration-nocal-1024×1024.png
  245. 245 http://files.smashingmagazine.com/wallpapers/jan-17/summer-celebration/nocal/jan-17-summer-celebration-nocal-1152×864.png
  246. 246 http://files.smashingmagazine.com/wallpapers/jan-17/summer-celebration/nocal/jan-17-summer-celebration-nocal-1280×720.png
  247. 247 http://files.smashingmagazine.com/wallpapers/jan-17/summer-celebration/nocal/jan-17-summer-celebration-nocal-1280×800.png
  248. 248 http://files.smashingmagazine.com/wallpapers/jan-17/summer-celebration/nocal/jan-17-summer-celebration-nocal-1280×960.png
  249. 249 http://files.smashingmagazine.com/wallpapers/jan-17/summer-celebration/nocal/jan-17-summer-celebration-nocal-1280×1024.png
  250. 250 http://files.smashingmagazine.com/wallpapers/jan-17/summer-celebration/nocal/jan-17-summer-celebration-nocal-1400×1050.png
  251. 251 http://files.smashingmagazine.com/wallpapers/jan-17/summer-celebration/nocal/jan-17-summer-celebration-nocal-1440×900.png
  252. 252 http://files.smashingmagazine.com/wallpapers/jan-17/summer-celebration/nocal/jan-17-summer-celebration-nocal-1600×1200.png
  253. 253 http://files.smashingmagazine.com/wallpapers/jan-17/summer-celebration/nocal/jan-17-summer-celebration-nocal-1680×1050.png
  254. 254 http://files.smashingmagazine.com/wallpapers/jan-17/summer-celebration/nocal/jan-17-summer-celebration-nocal-1680×1200.png
  255. 255 http://files.smashingmagazine.com/wallpapers/jan-17/summer-celebration/nocal/jan-17-summer-celebration-nocal-1920×1080.png
  256. 256 http://files.smashingmagazine.com/wallpapers/jan-17/summer-celebration/nocal/jan-17-summer-celebration-nocal-1920×1200.png
  257. 257 http://files.smashingmagazine.com/wallpapers/jan-17/summer-celebration/nocal/jan-17-summer-celebration-nocal-1920×1440.png
  258. 258 http://files.smashingmagazine.com/wallpapers/jan-17/summer-celebration/nocal/jan-17-summer-celebration-nocal-2560×1440.png
  259. 259 http://lucasdebelder.be/
  260. 260 http://files.smashingmagazine.com/wallpapers/jan-17/2017-the-year-of-the-rooster/jan-17-2017-the-year-of-the-rooster-full.png
  261. 261 http://files.smashingmagazine.com/wallpapers/jan-17/2017-the-year-of-the-rooster/jan-17-2017-the-year-of-the-rooster-preview.png
  262. 262 http://files.smashingmagazine.com/wallpapers/jan-17/2017-the-year-of-the-rooster/cal/jan-17-2017-the-year-of-the-rooster-cal-320×480.png
  263. 263 http://files.smashingmagazine.com/wallpapers/jan-17/2017-the-year-of-the-rooster/cal/jan-17-2017-the-year-of-the-rooster-cal-640×480.png
  264. 264 http://files.smashingmagazine.com/wallpapers/jan-17/2017-the-year-of-the-rooster/cal/jan-17-2017-the-year-of-the-rooster-cal-800×480.png
  265. 265 http://files.smashingmagazine.com/wallpapers/jan-17/2017-the-year-of-the-rooster/cal/jan-17-2017-the-year-of-the-rooster-cal-800×600.png
  266. 266 http://files.smashingmagazine.com/wallpapers/jan-17/2017-the-year-of-the-rooster/cal/jan-17-2017-the-year-of-the-rooster-cal-1024×768.png
  267. 267 http://files.smashingmagazine.com/wallpapers/jan-17/2017-the-year-of-the-rooster/cal/jan-17-2017-the-year-of-the-rooster-cal-1024×1024.png
  268. 268 http://files.smashingmagazine.com/wallpapers/jan-17/2017-the-year-of-the-rooster/cal/jan-17-2017-the-year-of-the-rooster-cal-1152×864.png
  269. 269 http://files.smashingmagazine.com/wallpapers/jan-17/2017-the-year-of-the-rooster/cal/jan-17-2017-the-year-of-the-rooster-cal-1280×720.png
  270. 270 http://files.smashingmagazine.com/wallpapers/jan-17/2017-the-year-of-the-rooster/cal/jan-17-2017-the-year-of-the-rooster-cal-1280×800.png
  271. 271 http://files.smashingmagazine.com/wallpapers/jan-17/2017-the-year-of-the-rooster/cal/jan-17-2017-the-year-of-the-rooster-cal-1280×960.png
  272. 272 http://files.smashingmagazine.com/wallpapers/jan-17/2017-the-year-of-the-rooster/cal/jan-17-2017-the-year-of-the-rooster-cal-1280×1024.png
  273. 273 http://files.smashingmagazine.com/wallpapers/jan-17/2017-the-year-of-the-rooster/cal/jan-17-2017-the-year-of-the-rooster-cal-1400×1050.png
  274. 274 http://files.smashingmagazine.com/wallpapers/jan-17/2017-the-year-of-the-rooster/cal/jan-17-2017-the-year-of-the-rooster-cal-1440×900.png
  275. 275 http://files.smashingmagazine.com/wallpapers/jan-17/2017-the-year-of-the-rooster/cal/jan-17-2017-the-year-of-the-rooster-cal-1600×1200.png
  276. 276 http://files.smashingmagazine.com/wallpapers/jan-17/2017-the-year-of-the-rooster/cal/jan-17-2017-the-year-of-the-rooster-cal-1680×1050.png
  277. 277 http://files.smashingmagazine.com/wallpapers/jan-17/2017-the-year-of-the-rooster/cal/jan-17-2017-the-year-of-the-rooster-cal-1680×1200.png
  278. 278 http://files.smashingmagazine.com/wallpapers/jan-17/2017-the-year-of-the-rooster/cal/jan-17-2017-the-year-of-the-rooster-cal-1920×1080.png
  279. 279 http://files.smashingmagazine.com/wallpapers/jan-17/2017-the-year-of-the-rooster/cal/jan-17-2017-the-year-of-the-rooster-cal-1920×1200.png
  280. 280 http://files.smashingmagazine.com/wallpapers/jan-17/2017-the-year-of-the-rooster/cal/jan-17-2017-the-year-of-the-rooster-cal-1920×1440.png
  281. 281 http://files.smashingmagazine.com/wallpapers/jan-17/2017-the-year-of-the-rooster/cal/jan-17-2017-the-year-of-the-rooster-cal-2560×1440.png
  282. 282 http://files.smashingmagazine.com/wallpapers/jan-17/2017-the-year-of-the-rooster/cal/jan-17-2017-the-year-of-the-rooster-cal-3840×2160.png
  283. 283 http://files.smashingmagazine.com/wallpapers/jan-17/2017-the-year-of-the-rooster/nocal/jan-17-2017-the-year-of-the-rooster-nocal-320×480.png
  284. 284 http://files.smashingmagazine.com/wallpapers/jan-17/2017-the-year-of-the-rooster/nocal/jan-17-2017-the-year-of-the-rooster-nocal-640×480.png
  285. 285 http://files.smashingmagazine.com/wallpapers/jan-17/2017-the-year-of-the-rooster/nocal/jan-17-2017-the-year-of-the-rooster-nocal-800×480.png
  286. 286 http://files.smashingmagazine.com/wallpapers/jan-17/2017-the-year-of-the-rooster/nocal/jan-17-2017-the-year-of-the-rooster-nocal-800×600.png
  287. 287 http://files.smashingmagazine.com/wallpapers/jan-17/2017-the-year-of-the-rooster/nocal/jan-17-2017-the-year-of-the-rooster-nocal-1024×768.png
  288. 288 http://files.smashingmagazine.com/wallpapers/jan-17/2017-the-year-of-the-rooster/nocal/jan-17-2017-the-year-of-the-rooster-nocal-1024×1024.png
  289. 289 http://files.smashingmagazine.com/wallpapers/jan-17/2017-the-year-of-the-rooster/nocal/jan-17-2017-the-year-of-the-rooster-nocal-1152×864.png
  290. 290 http://files.smashingmagazine.com/wallpapers/jan-17/2017-the-year-of-the-rooster/nocal/jan-17-2017-the-year-of-the-rooster-nocal-1280×720.png
  291. 291 http://files.smashingmagazine.com/wallpapers/jan-17/2017-the-year-of-the-rooster/nocal/jan-17-2017-the-year-of-the-rooster-nocal-1280×800.png
  292. 292 http://files.smashingmagazine.com/wallpapers/jan-17/2017-the-year-of-the-rooster/nocal/jan-17-2017-the-year-of-the-rooster-nocal-1280×960.png
  293. 293 http://files.smashingmagazine.com/wallpapers/jan-17/2017-the-year-of-the-rooster/nocal/jan-17-2017-the-year-of-the-rooster-nocal-1280×1024.png
  294. 294 http://files.smashingmagazine.com/wallpapers/jan-17/2017-the-year-of-the-rooster/nocal/jan-17-2017-the-year-of-the-rooster-nocal-1400×1050.png
  295. 295 http://files.smashingmagazine.com/wallpapers/jan-17/2017-the-year-of-the-rooster/nocal/jan-17-2017-the-year-of-the-rooster-nocal-1440×900.png
  296. 296 http://files.smashingmagazine.com/wallpapers/jan-17/2017-the-year-of-the-rooster/nocal/jan-17-2017-the-year-of-the-rooster-nocal-1600×1200.png
  297. 297 http://files.smashingmagazine.com/wallpapers/jan-17/2017-the-year-of-the-rooster/nocal/jan-17-2017-the-year-of-the-rooster-nocal-1680×1050.png
  298. 298 http://files.smashingmagazine.com/wallpapers/jan-17/2017-the-year-of-the-rooster/nocal/jan-17-2017-the-year-of-the-rooster-nocal-1680×1200.png
  299. 299 http://files.smashingmagazine.com/wallpapers/jan-17/2017-the-year-of-the-rooster/nocal/jan-17-2017-the-year-of-the-rooster-nocal-1920×1080.png
  300. 300 http://files.smashingmagazine.com/wallpapers/jan-17/2017-the-year-of-the-rooster/nocal/jan-17-2017-the-year-of-the-rooster-nocal-1920×1200.png
  301. 301 http://files.smashingmagazine.com/wallpapers/jan-17/2017-the-year-of-the-rooster/nocal/jan-17-2017-the-year-of-the-rooster-nocal-1920×1440.png
  302. 302 http://files.smashingmagazine.com/wallpapers/jan-17/2017-the-year-of-the-rooster/nocal/jan-17-2017-the-year-of-the-rooster-nocal-2560×1440.png
  303. 303 http://files.smashingmagazine.com/wallpapers/jan-17/2017-the-year-of-the-rooster/nocal/jan-17-2017-the-year-of-the-rooster-nocal-3840×2160.png
  304. 304 http://www.popwebdesign.net/index_eng.html
  305. 305 http://files.smashingmagazine.com/wallpapers/jan-17/new-beginnings/jan-17-new-beginnings-full.jpg
  306. 306 http://files.smashingmagazine.com/wallpapers/jan-17/new-beginnings/jan-17-new-beginnings-preview.jpg
  307. 307 http://files.smashingmagazine.com/wallpapers/jan-17/new-beginnings/cal/jan-17-new-beginnings-cal-320×480.jpg
  308. 308 http://files.smashingmagazine.com/wallpapers/jan-17/new-beginnings/cal/jan-17-new-beginnings-cal-640×480.jpg
  309. 309 http://files.smashingmagazine.com/wallpapers/jan-17/new-beginnings/cal/jan-17-new-beginnings-cal-800×480.jpg
  310. 310 http://files.smashingmagazine.com/wallpapers/jan-17/new-beginnings/cal/jan-17-new-beginnings-cal-800×600.jpg
  311. 311 http://files.smashingmagazine.com/wallpapers/jan-17/new-beginnings/cal/jan-17-new-beginnings-cal-1024×768.jpg
  312. 312 http://files.smashingmagazine.com/wallpapers/jan-17/new-beginnings/cal/jan-17-new-beginnings-cal-1152×864.jpg
  313. 313 http://files.smashingmagazine.com/wallpapers/jan-17/new-beginnings/cal/jan-17-new-beginnings-cal-1280×720.jpg
  314. 314 http://files.smashingmagazine.com/wallpapers/jan-17/new-beginnings/cal/jan-17-new-beginnings-cal-1280×800.jpg
  315. 315 http://files.smashingmagazine.com/wallpapers/jan-17/new-beginnings/cal/jan-17-new-beginnings-cal-1280×960.jpg
  316. 316 http://files.smashingmagazine.com/wallpapers/jan-17/new-beginnings/cal/jan-17-new-beginnings-cal-1280×1024.jpg
  317. 317 http://files.smashingmagazine.com/wallpapers/jan-17/new-beginnings/cal/jan-17-new-beginnings-cal-1400×1050.jpg
  318. 318 http://files.smashingmagazine.com/wallpapers/jan-17/new-beginnings/cal/jan-17-new-beginnings-cal-1440×900.jpg
  319. 319 http://files.smashingmagazine.com/wallpapers/jan-17/new-beginnings/cal/jan-17-new-beginnings-cal-1600×1200.jpg
  320. 320 http://files.smashingmagazine.com/wallpapers/jan-17/new-beginnings/cal/jan-17-new-beginnings-cal-1680×1050.jpg
  321. 321 http://files.smashingmagazine.com/wallpapers/jan-17/new-beginnings/cal/jan-17-new-beginnings-cal-1680×1200.jpg
  322. 322 http://files.smashingmagazine.com/wallpapers/jan-17/new-beginnings/cal/jan-17-new-beginnings-cal-1920×1080.jpg
  323. 323 http://files.smashingmagazine.com/wallpapers/jan-17/new-beginnings/cal/jan-17-new-beginnings-cal-1920×1200.jpg
  324. 324 http://files.smashingmagazine.com/wallpapers/jan-17/new-beginnings/cal/jan-17-new-beginnings-cal-1920×1440.jpg
  325. 325 http://files.smashingmagazine.com/wallpapers/jan-17/new-beginnings/cal/jan-17-new-beginnings-cal-2560×1440.jpg
  326. 326 http://files.smashingmagazine.com/wallpapers/jan-17/new-beginnings/nocal/jan-17-new-beginnings-nocal-320×480.jpg
  327. 327 http://files.smashingmagazine.com/wallpapers/jan-17/new-beginnings/nocal/jan-17-new-beginnings-nocal-640×480.jpg
  328. 328 http://files.smashingmagazine.com/wallpapers/jan-17/new-beginnings/nocal/jan-17-new-beginnings-nocal-800×480.jpg
  329. 329 http://files.smashingmagazine.com/wallpapers/jan-17/new-beginnings/nocal/jan-17-new-beginnings-nocal-800×600.jpg
  330. 330 http://files.smashingmagazine.com/wallpapers/jan-17/new-beginnings/nocal/jan-17-new-beginnings-nocal-1024×768.jpg
  331. 331 http://files.smashingmagazine.com/wallpapers/jan-17/new-beginnings/nocal/jan-17-new-beginnings-nocal-1152×864.jpg
  332. 332 http://files.smashingmagazine.com/wallpapers/jan-17/new-beginnings/nocal/jan-17-new-beginnings-nocal-1280×720.jpg
  333. 333 http://files.smashingmagazine.com/wallpapers/jan-17/new-beginnings/nocal/jan-17-new-beginnings-nocal-1280×800.jpg
  334. 334 http://files.smashingmagazine.com/wallpapers/jan-17/new-beginnings/nocal/jan-17-new-beginnings-nocal-1280×960.jpg
  335. 335 http://files.smashingmagazine.com/wallpapers/jan-17/new-beginnings/nocal/jan-17-new-beginnings-nocal-1280×1024.jpg
  336. 336 http://files.smashingmagazine.com/wallpapers/jan-17/new-beginnings/nocal/jan-17-new-beginnings-nocal-1400×1050.jpg
  337. 337 http://files.smashingmagazine.com/wallpapers/jan-17/new-beginnings/nocal/jan-17-new-beginnings-nocal-1440×900.jpg
  338. 338 http://files.smashingmagazine.com/wallpapers/jan-17/new-beginnings/nocal/jan-17-new-beginnings-nocal-1600×1200.jpg
  339. 339 http://files.smashingmagazine.com/wallpapers/jan-17/new-beginnings/nocal/jan-17-new-beginnings-nocal-1680×1050.jpg
  340. 340 http://files.smashingmagazine.com/wallpapers/jan-17/new-beginnings/nocal/jan-17-new-beginnings-nocal-1680×1200.jpg
  341. 341 http://files.smashingmagazine.com/wallpapers/jan-17/new-beginnings/nocal/jan-17-new-beginnings-nocal-1920×1080.jpg
  342. 342 http://files.smashingmagazine.com/wallpapers/jan-17/new-beginnings/nocal/jan-17-new-beginnings-nocal-1920×1200.jpg
  343. 343 http://files.smashingmagazine.com/wallpapers/jan-17/new-beginnings/nocal/jan-17-new-beginnings-nocal-1920×1440.jpg
  344. 344 http://files.smashingmagazine.com/wallpapers/jan-17/new-beginnings/nocal/jan-17-new-beginnings-nocal-2560×1440.jpg
  345. 345 http://liapantazi.com
  346. 346 http://files.smashingmagazine.com/wallpapers/jan-17/year-of-the-rooster/jan-17-year-of-the-rooster-full.jpg
  347. 347 http://files.smashingmagazine.com/wallpapers/jan-17/year-of-the-rooster/jan-17-year-of-the-rooster-preview.jpg
  348. 348 http://files.smashingmagazine.com/wallpapers/jan-17/year-of-the-rooster/cal/jan-17-year-of-the-rooster-cal-640×480.jpg
  349. 349 http://files.smashingmagazine.com/wallpapers/jan-17/year-of-the-rooster/cal/jan-17-year-of-the-rooster-cal-800×600.jpg
  350. 350 http://files.smashingmagazine.com/wallpapers/jan-17/year-of-the-rooster/cal/jan-17-year-of-the-rooster-cal-1024×768.jpg
  351. 351 http://files.smashingmagazine.com/wallpapers/jan-17/year-of-the-rooster/cal/jan-17-year-of-the-rooster-cal-1152×864.jpg
  352. 352 http://files.smashingmagazine.com/wallpapers/jan-17/year-of-the-rooster/cal/jan-17-year-of-the-rooster-cal-1280×720.jpg
  353. 353 http://files.smashingmagazine.com/wallpapers/jan-17/year-of-the-rooster/cal/jan-17-year-of-the-rooster-cal-1280×800.jpg
  354. 354 http://files.smashingmagazine.com/wallpapers/jan-17/year-of-the-rooster/cal/jan-17-year-of-the-rooster-cal-1280×960.jpg
  355. 355 http://files.smashingmagazine.com/wallpapers/jan-17/year-of-the-rooster/cal/jan-17-year-of-the-rooster-cal-1400×1050.jpg
  356. 356 http://files.smashingmagazine.com/wallpapers/jan-17/year-of-the-rooster/cal/jan-17-year-of-the-rooster-cal-1440×900.jpg
  357. 357 http://files.smashingmagazine.com/wallpapers/jan-17/year-of-the-rooster/cal/jan-17-year-of-the-rooster-cal-1600×1200.jpg
  358. 358 http://files.smashingmagazine.com/wallpapers/jan-17/year-of-the-rooster/cal/jan-17-year-of-the-rooster-cal-1680×1050.jpg
  359. 359 http://files.smashingmagazine.com/wallpapers/jan-17/year-of-the-rooster/cal/jan-17-year-of-the-rooster-cal-1920×1080.jpg
  360. 360 http://files.smashingmagazine.com/wallpapers/jan-17/year-of-the-rooster/cal/jan-17-year-of-the-rooster-cal-1920×1200.jpg
  361. 361 http://files.smashingmagazine.com/wallpapers/jan-17/year-of-the-rooster/cal/jan-17-year-of-the-rooster-cal-1920×1440.jpg
  362. 362 http://files.smashingmagazine.com/wallpapers/jan-17/year-of-the-rooster/cal/jan-17-year-of-the-rooster-cal-2560×1440.jpg
  363. 363 http://files.smashingmagazine.com/wallpapers/jan-17/year-of-the-rooster/cal/jan-17-year-of-the-rooster-cal-1366×768.jpg
  364. 364 http://files.smashingmagazine.com/wallpapers/jan-17/year-of-the-rooster/nocal/jan-17-year-of-the-rooster-nocal-640×480.jpg
  365. 365 http://files.smashingmagazine.com/wallpapers/jan-17/year-of-the-rooster/nocal/jan-17-year-of-the-rooster-nocal-800×600.jpg
  366. 366 http://files.smashingmagazine.com/wallpapers/jan-17/year-of-the-rooster/nocal/jan-17-year-of-the-rooster-nocal-1024×768.jpg
  367. 367 http://files.smashingmagazine.com/wallpapers/jan-17/year-of-the-rooster/nocal/jan-17-year-of-the-rooster-nocal-1152×864.jpg
  368. 368 http://files.smashingmagazine.com/wallpapers/jan-17/year-of-the-rooster/nocal/jan-17-year-of-the-rooster-nocal-1280×720.jpg
  369. 369 http://files.smashingmagazine.com/wallpapers/jan-17/year-of-the-rooster/nocal/jan-17-year-of-the-rooster-nocal-1280×800.jpg
  370. 370 http://files.smashingmagazine.com/wallpapers/jan-17/year-of-the-rooster/nocal/jan-17-year-of-the-rooster-nocal-1280×960.jpg
  371. 371 http://files.smashingmagazine.com/wallpapers/jan-17/year-of-the-rooster/nocal/jan-17-year-of-the-rooster-nocal-1400×1050.jpg
  372. 372 http://files.smashingmagazine.com/wallpapers/jan-17/year-of-the-rooster/nocal/jan-17-year-of-the-rooster-nocal-1440×900.jpg
  373. 373 http://files.smashingmagazine.com/wallpapers/jan-17/year-of-the-rooster/nocal/jan-17-year-of-the-rooster-nocal-1600×1200.jpg
  374. 374 http://files.smashingmagazine.com/wallpapers/jan-17/year-of-the-rooster/nocal/jan-17-year-of-the-rooster-nocal-1680×1050.jpg
  375. 375 http://files.smashingmagazine.com/wallpapers/jan-17/year-of-the-rooster/nocal/jan-17-year-of-the-rooster-nocal-1920×1080.jpg
  376. 376 http://files.smashingmagazine.com/wallpapers/jan-17/year-of-the-rooster/nocal/jan-17-year-of-the-rooster-nocal-1920×1200.jpg
  377. 377 http://files.smashingmagazine.com/wallpapers/jan-17/year-of-the-rooster/nocal/jan-17-year-of-the-rooster-nocal-1920×1440.jpg
  378. 378 http://files.smashingmagazine.com/wallpapers/jan-17/year-of-the-rooster/nocal/jan-17-year-of-the-rooster-nocal-2560×1440.jpg
  379. 379 http://files.smashingmagazine.com/wallpapers/jan-17/year-of-the-rooster/nocal/jan-17-year-of-the-rooster-nocal-1366×768.jpg
  380. 380 https://www.creitive.com/
  381. 381 http://files.smashingmagazine.com/wallpapers/jan-17/reindeer/jan-17-reindeer-full.png
  382. 382 http://files.smashingmagazine.com/wallpapers/jan-17/reindeer/jan-17-reindeer-preview.png
  383. 383 http://files.smashingmagazine.com/wallpapers/jan-17/reindeer/cal/jan-17-reindeer-cal-320×480.png
  384. 384 http://files.smashingmagazine.com/wallpapers/jan-17/reindeer/cal/jan-17-reindeer-cal-640×480.png
  385. 385 http://files.smashingmagazine.com/wallpapers/jan-17/reindeer/cal/jan-17-reindeer-cal-800×480.png
  386. 386 http://files.smashingmagazine.com/wallpapers/jan-17/reindeer/cal/jan-17-reindeer-cal-800×600.png
  387. 387 http://files.smashingmagazine.com/wallpapers/jan-17/reindeer/cal/jan-17-reindeer-cal-1024×768.png
  388. 388 http://files.smashingmagazine.com/wallpapers/jan-17/reindeer/cal/jan-17-reindeer-cal-1024×1024.png
  389. 389 http://files.smashingmagazine.com/wallpapers/jan-17/reindeer/cal/jan-17-reindeer-cal-1152×864.png
  390. 390 http://files.smashingmagazine.com/wallpapers/jan-17/reindeer/cal/jan-17-reindeer-cal-1280×720.png
  391. 391 http://files.smashingmagazine.com/wallpapers/jan-17/reindeer/cal/jan-17-reindeer-cal-1280×800.png
  392. 392 http://files.smashingmagazine.com/wallpapers/jan-17/reindeer/cal/jan-17-reindeer-cal-1280×960.png
  393. 393 http://files.smashingmagazine.com/wallpapers/jan-17/reindeer/cal/jan-17-reindeer-cal-1400×1050.png
  394. 394 http://files.smashingmagazine.com/wallpapers/jan-17/reindeer/cal/jan-17-reindeer-cal-1440×900.png
  395. 395 http://files.smashingmagazine.com/wallpapers/jan-17/reindeer/cal/jan-17-reindeer-cal-1600×1200.png
  396. 396 http://files.smashingmagazine.com/wallpapers/jan-17/reindeer/cal/jan-17-reindeer-cal-1680×1050.png
  397. 397 http://files.smashingmagazine.com/wallpapers/jan-17/reindeer/cal/jan-17-reindeer-cal-1680×1200.png
  398. 398 http://files.smashingmagazine.com/wallpapers/jan-17/reindeer/cal/jan-17-reindeer-cal-1920×1080.png
  399. 399 http://files.smashingmagazine.com/wallpapers/jan-17/reindeer/cal/jan-17-reindeer-cal-1920×1200.png
  400. 400 http://files.smashingmagazine.com/wallpapers/jan-17/reindeer/cal/jan-17-reindeer-cal-1920×1440.png
  401. 401 http://files.smashingmagazine.com/wallpapers/jan-17/reindeer/cal/jan-17-reindeer-cal-2560×1440.png
  402. 402 http://files.smashingmagazine.com/wallpapers/jan-17/reindeer/nocal/jan-17-reindeer-nocal-320×480.png
  403. 403 http://files.smashingmagazine.com/wallpapers/jan-17/reindeer/nocal/jan-17-reindeer-nocal-640×480.png
  404. 404 http://files.smashingmagazine.com/wallpapers/jan-17/reindeer/nocal/jan-17-reindeer-nocal-800×480.png
  405. 405 http://files.smashingmagazine.com/wallpapers/jan-17/reindeer/nocal/jan-17-reindeer-nocal-800×600.png
  406. 406 http://files.smashingmagazine.com/wallpapers/jan-17/reindeer/nocal/jan-17-reindeer-nocal-1024×768.png
  407. 407 http://files.smashingmagazine.com/wallpapers/jan-17/reindeer/nocal/jan-17-reindeer-nocal-1024×1024.png
  408. 408 http://files.smashingmagazine.com/wallpapers/jan-17/reindeer/nocal/jan-17-reindeer-nocal-1152×864.png
  409. 409 http://files.smashingmagazine.com/wallpapers/jan-17/reindeer/nocal/jan-17-reindeer-nocal-1280×720.png
  410. 410 http://files.smashingmagazine.com/wallpapers/jan-17/reindeer/nocal/jan-17-reindeer-nocal-1280×800.png
  411. 411 http://files.smashingmagazine.com/wallpapers/jan-17/reindeer/nocal/jan-17-reindeer-nocal-1280×960.png
  412. 412 http://files.smashingmagazine.com/wallpapers/jan-17/reindeer/nocal/jan-17-reindeer-nocal-1400×1050.png
  413. 413 http://files.smashingmagazine.com/wallpapers/jan-17/reindeer/nocal/jan-17-reindeer-nocal-1440×900.png
  414. 414 http://files.smashingmagazine.com/wallpapers/jan-17/reindeer/nocal/jan-17-reindeer-nocal-1600×1200.png
  415. 415 http://files.smashingmagazine.com/wallpapers/jan-17/reindeer/nocal/jan-17-reindeer-nocal-1680×1050.png
  416. 416 http://files.smashingmagazine.com/wallpapers/jan-17/reindeer/nocal/jan-17-reindeer-nocal-1680×1200.png
  417. 417 http://files.smashingmagazine.com/wallpapers/jan-17/reindeer/nocal/jan-17-reindeer-nocal-1920×1080.png
  418. 418 http://files.smashingmagazine.com/wallpapers/jan-17/reindeer/nocal/jan-17-reindeer-nocal-1920×1200.png
  419. 419 http://files.smashingmagazine.com/wallpapers/jan-17/reindeer/nocal/jan-17-reindeer-nocal-1920×1440.png
  420. 420 http://files.smashingmagazine.com/wallpapers/jan-17/reindeer/nocal/jan-17-reindeer-nocal-2560×1440.png
  421. 421 http://0effortthemes.com/
  422. 422 http://files.smashingmagazine.com/wallpapers/jan-17/travel-explore/jan-17-travel-explore-full.jpg
  423. 423 http://files.smashingmagazine.com/wallpapers/jan-17/travel-explore/jan-17-travel-explore-preview.jpg
  424. 424 http://files.smashingmagazine.com/wallpapers/jan-17/travel-explore/cal/jan-17-travel-explore-cal-1280×720.jpg
  425. 425 http://files.smashingmagazine.com/wallpapers/jan-17/travel-explore/cal/jan-17-travel-explore-cal-1280×800.jpg
  426. 426 http://files.smashingmagazine.com/wallpapers/jan-17/travel-explore/cal/jan-17-travel-explore-cal-1280×960.jpg
  427. 427 http://files.smashingmagazine.com/wallpapers/jan-17/travel-explore/cal/jan-17-travel-explore-cal-1280×1024.jpg
  428. 428 http://files.smashingmagazine.com/wallpapers/jan-17/travel-explore/cal/jan-17-travel-explore-cal-1400×1050.jpg
  429. 429 http://files.smashingmagazine.com/wallpapers/jan-17/travel-explore/cal/jan-17-travel-explore-cal-1440×900.jpg
  430. 430 http://files.smashingmagazine.com/wallpapers/jan-17/travel-explore/cal/jan-17-travel-explore-cal-1600×1200.jpg
  431. 431 http://files.smashingmagazine.com/wallpapers/jan-17/travel-explore/cal/jan-17-travel-explore-cal-1680×1050.jpg
  432. 432 http://files.smashingmagazine.com/wallpapers/jan-17/travel-explore/cal/jan-17-travel-explore-cal-1680×1200.jpg
  433. 433 http://files.smashingmagazine.com/wallpapers/jan-17/travel-explore/cal/jan-17-travel-explore-cal-1920×1080.jpg
  434. 434 http://files.smashingmagazine.com/wallpapers/jan-17/travel-explore/cal/jan-17-travel-explore-cal-1920×1440.jpg
  435. 435 http://files.smashingmagazine.com/wallpapers/jan-17/travel-explore/cal/jan-17-travel-explore-cal-2560×1440.jpg
  436. 436 http://files.smashingmagazine.com/wallpapers/jan-17/travel-explore/cal/jan-17-travel-explore-cal-1366×768.jpg
  437. 437 http://files.smashingmagazine.com/wallpapers/jan-17/travel-explore/nocal/jan-17-travel-explore-nocal-1280×720.jpg
  438. 438 http://files.smashingmagazine.com/wallpapers/jan-17/travel-explore/nocal/jan-17-travel-explore-nocal-1280×800.jpg
  439. 439 http://files.smashingmagazine.com/wallpapers/jan-17/travel-explore/nocal/jan-17-travel-explore-nocal-1280×960.jpg
  440. 440 http://files.smashingmagazine.com/wallpapers/jan-17/travel-explore/nocal/jan-17-travel-explore-nocal-1280×1024.jpg
  441. 441 http://files.smashingmagazine.com/wallpapers/jan-17/travel-explore/nocal/jan-17-travel-explore-nocal-1400×1050.jpg
  442. 442 http://files.smashingmagazine.com/wallpapers/jan-17/travel-explore/nocal/jan-17-travel-explore-nocal-1440×900.jpg
  443. 443 http://files.smashingmagazine.com/wallpapers/jan-17/travel-explore/nocal/jan-17-travel-explore-nocal-1600×1200.jpg
  444. 444 http://files.smashingmagazine.com/wallpapers/jan-17/travel-explore/nocal/jan-17-travel-explore-nocal-1680×1050.jpg
  445. 445 http://files.smashingmagazine.com/wallpapers/jan-17/travel-explore/nocal/jan-17-travel-explore-nocal-1680×1200.jpg
  446. 446 http://files.smashingmagazine.com/wallpapers/jan-17/travel-explore/nocal/jan-17-travel-explore-nocal-1920×1080.jpg
  447. 447 http://files.smashingmagazine.com/wallpapers/jan-17/travel-explore/nocal/jan-17-travel-explore-nocal-1920×1440.jpg
  448. 448 http://files.smashingmagazine.com/wallpapers/jan-17/travel-explore/nocal/jan-17-travel-explore-nocal-2560×1440.jpg
  449. 449 http://files.smashingmagazine.com/wallpapers/jan-17/travel-explore/nocal/jan-17-travel-explore-nocal-1366×768.jpg
  450. 450 http://melissa.bogemans.com/
  451. 451 http://files.smashingmagazine.com/wallpapers/jan-17/the-rooster-wishes-you-a-happy-new-year/jan-17-the-rooster-wishes-you-a-happy-new-year-full.png
  452. 452 http://files.smashingmagazine.com/wallpapers/jan-17/the-rooster-wishes-you-a-happy-new-year/jan-17-the-rooster-wishes-you-a-happy-new-year-preview.png
  453. 453 http://files.smashingmagazine.com/wallpapers/jan-17/the-rooster-wishes-you-a-happy-new-year/cal/jan-17-the-rooster-wishes-you-a-happy-new-year-cal-640×480.png
  454. 454 http://files.smashingmagazine.com/wallpapers/jan-17/the-rooster-wishes-you-a-happy-new-year/cal/jan-17-the-rooster-wishes-you-a-happy-new-year-cal-800×480.png
  455. 455 http://files.smashingmagazine.com/wallpapers/jan-17/the-rooster-wishes-you-a-happy-new-year/cal/jan-17-the-rooster-wishes-you-a-happy-new-year-cal-800×600.png
  456. 456 http://files.smashingmagazine.com/wallpapers/jan-17/the-rooster-wishes-you-a-happy-new-year/cal/jan-17-the-rooster-wishes-you-a-happy-new-year-cal-1024×768.png
  457. 457 http://files.smashingmagazine.com/wallpapers/jan-17/the-rooster-wishes-you-a-happy-new-year/cal/jan-17-the-rooster-wishes-you-a-happy-new-year-cal-1024×1024.png
  458. 458 http://files.smashingmagazine.com/wallpapers/jan-17/the-rooster-wishes-you-a-happy-new-year/cal/jan-17-the-rooster-wishes-you-a-happy-new-year-cal-1152×864.png
  459. 459 http://files.smashingmagazine.com/wallpapers/jan-17/the-rooster-wishes-you-a-happy-new-year/cal/jan-17-the-rooster-wishes-you-a-happy-new-year-cal-1280×720.png
  460. 460 http://files.smashingmagazine.com/wallpapers/jan-17/the-rooster-wishes-you-a-happy-new-year/cal/jan-17-the-rooster-wishes-you-a-happy-new-year-cal-1280×800.png
  461. 461 http://files.smashingmagazine.com/wallpapers/jan-17/the-rooster-wishes-you-a-happy-new-year/cal/jan-17-the-rooster-wishes-you-a-happy-new-year-cal-1280×960.png
  462. 462 http://files.smashingmagazine.com/wallpapers/jan-17/the-rooster-wishes-you-a-happy-new-year/cal/jan-17-the-rooster-wishes-you-a-happy-new-year-cal-1280×1024.png
  463. 463 http://files.smashingmagazine.com/wallpapers/jan-17/the-rooster-wishes-you-a-happy-new-year/cal/jan-17-the-rooster-wishes-you-a-happy-new-year-cal-1400×1050.png
  464. 464 http://files.smashingmagazine.com/wallpapers/jan-17/the-rooster-wishes-you-a-happy-new-year/cal/jan-17-the-rooster-wishes-you-a-happy-new-year-cal-1440×900.png
  465. 465 http://files.smashingmagazine.com/wallpapers/jan-17/the-rooster-wishes-you-a-happy-new-year/cal/jan-17-the-rooster-wishes-you-a-happy-new-year-cal-1600×1200.png
  466. 466 http://files.smashingmagazine.com/wallpapers/jan-17/the-rooster-wishes-you-a-happy-new-year/cal/jan-17-the-rooster-wishes-you-a-happy-new-year-cal-1680×1050.png
  467. 467 http://files.smashingmagazine.com/wallpapers/jan-17/the-rooster-wishes-you-a-happy-new-year/cal/jan-17-the-rooster-wishes-you-a-happy-new-year-cal-1680×1200.png
  468. 468 http://files.smashingmagazine.com/wallpapers/jan-17/the-rooster-wishes-you-a-happy-new-year/cal/jan-17-the-rooster-wishes-you-a-happy-new-year-cal-1920×1080.png
  469. 469 http://files.smashingmagazine.com/wallpapers/jan-17/the-rooster-wishes-you-a-happy-new-year/cal/jan-17-the-rooster-wishes-you-a-happy-new-year-cal-1920×1200.png
  470. 470 http://files.smashingmagazine.com/wallpapers/jan-17/the-rooster-wishes-you-a-happy-new-year/cal/jan-17-the-rooster-wishes-you-a-happy-new-year-cal-1920×1440.png
  471. 471 http://files.smashingmagazine.com/wallpapers/jan-17/the-rooster-wishes-you-a-happy-new-year/cal/jan-17-the-rooster-wishes-you-a-happy-new-year-cal-2560×1440.png
  472. 472 http://files.smashingmagazine.com/wallpapers/jan-17/the-rooster-wishes-you-a-happy-new-year/nocal/jan-17-the-rooster-wishes-you-a-happy-new-year-nocal-640×480.png
  473. 473 http://files.smashingmagazine.com/wallpapers/jan-17/the-rooster-wishes-you-a-happy-new-year/nocal/jan-17-the-rooster-wishes-you-a-happy-new-year-nocal-800×480.png
  474. 474 http://files.smashingmagazine.com/wallpapers/jan-17/the-rooster-wishes-you-a-happy-new-year/nocal/jan-17-the-rooster-wishes-you-a-happy-new-year-nocal-800×600.png
  475. 475 http://files.smashingmagazine.com/wallpapers/jan-17/the-rooster-wishes-you-a-happy-new-year/nocal/jan-17-the-rooster-wishes-you-a-happy-new-year-nocal-1024×768.png
  476. 476 http://files.smashingmagazine.com/wallpapers/jan-17/the-rooster-wishes-you-a-happy-new-year/nocal/jan-17-the-rooster-wishes-you-a-happy-new-year-nocal-1024×1024.png
  477. 477 http://files.smashingmagazine.com/wallpapers/jan-17/the-rooster-wishes-you-a-happy-new-year/nocal/jan-17-the-rooster-wishes-you-a-happy-new-year-nocal-1152×864.png
  478. 478 http://files.smashingmagazine.com/wallpapers/jan-17/the-rooster-wishes-you-a-happy-new-year/nocal/jan-17-the-rooster-wishes-you-a-happy-new-year-nocal-1280×720.png
  479. 479 http://files.smashingmagazine.com/wallpapers/jan-17/the-rooster-wishes-you-a-happy-new-year/nocal/jan-17-the-rooster-wishes-you-a-happy-new-year-nocal-1280×800.png
  480. 480 http://files.smashingmagazine.com/wallpapers/jan-17/the-rooster-wishes-you-a-happy-new-year/nocal/jan-17-the-rooster-wishes-you-a-happy-new-year-nocal-1280×960.png
  481. 481 http://files.smashingmagazine.com/wallpapers/jan-17/the-rooster-wishes-you-a-happy-new-year/nocal/jan-17-the-rooster-wishes-you-a-happy-new-year-nocal-1280×1024.png
  482. 482 http://files.smashingmagazine.com/wallpapers/jan-17/the-rooster-wishes-you-a-happy-new-year/nocal/jan-17-the-rooster-wishes-you-a-happy-new-year-nocal-1400×1050.png
  483. 483 http://files.smashingmagazine.com/wallpapers/jan-17/the-rooster-wishes-you-a-happy-new-year/nocal/jan-17-the-rooster-wishes-you-a-happy-new-year-nocal-1440×900.png
  484. 484 http://files.smashingmagazine.com/wallpapers/jan-17/the-rooster-wishes-you-a-happy-new-year/nocal/jan-17-the-rooster-wishes-you-a-happy-new-year-nocal-1600×1200.png
  485. 485 http://files.smashingmagazine.com/wallpapers/jan-17/the-rooster-wishes-you-a-happy-new-year/nocal/jan-17-the-rooster-wishes-you-a-happy-new-year-nocal-1680×1050.png
  486. 486 http://files.smashingmagazine.com/wallpapers/jan-17/the-rooster-wishes-you-a-happy-new-year/nocal/jan-17-the-rooster-wishes-you-a-happy-new-year-nocal-1680×1200.png
  487. 487 http://files.smashingmagazine.com/wallpapers/jan-17/the-rooster-wishes-you-a-happy-new-year/nocal/jan-17-the-rooster-wishes-you-a-happy-new-year-nocal-1920×1080.png
  488. 488 http://files.smashingmagazine.com/wallpapers/jan-17/the-rooster-wishes-you-a-happy-new-year/nocal/jan-17-the-rooster-wishes-you-a-happy-new-year-nocal-1920×1200.png
  489. 489 http://files.smashingmagazine.com/wallpapers/jan-17/the-rooster-wishes-you-a-happy-new-year/nocal/jan-17-the-rooster-wishes-you-a-happy-new-year-nocal-1920×1440.png
  490. 490 http://files.smashingmagazine.com/wallpapers/jan-17/the-rooster-wishes-you-a-happy-new-year/nocal/jan-17-the-rooster-wishes-you-a-happy-new-year-nocal-2560×1440.png
  491. 491 http://www.safiabegum.com
  492. 492 http://files.smashingmagazine.com/wallpapers/jan-17/happy-birthday-a-a-milne/jan-17-happy-birthday-a-a-milne-full.png
  493. 493 http://files.smashingmagazine.com/wallpapers/jan-17/happy-birthday-a-a-milne/jan-17-happy-birthday-a-a-milne-preview.png
  494. 494 http://files.smashingmagazine.com/wallpapers/jan-17/happy-birthday-a-a-milne/cal/jan-17-happy-birthday-a-a-milne-cal-320×480.png
  495. 495 http://files.smashingmagazine.com/wallpapers/jan-17/happy-birthday-a-a-milne/cal/jan-17-happy-birthday-a-a-milne-cal-640×480.png
  496. 496 http://files.smashingmagazine.com/wallpapers/jan-17/happy-birthday-a-a-milne/cal/jan-17-happy-birthday-a-a-milne-cal-800×480.png
  497. 497 http://files.smashingmagazine.com/wallpapers/jan-17/happy-birthday-a-a-milne/cal/jan-17-happy-birthday-a-a-milne-cal-800×600.png
  498. 498 http://files.smashingmagazine.com/wallpapers/jan-17/happy-birthday-a-a-milne/cal/jan-17-happy-birthday-a-a-milne-cal-1024×768.png
  499. 499 http://files.smashingmagazine.com/wallpapers/jan-17/happy-birthday-a-a-milne/cal/jan-17-happy-birthday-a-a-milne-cal-1024×1024.png
  500. 500 http://files.smashingmagazine.com/wallpapers/jan-17/happy-birthday-a-a-milne/cal/jan-17-happy-birthday-a-a-milne-cal-1280×720.png
  501. 501 http://files.smashingmagazine.com/wallpapers/jan-17/happy-birthday-a-a-milne/cal/jan-17-happy-birthday-a-a-milne-cal-1280×800.png
  502. 502 http://files.smashingmagazine.com/wallpapers/jan-17/happy-birthday-a-a-milne/cal/jan-17-happy-birthday-a-a-milne-cal-1280×960.png
  503. 503 http://files.smashingmagazine.com/wallpapers/jan-17/happy-birthday-a-a-milne/cal/jan-17-happy-birthday-a-a-milne-cal-1280×1024.png
  504. 504 http://files.smashingmagazine.com/wallpapers/jan-17/happy-birthday-a-a-milne/cal/jan-17-happy-birthday-a-a-milne-cal-1400×1050.png
  505. 505 http://files.smashingmagazine.com/wallpapers/jan-17/happy-birthday-a-a-milne/cal/jan-17-happy-birthday-a-a-milne-cal-1440×900.png
  506. 506 http://files.smashingmagazine.com/wallpapers/jan-17/happy-birthday-a-a-milne/cal/jan-17-happy-birthday-a-a-milne-cal-1600×1200.png
  507. 507 http://files.smashingmagazine.com/wallpapers/jan-17/happy-birthday-a-a-milne/cal/jan-17-happy-birthday-a-a-milne-cal-1680×1050.png
  508. 508 http://files.smashingmagazine.com/wallpapers/jan-17/happy-birthday-a-a-milne/cal/jan-17-happy-birthday-a-a-milne-cal-1680×1200.png
  509. 509 http://files.smashingmagazine.com/wallpapers/jan-17/happy-birthday-a-a-milne/cal/jan-17-happy-birthday-a-a-milne-cal-1920×1080.png
  510. 510 http://files.smashingmagazine.com/wallpapers/jan-17/happy-birthday-a-a-milne/cal/jan-17-happy-birthday-a-a-milne-cal-1920×1200.png
  511. 511 http://files.smashingmagazine.com/wallpapers/jan-17/happy-birthday-a-a-milne/cal/jan-17-happy-birthday-a-a-milne-cal-1920×1440.png
  512. 512 http://files.smashingmagazine.com/wallpapers/jan-17/happy-birthday-a-a-milne/cal/jan-17-happy-birthday-a-a-milne-cal-2560×1440.png
  513. 513 http://files.smashingmagazine.com/wallpapers/jan-17/happy-birthday-a-a-milne/cal/jan-17-happy-birthday-a-a-milne-cal-1366×768.png
  514. 514 http://files.smashingmagazine.com/wallpapers/jan-17/happy-birthday-a-a-milne/nocal/jan-17-happy-birthday-a-a-milne-nocal-320×480.png
  515. 515 http://files.smashingmagazine.com/wallpapers/jan-17/happy-birthday-a-a-milne/nocal/jan-17-happy-birthday-a-a-milne-nocal-640×480.png
  516. 516 http://files.smashingmagazine.com/wallpapers/jan-17/happy-birthday-a-a-milne/nocal/jan-17-happy-birthday-a-a-milne-nocal-800×480.png
  517. 517 http://files.smashingmagazine.com/wallpapers/jan-17/happy-birthday-a-a-milne/nocal/jan-17-happy-birthday-a-a-milne-nocal-800×600.png
  518. 518 http://files.smashingmagazine.com/wallpapers/jan-17/happy-birthday-a-a-milne/nocal/jan-17-happy-birthday-a-a-milne-nocal-1024×768.png
  519. 519 http://files.smashingmagazine.com/wallpapers/jan-17/happy-birthday-a-a-milne/nocal/jan-17-happy-birthday-a-a-milne-nocal-1024×1024.png
  520. 520 http://files.smashingmagazine.com/wallpapers/jan-17/happy-birthday-a-a-milne/nocal/jan-17-happy-birthday-a-a-milne-nocal-1280×720.png
  521. 521 http://files.smashingmagazine.com/wallpapers/jan-17/happy-birthday-a-a-milne/nocal/jan-17-happy-birthday-a-a-milne-nocal-1280×800.png
  522. 522 http://files.smashingmagazine.com/wallpapers/jan-17/happy-birthday-a-a-milne/nocal/jan-17-happy-birthday-a-a-milne-nocal-1280×960.png
  523. 523 http://files.smashingmagazine.com/wallpapers/jan-17/happy-birthday-a-a-milne/nocal/jan-17-happy-birthday-a-a-milne-nocal-1280×1024.png
  524. 524 http://files.smashingmagazine.com/wallpapers/jan-17/happy-birthday-a-a-milne/nocal/jan-17-happy-birthday-a-a-milne-nocal-1400×1050.png
  525. 525 http://files.smashingmagazine.com/wallpapers/jan-17/happy-birthday-a-a-milne/nocal/jan-17-happy-birthday-a-a-milne-nocal-1440×900.png
  526. 526 http://files.smashingmagazine.com/wallpapers/jan-17/happy-birthday-a-a-milne/nocal/jan-17-happy-birthday-a-a-milne-nocal-1600×1200.png
  527. 527 http://files.smashingmagazine.com/wallpapers/jan-17/happy-birthday-a-a-milne/nocal/jan-17-happy-birthday-a-a-milne-nocal-1680×1050.png
  528. 528 http://files.smashingmagazine.com/wallpapers/jan-17/happy-birthday-a-a-milne/nocal/jan-17-happy-birthday-a-a-milne-nocal-1680×1200.png
  529. 529 http://files.smashingmagazine.com/wallpapers/jan-17/happy-birthday-a-a-milne/nocal/jan-17-happy-birthday-a-a-milne-nocal-1920×1080.png
  530. 530 http://files.smashingmagazine.com/wallpapers/jan-17/happy-birthday-a-a-milne/nocal/jan-17-happy-birthday-a-a-milne-nocal-1920×1200.png
  531. 531 http://files.smashingmagazine.com/wallpapers/jan-17/happy-birthday-a-a-milne/nocal/jan-17-happy-birthday-a-a-milne-nocal-1920×1440.png
  532. 532 http://files.smashingmagazine.com/wallpapers/jan-17/happy-birthday-a-a-milne/nocal/jan-17-happy-birthday-a-a-milne-nocal-2560×1440.png
  533. 533 http://files.smashingmagazine.com/wallpapers/jan-17/happy-birthday-a-a-milne/nocal/jan-17-happy-birthday-a-a-milne-nocal-1366×768.png
  534. 534 http://www.facebook.com/doud.design
  535. 535 http://files.smashingmagazine.com/wallpapers/jan-17/ice-crime/jan-17-ice-crime-full.jpg
  536. 536 http://files.smashingmagazine.com/wallpapers/jan-17/ice-crime/jan-17-ice-crime-preview.jpg
  537. 537 http://files.smashingmagazine.com/wallpapers/jan-17/ice-crime/cal/jan-17-ice-crime-cal-1280×1024.jpg
  538. 538 http://files.smashingmagazine.com/wallpapers/jan-17/ice-crime/cal/jan-17-ice-crime-cal-1400×1050.jpg
  539. 539 http://files.smashingmagazine.com/wallpapers/jan-17/ice-crime/cal/jan-17-ice-crime-cal-1440×900.jpg
  540. 540 http://files.smashingmagazine.com/wallpapers/jan-17/ice-crime/cal/jan-17-ice-crime-cal-1600×1200.jpg
  541. 541 http://files.smashingmagazine.com/wallpapers/jan-17/ice-crime/cal/jan-17-ice-crime-cal-1680×1050.jpg
  542. 542 http://files.smashingmagazine.com/wallpapers/jan-17/ice-crime/cal/jan-17-ice-crime-cal-1680×1200.jpg
  543. 543 http://files.smashingmagazine.com/wallpapers/jan-17/ice-crime/cal/jan-17-ice-crime-cal-1920×1080.jpg
  544. 544 http://files.smashingmagazine.com/wallpapers/jan-17/ice-crime/cal/jan-17-ice-crime-cal-1920×1200.jpg
  545. 545 http://files.smashingmagazine.com/wallpapers/jan-17/ice-crime/cal/jan-17-ice-crime-cal-1920×1440.jpg
  546. 546 http://files.smashingmagazine.com/wallpapers/jan-17/ice-crime/cal/jan-17-ice-crime-cal-2560×1440.jpg
  547. 547 http://files.smashingmagazine.com/wallpapers/jan-17/ice-crime/cal/jan-17-ice-crime-cal-1366×768.jpg
  548. 548 http://files.smashingmagazine.com/wallpapers/jan-17/ice-crime/nocal/jan-17-ice-crime-nocal-1280×1024.jpg
  549. 549 http://files.smashingmagazine.com/wallpapers/jan-17/ice-crime/nocal/jan-17-ice-crime-nocal-1400×1050.jpg
  550. 550 http://files.smashingmagazine.com/wallpapers/jan-17/ice-crime/nocal/jan-17-ice-crime-nocal-1440×900.jpg
  551. 551 http://files.smashingmagazine.com/wallpapers/jan-17/ice-crime/nocal/jan-17-ice-crime-nocal-1600×1200.jpg
  552. 552 http://files.smashingmagazine.com/wallpapers/jan-17/ice-crime/nocal/jan-17-ice-crime-nocal-1680×1050.jpg
  553. 553 http://files.smashingmagazine.com/wallpapers/jan-17/ice-crime/nocal/jan-17-ice-crime-nocal-1680×1200.jpg
  554. 554 http://files.smashingmagazine.com/wallpapers/jan-17/ice-crime/nocal/jan-17-ice-crime-nocal-1920×1080.jpg
  555. 555 http://files.smashingmagazine.com/wallpapers/jan-17/ice-crime/nocal/jan-17-ice-crime-nocal-1920×1200.jpg
  556. 556 http://files.smashingmagazine.com/wallpapers/jan-17/ice-crime/nocal/jan-17-ice-crime-nocal-1920×1440.jpg
  557. 557 http://files.smashingmagazine.com/wallpapers/jan-17/ice-crime/nocal/jan-17-ice-crime-nocal-2560×1440.jpg
  558. 558 http://files.smashingmagazine.com/wallpapers/jan-17/ice-crime/nocal/jan-17-ice-crime-nocal-1366×768.jpg
  559. 559 https://www.behance.net/jamesmitchell23
  560. 560 http://files.smashingmagazine.com/wallpapers/jan-17/the-worried-weighing-scales/jan-17-the-worried-weighing-scales-full.jpg
  561. 561 http://files.smashingmagazine.com/wallpapers/jan-17/the-worried-weighing-scales/jan-17-the-worried-weighing-scales-preview.jpg
  562. 562 http://files.smashingmagazine.com/wallpapers/jan-17/the-worried-weighing-scales/cal/jan-17-the-worried-weighing-scales-cal-1280×720.jpg
  563. 563 http://files.smashingmagazine.com/wallpapers/jan-17/the-worried-weighing-scales/cal/jan-17-the-worried-weighing-scales-cal-1280×800.jpg
  564. 564 http://files.smashingmagazine.com/wallpapers/jan-17/the-worried-weighing-scales/cal/jan-17-the-worried-weighing-scales-cal-1440×900.jpg
  565. 565 http://files.smashingmagazine.com/wallpapers/jan-17/the-worried-weighing-scales/cal/jan-17-the-worried-weighing-scales-cal-1680×1050.jpg
  566. 566 http://files.smashingmagazine.com/wallpapers/jan-17/the-worried-weighing-scales/cal/jan-17-the-worried-weighing-scales-cal-1920×1080.jpg
  567. 567 http://files.smashingmagazine.com/wallpapers/jan-17/the-worried-weighing-scales/cal/jan-17-the-worried-weighing-scales-cal-1920×1200.jpg
  568. 568 http://files.smashingmagazine.com/wallpapers/jan-17/the-worried-weighing-scales/cal/jan-17-the-worried-weighing-scales-cal-2560×1440.jpg
  569. 569 http://files.smashingmagazine.com/wallpapers/jan-17/the-worried-weighing-scales/cal/jan-17-the-worried-weighing-scales-cal-1366×768.jpg
  570. 570 http://files.smashingmagazine.com/wallpapers/jan-17/the-worried-weighing-scales/cal/jan-17-the-worried-weighing-scales-cal-2880×1800.jpg
  571. 571 http://files.smashingmagazine.com/wallpapers/jan-17/the-worried-weighing-scales/nocal/jan-17-the-worried-weighing-scales-nocal-1280×720.jpg
  572. 572 http://files.smashingmagazine.com/wallpapers/jan-17/the-worried-weighing-scales/nocal/jan-17-the-worried-weighing-scales-nocal-1280×800.jpg
  573. 573 http://files.smashingmagazine.com/wallpapers/jan-17/the-worried-weighing-scales/nocal/jan-17-the-worried-weighing-scales-nocal-1440×900.jpg
  574. 574 http://files.smashingmagazine.com/wallpapers/jan-17/the-worried-weighing-scales/nocal/jan-17-the-worried-weighing-scales-nocal-1680×1050.jpg
  575. 575 http://files.smashingmagazine.com/wallpapers/jan-17/the-worried-weighing-scales/nocal/jan-17-the-worried-weighing-scales-nocal-1920×1080.jpg
  576. 576 http://files.smashingmagazine.com/wallpapers/jan-17/the-worried-weighing-scales/nocal/jan-17-the-worried-weighing-scales-nocal-1920×1200.jpg
  577. 577 http://files.smashingmagazine.com/wallpapers/jan-17/the-worried-weighing-scales/nocal/jan-17-the-worried-weighing-scales-nocal-2560×1440.jpg
  578. 578 http://files.smashingmagazine.com/wallpapers/jan-17/the-worried-weighing-scales/nocal/jan-17-the-worried-weighing-scales-nocal-1366×768.jpg
  579. 579 http://files.smashingmagazine.com/wallpapers/jan-17/the-worried-weighing-scales/nocal/jan-17-the-worried-weighing-scales-nocal-2880×1800.jpg
  580. 580 http://www.code-master.be
  581. 581 http://files.smashingmagazine.com/wallpapers/jan-17/wake-up-it-is-time-to-study/jan-17-wake-up-it-is-time-to-study-full.jpg
  582. 582 http://files.smashingmagazine.com/wallpapers/jan-17/wake-up-it-is-time-to-study/jan-17-wake-up-it-is-time-to-study-preview.jpg
  583. 583 http://files.smashingmagazine.com/wallpapers/jan-17/wake-up-it-is-time-to-study/cal/jan-17-wake-up-it-is-time-to-study-cal-640×480.jpg
  584. 584 http://files.smashingmagazine.com/wallpapers/jan-17/wake-up-it-is-time-to-study/cal/jan-17-wake-up-it-is-time-to-study-cal-800×600.jpg
  585. 585 http://files.smashingmagazine.com/wallpapers/jan-17/wake-up-it-is-time-to-study/cal/jan-17-wake-up-it-is-time-to-study-cal-1024×768.jpg
  586. 586 http://files.smashingmagazine.com/wallpapers/jan-17/wake-up-it-is-time-to-study/cal/jan-17-wake-up-it-is-time-to-study-cal-1280×800.jpg
  587. 587 http://files.smashingmagazine.com/wallpapers/jan-17/wake-up-it-is-time-to-study/cal/jan-17-wake-up-it-is-time-to-study-cal-1440×900.jpg
  588. 588 http://files.smashingmagazine.com/wallpapers/jan-17/wake-up-it-is-time-to-study/cal/jan-17-wake-up-it-is-time-to-study-cal-1680×1050.jpg
  589. 589 http://files.smashingmagazine.com/wallpapers/jan-17/wake-up-it-is-time-to-study/cal/jan-17-wake-up-it-is-time-to-study-cal-1920×1200.jpg
  590. 590 http://files.smashingmagazine.com/wallpapers/jan-17/wake-up-it-is-time-to-study/cal/jan-17-wake-up-it-is-time-to-study-cal-2880×1800.jpg
  591. 591 http://files.smashingmagazine.com/wallpapers/jan-17/wake-up-it-is-time-to-study/nocal/jan-17-wake-up-it-is-time-to-study-nocal-640×480.jpg
  592. 592 http://files.smashingmagazine.com/wallpapers/jan-17/wake-up-it-is-time-to-study/nocal/jan-17-wake-up-it-is-time-to-study-nocal-800×600.jpg
  593. 593 http://files.smashingmagazine.com/wallpapers/jan-17/wake-up-it-is-time-to-study/nocal/jan-17-wake-up-it-is-time-to-study-nocal-1024×768.jpg
  594. 594 http://files.smashingmagazine.com/wallpapers/jan-17/wake-up-it-is-time-to-study/nocal/jan-17-wake-up-it-is-time-to-study-nocal-1280×800.jpg
  595. 595 http://files.smashingmagazine.com/wallpapers/jan-17/wake-up-it-is-time-to-study/nocal/jan-17-wake-up-it-is-time-to-study-nocal-1440×900.jpg
  596. 596 http://files.smashingmagazine.com/wallpapers/jan-17/wake-up-it-is-time-to-study/nocal/jan-17-wake-up-it-is-time-to-study-nocal-1680×1050.jpg
  597. 597 http://files.smashingmagazine.com/wallpapers/jan-17/wake-up-it-is-time-to-study/nocal/jan-17-wake-up-it-is-time-to-study-nocal-1920×1200.jpg
  598. 598 http://files.smashingmagazine.com/wallpapers/jan-17/wake-up-it-is-time-to-study/nocal/jan-17-wake-up-it-is-time-to-study-nocal-2880×1800.jpg
  599. 599 https://www.behance.net/gallery/46394693/zzzz?unverified=1
  600. 600 http://files.smashingmagazine.com/wallpapers/jan-17/angels-of-heaven/jan-17-angels-of-heaven-full.jpg
  601. 601 http://files.smashingmagazine.com/wallpapers/jan-17/angels-of-heaven/jan-17-angels-of-heaven-preview.jpg
  602. 602 http://files.smashingmagazine.com/wallpapers/jan-17/angels-of-heaven/cal/jan-17-angels-of-heaven-cal-320×480.jpg
  603. 603 http://files.smashingmagazine.com/wallpapers/jan-17/angels-of-heaven/cal/jan-17-angels-of-heaven-cal-800×600.jpg
  604. 604 http://files.smashingmagazine.com/wallpapers/jan-17/angels-of-heaven/cal/jan-17-angels-of-heaven-cal-1280×720.jpg
  605. 605 http://files.smashingmagazine.com/wallpapers/jan-17/angels-of-heaven/cal/jan-17-angels-of-heaven-cal-1280×1024.jpg
  606. 606 http://files.smashingmagazine.com/wallpapers/jan-17/angels-of-heaven/cal/jan-17-angels-of-heaven-cal-1920×1080.jpg
  607. 607 http://files.smashingmagazine.com/wallpapers/jan-17/angels-of-heaven/cal/jan-17-angels-of-heaven-cal-2560×1440.jpg
  608. 608 http://files.smashingmagazine.com/wallpapers/jan-17/angels-of-heaven/nocal/jan-17-angels-of-heaven-nocal-320×480.jpg
  609. 609 http://files.smashingmagazine.com/wallpapers/jan-17/angels-of-heaven/nocal/jan-17-angels-of-heaven-nocal-800×600.jpg
  610. 610 http://files.smashingmagazine.com/wallpapers/jan-17/angels-of-heaven/nocal/jan-17-angels-of-heaven-nocal-1280×720.jpg
  611. 611 http://files.smashingmagazine.com/wallpapers/jan-17/angels-of-heaven/nocal/jan-17-angels-of-heaven-nocal-1280×1024.jpg
  612. 612 http://files.smashingmagazine.com/wallpapers/jan-17/angels-of-heaven/nocal/jan-17-angels-of-heaven-nocal-1920×1080.jpg
  613. 613 http://files.smashingmagazine.com/wallpapers/jan-17/angels-of-heaven/nocal/jan-17-angels-of-heaven-nocal-2560×1440.jpg
  614. 614 https://www.behance.net/filipatravassos
  615. 615 http://files.smashingmagazine.com/wallpapers/jan-17/the-tree/jan-17-the-tree-full.png
  616. 616 http://files.smashingmagazine.com/wallpapers/jan-17/the-tree/jan-17-the-tree-preview.png
  617. 617 http://files.smashingmagazine.com/wallpapers/jan-17/the-tree/cal/jan-17-the-tree-cal-640×480.png
  618. 618 http://files.smashingmagazine.com/wallpapers/jan-17/the-tree/cal/jan-17-the-tree-cal-800×600.png
  619. 619 http://files.smashingmagazine.com/wallpapers/jan-17/the-tree/cal/jan-17-the-tree-cal-1024×1024.png
  620. 620 http://files.smashingmagazine.com/wallpapers/jan-17/the-tree/cal/jan-17-the-tree-cal-1280×720.png
  621. 621 http://files.smashingmagazine.com/wallpapers/jan-17/the-tree/cal/jan-17-the-tree-cal-1280×960.png
  622. 622 http://files.smashingmagazine.com/wallpapers/jan-17/the-tree/cal/jan-17-the-tree-cal-1366×768.png
  623. 623 http://files.smashingmagazine.com/wallpapers/jan-17/the-tree/cal/jan-17-the-tree-cal-1440×900.png
  624. 624 http://files.smashingmagazine.com/wallpapers/jan-17/the-tree/cal/jan-17-the-tree-cal-1680×1050.png
  625. 625 http://files.smashingmagazine.com/wallpapers/jan-17/the-tree/cal/jan-17-the-tree-cal-1920×1200.png
  626. 626 http://files.smashingmagazine.com/wallpapers/jan-17/the-tree/cal/jan-17-the-tree-cal-2560×1440.png
  627. 627 http://files.smashingmagazine.com/wallpapers/jan-17/the-tree/nocal/jan-17-the-tree-nocal-640×480.png
  628. 628 http://files.smashingmagazine.com/wallpapers/jan-17/the-tree/nocal/jan-17-the-tree-nocal-800×600.png
  629. 629 http://files.smashingmagazine.com/wallpapers/jan-17/the-tree/nocal/jan-17-the-tree-nocal-1024×1024.png
  630. 630 http://files.smashingmagazine.com/wallpapers/jan-17/the-tree/nocal/jan-17-the-tree-nocal-1280×720.png
  631. 631 http://files.smashingmagazine.com/wallpapers/jan-17/the-tree/nocal/jan-17-the-tree-nocal-1280×960.png
  632. 632 http://files.smashingmagazine.com/wallpapers/jan-17/the-tree/nocal/jan-17-the-tree-nocal-1366×768.png
  633. 633 http://files.smashingmagazine.com/wallpapers/jan-17/the-tree/nocal/jan-17-the-tree-nocal-1440×900.png
  634. 634 http://files.smashingmagazine.com/wallpapers/jan-17/the-tree/nocal/jan-17-the-tree-nocal-1680×1050.png
  635. 635 http://files.smashingmagazine.com/wallpapers/jan-17/the-tree/nocal/jan-17-the-tree-nocal-1920×1200.png
  636. 636 http://files.smashingmagazine.com/wallpapers/jan-17/the-tree/nocal/jan-17-the-tree-nocal-2560×1440.png
  637. 637 http://thomasdebelder.be/
  638. 638 http://files.smashingmagazine.com/wallpapers/jan-17/lets-do-great-things-together/jan-17-lets-do-great-things-together-full.jpg
  639. 639 http://files.smashingmagazine.com/wallpapers/jan-17/lets-do-great-things-together/jan-17-lets-do-great-things-together-preview.jpg
  640. 640 http://files.smashingmagazine.com/wallpapers/jan-17/lets-do-great-things-together/cal/jan-17-lets-do-great-things-together-cal-1024×768.jpg
  641. 641 http://files.smashingmagazine.com/wallpapers/jan-17/lets-do-great-things-together/cal/jan-17-lets-do-great-things-together-cal-1280×1024.jpg
  642. 642 http://files.smashingmagazine.com/wallpapers/jan-17/lets-do-great-things-together/cal/jan-17-lets-do-great-things-together-cal-1440×900.jpg
  643. 643 http://files.smashingmagazine.com/wallpapers/jan-17/lets-do-great-things-together/cal/jan-17-lets-do-great-things-together-cal-1680×1200.jpg
  644. 644 http://files.smashingmagazine.com/wallpapers/jan-17/lets-do-great-things-together/cal/jan-17-lets-do-great-things-together-cal-1920×1080.jpg
  645. 645 http://files.smashingmagazine.com/wallpapers/jan-17/lets-do-great-things-together/cal/jan-17-lets-do-great-things-together-cal-1920×1200.jpg
  646. 646 http://files.smashingmagazine.com/wallpapers/jan-17/lets-do-great-things-together/cal/jan-17-lets-do-great-things-together-cal-1920×1440.jpg
  647. 647 http://files.smashingmagazine.com/wallpapers/jan-17/lets-do-great-things-together/cal/jan-17-lets-do-great-things-together-cal-2560×1440.jpg
  648. 648 http://files.smashingmagazine.com/wallpapers/jan-17/lets-do-great-things-together/nocal/jan-17-lets-do-great-things-together-nocal-1024×768.jpg
  649. 649 http://files.smashingmagazine.com/wallpapers/jan-17/lets-do-great-things-together/nocal/jan-17-lets-do-great-things-together-nocal-1280×1024.jpg
  650. 650 http://files.smashingmagazine.com/wallpapers/jan-17/lets-do-great-things-together/nocal/jan-17-lets-do-great-things-together-nocal-1440×900.jpg
  651. 651 http://files.smashingmagazine.com/wallpapers/jan-17/lets-do-great-things-together/nocal/jan-17-lets-do-great-things-together-nocal-1680×1200.jpg
  652. 652 http://files.smashingmagazine.com/wallpapers/jan-17/lets-do-great-things-together/nocal/jan-17-lets-do-great-things-together-nocal-1920×1080.jpg
  653. 653 http://files.smashingmagazine.com/wallpapers/jan-17/lets-do-great-things-together/nocal/jan-17-lets-do-great-things-together-nocal-1920×1200.jpg
  654. 654 http://files.smashingmagazine.com/wallpapers/jan-17/lets-do-great-things-together/nocal/jan-17-lets-do-great-things-together-nocal-1920×1440.jpg
  655. 655 http://files.smashingmagazine.com/wallpapers/jan-17/lets-do-great-things-together/nocal/jan-17-lets-do-great-things-together-nocal-2560×1440.jpg
  656. 656 http://www.marijazaric.com/
  657. 657 http://files.smashingmagazine.com/wallpapers/jan-17/observing-cat/jan-17-observing-cat-full.jpg
  658. 658 http://files.smashingmagazine.com/wallpapers/jan-17/observing-cat/jan-17-observing-cat-preview.jpg
  659. 659 http://files.smashingmagazine.com/wallpapers/jan-17/observing-cat/cal/jan-17-observing-cat-cal-800×450.jpg
  660. 660 http://files.smashingmagazine.com/wallpapers/jan-17/observing-cat/cal/jan-17-observing-cat-cal-1280×720.jpg
  661. 661 http://files.smashingmagazine.com/wallpapers/jan-17/observing-cat/cal/jan-17-observing-cat-cal-1366×768.jpg
  662. 662 http://files.smashingmagazine.com/wallpapers/jan-17/observing-cat/cal/jan-17-observing-cat-cal-1440×810.jpg
  663. 663 http://files.smashingmagazine.com/wallpapers/jan-17/observing-cat/cal/jan-17-observing-cat-cal-1600×900.jpg
  664. 664 http://files.smashingmagazine.com/wallpapers/jan-17/observing-cat/cal/jan-17-observing-cat-cal-1680×945.jpg
  665. 665 http://files.smashingmagazine.com/wallpapers/jan-17/observing-cat/cal/jan-17-observing-cat-cal-1920×1080.jpg
  666. 666 http://files.smashingmagazine.com/wallpapers/jan-17/observing-cat/cal/jan-17-observing-cat-cal-2560×1440.jpg
  667. 667 http://files.smashingmagazine.com/wallpapers/jan-17/observing-cat/nocal/jan-17-observing-cat-nocal-800×450.jpg
  668. 668 http://files.smashingmagazine.com/wallpapers/jan-17/observing-cat/nocal/jan-17-observing-cat-nocal-1280×720.jpg
  669. 669 http://files.smashingmagazine.com/wallpapers/jan-17/observing-cat/nocal/jan-17-observing-cat-nocal-1366×768.jpg
  670. 670 http://files.smashingmagazine.com/wallpapers/jan-17/observing-cat/nocal/jan-17-observing-cat-nocal-1440×810.jpg
  671. 671 http://files.smashingmagazine.com/wallpapers/jan-17/observing-cat/nocal/jan-17-observing-cat-nocal-1600×900.jpg
  672. 672 http://files.smashingmagazine.com/wallpapers/jan-17/observing-cat/nocal/jan-17-observing-cat-nocal-1680×945.jpg
  673. 673 http://files.smashingmagazine.com/wallpapers/jan-17/observing-cat/nocal/jan-17-observing-cat-nocal-1920×1080.jpg
  674. 674 http://files.smashingmagazine.com/wallpapers/jan-17/observing-cat/nocal/jan-17-observing-cat-nocal-2560×1440.jpg
  675. 675 https://www.behance.net/RodFlores
  676. 676 http://files.smashingmagazine.com/wallpapers/jan-17/it-shines/jan-17-it-shines-full.jpg
  677. 677 http://files.smashingmagazine.com/wallpapers/jan-17/it-shines/jan-17-it-shines-preview.jpg
  678. 678 http://files.smashingmagazine.com/wallpapers/jan-17/it-shines/cal/jan-17-it-shines-cal-1024×768.jpg
  679. 679 http://files.smashingmagazine.com/wallpapers/jan-17/it-shines/cal/jan-17-it-shines-cal-1280×720.jpg
  680. 680 http://files.smashingmagazine.com/wallpapers/jan-17/it-shines/cal/jan-17-it-shines-cal-1280×800.jpg
  681. 681 http://files.smashingmagazine.com/wallpapers/jan-17/it-shines/cal/jan-17-it-shines-cal-1366×768.jpg
  682. 682 http://files.smashingmagazine.com/wallpapers/jan-17/it-shines/cal/jan-17-it-shines-cal-1440×900.jpg
  683. 683 http://files.smashingmagazine.com/wallpapers/jan-17/it-shines/cal/jan-17-it-shines-cal-1680×1050.jpg
  684. 684 http://files.smashingmagazine.com/wallpapers/jan-17/it-shines/cal/jan-17-it-shines-cal-1920×1080.jpg
  685. 685 http://files.smashingmagazine.com/wallpapers/jan-17/it-shines/cal/jan-17-it-shines-cal-2560×1440.jpg
  686. 686 http://files.smashingmagazine.com/wallpapers/jan-17/it-shines/nocal/jan-17-it-shines-nocal-1024×768.jpg
  687. 687 http://files.smashingmagazine.com/wallpapers/jan-17/it-shines/nocal/jan-17-it-shines-nocal-1280×720.jpg
  688. 688 http://files.smashingmagazine.com/wallpapers/jan-17/it-shines/nocal/jan-17-it-shines-nocal-1280×800.jpg
  689. 689 http://files.smashingmagazine.com/wallpapers/jan-17/it-shines/nocal/jan-17-it-shines-nocal-1366×768.jpg
  690. 690 http://files.smashingmagazine.com/wallpapers/jan-17/it-shines/nocal/jan-17-it-shines-nocal-1440×900.jpg
  691. 691 http://files.smashingmagazine.com/wallpapers/jan-17/it-shines/nocal/jan-17-it-shines-nocal-1680×1050.jpg
  692. 692 http://files.smashingmagazine.com/wallpapers/jan-17/it-shines/nocal/jan-17-it-shines-nocal-1920×1080.jpg
  693. 693 http://files.smashingmagazine.com/wallpapers/jan-17/it-shines/nocal/jan-17-it-shines-nocal-2560×1440.jpg
  694. 694 https://www.smashingmagazine.com/desktop-wallpaper-calendars-join-in/

↑ Back to topTweet itShare on Facebook

Improving The UX Of Names With Vocalizer.js

Improving The UX Of Names With Vocalizer.js

We have all encountered names that are difficult to pronounce. Having a challenging name myself, I get different pronunciations of my first name, Atif, all the time. In order to solve my own naming problem, I built a Javascript plugin called Vocalizer. In this article, I will introduce what Vocalizer is and a few different ways to use it.

How It Started Link

Earlier this year, I redesigned my portfolio website. During this process, I decided to add a feature that educated visitors on how to say my name. One day, I opened the “Voice Memos” app on my iPhone, tapped “Record”, and asked my wife to say my first name. Then, I embedded a small button onto the landing page after my first name. Clicking on that button would play the audio file of my name.

1
The audio pronunciation button that I added to my website (Large preview2)

After launching the website, I received a few emails and tweets calling out the audio feature. I even attended a few conferences and meetups where people pronounced my name the right way. A few people expressed interest in implementing the pronunciation feature on their own websites.

Over the next few weeks, I spent time converting my singular implementation into a reusable plugin. Before publicly releasing it, I stumbled upon a company called NameShouts, which is an audio-based pronunciation tool with a repository of over 70,000 name pronunciations. I reached out to them for access to their API, implemented it into my plugin, and open-sourced it.

How To Use Vocalizer Link

Vocalizer is a simple, lightweight JavaScript plugin that facilitates the accessibility of difficult to pronounce names. If you’re someone who is unsure of how to say a certain name, Vocalizer shows you how. Or, if you’re someone with an unfamiliar name, Vocalizer shows others how to pronounce it.

A closer view of what an implementation of Vocalizer looks like.3
A close-up view of what an implementation of Vocalizer looks like (Large preview4)

The benefit of using NameShouts’ API is that it makes the implementation as quick as possible. In its simplest usage, there are only two steps required to add it to a website.

First, you must include the Javascript library before the closing </body> tag within the code of your website:

<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/vocalizer/1.0.0/vocalizer.min.js">

Next, all you have to do is wrap your first name in a <span> tag with the specified attributes:

<span data-source="auto">NAME</span>

Note: The latest version of Vocalizer.js is available on CDNJS5, or you can choose to download6 and serve the files from your own server.

As you might have noticed, the data-source attribute is set to auto in the example above. This attribute determines the source of the audio file.

When data-source is set to auto, the library will use the NameShouts API. This option is completely hands-off. Vocalizer will automatically search NameShouts’ name listing and feed in the audio file from their servers.

The alternative option is to manually record and use your own audio file instead of the API. In this scenario, the data-source attribute should be set to the path to your audio file. For example:

<span data-source="assets/audio/daenerys.mp3">Daenerys</span>

There’s a chance that NameShouts’ library does not have the pronunciation for your name, and in that event, you should use your own audio recording or Vocalizer won’t be doing its job!

How It Works Link

The actual source code for Vocalizer.js is about eighty lines of code. Let me explain exactly what’s happening under the hood.

When the user wraps his or her name within the <span> tag with the class vocalizer, a Javascript function stores that name into a string:

var name = document.getElementsByClassName('vocalizer'); var names = []; for (var i = 0; i < name.length; i++) { var data_source = name[i].getAttribute("data-source"); names[i] = name[i].innerHTML.toLowerCase().replace(/W/g,'') var request = buildRequests(names[i]); fetchAudio(data_source, request, i); }

We perform this inside of a loop in case there are multiple usages of Vocalizer on the page.

Next, a conditional checks the data-source attribute to see if you’re opting to use the NameShouts API to source the pronunciation or if you’re using your own audio file:

var data_source = name[i].getAttribute("data-source"); if (data_source == 'auto') { /* code for using NameShouts API */ } else { /* code for using your own audio file */ }

The buildRequest() function that we call inside that loop returns the path for the endpoint based on the user’s name.

function buildRequests(n) { return request = 'https://www.nameshouts.com/api/names/'+n; } 

From there, we pass the request to the fetchAudio() function and make our xmlHttpRequest to the NameShouts API.

var xhr = new XMLHttpRequest(); xhr.open('GET', request, true); xhr.onload = function (e) { if (xhr.readyState === 4) { if (xhr.status === 200) { var audioPath = JSON.parse(xhr.responseText).message[names[i]][0]["path"]; var audio = new Audio(BASE_URL+audioPath+'.mp3'); audio.playbackRate = 0.75; name[i].addEventListener('click', function() { audio.play(); }, false); } else { console.error(xhr.statusText); } } } xhr.onerror = function (e) { console.error(xhr.statusText); }; xhr.send(null); 

NameShouts’ API returns a JSON object that contains the name of the audio file corresponding to your name. From there, we combine NameShouts’ base URL (where the audio files are stored) and the audio file’s path.

In the event the name you are targeting does not exist within the NameShouts API, the plugin will throw an error.

A solution to this situation would be to record and link your own audio file. Setting the data-source attribute to a file path designates your own audio file. In that case, we just create an Audio element based on the file path from data-source:

var audioPath = sourceType; var btn = document.getElementsByClassName('vocalizer'); var audio = new Audio(audioPath, function() { 'Error!'; }); 

On the front end, an audio button appears after the targeted name. The cosmetics are added with CSS styles on the pseudo-element :after on the <span> tag.

Finally, we add a click event to the audio button:

btn[i].addEventListener('click', function() { audio.play(); }, false); 

Other Use Cases Link

Example: Blogs and News Publications Link

Vocalizer’s use case can extend beyond just personal websites. I can see blogs and digital news publications begin to adopt the plugin, as well.

An example of how Vocalizer could be used by news publications, such as Vox.com.7
An example of how Vocalizer could be used by news publications, such as Vox.com (Image credit8) (Large preview9)

Imagine you are browsing news stories on Vox.com10 and you see the name of a political figure or a region of the world with a name in which you are unfamiliar. In that situation, Vocalizer could educate you on its pronunciation. In theory, this would better equip you to discuss these current events and issues. No one wants to sound uninformed.

Example: Social Media Platforms Link

Another hypothetical use case could be on social media websites. LinkedIn comes to mind for its role in facilitating professional connections.

Potential usage on social media websites, such as LinkedIn.11
Potential usage on social media websites, such as LinkedIn (Image credit: LinkedIn12) (Large preview13)

In an age when people often connect with each other via social media platforms, such as Facebook, Twitter, or LinkedIn, prior to meeting — a tool like Vocalizer could prove useful.

Unbeknownst to me, Facebook recently rolled out a similar feature that automatically generates audio to enunciate names.

Facebook's feature that displays the pronunciation of names14
Facebook’s feature that displays the pronunciation of names (Image credit15) (Large preview16)

It’s nice to see mainstream platforms focus on these types of accessibility features. Unfortunately, there is no guarantee that autogenerated playback will be correct. Facebook’s pronunciation tool mangles my last name.

Challenges Link

With every potential solution, there are problems. Vocalizer faces issues of its own. The main issue is that two people with the same name do not always pronounce their name in the same way.

Often, a person’s origin language dictates the pronunciation of their name. For example, the name José in Spanish is pronounced HOH-SEH. In French, the same name is pronounced JOO-ZE. Vocalizer’s current implementation does not cater to these circumstances unless you opt to use a custom recording.

Pushing Accessibility Further Link

In the last few years, web evangelists have emphasized the importance of web accessibility. Most accessibility functions cater to people with physical and cognitive disabilities. I believe there is a lack of attention in regards to inclusion and cross-cultural accessibility.

Though unintentional, in a way, Vocalizer seeks to enable cultural accessibility. Technology companies continually strive to diversify their workforces. We’re seeing heightened mobility in our professional lives. As a result, multiculturalism is becoming more and more prevalent.

For what it is — I hope Vocalizer helps familiarize people with names from other cultures or ethnicities.

The Future Of Vocalizer Link

There are a few features and improvements I would like to make on future versions of Vocalizer.js:

  • Language support for names with alternate pronunciations
  • More graceful handling of implementation errors
  • Adding a fallback for the situations when a name is not in NameShouts’ API
  • Ability to easily customize audio buttons styles

To further expand on the idea, I launched a free, web-based version of Vocalizer at Vocalizer.io.17

The web tool allows you to record your name in the browser. Then, it generates the code snippet required to add Vocalizer to your website.

Conclusion Link

A 2014 study18 found that people with easier-to-pronounce names are deemed “more trustworthy”. I built Vocalizer to solve a problem that has persisted all my life. Now, I hope this will prove useful to others, helping them solve the same problem.

Thanks so much for reading! Please don’t hesitate to tweet to me19 if you have any questions, comments or feedback.

(vf, aa, il)

Footnotes Link

  1. 1 https://www.smashingmagazine.com/wp-content/uploads/2016/12/The-audio-pronunciation-button-large-opt.jpg
  2. 2 https://www.smashingmagazine.com/wp-content/uploads/2016/12/The-audio-pronunciation-button-large-opt.jpg
  3. 3 https://www.smashingmagazine.com/wp-content/uploads/2016/12/implementation-of-Vocalizer-large-opt.jpg
  4. 4 https://www.smashingmagazine.com/wp-content/uploads/2016/12/implementation-of-Vocalizer-large-opt.jpg
  5. 5 https://cdnjs.com/
  6. 6 https://github.com/atifazam/vocalizer
  7. 7 https://www.smashingmagazine.com/wp-content/uploads/2016/12/example-of-how-Vocalizer-could-be-used-large-opt.jpg
  8. 8 http://www.vox.com/
  9. 9 https://www.smashingmagazine.com/wp-content/uploads/2016/12/example-of-how-Vocalizer-could-be-used-large-opt.jpg
  10. 10 http://www.vox.com/
  11. 11 https://www.smashingmagazine.com/wp-content/uploads/2016/12/Potential-usage-on-social-media-websites-large-opt.jpg
  12. 12 http://www.linkedin.com/
  13. 13 https://www.smashingmagazine.com/wp-content/uploads/2016/12/Potential-usage-on-social-media-websites-large-opt.jpg
  14. 14 https://www.smashingmagazine.com/wp-content/uploads/2016/12/fb-large-opt.png
  15. 15 http://www.facebook.com/
  16. 16 https://www.smashingmagazine.com/wp-content/uploads/2016/12/fb-large-opt.png
  17. 17 https://www.vocalizer.io
  18. 18 http://news.uci.edu/press-releases/uc-irvine-led-study-finds-truthiness-in-peoples-names/
  19. 19 https://www.twitter.com/atifazm

↑ Back to topTweet itShare on Facebook

☑️ The Ultimate Digital Clean-Up Checklist: Are You Prepared For The New Year?

☑️ The Ultimate Digital Clean-Up Checklist: Are You Prepared For The New Year?

With a couple of days left until New Year’s Eve, it’s just about time to set aside 60 minutes to clean up, sort out and back up your digital footprint, to ensure a good smooth start to 2017. So many little details tend to get forgotten or overlooked every single time, only to get fixed hastily later — but doesn’t it just feel right when everything is in the right place, neatly organized, even if you aren’t a compulsory cleaner or an obsessed perfectionist?

This is not a generic article about unspectacular things like getting to inbox zero or changing the copyright year in your footer (although that’s a good idea!) — we published a detailed checklist1 of all of those details a couple of years ago. Instead, you’ll find below an overview of all of those obscure little things that I forget about every year; so, I decided to gather them all in one place once and for all.

The list below serves as a personal reminder for yours truly, and I thought that it might be useful for you as well. In fact, I set up a yearly reminder on December 28th just to have a couple of days to free the mind for the more important things in life and to start the next year without second thoughts or unresolved issues. Curious? Well, let’s dive in!

If you think something is missing, do please let us know in the comments so that we can put it all together and benefit from it collectively.

Collect The Things You Need Link

Invoices! Who doesn’t occasionally forget to include a payslip in their invoice, basically throwing money out of the window? Extract all the receipts and payslips that have accumulated over the year. You might already be using a dedicated phone app to scan, keep, organize, submit and track your receipts, but you might still have some neglected receipts in your inbox as well.

  • Collect train, bus and airplane PDF tickets and receipts. You could organize them by destination and add a date stamp in a separate folder (for example, 2016/Dec-London/Receipts).
  • Collect Uber, Lyft, Gett and other PDF receipts, and save them in those folders as well (for example, 2016/Dec-London/Receipts/Cabs).
  • Collect PDF receipts for accommodation business expenses (Airbnb, hotels, takeout food), and save them in those folders (for example, 2016/Dec-London/Receipts/Accommodation).
  • Collect one-time expenses for printed books and eBooks, including any online purchases (such as from Amazon). Don’t forget those handy utilities (Alfred, TextExpander, etc.), mobile apps, as well as your third-party text editor and calendar applications. Again, save them in those folders (for example, 2016/one-time-expenses).
  • Collect monthly digital expenses as PDF receipts and save them. Think of mobile phone charges, roaming expenses, Internet and TV, GitHub, CodePen, Typekit, Dropbox, Spotify, Slack, BrowserStack, Amazon S3, Adobe Creative Cloud, email services such as MailChimp, Litmus and Campaign Monitor, Flickr, Vimeo, Dribbble, Netflix, CRM tools, Amazon Prime, external services, hosting services and CDNs, usability testing tools, conference and workshop tickets, learning services such as Treehouse and Skillshare, and other monthly service costs2. Not to mention the antivirus software and firewalls that you’re using (and probably paying for monthly as well). Your monthly digital service costs might be higher than you think.

Once you’ve collected all of the receipts, you could set up a little spreadsheet3 to keep track of your expenses (even using the free Google Spreadsheet template4). Your accountant will appreciate it, and you can set up a budget allowance of how much you’d like to spend next year. Knowing where you stand will help you decide how much money to set aside next year, and how you’d like to approach it strategically.

5
You can grab and customize a free monthly expenses Google Spreadsheet template6.

While you’re at it, double-check that all outstanding invoices have been sent and paid, and set up invoice reminders to be sent out automatically either in late December or in early January — for example, with Boomerang for Gmail97.

Respondable by Boomerang8
Boomerang for Gmail97 allows you to send reminders automatically, or send emails later.

Delete Email Notifications Link

Throughout the year, we are bombarded with all kinds of notifications — Twitter mentions, Basecamp messages, Trello cards, GitHub updates. Do you really need them? Quite frankly, more often than not, they clutter search, making it more difficult to find things you’re looking for. Delete all notifications that have come in over the years:

  • Twitter (from notify@twitter.com),
  • Facebook,
  • LinkedIn,
  • Pinterest,
  • Trello,
  • Slack,
  • Basecamp,
  • Dropbox,
  • Google Docs,
  • GitHub,
  • Reddit,
  • comments, replies, forum messages.

Review Privacy And Notification Settings Link

While you’re at it, review your notification settings as well. Do you really need hourly notifications, or would daily notifications do just fine? It’s probably a good idea to reduce the frequency of notifications and then see whether you are missing anything — you can always adjust the frequency later.

Delete any other notifications you probably don’t need just by browsing your incoming messages by sender’s address to identify the usual and not-so-usual suspects. You could set up a separate email address just for notifications (for example, notifications@smashingmagazine.com) to prevent them from flooding your primary inbox, so that you can stay focused on emails from colleagues and coworkers.

Also, double check your privacy settings in the applications you are using the most. Review the ads settings, data collection settings and security settings and activities in Gmail10, Facebook11, Twitter12, LinkedIn13, Pinterest14 and Instagram. Double points if you have installed an ad blocker and Privacy Badger15 that blocks spying ads and invisible trackers.

Triple points if you also review authorized apps in Twitter, Facebook and Gmail. You’ve probably tried quite a few apps over the year once and never used them again; no need to grant them permission to access your accounts. Ah, quadruple your points if you look into the front-end performance checklist 201716 as well at this point!

Delete Irrelevant Email Link

Everybody loves a good ol’ email newsletter. We here are guilty of this as much as any other (albeit lovely) company, and indeed we send Smashing newsletters every now and again (sorry about that!). It might just be time to revisit all of your subscriptions. If you haven’t opened more than five newsletters from a single source, then you might not need them after all. Be brutal and unsubscribe from as many newsletters17 as you can. Depending on how thorough your cleaning preferences are, you might choose to either archive or delete messages received.

Unroll.me18
Services such as Unroll.Me19, help you clean up your inbox by unsubscribing from newsletters you don’t need with one single click.
  • Clean up your news alerts and notifications (New York Times, Quartz Daily).
  • Clean up all out-of-office replies and automatic replies (filter by “out-of-office” and “automatic reply”).
  • Clean up all event reminders (Meetup.com, Eventbrite, etc.) — just save tickets that you will need for invoicing later, though!
  • Clean up all form submissions (for example, Wufoo and Typeform). You can track conversations in email or download Excel spreadsheets later if needed.
  • Clean up all the drafts of messages that you started writing and never finished. If you haven’t sent them out yet, maybe you will never send them at all. Might be a good idea to check the contents of those drafts before deleting them, though — keep the good ideas and delete the unnecessary stuff!
  • Archive customer support tickets and discussions, as well as emails that are older than a certain threshold. An email that is about three years old might be important enough to look up one day but doesn’t need to be synced across all of your devices.
  • Clean up all newsletters that you’ve never managed to readand that you won’t be able to read this year. Chances are that if something is important and worth reading, it will bubble up in your conversations with colleagues or on Twitter or Facebook at some point anyway.
  • Clean up all marketing newsletters from companies you admire and don’t feel like unsubscribing from (MailChimp, Litmus, TED, type foundries, fashion brands etc.).
  • Delete spam messages and, you know, deleted messages — for good.

Again, just to keep all of these emails away from your primary inbox, it might be a good idea to set up a dedicated account for newsletters and form submissions. Also, set up a filter for all out-of-office replies and automatic replies.

Revisit The Email Signature And Text Shortcuts Link

Double-check that your email signature is up to date, especially your phone number, VAT number and postal address. Is including your mobile phone number in every email absolutely necessary? Maybe your office number would do just fine.

And if you need a bit of inspiration for a tasteful email signature, Kat Neville has got your back with “The Art and Science of the Email Signature20” — an article published seven years ago and still relevant today.

Also, if you’re using shortcuts and text abbreviations, possibly with a tool such as TextExpander, revisit your text snippets and write new ones, to save precious minutes next year.

Delete Apps You Don’t Need Link

Unless you’re an extraordinary, super-organized machine, all of your devices have complained to you throughout the year about the lack of space. Well, removing unnecessary email will help, but the main problem usually isn’t just email.

Among all of the apps installed on your phone, tablet, phablet, desktop, laptop, schlaptop, smart TV or anything in between, you are probably not using most of them. If you can’t even remember what an app does, chances are high that you don’t really need it on that device.

You probably have Dropbox21 and Basecamp22 and Trello23 installed on your mobile phone, but how often do you actually access them? Do you need to fully sync your personal folder — usually you’ll have your laptop nearby anyway, right? Delete all the apps you don’t use — maybe you’ve replaced some of the installed ones with the newer, better alternatives, or maybe you tend to use the services on desktop, and the mobile apps aren’t useful anyway?

While finding your way through your apps and looking through the ones you use a lot, revise your privacy and notification settings on mobile — many of them might be slowing you down and draining your battery because they are running in the background. Check what apps are actively updating, refreshing and collecting data about you behind your back in the “Background App Refresh” settings — deactivating them might be a good idea. Also, don’t forget to archive your chat messages and media files sent via WhatsApp and Viber. And — if you’d like to go all the way — delete your accounts on services you don’t use24.

Offload Images And Videos To An External Hard Drive Link

Everybody needs access to a memorable concert video or colorful pictures from a recent trip — I get it. However, when you need space, you need to be reassured that if you delete that great video, you will still be able to find it easily when needed. Having an overloaded phone and running out of space is that one thing that is probably the most annoying (at least to me!) during the year.

Offload all images from your phone and tablet to Dropbox, Google Drive, iCloud, and your laptop or desktop, or just get a dedicated external hard drive and store them there neatly. This goes for movies you haven’t watched yet and TV shows you’re saving for that long-haul intercontinental flight next year.

Also, unless you already have automated backup in place, back up all critical data — you can also request your Twitter archive25, backup your WhatsApp messages26, and export your Facebook messages27 and export your Medium posts28, if that’s your kind of thing.

Revisit Your Ultimate Restore Reboot Kit Link

What happens if your phone drowns or your laptop decides to cease cooperating with you? Be ready in case something happens to your machine and you need it right away. Obviously, you have backed up your phone and your desktop, but what if something fails or you don’t have online access? (Yep, it’s happened to me29 — start watching the first video at 5:55:25).

Prepare a Restore Kit, a folder collecting all your important applications, settings and license codes. Take a close look at all of the applications you use regularly and write them down. You might end up with something like what follows.

Desktop Link

Gmail, Sublime, GitHub Desktop, SizeUp, TextExpander, Alfred, Fantastical, Tweetdeck, Screenflow, IA Writer, Slack, Skype, Pages, Keynote, Disk Order, Dropbox, 1Password, OpenPASS, Chrome, Canary, Firefox, Opera, browser extensions (Adblock, Boomerang for Gmail, BrowserStack, link checker, DotVPN, Emmet Re:view, Eye Dropper, Facebook Disconnect, Full Page Screen Capture, Lighthouse, OneTab, Privacy Badger, Session Manager, The Great Suspender, WebPagetest, Window Resizer), Transmission (FTP client), The Unarchiver, GoToMeeting, DaisyDisk, Open Broadcaster Software, Lookback, VLC, uTorrent, Spotify, Adobe Creative Cloud.

Mobile Link

Google Maps, WhatsApp, Skype, Foursquare, Instagram, Messenger, Twitter, Facebook, Google Translate, Shopify, Shazam, Spotify, Uber, Lyft, iA Writer, SpeedSmart, Google Authenticator, Opera Mini, Trello, Slack, Airbnb, Adblock, Revolut, banking application

Download the latest versions of these applications, extract the settings or config files from your existing apps, and store them all both locally and on a USB stick. Some services live online, so make sure to reference them (for example, in a plain-text file). Also, don’t forget to extract, encrypt and store the license codes for all of your locally installed applications:

  • Save encrypted passwords for your Google Chrome and Firefox accounts, so that you don’t need to sync bookmarks, popular search hits, your browsing history or extensions.
  • Save encrypted credentials to access your primary email account.
  • Save encrypted PIN and PUK codes for your mobile phone.
  • Take a screenshot of the arrangement of icons on your desktop, tablet and phone — including the deck and app icons on your phone. They will serve as a point of reference. Sync them via Dropbox — just in case mobile/desktop backup fails at some point in the future (yep, happened to me already as well).

If you put all of these files together in a separate Restore Kit folder, encrypted and stored both locally and on an external USB drive, you’ll be able to set up your working environment and get up and running completely from scratch within half an hour. Bonus points if you use Ninite30 (Windows), Get Mac Apps31, createOSXinstallPkg32 or Homebrew Cask33 (Mac) with a little shell script34 to bundle a handful of installable packages and run them at once one after another automatically. Better to feel safe than sorry!

Caskroom35
Caskroom36 installs your apps to your /Applications folder in the same way as you would manually, but with just one click.

Random Stuff Link

Just to make sure you don’t leave out something important in your to-do-list or in the “considered-to-be-spam” trench of your inbox, below is a quick checklist of a few things that could be helpful to revisit before diving into the new year:

  • Install updates you’ve been delaying for weeks.
  • Check Facebook’s hidden tab, “Message requests,” for people who aren’t your Facebook friends.
  • Check whether you’re overpaying for mobile, Internet or web services — prices tend to change all the time.
  • Learn one new keyboard shortcut a week, and define at least one custom text abbreviation a week.
  • Remove sharing buttons, links and any irrelevant content from the footer.
  • Review if you need all reserved and parked domains and check when they expire, to set up notifications and extend the license in time.
  • Clean up your desktop before the new year starts — when in doubt, just quickly hide all of the icons on your desktop37.
  • Write down important phone numbers of relatives, close friends and colleagues — on paper — and store them carefully.
  • Whenever a loved one mentions something they’d love to have, write it down and order it right away — you’ll find an occasion to give it to them later in the year.
No icons on desktop38
A simple shell command39 helps you hide the icons on your desktop.

Clean up your desktop before the new year starts — when in doubt, just quickly hide all of the icons on your desktop.

Set Up Cleanup Reminders For Future Years Link

Of course, in a perfect world, we would properly name all files and keep them in properly grouped and marked folders, and we would keep our inbox lean and clean. But more often than not, our data isn’t as neatly organized as we’d love it to be. Set up a cleaning reminder for late December 2017 (and December 2018), maybe even with a link to this article.

Quick Wins Link

Phew! Here we go. Now, this list is quite comprehensive, and taking on the task of cleaning up your digital footprint might be the most tedious task you accomplish this entire year! So, if you had just one hour to get significant improvements, what would you do? Let’s boil it all down to 7 low-hanging fruits.

  • Think of and collect the receipts for the highest business expenses to send to your accountant early next year.
  • Double-check that all outstanding invoices have been sent and paid.
  • Revisit the frequency of notifications for services you use. Delete email notifications. The usual suspects are email, Twitter, Facebook, Trello and Slack.
  • Review your privacy settings, ads settings, data collection settings and security settings and review authorized apps in Twitter, Facebook, Gmail and others.
  • Create separate email accounts (and/or filters) for notifications and receipts.
  • Delete apps that you don’t need on your phone, tablet and desktop.
  • Revisit your ultimate restore or reboot kit: List essential apps, and collect and sync config and settings files, encrypted license files and the arrangement of icons on your screens. Whenever a loved one mentions something they’d love to have, write it down and order it right away.

Fantastic — you made it! Reward yourself for the last days of the year: uncork and share a bottle of champagne with your family or your friends who managed to get through the checklist just like you, and have a good clean start to 2017! 😉

Not good enough? Well, let us know what’s missing in the comments below!

(al, il)

Footnotes Link

  1. 1 https://www.smashingmagazine.com/2010/01/dont-forget-the-small-stuff-this-year/
  2. 2 https://css-tricks.com/web-developer-economics-monthly-service-costs/
  3. 3 https://docs.google.com/spreadsheets/d/1JAkySUuc-or495xG3sy2HLbbnwpYqwnWCc9L4jud7Mo/edit#gid=0
  4. 4 https://docs.google.com/spreadsheets/d/1b8ps-HQIAFCtCVA4-cFTn-VxOlms3r7nu_jwtrZa1yA/edit#gid=0
  5. 5 https://docs.google.com/spreadsheets/d/1b8ps-HQIAFCtCVA4-cFTn-VxOlms3r7nu_jwtrZa1yA/edit#gid=0
  6. 6 https://docs.google.com/spreadsheets/d/1b8ps-HQIAFCtCVA4-cFTn-VxOlms3r7nu_jwtrZa1yA/edit#gid=0
  7. 7 http://www.boomeranggmail.com/
  8. 8 http://www.boomeranggmail.com/
  9. 9 http://www.boomeranggmail.com/
  10. 10 https://myaccount.google.com/security?pli=1
  11. 11 https://www.facebook.com/settings?tab=privacy
  12. 12 https://twitter.com/settings/security
  13. 13 https://www.linkedin.com/psettings/
  14. 14 https://in.pinterest.com/settings/
  15. 15 https://www.eff.org/privacybadger
  16. 16 https://www.smashingmagazine.com/2016/12/front-end-performance-checklist-2017-pdf-pages/
  17. 17 https://unroll.me/
  18. 18 https://unroll.me/
  19. 19 https://unroll.me/
  20. 20 https://www.smashingmagazine.com/2010/02/the-art-and-science-of-the-email-signature/
  21. 21 https://www.dropbox.com/
  22. 22 https://basecamp.com/
  23. 23 https://trello.com/
  24. 24 http://deseat.me/
  25. 25 http://twitter.timehop.com/howto
  26. 26 https://www.whatsapp.com/faq/en/android/20887921
  27. 27 https://www.facebook.com/help/community/question/?id=246257462227260
  28. 28 https://help.medium.com/hc/en-us/articles/214043918-Export-content-from-Medium
  29. 29 http://www.trinidad.ee/blog/wud-2015-tallinn-conference-broke-the-record-again/
  30. 30 https://ninite.com/
  31. 31 http://www.getmacapps.com/
  32. 32 https://github.com/munki/createOSXinstallPkg
  33. 33 https://caskroom.github.io/
  34. 34 http://www.getmacapps.com/raw/xth50kli8e9
  35. 35 https://caskroom.github.io/
  36. 36 https://caskroom.github.io/
  37. 37 http://www.cultofmac.com/272595/quickly-hide-icons-desktop-os-x-tips/
  38. 38 http://www.cultofmac.com/272595/quickly-hide-icons-desktop-os-x-tips/
  39. 39 http://www.cultofmac.com/272595/quickly-hide-icons-desktop-os-x-tips/

↑ Back to topTweet itShare on Facebook

Strategies For Effective Mobile Landing Pages

Strategies For Effective Mobile Landing Pages

When designing a landing page to promote a product or service online, you’re ultimately pointing users toward one goal. That goal most often relates to generating business via sales or leads. You may want users to purchase a product immediately, or you may simply want them to sign up for a mailing list. Whatever the goal, you want to ensure that every piece of the user experience works toward fulfilling that goal.

If you don’t yet have goals in mind, start by defining goals. Are you seeking to generate a 10% increase in qualified leads? Are you looking to build sales by 20%? Establishing clear key performance indicators based on what will benefit your business will ultimately help you understand how to properly approach a landing page.

Every goal should tie to a clear business outcome. For example, let’s say you run a software-as-a-service company and have determined that 100 new customers would provide the income you need to meet your revenue goals for the year. If you’ve established proper analytics and are carefully tracking results from your website, you might know that 10% of people who sign up for your mailing list are likely to become paying customers. So, you establish a goal of getting 1,000 new email registrations, which would likely result in your end goal of 100 new customers.

For more on establishing realistic goals and correlating those to online goals, see Avinash Kaushik’s article “Web Analytics 101: Definitions: Goals, Metrics, KPIs, Dimensions, Targets1.” Start with a foundation of being able to track the right data, and build from there to establish metrics you can seek to improve.

Ultimately, the best way to convert a user on a mobile landing page is to provide a clear description of what you’re offering, along with obvious ways to contact you. Be clear in describing what your product does and how you’re solving your target customer’s problems. For instance, “Best vacuum ever” says less than “Breathe more easily with a vacuum that removes 99% of allergens.” Clear contact options include simple, prominent forms and visible phone numbers, so that visitors don’t have to struggle to find out how to reach you.

Get to the point of what you’re selling and show the user how to buy it or contact you. Lack of any distractions, whether from a content or technical standpoint, will help to ensure the page supports your goal of converting users.

Sadly, too often businesses design landing pages without clearly thinking through every context in which users will be viewing the page, including what devices they’ll be on. Creating landing pages with mobile users in mind will help you to focus on how best to convert people on smartphones.

Choosing Your Tools Link

To create a landing page that follows the guidelines we’ll be talking about, you’ll need to pick the right tools to build and host it. If you have the right coding expertise, of course, you could build a page from scratch. However, a number of platforms exist to streamline the creation of landing pages. While the primary purpose of this article is to help you plan the elements and structure of a landing page, here are some brief suggestions of tools to build one.

First, if you already have a hosting service, then WordPress offers an excellent starting point for building a responsive landing page that easily integrates with plugins for forms and other elements. You will find a number of pre-built templates on websites such as ThemeForest2.

Next, several other tools allow you to create and host pages on their platforms. Unbounce3 and Wishpond4 are two popular platforms that enable you not only to build pages but also to implement A/B testing, which we’ll discuss in the last section. Neil Patel has a detailed overview5 of various platforms for landing pages.

Consider The Content Link

A quick Google search will give you thousands of articles recommending various optimal lengths for landing page content. One source says to include at least 500 words6, while another recommends up to 1,000 words7. In reality, the ideal length will depend on what you’re selling and who your audience is, and you can test to determine the length that converts best. However, once the content has been condensed into a mobile format, you’ll need to especially consider how much your users will be willing to read and how far they’ll scroll before you lose the opportunity for a conversion. You can test pages with more or less content (for instance, testing a 500-word page against a 1,000-word page) with an A/B testing tool (discussed in more detail later), monitoring conversion rates to determine whether users are more likely to contact you with more or fewer words to read through.

To identify what content lengths are ideal for your users, you can test to see how long, on average, they’re scrolling through the content. In addition to scrolling, you should factor in how likely people are to engage with content by watching videos, clicking links or filling out forms. Measuring this activity is possible using a heatmapping tool, which we’ll also talk about more in depth later in this article.

In addition, you may start with some assumptions, such as thinking that most mobile users stop at “the fold” of the bottom of their screen. However, several studies8 show that most website visitors will naturally scroll as long as the page provides a user-friendly interface for doing so. For instance, a Time article9 shares that 66% of activity on a page happens below the fold. With this in mind, still keep important content and elements visible as high as possible, but don’t shy away from providing more detail in the copy.

If you’re looking to generate leads for an air-conditioning repair business, people are more likely to want to get right to the point of calling or filling out a form. If someone’s air-conditioning unit is broken on a 90-degree day, they likely won’t want to read a 2,000-word writeup on the inner workings of an air conditioner. They’ll probably be turned off by having to scroll through lengthy text before reaching a section containing contact information. They’ll want to reach right out to someone who can come to fix their unit, and feel assured that the person they contact can arrive quickly to take care of the problem.

However, if you’re selling luxury gold watches for $5,000 each, you’ll likely be better off including a detailed explanation of what sets your watches apart. In this case, you’re targeting a niche wealthy audience who will want to read and visualize details about your products in order to make a purchasing decision. They’re not so likely to make a purchasing decision on a whim with limited information: They’ll want to see pictures showing all angles of the luxury watch, a video about how each watch is handcrafted from the finest-quality materials, and a writeup about a lifetime guarantee.

Whatever the content’s length, take care that individual paragraphs don’t become excessively long when viewed on a mobile device. While a paragraph may stretch to only four lines of text on a desktop screen, the same paragraph might take up ten lines when compressed to a mobile screen size. More frequent paragraphs break will improve legibility.

Focus On Conversions Link

Whether promoted via paid search or a social media campaign, a landing page should keep a focus on converting users into sales or leads. In the midst of ensuring brand integrity and writing copy to present a product or service, don’t let this main goal fall by the wayside. Especially in the limited amount of space available on a mobile device, you’ll have a brief window in which to grab the user’s attention and, ultimately, to get them to convert.

For a service-related business looking to generate leads, like the air-conditioning repair example, you should feature a phone number prominently across all devices. When users are looking to fix a problem right away, especially when browsing on a phone, they often prefer to place a call for service. Make sure to include click-to-call functionality10 on the mobile version of the page.

11
Progressive Insurance’s landing page (View large version12)

For instance, look at the landing page above used for paid search. In a desktop format, the only conversion option is a quote form. However, once the page shrinks to a mobile size, a phone icon appears in the upper-right corner, giving the option to click to call. This change provides a positive conversion focus for mobile, since users searching for insurance from a smartphone would likely want to speak with an agent.

In addition to a phone number, ensure that a form features prominently on mobile. Some responsive design templates that include a form might shrink to the point where the form no longer shows up at a mobile size. This will more than likely result in fewer leads.

Make sure the form’s fields are large enough to be tapped easily with a finger. While a form might work perfectly at a desktop size, the fields might shrink to the point where they’re difficult to select on a phone. For more on designing landing page forms that will aid the conversion process on mobile and not turn off users, see UserTesting’s article covering form usability resources13.

Avoid User Experience Barriers Link

When creating a mobile landing page, a marketing mindset too often leads to one overlooking the user experience. In the process of introducing every possible piece of content or way of presenting a signup form, you could end up turning off users who might have otherwise taken time to read the page and converted. Before launching any campaign, review your landing page on multiple devices with multiple users to determine possible issues to fix. Below are a few examples of potential barriers.

Interstitial Forms Link

Interstitial forms are a tempting option to “force” users to convert. However, they tend to create a higher number of annoyed users than converted users, especially on mobile. For instance, a Google study14 reveals that an interstitial ad promoting a Google+ app download resulted in 69% of users immediately leaving the page without engaging.

While an interstitial newsletter signup form might be easy to close on desktop, the same popup on a phone might shrink to the point that the “x” is painful to tap. Be careful especially of such conversion tactics that turn into a frustrating barrier for mobile users. Ironically, people can be turned away by the very elements intended to add an extra chance of conversion. For instance, according to a study cited in VentureBeat15, “viewers were 2X as likely to have a negative emotional response to a full page interstitial ad than to a rewarded, opt-in ad.” Also, note that Google recently began penalizing websites16 for some obtrusive interstitial formats.

Interstitial examples on mobile landing pages17
Interstitial examples on mobile landing pages (View large version18)

Responsive Design Flaws Link

In addition, think about how responsive design factors into the mobile experience. In theory, the idea of responsively stacking elements to fit a screen size works well. This setup could, however, result in a user having to scroll excessively to get to a form, if you don’t carefully plan out how elements will stack at a mobile size. A templated website might stack a form at the bottom, but you should readjust the layout to place the form higher on the page or include a clear “Contact” button that scrolls with the user’s activity and leads directly to the form when clicked.

In this example, the form jumps to the bottom of the page in the mobile version.19
In this example, the form jumps to the bottom of the page in the mobile version. (View large version20)

Text Considerations Link

Also, think about how text will look when compressed to a mobile size. Will it be too small? Does the color allow for easy legibility? For instance, the white text for the page below looks fine over a dark background at a large size but blends with the light-blue background at a mobile size. However, on a positive note, see how the form fields go from four to one, making the process of completing the form simpler on mobile.

Example of legibility issues on mobile landing page21
Example of legibility issues on mobile landing page (View large version22)

Additionally, don’t keep the user captive on the landing page. While you do want to focus on conversion and don’t necessarily need your website’s full navigation bar, you also don’t want to frustrate a user who’s looking for more information about your brand. Make your logo clickable back to your primary website, or provide footer links back to it.

Test The Experience Link

To better identify what elements of the website are and aren’t working, test the experience of the website on mobile devices. Enlist people using different phone models across both Android and iOS, either finding people you know or using a website such as UserTesting23.

With the launch of a page, you can A/B test the placement of elements on the website using a tool such as Optimizely24 or Google Analytics’ free Content Experiments25. For instance, in the case of pricier products sold to a niche audience, you might want to test if these people will indeed respond to a form they see immediately or if they will need to read through content and view imagery before deciding to convert. For more ideas and tips, see Shopify’s “Beginner’s Guide to Simple A/B Testing26.”

In addition, install a heatmapping tool such as Crazy Egg27 or Hotjar28 to measure clicking and scrolling activity via a tracking script inserted in your website. This data will allow you to look more closely at how people are scrolling and what elements of the page they’re interacting with. In this way, you can determine how far into the content the average user is likely to read, as well as what buttons and form configurations are likely to produce a response.

Example of a heatmap29
Example of a heatmap (View large version30)

Be sure to look at heatmaps specific to mobile. While desktop heatmaps might show no issues, mobile might show a different story. Of course, data will vary from website to website, but you might find that a larger percentage of your desktop users scroll through an entire page than mobile users (or vice versa). Or you might find that desktop users are more inclined to fill out a lengthier form, whereas mobile users fill out the first two fields and then drop out due to faulty functionality on mobile. In the example below, see how users scroll through more of the content on desktop than on mobile. Based on this data, the developer would be wise to take out some of the lengthy content on the mobile version of the page.

Heatmaps showing desktop versus mobile scrolling patterns31
Heatmaps showing desktop versus mobile scrolling patterns (View large version32)

In addition, use Google Analytics to review mobile performance on your landing page. Segment by device when looking at the data to identify specific issues with mobile use. For instance, in the example shown below, we’ve selected a specific landing page under the “Behavior” → “Landing Pages” report, and used the “Secondary Dimension” dropdown menu to break out performance by device category. Here, we can see that mobile sessions resulted in a significantly lower conversion rate than desktop (0.65% versus 2.35%), indicating a potential flag of a poor user experience.

Comparing mobile analytics to other devices33
Comparing mobile analytics to other devices (View large version34)

Understand Perceived Performance Link

While page-loading speed is crucial for any website on any device, you should especially consider how quickly a page appears to load on mobile. One extra second of time spent waiting for an image to load could mean that an impatient mobile user gives up. In order to keep the user’s attention, make sure that resources load as quickly as possible in the user’s eyes.

One useful solution involves preloading resources on a landing page. You can use HTML5 prefetch35 to fetch some assets that will be used on a page that appears when the user clicks a call-to-action button on a landing page. In addition, you could also dynamically inject resource hints that tell the browser to download the required resources ahead of time. For more on this topic, see Denys Mishunov’s series on “Why Performance Matters36” (including part 237 and part 338) and CSS-Tricks’ article on prefetching39.

Conclusion Link

Here’s a recap of what to keep in mind when designing a landing page:

  • Define your goals to determine what to say on the page and what action you want users to take.
  • Describe your product or service as concisely as possible to grab the attention of users.
  • Break content into brief, readable paragraphs.
  • Exclude distracting elements, such as large navigation bars and excessive external links.
  • If appropriate, show imagery and/or video related to what you’re selling.
  • Place conversion elements such as forms and phone numbers in highly visible sections.
  • Test landing-page performance via analytics, heatmapping and A/B testing tools to determine changes to content length and page elements to include.

When building a landing page for any online campaign, take special care to consider the mobile experience. Review the presentation of content, as well as the prominence of contact information. Solicit the opinions of multiple users to identify issues, and test with analytics data to determine usability. With a clear plan in place for mobile, you’ll better convert users coming from multiple devices.

(da, il, yk, al, vf)

Footnotes Link

  1. 1 http://www.kaushik.net/avinash/web-analytics-101-definitions-goals-metrics-kpis-dimensions-targets/
  2. 2 https://themeforest.net/category/marketing/landing-pages
  3. 3 http://unbounce.com
  4. 4 http://wishpond.com
  5. 5 http://neilpatel.com/2015/08/20/12-tools-that-can-help-you-build-high-converting-landing-pages/
  6. 6 https://blog.crazyegg.com/2014/11/03/landing-page-500-words/
  7. 7 https://www.jeremysaid.com/blog/how-many-words-should-you-have-on-your-landing-page/
  8. 8 http://uxmyths.com/post/654047943/myth-people-dont-scroll
  9. 9 http://time.com/12933/what-you-think-you-know-about-the-web-is-wrong/
  10. 10 https://knowledge.hubspot.com/articles/kcs_article/cos-general/how-to-make-a-click-to-call-button-for-your-website
  11. 11 https://www.smashingmagazine.com/wp-content/uploads/2016/10/progressive-landing800-opt-1.jpg
  12. 12 https://www.smashingmagazine.com/wp-content/uploads/2016/10/progressive-landing800-opt-1.jpg
  13. 13 https://www.usertesting.com/blog/2013/04/04/42-form-usability-resources/
  14. 14 https://techcrunch.com/2015/07/26/google-studies-how-much-interstitials-suck-on-mobile/
  15. 15 http://venturebeat.com/2016/09/27/new-brain-activity-study-shows-that-mobile-interstitial-ads-are-failing-everyone/
  16. 16 https://webmasters.googleblog.com/2016/08/helping-users-easily-access-content-on.html
  17. 17 https://www.smashingmagazine.com/wp-content/uploads/2016/10/mobile-popup800-opt-1.jpg
  18. 18 https://www.smashingmagazine.com/wp-content/uploads/2016/10/mobile-popup800-opt-1.jpg
  19. 19 https://www.smashingmagazine.com/wp-content/uploads/2016/10/responsive-page-form800-opt-1.jpg
  20. 20 https://www.smashingmagazine.com/wp-content/uploads/2016/10/responsive-page-form800-opt-1.jpg
  21. 21 https://www.smashingmagazine.com/wp-content/uploads/2016/10/responsive-landing-page800-opt-1.jpg
  22. 22 https://www.smashingmagazine.com/wp-content/uploads/2016/10/responsive-landing-page800-opt-1.jpg
  23. 23 https://www.usertesting.com/
  24. 24 https://www.optimizely.com/
  25. 25 https://support.google.com/analytics/answer/1745152?hl=en
  26. 26 https://www.shopify.com/blog/12385217-the-beginners-guide-to-simple-a-b-testing
  27. 27 http://crazyegg.com
  28. 28 http://hotjar.com
  29. 29 https://www.smashingmagazine.com/wp-content/uploads/2016/10/heatmap800-opt-1.jpg
  30. 30 https://www.smashingmagazine.com/wp-content/uploads/2016/10/heatmap800-opt-1.jpg
  31. 31 https://www.smashingmagazine.com/wp-content/uploads/2016/10/scroll-difference800-opt.jpg
  32. 32 https://www.smashingmagazine.com/wp-content/uploads/2016/10/scroll-difference800-opt.jpg
  33. 33 https://www.smashingmagazine.com/wp-content/uploads/2016/10/mobile-analytics800-opt-1.jpg
  34. 34 https://www.smashingmagazine.com/wp-content/uploads/2016/10/mobile-analytics800-opt-1.jpg
  35. 35 https://medium.com/@luisvieira_gmr/html5-prefetch-1e54f6dda15d#.iwn4ggwp0
  36. 36 https://www.smashingmagazine.com/2015/09/why-performance-matters-the-perception-of-time/
  37. 37 https://www.smashingmagazine.com/2015/11/why-performance-matters-part-2-perception-management/
  38. 38 https://www.smashingmagazine.com/2015/12/performance-matters-part-3-tolerance-management/
  39. 39 https://css-tricks.com/prefetching-preloading-prebrowsing/

↑ Back to topTweet itShare on Facebook

Web Development Reading List #164: Enjoy The End Of 2016, It Wasn’t The Worst

Web Development Reading List #164: Enjoy The End Of 2016, It Wasn’t The Worst

Welcome to the last reading list of the year. I’m happy to still have you as a reader and very grateful to all the people who value and support my work. I hope you’ll be on vacation for the upcoming days or can relax a bit from your daily work. Remind to take care of yourself, and see you next year!

Concept & Design Link

Security Link

Web Performance Link

8
A preview of an animation flow on mobile. (Image credit9)

CSS/Sass Link

Work & Life Link

Forget About Setting Goals. Focus on This Instead.14
Having a system is what matters. Committing to the process is what makes the difference. (Image credit15)

Going Beyond… Link

And with that, I’ll close for this week. If you like what I write each week, please support me with a donation18 or share this resource with other people. You can learn more about the costs of the project here19. It’s available via email, RSS and online.

— Anselm

Footnotes Link

  1. 1 https://24ways.org/2016/animation-in-design-systems/
  2. 2 https://24ways.org/2016/front-end-developers-are-information-architects-too/
  3. 3 https://thehackerblog.com/the-orphaned-internet-taking-over-120k-domains-via-a-dns-vulnerability-in-aws-google-cloud-rackspace-and-digital-ocean/index.html
  4. 4 https://www.smashingmagazine.com/2016/12/front-end-performance-checklist-2017-pdf-pages/
  5. 5 http://calendar.perfplanet.com/2016/cache-digests-http2-server-push/
  6. 6 http://calendar.perfplanet.com/2016/no-font-face-bulletproof-syntax/
  7. 7 http://calendar.perfplanet.com/2016/loading-web-fonts-asynchronously/
  8. 8 https://24ways.org/2016/animation-in-design-systems/
  9. 9 https://24ways.org/2016/animation-in-design-systems/
  10. 10 http://callmenick.com/post/multi-line-padded-text-css-box-decoration-break
  11. 11 http://jamesclear.com/goals-systems
  12. 12 https://www.linkedin.com/pulse/i-have-side-code-projects-show-you-ezekiel-buchheit
  13. 13 https://medium.com/@jdan/quantifying-my-off-days-27e85f5bc157
  14. 14 http://jamesclear.com/goals-systems
  15. 15 http://jamesclear.com/goals-systems
  16. 16 https://medium.com/@angushervey/99-reasons-why-2016-has-been-a-great-year-for-humanity-8420debc2823
  17. 17 https://techcrunch.com/2016/12/13/ieee-puts-out-a-first-draft-guide-for-how-tech-can-achieve-ethical-ai-design/
  18. 18 https://wdrl.info/donate
  19. 19 https://wdrl.info/costs/

↑ Back to topTweet itShare on Facebook

Conversational Design Essentials: Tips For Building A Chatbot

Conversational Design Essentials: Tips For Building A Chatbot

Human interactions are incredibly fascinating if you take a close look at them — the social awkwardness, the communication styles, the way knowledge is transferred, the way stories are told and trust is built.

But what happens when a machine evokes the same response?

Conversational interfaces have become the new hotness in UX design. Google is about to release a new virtual assistant chatbot1; Facebook has already launched the updated Messenger platform with chatbots2; and Microsoft went as far as to claim that the operating system of the future isn’t Windows, but “conversation as a platform.”

What all of the big industry players have already figured out is that advances in artificial intelligence (AI) can solve a very important UX problem: making faceless branded websites and apps feel really personal.

3
Facebook Messenger presentation: booking a hotel room on the go (View large version4)

Chatbots can create a more genuine, custom-tailored experience, one that could be compared to the experience in a store — you get a smile from the salesperson, some chit chat and a friendly wink, which makes the whole buying experience more personal and pleasant. For brands, this represents an opportunity to extend and manage relationships with their customers and to go beyond being “just a product.”

However, building a genuinely helpful and attractive chatbot is still a challenge from a UX standpoint. Though we now have brilliant machine learning, which advances AI and natural-language processing (NLP) technologies, we are still somewhat limited in the type of helper we can create, and we need to force the most out of what we have. Matt Schlicht, founder of the Chatbots Magazine has created a very comprehensive guide5 summarizing the current state of the chatbot ecosystem and opportunities for designers.

Recently, I worked on the chatbot project for Alty6 — a Facebook messenger bot to chit chat with potential customers, introduce them to the company and services offered, and send out email inquiries.

Chatbot7
(View large version8)

The experience was relatively new and challenging. Unlike the standard graphical user interface (GUI), the app needed to work seamlessly with little user input, provide new value by leveraging stored information, and anticipate users needs. Standard patterns and flows don’t really work in conversational design, or else they need significant readjustment. Check Bot UI Kit9 for Messenger platform, courtesy of Mockuuups and Botframe10 – a simple prototyping tool for emulating conversations developed by Alsadir Monk11 to get a better idea of the common flows on this platform.

1. Pick A Toolkit Link

As already stated the first challenge you are likely to encounter is that you have little control over the application’s appearance. You don’t need to fuss over typography, layouts or styling too much. If you are building a voice-control chatbot, it won’t even have a visual side! Hence, ditch most of the standard tools and power up your toolkit with new useful ones.

For our project, we opted for the simplest tool — Chatfuel12, a free, intuitive bot builder for Facebook Manager with a drag-and-drop interface and hardly any coding required.

However, if you plan to build a more advanced bot, it’s worth looking into the following tools:

  • Twine13
    This non-linear text editor creates text scripts and message sequences for your dialogs.
  • Wit14
    This indispensable tool will help you convert voice and text commands into actions. Dozens of handy commands have been created by the community, and you can add custom ones.
  • Botkit15
    Howdy’s Botkit offers a handy set of commands and ready-made code for you to build your first Slack chatbot.
  • Api.ai16
    Recently acquired by Google, this robust and comprehensive platform will help you build any type of conversational UX interface.
  • Botwiki17
    This wiki answers all of the common chatbot questions.

Few of the standard controls or styles we use in standard apps apply to conversational design.

2. Hint To The User On How To Get Started Link

Conversational design completely changes the way users interact with an app. Typically, when a user opens a new iOS app, they will see some familiar elements, such as a menu, a panel to log in or create an account, buttons and so on — the elements they already know how to interact with based on common schemas18.

However, the first encounter with a chatbot is less conventional. The user will be staring at a blank screen, lost in assumptions about what to do next or how to interact with the app. They face two simple problems:

  • “I have no idea what I’m supposed to do.”
  • “What exactly can this thing do for me?”

Chatbots don’t seem intuitive for most users yet. Hence, your first task is to prompt the user on what’s about to happen next. Start with a quick introduction and a straightforward call to action, something like:

Chatbot19
(View large version20)

Keep it short and simple. Invite users to experience one quick benefit of your app and to enjoy the result immediately.

In the case of Alty’s bot, we opted to include buttons within the conversation for a few key reasons:

  • Typing on the go could be cumbersome for some users, and chatbots are not always smart enough to detect typos (although we’ll talk about dealing with that later on).
  • Buttons can hint to users about what kind of questions the bot can answer and what actions it can perform.

3. Craft The Right Conversation Flow Link

You want your robot to seem like a wizard, rather than an obstacle, right?

One of the most challenging parts about designing a chatbot is to make the conversation flow as naturally and efficiently as possible. However, human interaction is typically messy and non-linear. Here are some tips for optimizing the app’s performance.

Teach Your Bot To Distinguish Between Different Types of Questions Link

Create the initial scope of questions that your bot will be capable of processing and answering efficiently. You can use a great library named qTypes21, which has over 40 sub-classifications for how questions should be answered. qType indicates the type of reply the user expects, and qSubType indicates the question’s format:

  • CH

    With alternative choice question, the bot is asked to pick between two alternatives (for example, “Is this shirt red or green?”).
  • WH

    These are questions starting with who, what, when, where or why.
  • YN

    These are yes or no questions (for example, “Do you have a dog?”).
  • TG

    A tag question is not an actual question, but rather an option to keep the conversation flowing (for example, “This beach is lovely, isn’t it?”).

When your bot receives one of the standard questions, it can produce more accurate replies based on the data from the library:

Chatbot22

Avoid asking rhetorical questions, because most users tend to respond to them anyway, even if the chatbot is just being polite.

Now that your bot is capable of understanding questions, the next challenge is to teach the app to render appropriate commands in return.

Validate Input Data More Effectively Link

A standard GUI allows you to refine inputted data easily when processing it. Is this email address valid? Is this username available? Is this phone number valid? You can easily restrict and refine inputted data before processing it.

Yet, in conversational design, things get a bit more complicated. The user is free to say or type whatever they’d like; hence, you need to be smart when constructing your questions and processing the answers.

Offer hints. Avoid open-ended questions whenever possible because they usually result into more confusion. Instead, prompt for the kind of answer you expect. For example:

What kind of case study would you like to see? We have ones for travel, social networking, design and personal finance apps.

Or you could present the information according to the format of the platform you are building on — for example, lists in the case of Facebook Messenger:

Chatbot23
(View large version24)

Also, confirm. If the answer is valid, repeat it to ensure that everything is correct, and then move on to the next question:

Got it. Travel apps. And what budget do you have in mind?

Or suggest what went wrong. If the inputted data isn’t valid, explain again what kind of answer you need. Ideally, distinguish between answers that you don’t understand and answers that are fine but that you can’t accept:

Chatbot25
(View large version26)

Don’t forget that users are talking to your app. They may use different words to describe the same thing — for example, “Thu,” “Thursday,” “tomorrow” or a word with a typo. You could either ask them to confirm their entry or focus on creating more advanced message sequences for your chatbot.

You can refine the inputted data by running it through Normalizer27, a library that converts UK and Canadian spelling to US English, explains common abbreviations and fixes over 4,000 misspelled words.

Wait for critical inputs. In some cases, you’ll need the user to input some essential information that you cannot proceed without. In standard GUIs, the problem is usually solved with a popup modal window that blocks access to everything until the user completes the task: “Did you validate your email address?,” with the window prompting “Yes” or “No.”

However, in conversational design, you should tackle this issue in a slightly different manner. This kind of a loop can get rather annoying with a robot, so make sure to explain the exact action you require and why you need it so critically. Prepare a few conversational snippets for this purpose to keep the chatbot from getting repetitive:

Chatbot28
(View large version29)

In general, think twice about whether certain information is critical in order to proceed. Whenever possible, make an educated guess, or ask for the same information again during a subsequent step.

Another option is to use buttons and pre-suggested texts that users can choose from both when asking questions and providing the replies. Buttons should improve the overall quality of user inputs, however, they may slightly reduce the engagement factor. So it’s best to use them only when you need to receive the essential data for proceeding.

As AI technology advances, it may become easier to train bots to make certain responses and to teach them to second-guess the user’s intention based on previous interactions stored in the database. Yet the majority of chatbots today don’t have fancy AI brains to respond to users; hence, for a better UX, you’ll need to tackle this job yourself.

4. Focus On The Microcopy Link

The designer should think like a copywriter when developing a chatbot. The content and the dialog will define your product’s style. The best apps are usually those that feature a fun conversational manner of speech. Hence, focus on the following:

  • Follow the same user flow as you would if you were actually speaking to a person.
  • The bot shouldn’t sound too clever, using complicated grammar or language structures. Keep it simple and be concise.
  • Don’t use gender-specific pronouns, because you never know who’s on the other side of the conversation.
  • Prepare a set of slightly different canned replies to make the conversation more human-like.
  • Add help messages and suggestions for when the user feels lost.
  • Write witty replies for unsupported topics, so that the bot doesn’t look dumb.

5. Reveal Features Gradually Link

Standard GUIs usually show all of the features available on the screen at once. The user can hover over icons, click buttons and access the menu to see what the app is capable of doing.

Interacting with a chatbot, however, can seem like the user is speaking into the void. Hence, hint at each next step, and gradually highlight unfamiliar features. Let’s explore what this means.

After receiving the initial command from the user, explain what’s about to happen next and what the robot will do to complete the task. Suggest the next possible steps and/or link to the FAQ page or user manual.

Unlock additional features after the first successful interaction. Disable “training mode,” and start suggesting additional features and more advanced tips. Base those features and tips on the user’s history and previously inputted data.

Ordering tacos with Taco Bell's chatbot30
Ordering tacos with Taco Bell’s chatbot (Image: Taco Bell31) (View large version32)

Prompt the user about new things to do. For instance, proactively suggest some other cool features of your robot:

Hey, you have a party coming up! Do you want me to order 5 large pizzas?

Conversational agility is one of the key strengths of Taco bot, for instance. The company used Wit.ai to power different conversation scenarios and even crack some jokes. The platform’s natural language processing technology, which is also now used to power Facebook’s M Virtual Assistant33, allows the bot to render different ordering styles. For instance, “Can I have a burrito?”, “Buritto, please”, and even hilariously respond to “I’m drunk” request, which triggers the “Ok. A cup of water added to your order” reply. Additionally, users can type a one-line comment like “sans cheese” and the bot will understand that the information refers to the previously ordered burrito.

However, if the chatbot initiates the conversation, make sure it gives relevant suggestions because you don’t want to appear like an obnoxious spammer, right?

Chatbots and Speech Recognition Link

Speech commands are becoming a thing with Siri and Google Now, yet developing such bots obviously takes human and material resources. Even the most powerful neural networks that are responsible for speech recognition are rather hard to train at the moment. The most common challenge is that, while small errors are simple enough to eliminate, the larger recurring ones can become even larger due to multiplication, as Andrew Gibiansky points out34.

For instance, if a user with an accent pronounces Apple as Eupple, the network might remember the command this way. Homophones are another major challenge for speech recognition; words like “flower” and “flour” sound identical, and understanding the right context might be hard.

Hence, if your aim is to build a simple chatbot, opting for speech commands might not be your best bet at the moment, unless you are ready to invest heavily in the architecture and advanced machine-learning technology stack.

Final Notes Link

While chatbots can be a great tool for creating more personalized customer experience, conversational design still have certain limitations. As Mariya Yao pointed out, there are clear cases when a conversation can help or hurt the UX35.

Before building a chatbot for your business, you should clearly define its purpose and the exact value it could bring to the user. Teach the bot to do one thing extremely good, such as delivering weather forecasts or introducing the company’s scope of service before experimenting further with more advanced features. That’s the key lesson we learned when developing the April bot based on user feedback.

(rb, vf, yk, il, al)

Footnotes Link

  1. 1 http://www.wired.com/2016/05/googles-new-virtual-assistant-chattier-heres/
  2. 2 https://techcrunch.com/2016/04/12/agents-on-messenger/
  3. 3 https://www.smashingmagazine.com/wp-content/uploads/2016/10/image14-opt.png
  4. 4 https://www.smashingmagazine.com/wp-content/uploads/2016/10/image14-opt.png
  5. 5 https://chatbotsmagazine.com/the-complete-beginner-s-guide-to-chatbots-8280b7b906ca#.4lwm5pfpm
  6. 6 https://alty.software
  7. 7 https://www.smashingmagazine.com/wp-content/uploads/2016/10/bot-blog_v4-1-opt.png
  8. 8 https://www.smashingmagazine.com/wp-content/uploads/2016/10/bot-blog_v4-1-opt.png
  9. 9 https://bots.mockuuups.com/
  10. 10 https://botframe.com/editor/new
  11. 11 https://twitter.com/almonk
  12. 12 https://chatfuel.com/
  13. 13 http://twinery.org/
  14. 14 https://wit.ai/
  15. 15 https://howdy.ai/botkit/
  16. 16 https://api.ai/
  17. 17 https://botwiki.org/
  18. 18 https://emergentbydesign.com/2010/04/05/essential-skills-for-21st-century-survival-part-i-pattern-recognition/
  19. 19 https://www.smashingmagazine.com/wp-content/uploads/2016/10/bot-blog_v3-4-opt.png
  20. 20 https://www.smashingmagazine.com/wp-content/uploads/2016/10/bot-blog_v3-4-opt.png
  21. 21 https://github.com/superscriptjs/qtypes
  22. 22 https://www.smashingmagazine.com/wp-content/uploads/2016/10/image06-500-opt.png
  23. 23 https://www.smashingmagazine.com/wp-content/uploads/2016/10/bot-blog_v3-5-opt.png
  24. 24 https://www.smashingmagazine.com/wp-content/uploads/2016/10/bot-blog_v3-5-opt.png
  25. 25 https://www.smashingmagazine.com/wp-content/uploads/2016/12/bot-blog-v3-large-opt.png
  26. 26 https://www.smashingmagazine.com/wp-content/uploads/2016/12/bot-blog-v3-large-opt.png
  27. 27 https://github.com/superscriptjs/normalizer
  28. 28 https://www.smashingmagazine.com/wp-content/uploads/2016/10/bot-blog_v3-1-1-opt.png
  29. 29 https://www.smashingmagazine.com/wp-content/uploads/2016/10/bot-blog_v3-1-1-opt.png
  30. 30 https://www.smashingmagazine.com/wp-content/uploads/2016/10/tacobot_preview-343-opt.png
  31. 31 https://www.tacobell.com/feed/tacobot
  32. 32 https://www.smashingmagazine.com/wp-content/uploads/2016/10/tacobot_preview-343-opt.png
  33. 33 http://www.theverge.com/2015/10/26/9605526/facebook-m-hands-on-personal-assistant-ai
  34. 34 http://andrew.gibiansky.com/blog/machine-learning/speech-recognition-neural-networks/
  35. 35 https://www.smashingmagazine.com/2016/11/does-conversation-hurt-or-help-the-chatbot-ux/

↑ Back to topTweet itShare on Facebook

Front-End Performance Checklist 2017 (PDF, Apple Pages)

Front-End Performance Checklist 2017 (PDF, Apple Pages)

Are you using progressive booting already? What about tree-shaking and code-splitting in React and Angular? Have you set up Brotli or Zopfli compression, OCSP stapling and HPACK compression? Also, how about resource hints, client hints and CSS containment — not to mention IPv6, HTTP/2 and service workers?

Back in the day, performance was often a mere afterthought. Often deferred till the very end of the project, it would boil down to minification, concatenation, asset optimization and potentially a few fine adjustments on the server’s config file. Looking back now, things seem to have changed quite significantly.

Performance isn’t just a technical concern: It matters, and when baking it into the workflow, design decisions have to be informed by their performance implications. Performance has to be measured, monitored and refined continually, and the growing complexity of the web poses new challenges that make it hard to keep track of metrics, because metrics will vary significantly depending on the device, browser, protocol, network type and latency (CDNs, ISPs, caches, proxies, firewalls, load balancers and servers all play a role in performance).

So, if we created an overview of all the things we have to keep in mind when improving performance — from the very start of the process until the final release of the website — what would that list look like? Below you’ll find a (hopefully unbiased and objective) front-end performance checklist for 2017 — an overview of the issues you might need to consider to ensure that your response times are fast and your website smooth.

(You can also just download the checklist PDF1 (0.129 MB) or download the checklist in Apple Pages2 (0.236 MB). Happy optimizing!)

Front-End Performance Checklist 2017 Link

Micro-optimizations are great for keeping a performance on track, but it’s critical to have clearly defined targets in mind — measurable goals that would influence any decisions made throughout the process. There are a couple of different models, and the ones discussed below are quite opinionated — just make sure to set your own priorities early on.

Getting Ready And Setting Goals Link

  1. Be 20% faster than your fastest competitor.

    According to psychological research3, if you want users to feel that your website is faster than any other website, you need to be at least 20% faster. Full-page loading time isn’t as relevant as metrics such as start rendering time, the first meaningful paint4 (i.e. the time required for a page to display its primary content) and the time to interactive5 (the time at which a page — and primarily a single-page application — appears to be ready enough that a user can interact with it).

    Measure start rendering (with WebPagetest1686) and first meaningful paint times (with Lighthouse1727) on a Moto G, a mid-range Samsung device and a good middle-of-the-road device like a Nexus 4, preferably in an open device lab8 — on regular 3G, 4G and Wi-Fi connections.

    9
    Lighthouse, a new performance auditing tool by Google.

    Look at your analytics to see what your users are on. You can then mimic the 90th percentile’s experience for testing. Collect data, set up a spreadsheet10, shave off 20%, and set up your goals (i.e. performance budgets11) this way. Now you have something measurable to test against. If you’re keeping the budget in mind and trying to ship down just the minimal script to get a quick time-to-interactive value, then you’re on a reasonable path.

    12
    Performance budget builder13 by Brad Frost.

    Share the checklist with your colleagues. Make sure that the checklist is familiar to every member of your team to avoid misunderstandings down the line. Every decision has performance implications, and the project would hugely benefit from front-end developers being actively involved when the concept, UX and visual design are decided on. Map design decisions against performance budget and the priorities defined in the checklist.

  2. 100-millisecond response time, 60 frames per second.

    The RAIL performance model14 gives you healthy targets: Do your best to provide feedback in less than 100 milliseconds after initial input. To allow for <100 milliseconds response, the page must yield control back to main thread at latest after every <50 milliseconds. For high pressure points like animation, it’s best to do nothing else where you can and the absolute minimum where you can’t.

    Also, each frame of animation should be completed in less than 16 milliseconds, thereby achieving 60 frames per second (1 second ÷ 60 = 16.6 milliseconds) — preferably under 10 milliseconds. Because the browser needs time to paint the new frame to the screen your code should finish executing before hitting the 16.6 milliseconds mark. Be optimistic15 and use the idle time wisely. Obviously, these targets apply to runtime performance, rather than loading performance.

  3. First meaningful paint under 1.25 seconds, SpeedIndex under 1000.

    Although it might be very difficult to achieve, your ultimate goal should be a start rendering time under 1 second and a SpeedIndex16 value under 1000 (on a fast connection). For the first meaningful paint, count on 1250 milliseconds at most. For mobile, a start rendering time under 3 seconds for 3G on a mobile device is acceptable17. Being slightly above that is fine, but push to get these values as low as possible.

Defining the Environment Link

  1. Choose and set up your build tools.

    Don’t pay much attention to what’s supposedly cool these days. Stick to your environment for building, be it Grunt, Gulp, Webpack, PostCSS or a combination of tools. As long as you are getting results fast and you have no issues maintaining your build process, you’re doing just fine.
  2. Progressive enhancement.

    Keeping progressive enhancement18 as the guiding principle of your front-end architecture and deployment is a safe bet. Design and build the core experience first, and then enhance the experience with advanced features for capable browsers, creating resilient19 experiences. If your website runs fast on a slow machine with a poor screen in a poor browser on a suboptimal network, then it will only run faster on a fast machine with a good browser on a decent network.
  3. Angular, React, Ember and co.

    Favor a framework that enables server-side rendering. Be sure to measure boot times in server- and client-rendered modes on mobile devices before settling on a framework (because changing that afterwards, due to performance issues, can be extremely hard). If you do use a JavaScript framework, make sure your choice is informed20 and well considered21. Different frameworks will have different effects on performance and will require different strategies of optimization, so you have to clearly understand all of the nuts and bolts of the framework you’ll be relying on. When building a web app, look into the PRPL pattern22 and application shell architecture23.
  4. 24
    PRPL stands for Pushing critical resource, Rendering initial route, Pre-caching remaining routes and Lazy-loading remaining routes on demand.
    25
    An application shell26 is the minimal HTML, CSS, and JavaScript powering a user interface.
  5. AMP or Instant Articles?

    Depending on the priorities and strategy of your organization, you might want to consider using Google’s AMP27 or Facebook’s Instant Articles28. You can achieve good performance without them, but AMP does provide a solid performance framework with a free content delivery network (CDN), while Instant Articles will boost your performance on Facebook. You could build progressive web AMPs29, too.
  6. Choose your CDN wisely.

    Depending on how much dynamic data you have, you might be able to “outsource” some part of the content to a static site generator30, pushing it to a CDN and serving a static version from it, thus avoiding database requests. You could even choose a static-hosting platform31 based on a CDN, enriching your pages with interactive components as enhancements (JAMStack32).

    Notice that CDNs can serve (and offload) dynamic content as well? So, restricting your CDN to static assets is not necessary. Double-check whether your CDN performs content compression and conversion, smart HTTP/2 delivery, edge-side includes, which assemble static and dynamic parts of pages at the CDN’s edge (i.e. the server closest to the user), and other tasks.

Build Optimizations Link

  1. Set your priorities straight.

    It’s a good idea to know what you are dealing with first. Run an inventory of all of your assets (JavaScript, images, fonts, third-party scripts and “expensive” modules on the page, such as carousels, complex infographics and multimedia content), and break them down in groups.

    Set up a spreadsheet. Define the basic core experience for legacy browsers (i.e. fully accessible core content), the enhanced experience for capable browsers (i.e. the enriched, full experience) and the extras (assets that aren’t absolutely required and can be lazy-loaded, such as web fonts, unnecessary styles, carousel scripts, video players, social media buttons, large images). We published an article on “Improving Smashing Magazine’s Performance33,” which describes this approach in detail.

  2. Use the “cutting-the-mustard” technique.

    Use the cutting-the-mustard technique34 to send the core experience to legacy browsers and an enhanced experience to modern browsers. Be strict in loading your assets: Load the core experience immediately, the enhancements on DomContentLoaded and the extras on the load event.

    Note that the technique deduces device capability from browser version, which is no longer something we can do these days. For example, cheap Android phones in developing countries mostly run Chrome and will cut the mustard despite their limited memory and CPU capabilities. Beware that, while we don’t really have an alternative, use of the technique has become more limited recently.

  3. Consider micro-optimization and progressive booting.

    In some apps, you might need some time to initialize the app before you can render the page. Display skeleton screens35 instead of loading indicators. Look for modules and techniques to speed up the initial rendering time (for example, tree-shaking36 and code-splitting37), because most performance issues come from the initial parsing time to bootstrap the app. Also, use an ahead-of-time compiler38 to offload some of the client-side rendering39 to the server40 and, hence, output usable results quickly. Finally, consider using Optimize.js41 for faster initial loading by wrapping eagerly invoked functions (it might not be necessary42 any longer, though).

    Progressive booting43
    Progressive booting44 means using server-side rendering to get a quick first meaningful paint, but also include some minimal JavaScript to keep the time-to-interactive close to the first meaningful paint.

    Client-side rendering or server-side rendering? In both scenarios, our goal should be to set up progressive booting45: Use server-side rendering to get a quick first meaningful paint, but also include some minimal JavaScript to keep the time-to-interactive close to the first meaningful paint. We can then, either on demand or as time allows, boot non-essential parts of the app. Unfortunately, as Paul Lewis noticed46, frameworks typically have no concept of priority that can be surfaced to developers, and hence progressive booting is difficult to implement with most libraries and frameworks. If you have the time and resources, use this strategy to ultimately boost performance.

  4. Are HTTP cache headers set properly?

    Double-check that expires, cache-control, max-age and other HTTP cache headers have been set properly. In general, resources should be cacheable either for a very short time (if they are likely to change) or indefinitely (if they are static) — you can just change their version in the URL when needed.

    If possible, use Cache-control: immutable, designed for fingerprinted static resources, to avoid revalidation (as of December 2016, supported only in Firefox47 on https:// transactions). You can use Heroku’s primer on HTTP caching headers48, Jake Archibald’s “Caching Best Practices49” and Ilya Grigorik’s HTTP caching primer50 as guides.

  5. Limit third-party libraries, and load JavaScript asynchronously.

    When the user requests a page, the browser fetches the HTML and constructs the DOM, then fetches the CSS and constructs the CSSOM, and then generates a rendering tree by matching the DOM and CSSOM. If any JavaScript needs to be resolved, the browser won’t start rendering the page until it’s resolved, thus delaying rendering. As developers, we have to explicitly tell the browser not to wait and to start rendering the page. The way to do this for scripts is with the defer and async attributes in HTML.

    In practice, it turns out we should prefer defer to async51 (at a cost to users of Internet Explorer52 up to and including version 9, because you’re likely to break scripts for them). Also, limit the impact of third-party libraries and scripts, especially with social sharing buttons and <iframe> embeds (such as maps). You can use static social sharing buttons53 (such as by SSBG54) and static links to interactive maps55 instead.

  6. Are images properly optimized?

    As far as possible, use responsive images56 with srcset, sizes and the <picture> element. While you’re at it, you could also make use of the WebP format57 by serving WebP images with the <picture> element and a JPEG fallback (see Andreas Bovens’ code snippet58) or by using content negotiation (using Accept headers). Sketch natively supports WebP, and WebP images can be exported from Photoshop using a WebP plugin for Photoshop59. Other options are available60, too.

    Responsive Image Breakpoints Generator61
    Responsive Image Breakpoints Generator6562 automates images and markup generation.

    You can also use client hints63, which are now gaining browser support64. Not enough resources to bake in sophisticated markup for responsive images? Use the Responsive Image Breakpoints Generator6562 or a service such as Cloudinary66 to automate image optimization. Also, in many cases, using srcset and sizes alone will reap significant benefits. On Smashing Magazine, we use the postfix -opt for image names — for example, brotli-compression-opt.png; whenever an image contains that postfix, everybody on the team knows that it’s been optimized.

  7. Take image optimization to the next level.

    When you’re working on a landing page on which it’s critical that a particular image loads blazingly fast, make sure that JPEGs are progressive and compressed with mozJPEG67 (which improves the start rendering time by manipulating scan levels), Pingo68 for PNG, Lossy GIF69 for GIF and SVGOMG70 for SVG. Blur out unnecessary parts of the image (by applying a Gaussian blur filter to them) to reduce the file size, and eventually you might even start to remove colors or make a picture black and white to reduce the size further. For background images, exporting photos from Photoshop with 0 to 10% quality can be absolutely acceptable as well.

    Not good enough? Well, you can also improve perceived performance for images with the multiple71background72images73technique74.

  8. Are web fonts optimized?

    Chances are high that the web fonts you are serving include glyphs and extra features that aren’t being used. You can ask your type foundry to subset web fonts or subset them yourself75 if you are using open-source fonts (for example, by including only Latin with some special accent glyphs) to minimize their file sizes. WOFF2 support76 is great, and you can use WOFF and OTF as fallbacks for browsers that don’t support it. Also, choose one of the strategies from Zach Leatherman’s “Comprehensive Guide to Font-Loading Strategies8077,” and use a service worker cache to cache fonts persistently. Need a quick win? Pixel Ambacht has a quick tutorial and case study78 to get your fonts in order.

    79
    Zach Leatherman’s Comprehensive Guide to Font-Loading Strategies8077 provides a dozen of options for bettern web font delivery.

    If you can’t serve fonts from your server and are relying on third-party hosts, make sure to use Web Font Loader81. FOUT is better than FOIT82; start rendering text in the fallback right away, and load fonts asynchronously — you could also use loadCSS83 for that. You might be able to get away with locally installed OS fonts84 as well.

  9. Push critical CSS quickly.

    To ensure that browsers start rendering your page as quickly as possible, it’s become a common practice85 to collect all of the CSS required to start rendering the first visible portion of the page (known as “critical CSS” or “above-the-fold CSS”) and add it inline in the <head> of the page, thus reducing roundtrips. Due to the limited size of packages exchanged during the slow start phase, your budget for critical CSS is around 14 KB. If you go beyond that, the browser will need addition roundtrips to fetch more styles. CriticalCSS86 and Critical87 enable you to do just that. You might need to do it for every template you’re using. If possible, consider using the conditional inlining approach88 used by the Filament Group.

    With HTTP/2, critical CSS could be stored in a separate CSS file and delivered via a server push without bloating the HTML. The catch is that server pushing isn’t supported consistently and has some caching issues (see slide 114 onwards of Hooman Beheshti’s presentation89). The effect could, in fact, be negative90 and bloat the network buffers, preventing genuine frames in the document from being delivered. Server pushing is much more effective on warm connections91 due to the TCP slow start. So, you might need to create a cache-aware HTTP/2 server push mechanism92. Keep in mind, though, that the new cache-digest specification93 will negate the need to manually build these “cache-aware” servers.

  10. Use tree-shaking and code-splitting to reduce payloads.

    Tree-shaking94 is a way to clean up your build process by only including code that is actually used in production. You can use Webpack 2 to eliminate unused exports95, and UnCSS96 or Helium97 to remove unused styles from CSS. Also, you might want to consider learning how to write efficient CSS selectors98 as well as how to avoid bloat and expensive styles99.

    Code-splitting100 is another Webpack feature that splits your code base into “chunks” that are loaded on demand. Once you define split points in your code, Webpack takes care of the dependencies and outputted files. It basically enables you to keep the initial download small and to request code on demand, when requested by the application.

    Note that Rollup101 shows significantly better results than Browserify exports. While we’re at it, you might want to check out Rollupify102, which converts ECMAScript 2015 modules into one big CommonJS module — because small modules can have a surprisingly high performance cost103 depending on your choice of bundler and module system.

  11. Improve rendering performance.

    Isolate expensive components with CSS containment104 — for example, to limit the scope of the browser’s styles, of layout and paint work for off-canvas navigation, or of third-party widgets. Make sure that there is no lag when scrolling the page or when an element is animated, and that you’re consistently hitting 60 frames per second. If that’s not possible, then at least making the frames per second consistent is preferable to a mixed range of 60 to 15. Use CSS’ will-change105 to inform the browser of which elements and properties will change.

    Also, measure runtime rendering performance106 (for example, in DevTools107). To get started, check Paul Lewis’ free Udacity course on browser-rendering optimization108. We also have a lil’ article by Sergey Chikuyonok on how to get GPU animation right109.

  12. Warm up the connection to speed up delivery.

    Use skeleton screens, and lazy-load all expensive components, such as fonts, JavaScript, carousels, videos and iframes. Use resource hints110 to save time on dns-prefetch111 (which performs a DNS lookup in the background), preconnect112 (which asks the browser to start the connection handshake (DNS, TCP, TLS) in the background), prefetch113 (which asks the browser to request a resource), prerender114 (which asks the browser to render the specified page in the background) and preload115 (which prefetches resources without executing them, among other things). Note that in practice, depending on browser support, you’ll prefer preconnect to dns-prefetch, and you’ll be cautious with using prefetch and prerender — the latter should only be used if you are very confident about where the user will go next (for example, in a purchasing funnel).

HTTP/2 Link

  1. Get ready for HTTP/2.

    With Google moving towards a more secure web116 and eventual treatment of all HTTP pages in Chrome as being “not secure,” you’ll need to decide on whether to keep betting on HTTP/1.1 or set up an HTTP/2 environment117. HTTP/2 is supported very well118; it isn’t going anywhere; and, in most cases, you’re better off with it. The investment will be quite significant, but you’ll need to move to HTTP/2 sooner or later. On top of that, you can get a major performance boost119 with service workers and server push (at least long term).

    HTTP/2120
    Eventually, Google plans to label all HTTP pages as non-secure, and change the HTTP security indicator to the red triangle that Chrome uses for broken HTTPS. (Image source121)

    The downsides are that you’ll have to migrate to HTTPS, and depending on how large your HTTP/1.1 user base is (that is, users on legacy operating systems or with legacy browsers), you’ll have to send different builds, which would require you to adapt a different build process122. Beware: Setting up both migration and a new build process might be tricky and time-consuming. For the rest of this article, I’ll assume that you’re either switching to or have already switched to HTTP/2.

  2. Properly deploy HTTP/2.

    Again, serving assets over HTTP/2123 requires a major overhaul of how you’ve been serving assets so far. You’ll need to find a fine balance between packaging modules and loading many small modules in parallel.

    On the one hand, you might want to avoid concatenating assets altogether, instead breaking down your entire interface into many small modules, compressing them as a part of the build process, referencing them via the “scout” approach124 and loading them in parallel. A change in one file won’t require the entire style sheet or JavaScript to be redownloaded.

    On the other hand, packaging still matters125 because there are issues with sending many small JavaScript files to the browser. First, compression will suffer. The compression of a large package will benefit from dictionary reuse, whereas small separate packages will not. There’s standard work to address that, but it’s far out for now. Secondly, browsers have not yet been optimized for such workflows. For example, Chrome will trigger inter-process communications126 (IPCs) linear to the number of resources, so including hundreds of resources will have browser runtime costs.

    Progressive CSS loading127
    To achieve best results with HTTP/2, consider to load CSS progressively129128, as suggested by Chrome’s Jake Archibald.

    Still, you can try to load CSS progressively129128. Obviously, by doing so, you are actively penalizing HTTP/1.1 users, so you might need to generate and serve different builds to different browsers as part of your deployment process, which is where things get slightly more complicated. You could get away with HTTP/2 connection coalescing130, which allows you to use domain sharding while benefiting from HTTP/2, but achieving this in practice is difficult.

    What to do? If you’re running over HTTP/2, sending around 10 packages seems like a decent compromise (and isn’t too bad for legacy browsers). Experiment and measure to find the right balance for your website.

  3. Make sure the security on your server is bulletproof.

    All browser implementations of HTTP/2 run over TLS, so you will probably want to avoid security warnings or some elements on your page not working. Double-check that your security headers are set properly131, eliminate known vulnerabilities132, and check your certificate133.

    Haven’t migrated to HTTPS yet? Check The HTTPS-Only Standard134 for a thorough guide. Also, make sure that all external plugins and tracking scripts are loaded via HTTPS, that cross-site scripting isn’t possible and that both HTTP Strict Transport Security headers135 and Content Security Policy headers136 are properly set.

  4. Do your servers and CDNs support HTTP/2?

    Different servers and CDNs are probably going to support HTTP/2 differently. Use Is TLS Fast Yet?139137 to check your options, or quickly look up how your servers are performing and which features you can expect to be supported.
  5. 138
    Is TLS Fast Yet?139137 allows you to check your options for servers and CDNs when switching to HTTP/2.
  6. Is Brotli or Zopfli compression in use?

    Last year, Google introduced140Brotli141, a new open-source lossless data format, which is now widely supported142 in Chrome, Firefox and Opera. In practice, Brotli appears to be more effective143 than Gzip and Deflate. It might be slow to compress, depending on the settings, and slower compression will ultimately lead to higher compression rates. Still, it decompresses fast. Because the algorithm comes from Google, it’s not surprising that browsers will accept it only if the user is visiting a website over HTTPS — and yes, there are technical reasons for that as well. The catch is that Brotli doesn’t come preinstalled on most servers today, and it’s not easy to set up without self-compiling NGINX or Ubuntu. However, you can enable Brotli even on CDNs that don’t support it144 yet (with a service worker).

    Alternatively, you could look into using Zopfli’s compression algorithm145, which encodes data to Deflate, Gzip and Zlib formats. Any regular Gzip-compressed resource would benefit from Zopfli’s improved Deflate encoding, because the files will be 3 to 8% smaller than Zlib’s maximum compression. The catch is that files will take around 80 times longer to compress. That’s why it’s a good idea to use Zopfli on resources that don’t change much, files that are designed to be compressed once and downloaded many times.

  7. Is OCSP stapling enabled?

    By enabling OCSP stapling on your server146, you can speed up your TLS handshakes. The Online Certificate Status Protocol (OCSP) was created as an alternative to the Certificate Revocation List (CRL) protocol. Both protocols are used to check whether an SSL certificate has been revoked. However, the OCSP protocol does not require the browser to spend time downloading and then searching a list for certificate information, hence reducing the time required for a handshake.
  8. Have you adopted IPv6 yet?

    Because we’re running out of space with IPv4147 and major mobile networks are adopting IPv6 rapidly (the US has reached148 a 50% IPv6 adoption threshold), it’s a good idea to update your DNS to IPv6149 to stay bulletproof for the future. Just make sure that dual-stack support is provided across the network — it allows IPv6 and IPv4 to run simultaneously alongside each other. After all, IPv6 is not backwards-compatible. Also, studies show150 that IPv6 made those websites 10 to 15% faster due to neighbor discovery (NDP) and route optimization.
  9. Is HPACK compression in use?

    If you’re using HTTP/2, double-check that your servers implement HPACK compression151 for HTTP response headers to reduce unnecessary overhead. Because HTTP/2 servers are relatively new, they may not fully support the specification, with HPACK being an example. H2spec152 is a great (if very technically detailed) tool to check that. HPACK works153.
  10. h2spec154
    H2spec (View large version155) (Image source156)
  11. Are service workers used for caching and network fallbacks?

    No performance optimization over a network can be faster than a locally stored cache on user’s machine. If your website is running over HTTPS, use the “Pragmatist’s Guide to Service Workers157” to cache static assets in a service worker cache and store offline fallbacks (or even offline pages) and retrieve them from the user’s machine, rather than going to the network. Also, check Jake’s Offline Cookbook158 and the free Udacity course “Offline Web Applications159.” Browser support? It’s getting there160, and the fallback is the network anyway.

Testing and Monitoring Link

  1. Monitor mixed-content warnings.

    If you’ve recently migrated from HTTP to HTTPS, make sure to monitor both active and passive mixed-content warnings, with a tool such as Report-URI.io161. You can also use Mixed Content Scan162 to scan your HTTPS-enabled website for mixed content.
  2. Is your development workflow in DevTools optimized?

    Pick a debugging tool and click on every single button. Make sure you understand how to analyze rendering performance and console output, and how to debug JavaScript and edit CSS styles. Umar Hansa recently prepared a (huge) slidedeck163 and talk164 covering dozens of obscure tips and techniques to be aware of when debugging and testing in DevTools.
  3. Have you tested in proxy browsers and legacy browsers? Testing in Chrome and Firefox is not enough. Look into how your website works in proxy browsers and legacy browsers. UC Browser and Opera Mini, for instance, have a significant market share in Asia165 (up to 35% in Asia). Measure average Internet speed166 in your countries of interest to avoid big surprises down the road. Test with network throttling, and emulate a high-DPI device. BrowserStack167 is fantastic, but test on real devices as well.
  4. Is continuous monitoring set up?

    Having a private instance of WebPagetest1686 is always beneficial for quick and unlimited tests. Set up continuous monitoring of performance budgets with automatic alerts. Set your own user-timing marks to measure and monitor business-specific metrics. Look into using SpeedCurve169 to monitor changes in performance over time, and/or New Relic170 to get insights that WebPagetest cannot provide. Also, look into SpeedTracker171, Lighthouse1727 and Calibre173.

Quick Wins Link

This list is quite comprehensive, and completing all of the optimizations might take quite a while. So, if you had just 1 hour to get significant improvements, what would you do? Let’s boil it all down to 10 low-hanging fruits. Obviously, before you start and once you finish, measure results, including start rendering time and SpeedIndex on a 3G and cable connection.

  1. Your goal is a start rendering time under 1 second on cable and under 3 seconds on 3G, and a SpeedIndex value under 1000. Optimize for start rendering time and time-to-interactive.
  2. Prepare critical CSS for your main templates, and include it in the <head> of the page. (Your budget is 14 KB).
  3. Defer and lazy-load as many scripts as possible, both your own and third-party scripts — especially social media buttons, video players and expensive JavaScript.
  4. Add resource hints to speed up delivery with faster dns-lookup, preconnect, prefetch, preload and prerender.
  5. Subset web fonts and load them asynchronously (or just switch to system fonts instead).
  6. Optimize images, and consider using WebP for critical pages (such as landing pages).
  7. Check that HTTP cache headers and security headers are set properly.
  8. Enable Brotli or Zopfli compression on the server. (If that’s not possible, don’t forget to enable Gzip compression.)
  9. If HTTP/2 is available, enable HPACK compression and start monitoring mixed-content warnings. If you’re running over LTS, also enable OCSP stapling.
  10. If possible, cache assets such as fonts, styles, JavaScript and images — actually, as much as possible! — in a service worker cache.

Download The Checklist (PDF, Apple Pages) Link

With this checklist in mind, you should be prepared for any kind of front-end performance project. Feel free to download the print-ready PDF of the checklist as well as an editable Apple Pages document to customize the checklist for your needs:

If you need alternatives, you can also check the front-end checklist by Dan Rublic176 and the “Designer’s Web Performance Checklist177” by Jon Yablonski.

Off We Go! Link

Some of the optimizations might be beyond the scope of your work or budget or might just be overkill given the legacy code you have to deal with. That’s fine! Use this checklist as a general (and hopefully comprehensive) guide, and create your own list of issues that apply to your context. But most importantly, test and measure your own projects to identify issues before optimizing. Happy performance results in 2017, everyone!


Huge thanks to Anselm Hannemann, Patrick Hamann, Addy Osmani, Andy Davies, Tim Kadlec, Yoav Weiss, Rey Bango, Matthias Ott, Mariana Peralta, Jacob Groß, Tim Swalling, Bob Visser, Kev Adamson and Rodney Rehm for reviewing this article, as well as our fantastic community, which has shared techniques and lessons learned from its work in performance optimization for everybody to use. You are truly smashing! (al)

Footnotes Link

  1. 1 http://provide.smashingmagazine.com/performance-checklist/performance-checklist-1.0.pdf
  2. 2 http://provide.smashingmagazine.com/performance-checklist/performance-checklist-1.0.pages
  3. 3 https://www.smashingmagazine.com/2015/09/why-performance-matters-the-perception-of-time/#the-need-for-performance-optimization-the-20-rule
  4. 4 https://developers.google.com/web/tools/lighthouse/audits/first-meaningful-paint
  5. 5 https://developers.google.com/web/tools/lighthouse/audits/time-to-interactive
  6. 6 http://www.webpagetest.org/
  7. 7 https://github.com/GoogleChrome/lighthouse
  8. 8 https://www.smashingmagazine.com/2016/11/worlds-best-open-device-labs/
  9. 9 https://github.com/GoogleChrome/lighthouse
  10. 10 http://danielmall.com/articles/how-to-make-a-performance-budget/
  11. 11 http://bradfrost.com/blog/post/performance-budget-builder/
  12. 12 http://bradfrost.com/blog/post/performance-budget-builder/
  13. 13 http://bradfrost.com/blog/post/performance-budget-builder/
  14. 14 https://www.smashingmagazine.com/2015/10/rail-user-centric-model-performance/
  15. 15 http://info.meteor.com/blog/optimistic-ui-with-meteor-latency-compensation
  16. 16 https://sites.google.com/a/webpagetest.org/docs/using-webpagetest/metrics/speed-index
  17. 17 https://www.soasta.com/blog/google-mobile-web-performance-study/
  18. 18 https://www.aaron-gustafson.com/notebook/insert-clickbait-headline-about-progressive-enhancement-here/
  19. 19 https://resilientwebdesign.com/
  20. 20 https://www.youtube.com/watch?v=6I_GwgoGm1w
  21. 21 https://medium.com/@ZombieCodeKill/choosing-a-javascript-framework-535745d0ab90#.2op7rjakk
  22. 22 https://developers.google.com/web/fundamentals/performance/prpl-pattern/
  23. 23 https://developers.google.com/web/updates/2015/11/app-shell
  24. 24 https://developers.google.com/web/fundamentals/performance/prpl-pattern/
  25. 25 https://developers.google.com/web/updates/2015/11/app-shell
  26. 26 https://developers.google.com/web/updates/2015/11/app-shell
  27. 27 https://www.ampproject.org/
  28. 28 https://instantarticles.fb.com/
  29. 29 https://www.smashingmagazine.com/2016/12/progressive-web-amps/
  30. 30 https://www.smashingmagazine.com/2015/11/static-website-generators-jekyll-middleman-roots-hugo-review/
  31. 31 https://www.smashingmagazine.com/2015/11/modern-static-website-generators-next-big-thing/
  32. 32 https://jamstack.org/
  33. 33 https://www.smashingmagazine.com/2014/09/improving-smashing-magazine-performance-case-study/
  34. 34 http://responsivenews.co.uk/post/18948466399/cutting-the-mustard
  35. 35 https://twitter.com/lukew/status/665288063195594752
  36. 36 https://medium.com/@richavyas/aha-moments-from-ngconf-2016-part-1-angular-2-0-compile-cycle-6f462f68632e#.8b9afnsub
  37. 37 https://webpack.github.io/docs/code-splitting.html
  38. 38 https://www.lucidchart.com/techblog/2016/09/26/improving-angular-2-load-times/
  39. 39 https://www.smashingmagazine.com/2016/03/server-side-rendering-react-node-express/
  40. 40 http://redux.js.org/docs/recipes/ServerRendering.html
  41. 41 https://github.com/nolanlawson/optimize-js
  42. 42 https://twitter.com/tverwaes/status/809788255243739136
  43. 43 https://www.smashingmagazine.com/wp-content/uploads/2016/12/fmp-and-tti-opt.jpeg
  44. 44 https://aerotwist.com/blog/when-everything-is-important-nothing-is/
  45. 45 https://aerotwist.com/blog/when-everything-is-important-nothing-is/
  46. 46 https://aerotwist.com/blog/when-everything-is-important-nothing-is/#which-to-use-progressive-booting
  47. 47 https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control
  48. 48 https://devcenter.heroku.com/articles/increasing-application-performance-with-http-cache-headers
  49. 49 https://jakearchibald.com/2016/caching-best-practices/
  50. 50 https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/http-caching?hl=en
  51. 51 http://calendar.perfplanet.com/2016/prefer-defer-over-async/
  52. 52 https://github.com/h5bp/lazyweb-requests/issues/42
  53. 53 https://www.savjee.be/2015/01/Creating-static-social-share-buttons/
  54. 54 https://simplesharingbuttons.com
  55. 55 https://developers.google.com/maps/documentation/static-maps/intro
  56. 56 https://www.smashingmagazine.com/2014/05/responsive-images-done-right-guide-picture-srcset/
  57. 57 https://www.smashingmagazine.com/2015/10/webp-images-and-performance/
  58. 58 https://dev.opera.com/articles/responsive-images/#different-image-types-use-case
  59. 59 http://telegraphics.com.au/sw/product/WebPFormat#webpformat
  60. 60 https://developers.google.com/speed/webp/docs/using
  61. 61 https://www.smashingmagazine.com/wp-content/uploads/2016/12/responsive-image-breakpoints-generator-large-opt.jpeg
  62. 62 http://www.responsivebreakpoints.com/
  63. 63 https://www.smashingmagazine.com/2016/01/leaner-responsive-images-client-hints/
  64. 64 http://caniuse.com/#search=client-hints
  65. 65 http://www.responsivebreakpoints.com/
  66. 66 http://cloudinary.com/documentation/api_and_access_identifiers
  67. 67 https://github.com/mozilla/mozjpeg
  68. 68 http://css-ig.net/pingo
  69. 69 https://kornel.ski/lossygif
  70. 70 https://jakearchibald.github.io/svgomg/
  71. 71 http://csswizardry.com/2016/10/improving-perceived-performance-with-multiple-background-images/
  72. 72 https://jmperezperez.com/medium-image-progressive-loading-placeholder/
  73. 73 https://manu.ninja/dominant-colors-for-lazy-loading-images#tiny-thumbnails
  74. 74 https://css-tricks.com/the-blur-up-technique-for-loading-background-images/
  75. 75 https://www.fontsquirrel.com/tools/webfont-generator
  76. 76 http://caniuse.com/#search=woff2
  77. 77 https://www.zachleat.com/web/comprehensive-webfonts/
  78. 78 https://pixelambacht.nl/2016/font-awesome-fixed/
  79. 79 https://www.zachleat.com/web/comprehensive-webfonts/
  80. 80 https://www.zachleat.com/web/comprehensive-webfonts/
  81. 81 https://github.com/typekit/webfontloader
  82. 82 https://www.filamentgroup.com/lab/font-events.html
  83. 83 https://github.com/filamentgroup/loadCSS
  84. 84 https://www.smashingmagazine.com/2015/11/using-system-ui-fonts-practical-guide/
  85. 85 https://www.smashingmagazine.com/2015/08/understanding-critical-css/
  86. 86 https://github.com/filamentgroup/criticalCSS
  87. 87 https://github.com/addyosmani/critical
  88. 88 https://www.filamentgroup.com/lab/performance-rwd.html
  89. 89 http://www.slideshare.net/Fastly/http2-what-no-one-is-telling-you
  90. 90 http://calendar.perfplanet.com/2016/http2-push-the-details/
  91. 91 https://docs.google.com/document/d/1K0NykTXBbbbTlv60t5MyJvXjqKGsCVNYHyLEXIxYMv0/edit
  92. 92 https://css-tricks.com/cache-aware-server-push/
  93. 93 http://calendar.perfplanet.com/2016/cache-digests-http2-server-push/
  94. 94 https://medium.com/@roman01la/dead-code-elimination-and-tree-shaking-in-javascript-build-systems-fb8512c86edf
  95. 95 http://www.2ality.com/2015/12/webpack-tree-shaking.html
  96. 96 https://github.com/giakki/uncss
  97. 97 https://github.com/geuis/helium-css
  98. 98 http://csswizardry.com/2011/09/writing-efficient-css-selectors/
  99. 99 https://benfrain.com/css-performance-revisited-selectors-bloat-expensive-styles/
  100. 100 https://webpack.github.io/docs/code-splitting.html
  101. 101 http://rollupjs.org/
  102. 102 https://github.com/nolanlawson/rollupify
  103. 103 https://nolanlawson.com/2016/08/15/the-cost-of-small-modules/
  104. 104 http://caniuse.com/#search=contain
  105. 105 http://caniuse.com/#feat=will-change
  106. 106 https://aerotwist.com/blog/my-performance-audit-workflow/#runtime-performance
  107. 107 https://developers.google.com/web/tools/chrome-devtools/rendering-tools/
  108. 108 https://www.udacity.com/course/browser-rendering-optimization–ud860
  109. 109 https://www.smashingmagazine.com/2016/12/gpu-animation-doing-it-right/
  110. 110 https://w3c.github.io/resource-hints
  111. 111 http://caniuse.com/#search=dns-prefetch
  112. 112 http://www.caniuse.com/#search=preconnect
  113. 113 http://caniuse.com/#search=prefetch
  114. 114 http://caniuse.com/#search=prerender
  115. 115 https://www.smashingmagazine.com/2016/02/preload-what-is-it-good-for/
  116. 116 https://security.googleblog.com/2016/09/moving-towards-more-secure-web.html
  117. 117 https://http2.github.io/faq/
  118. 118 http://caniuse.com/#search=http2
  119. 119 https://www.youtube.com/watch?v=RWLzUnESylc&t=1s&list=PLNYkxOF6rcIBTs2KPy1E6tIYaWoFcG3uj&index=25
  120. 120 https://security.googleblog.com/2016/09/moving-towards-more-secure-web.html
  121. 121 https://security.googleblog.com/2016/09/moving-towards-more-secure-web.html
  122. 122 https://rmurphey.com/blog/2015/11/25/building-for-http2
  123. 123 https://www.youtube.com/watch?v=yURLTwZ3ehk
  124. 124 https://rmurphey.com/blog/2015/11/25/building-for-http2
  125. 125 http://engineering.khanacademy.org/posts/js-packaging-http2.htm
  126. 126 https://www.chromium.org/developers/design-documents/inter-process-communication
  127. 127 https://jakearchibald.com/2016/link-in-body/
  128. 128 https://jakearchibald.com/2016/link-in-body/
  129. 129 https://jakearchibald.com/2016/link-in-body/
  130. 130 https://daniel.haxx.se/blog/2016/08/18/http2-connection-coalescing/
  131. 131 https://securityheaders.io/
  132. 132 https://www.smashingmagazine.com/2016/01/eliminating-known-security-vulnerabilities-with-snyk/
  133. 133 https://www.ssllabs.com/ssltest/
  134. 134 https://https.cio.gov/faq/
  135. 135 https://www.owasp.org/index.php/HTTP_Strict_Transport_Security_Cheat_Sheet
  136. 136 https://content-security-policy.com/
  137. 137 https://istlsfastyet.com
  138. 138 https://istlsfastyet.com
  139. 139 https://istlsfastyet.com
  140. 140 https://opensource.googleblog.com/2015/09/introducing-brotli-new-compression.html
  141. 141 https://github.com/google/brotli
  142. 142 http://caniuse.com/#search=brotli
  143. 143 https://samsaffron.com/archive/2016/06/15/the-current-state-of-brotli-compression
  144. 144 http://calendar.perfplanet.com/2016/enabling-brotli-even-on-cdns-that-dont-support-it-yet/
  145. 145 https://blog.codinghorror.com/zopfli-optimization-literally-free-bandwidth/
  146. 146 https://www.digicert.com/enabling-ocsp-stapling.htm
  147. 147 https://en.wikipedia.org/wiki/IPv4_address_exhaustion
  148. 148 https://www.google.com/intl/en/ipv6/statistics.html#tab=ipv6-adoption&tab=ipv6-adoption
  149. 149 https://www.paessler.com/blog/2016/04/08/monitoring-news/ask-the-expert-current-status-on-ipv6
  150. 150 https://www.cloudflare.com/ipv6/
  151. 151 https://blog.cloudflare.com/hpack-the-silent-killer-feature-of-http-2/
  152. 152 https://github.com/summerwind/h2spec
  153. 153 https://www.keycdn.com/blog/http2-hpack-compression/
  154. 154 https://www.smashingmagazine.com/wp-content/uploads/2016/12/h2spec-example-large-opt.png
  155. 155 https://www.smashingmagazine.com/wp-content/uploads/2016/12/h2spec-example-large-opt.png
  156. 156 https://github.com/summerwind/h2spec
  157. 157 https://github.com/lyzadanger/pragmatist-service-worker
  158. 158 https://jakearchibald.com/2014/offline-cookbook/
  159. 159 https://www.udacity.com/course/offline-web-applications–ud899
  160. 160 http://caniuse.com/#search=serviceworker
  161. 161 https://report-uri.io/
  162. 162 https://github.com/bramus/mixed-content-scan
  163. 163 https://umaar.github.io/devtools-optimise-your-web-development-workflow-2016/#/
  164. 164 https://www.youtube.com/watch?v=N33lYfsAsoU
  165. 165 http://gs.statcounter.com/#mobile_browser-as-monthly-201511-201611
  166. 166 https://www.webworldwide.io/
  167. 167 https://www.browserstack.com
  168. 168 http://www.webpagetest.org/
  169. 169 https://speedcurve.com/
  170. 170 https://newrelic.com/browser-monitoring
  171. 171 https://speedtracker.org
  172. 172 https://github.com/GoogleChrome/lighthouse
  173. 173 https://calibreapp.com
  174. 174 http://provide.smashingmagazine.com/performance-checklist/performance-checklist-1.0.pdf
  175. 175 http://provide.smashingmagazine.com/performance-checklist/performance-checklist-1.0.pages
  176. 176 https://github.com/drublic/checklist
  177. 177 http://jonyablonski.com/designers-wpo-checklist/

↑ Back to topTweet itShare on Facebook

App Development Showdown: Why You Should Care About Revisiting The Native Vs. Hybrid Debate In 2017

App Development Showdown: Why You Should Care About Revisiting The Native Vs. Hybrid Debate In 2017

Back in 2007, the world met the iPhone for the very first time. After Apple’s product debut, it took less than six months for work to begin on PhoneGap, which would become one of the first and most adopted frameworks for hybrid mobile app development — that is, for apps written simultaneously for multiple platforms using HTML, CSS and JavaScript, rather than coded in native languages.

When compared with the prospect of learning an entirely new language and development environment in order to program iOS (and soon Android) apps, the appeal of this type of development to the already huge population of web developers in the world was palpable.

As with many things, however, execution in the real world didn’t quite live up to the hype.

It quickly became apparent that giving apps created in hybrid frameworks a “native” feel wasn’t always easy. Because these apps were essentially just rendering a web app in a native shell, mobile Internet connections and device hardware speeds at the time caused performance in many hybrid apps to range from “This is loading a little slower than my other apps” to “Apple straight up rejected this from the App Store for not behaving as expected!”

In short: Hybrid hadn’t quite delivered, and many would-be hybrid developers bit the bullet and learned to work in native development platforms, or decided to delay their app development ambitions indefinitely. It was kind of a bummer.

1
Hybrid app development is vying for your attention again. (View large version2)

As time went on, however, advancements in technology — namely, phone hardware — allowed for enough progress in the performance of hybrid apps to drive some bold new claims. A notable example is the report published by industry research giant Gartner predicting that, by 2016, 50% or more of apps deployed to the App Store and Google Play would be hybrid. The prediction was published way back in 2013, and the figure of 50% was picked up3 and plastered4 on virtually every5 website covering the mobile development industry.

Now, many native frameworks and development tools even boast robust showcase libraries highlighting hybrid apps that have successfully made their way to market. Probably among the most notable are Ionic’s6 and Appcelerator’s7.

Bringing The Record Current Link

Have hybrid apps hit parity with their native counterparts yet? There have been several indications that we’re at least moving in that direction. At any rate, being in the latter half of 2016 warrants a renewed discussion of the hybrid versus native debate — and what opportunities it might hold for current developers.

Native Apps Are Still Faster, But That Statement’s Weight Is More Limited Than Before. Link

There’s no beating around the bush: In our current development world, there are still situations in which native apps load and move about with more agility than their hybrid counterparts. That being said, the difference in experience is far less noticeable than even just a few years ago. Software development outfit Azoft wrote over a full year ago that, in its experience, hybrid apps were in many cases “just as good as native apps.” Additionally, the general consensus has gone from “Native is better” to “Native is better in certain cases.” Those certain cases tend to boil down to a few key factors now:

  • Graphical behavior

    Apps that need to utilize advanced 3D graphics, particle effects and multilayered animations are still not well suited to hybrid. Additionally, due to the knowledge and work put into such graphics, often used in games, the extent to which hybrid can expedite development (one of its main selling points) is diminished. This is because, where programming in hybrid frameworks can help you accomplish page-building and other app development tasks with less code, creating games and animations in general still requires specific knowledge and intensive work to get right.
  • Hardware responsiveness

    Apps that require very quick, responsive access to things like a device’s accelerometer or similar hardware components are often still better suited to native development as well. This is because the need to call on these components with JavaScript — as is the case with hybrid apps — represents an extra step the device has to execute. That being said, this reality is declining in severity and will only continue to do so as phone hardware becomes more powerful.
  • CPU requirements

    CPU-intensive apps (such as those that intercept camera input in real time to apply live filters, or that quickly render video, or that process large amounts of data simultaneously, etc.) are the other category of native-suited apps, due to the same logic we touched on above. Again, this gap will likely narrow over time.
A shot of this year's hit Pokemon GO8
A game like Pokemon GO almost certainly falls beyond the limits of hybrid development in 2016. (View large version9)

Hybrid Apps Still Have a Shorter Development Cycle and Time-To-Market. Link

Even in an extremely pro-native post on Y Media Labs10, the author concedes that clients are probably better off seeking hybrid development “if the desired time to market is less than six months.” His experience is far from exclusive: Most articles11 that explore this debate12 conclude that development cycles can be greatly reduced by opting for hybrid.

Despite a rapidly growing number of developers with native coding skill sets, traditional app development is still a slow and complex process in many cases, and the timeframe within which a company or individual wants to get their app rolling can sometimes rule out native on its own.

Native tools regularly improve to help developers work more efficiently, but they are often outpaced in time savings by their counterparts in the hybrid world. The developers behind Ionic, a barebones framework for developing hybrid apps with raw HTML, CSS and JavaScript, recently launched Ionic Creator13, a product with some drag-and-drop elements for prototyping; newcomer Aquro14 is making waves by combining visual workflows with web coding in its own way; and enterprise-focused companies such as Telerik15 have similar platforms as well.

It’s also worth noting that much of this discrepancy in development efficiency between native and hybrid can be attributed to multiplatform projects. Because Android and iOS (and, in some hybrid platforms, Windows and web apps) can be developed simultaneously, the work hours needed to be put into a multiplatform mobile app can be significantly reduced by going hybrid. Plus, every time a client needs to update or add features to an app, again, those changes only have to be written once to be deployed across all of their platforms. That’s generally a big advantage for both developers and their clients.

This Shorter Development Cycle Usually Means Lower Costs, as Well. Link

In a Comentum article16 by app developer Bernard Kohan specifically comparing native development with development of hybrid projects in PhoneGap, he concluded that, depending on the size of an app project, businesses could save between 32 and 36% on their bill by opting for hybrid. When app development projects in the business world almost always operate in the five to six digit range, that can mean a difference of a lot of money, and clients will start to take notice and more often request hybrid development if they feel it meets their needs.

The research for Kohan’s writeup was conducted in January of 2015, but the same trends have further developed since, and more recent investigations still find differences in the cost associated with the two development strategies.

What This Means For You, And How To Take Advantage Of It Link

The real takeaway from this shifting dynamic is a massive business opportunity for those who bother to take advantage of it.

Hybrid app development is likely to enter a golden era, when more enterprise clients and mid-sized businesses will want apps, but pricing can still be placed at a premium until the market is saturated.

Savvy developers can still charge large development fees to create apps for these clients with hybrid technologies, while undercutting native costs just enough to give these clients a deal they can feel good about. Plus, they can develop these apps at a quicker rate, which means a high hourly income and a client that’s going to sing your praises for delivering their company’s app in two and a half months, when native-based firms have projected four to five or more.

In a few years, however, the time savings of hybrid development will be better known, the expectations of buyers will be more closely aligned with the actual time involved in the creation of these apps, and the number of developers offering hybrid development will be higher, increasing the need to bid for jobs at competitive prices. Remember that this exact trend has played out in the world of website development over the past couple of decades.

A Hypothetical Example Link

Let’s say, today in 2016, ACME Thumbtacks wants to contract a developer for an internal Android and iOS app to link up with its inventory system and let workers submit new orders from within the app when stock is low.

They approach a native development house, which quotes them $80,000 and gives a projected delivery date six months away. Armed with your favorite hybrid framework and development environment, you are approached by the client for a second opinion, and you let them know that you can complete the job in just two to three months, for $50,000.

Huge project savings and half the lead time?! They’d be fools not to go with you, and you pocket one heck of a price for a couple of months’ work. Of course, these numbers will vary wildly from project to project, depending on the customer’s needs and ability to pay, but you get the idea.

A word of caution: It is still important to be clear about client expectations for their app and the feasibility of those expectations within a hybrid development framework. This ensures you’ll avoid embarrassing situations in which you might over-promise on functionality that should really still be executed natively!

This Same Scenario Might Look Different A Few Years From Now. Link

ACME Thumbtacks now knows that their app’s requirements aren’t intensive enough to necessitate native development, so they explicitly look for hybrid developers. Because so many others have jumped on the trend and are perfectly happy with quoting a client just $20,000 for a few months of work, gone are the days of easy money!

While you’ll still have plenty of work as an app developer, your golden goose will have flown away, or at least will have become more of a, uh, bronze pigeon. Plus, as the hybrid market becomes more and more crowded, those early adopters with more satisfied clients, testimonials and connections will be in a good place to maintain a high level of demand.

Much like web development in the late 1990s and early 2000s, hybrid app development will be a skill set that can be sold at a premium over the next few years. That, my friends, is the definition of an opportunity!

Of course, a lingering stigma continues to dog the hybrid development world. Depending on the structure you’re working in (freelance or independent, or working in a firm with immediate superiors to report to, etc.), you might need to help more people overcome the perception that clients of hybrid development projects might be left with a subpar product.

One of the best things you can do to address this is to have those skeptics download a few of the apps from the showcase pages linked to earlier (or a few of PhoneGap’s17) and consider whether the experiences they encounter would be satisfactory to a client. The truth of the matter is that most of these apps are likely indistinguishable from natively developed ones.

In the end, the decision of whether to jump through the hoops necessary to switch gears and/or start a whole new hybrid venture is up to you. But, hey, those hoops might just end up being made of gold.

Takeaways Link

  • Hybrid development maintains its speed advantage over native coding, especially for apps that need to run on multiple platforms.
  • Phone performance has helped hybrid development grow out of its stigma of clunkiness, but it’s still far from a perfect solution for some project types.
  • The hybrid route currently presents a great opportunity for web developers to make a seamless (and lucrative) move into app development.
  • App development, whether native or hybrid, has an upward trajectory in demand that’s probably worthy of your attention over the coming years.

(da, vf, il, al)

Footnotes Link

  1. 1 https://www.smashingmagazine.com/wp-content/uploads/2016/11/1-app-development-showdown-large-opt.png
  2. 2 https://www.smashingmagazine.com/wp-content/uploads/2016/11/1-app-development-showdown-large-opt.png
  3. 3 http://gadgets.ndtv.com/apps/news/over-50-percent-of-mobile-apps-to-be-html5-native-hybrids-by-2016-gartner-355385
  4. 4 http://www.idownloadblog.com/2013/02/04/gartner-mobile-apps-2016/
  5. 5 http://memeburn.com/2013/02/gartner-half-of-all-apps-to-be-hybrid-by-2016-expect-a-50-smartphone-this-year/
  6. 6 http://showcase.ionicframework.com/
  7. 7 http://www.appcelerator.com/customers/app-showcase/
  8. 8 https://www.smashingmagazine.com/wp-content/uploads/2016/11/3-app-development-showdown-large-opt.jpg
  9. 9 https://www.smashingmagazine.com/wp-content/uploads/2016/11/3-app-development-showdown-large-opt.jpg
  10. 10 http://www.ymedialabs.com/hybrid-vs-native-mobile-apps-the-answer-is-clear/
  11. 11 http://www.makeit.com/hybrid-app-development-vs-native-better-company/
  12. 12 https://www.mobiloud.com/blog/native-web-or-hybrid-apps/
  13. 13 http://ionicframework.com/
  14. 14 http://www.aquro.com/
  15. 15 http://telerik.com/
  16. 16 http://www.comentum.com/phonegap-vs-native-app-development.html
  17. 17 http://phonegap.com/app/

↑ Back to topTweet itShare on Facebook

The (Not So) Secret Powers Of The Mobile Browser

The (Not So) Secret Powers Of The Mobile Browser

Apple taught us, “There’s an app for that.” And we believed it. Why wouldn’t we? But time has passed since 2009. Our mobile users have gotten more mature and are starting to weigh having space for new photos against installing your big fat e-commerce app. Meanwhile, mobile browsers have also improved. New APIs are being supported, and they will bring native app-like functionality to the mobile browser.

We can now access video and audio and use WebRTC to build a live video-chat web apps directly in the browser, no native app or plugin required. We can build progressive web apps that bring users an almost native app experience, with a launch icon, notifications, offline support and more. Using geolocation, battery status, ambient light detection, Bluetooth and the physical web, we can even go beyond responsive web design and build websites that will automagically adapt to users’ needs and context.

To help us dig into this world of new (and not so new) functionality and to guide us through this journey in the world of “Everything is possible in a mobile browser,” I will illustrate this article with some fictional but plausible use cases. Dear reader, meet Zoe, my user. She’s around 30 and works as a developer in our industry in the very near future. She works all day long on a computer, so she doesn’t want to have one at home, and she uses her smartphone as a primary device to navigate the web.

Part 1: Accessing And Handling Images, Video And Audio Directly In The Browser Link

Video and Audio Conference in the Browser (With WebRTC) Link

Zoe is invited to speak at a conference. Instead of adding her on Skype, like people usually do, the conference organizers send Zoe a link to an online video and audio conference web app, AppRTC1.

Zoe simply enters the correct room number. The browser asks her permission to access her camera and microphone, and that’s it: She gets connected with the other person. Zoe doesn’t need to install or update any additional plugin or app. Everything happens directly in the browser, no extra steps, no friction.

2
Zoe doesn’t need to install anything to have an audio or video conference. (View large version3)

With a native app (especially on Android), you can ask users for a lot of permissions up front when they download your app. In the browser, users have to grant you access one API (i.e. one piece of functionality) at a time.

Using WebRTC4, you can open a direct real-time communication channel between two clients. You can then share sound, video and any other data directly between them.

Peer-to-peer explanation5
Using WebRTC for a peer-to-peer connection (View large version6)

This is powerful, but it’s supported only7 in Firefox and Chrome, and it’s under development for Edge and Safari. You will also need to access the video and audio streams. This can be done using the getUserMedia and Media Stream API8 (which is not supported9 in Internet Explorer or Safari).

Using this technology, we could imagine recreating a Google Hangouts or Facebook Messenger web app directly in the browser. The only thing missing would be access to the phone’s contacts. This is not currently possible from the browser with any kind of API.

Uploading a Picture From the Camera to the Browser Link

Zoe is asked by the conference’s organizers to fill her online bio for the conference. She logs into the website, goes to her account and finds the place to do so. When she taps on the “Update my picture” button, she can choose between taking a new picture with her camera or selecting a picture already taken. She chooses the first option and fills in her profile.

Media upload possibilities10
Zoe chooses to take a picture with her phone. (View large version11)

The HTML5 file input type has gotten a new attribute, named accept12.

You can pass a comma-separated list of types of content files. On mobile, this would trigger a dialog in which users can chose between different content sources or direct access to the camera:

<input type="file" name="image" accept="image/*"> 

If you want the user to skip the selection dialog and directly access their camera to take a picture, you can add the capture attribute:

<input type="file" name="capture" accept="image/*" capture="camera"> 

This would also work if you want to capture video or audio:

<input type="file" name="video" accept="video/*" capture="camcorder"> <input type="file" name="audio" accept="audio/*" capture="microphone"> 

If you want to have fun on your phone, I’ve put together a little demo with all of these inputs13.

Now that we can directly access media (videos, images and audio) in the browser, a whole new world of possibilities has opened up. You could change your avatar right on the responsive website of any of your social media accounts, and you could take and upload photos and videos to your timeline instantly. If you want to sell your car or bike on Craigslist, you don’t need to take pictures of it and then upload them to your computer; you can create your ad and add the images right in your mobile browser.

Having Fun With Inputs Link

If we want to go one step further, we could imagine recreating an Instagram-type app directly in the browser using CSS3 filters and input type files.

CSSgram14
This is what Una started doing with her CSSgram15. (View large version16)

There’s also a really fun guitar tuner17 web app that uses your microphone to make sure your guitar (or voice) is perfectly tuned. Pretty handy, isn’t it? Again, you don’t need to install anything.

Guitar tuner in the browser18
(View large version19)

Part 2: Enhancing A Conference Website Into A Web App Link

In this second part, I want to show you how we can enhance the user experience on a conference website. You might be familiar with the concept of progressive enhancement on the web. I encourage you to apply it to the techniques that follow: Make sure that all of the main functionality on your website is accessible and works on a wide range of mobile browsers, and then progressively enhance the website with launch icons, notifications and offline support to build a better experience on mobile devices that support it.

Installing And Launching The Website As A Progressive Web App Link

To access a website, most users either will already have it bookmarked and hidden in a sea of bookmark folders or will simply look for it on their favorite search engine. One of the main arguments in favor of apps is the launch icon: It’s already there, ready on the user’s home screen.

Favicon for the Home Screen Link

Now, imagine that you could do the same for a website and launch it from the home screen, like you would do for any native app. Most modern browsers have this option available in a menu.

Firefox, Safari and Chrome can all add a website to the home screen from the menu.20
A website can be added to the home screen from the menu in Firefox, Safari and Chrome. (View large version21)

You’ll need some extra files and size to satisfy the range of browsers out there on the market, but this will work on iOS, Android (Chrome, Opera and Firefox) and Edge for mobile.

The favicon for my portfolio on different OS22
The favicon for my portfolio on different OS’. (View large version23)

Chrome’s App Install Banner Link

Not a lot of users know that they can add a website directly to their home screen. To make this functionality more discoverable, Chrome 42+ introduced the App Install Banner24. For the moment, the banner appears when users have visited a website at least twice, with at least five minutes having elapsed between visits.

Smart 'add to home screen banner' in Chrome25
While preparing for her talk, Zoe visits the conference’s website a lot. After a few visits, a small banners appears, telling her she can add the website to her home screen. (View large version26)

Your website also has to meet a few technical criteria to trigger this banner, including having a service worker, being served over HTTPS (which we’ll get to later) and having a valid web app manifest file.

The Web App Manifest File Link

Specified by the W3C, a web app manifest27 is a simple JSON file that enables a developer to control a lot of things about their web app, including its name, icon, launch screen and theme colors, as well as how they want it to launch. Web Manifest Validator28 is a little online tool that will help you to validate the file. Once it’s created, you will need to link it to your website29.

{ "short_name" : "SuperConf", "name": "SuperConf, an amazing conference", // Defines a default URL to launch "start_url": "/index.html", "icons": [ { "src": "launchicon.png", "sizes": "96x96", "type": "image/png" } // Other icons go here ], // Launches the website without a URL bar "display": "standalone", // Provides a site-wide theme color "theme_color": "#fa9c00", // Provides a background color for the launch screen "background_color":"#ffffff" } 

It’s currently supported30 in Android WebView, Opera Mobile, Chrome for Android and apparently Firefox31 as well.

Splash Screen Link

Starting in Chrome 47+, browsers use the manifest’s theme_color, background_color, name and icons to automatically generate a launch screen32 while a website loads.

Splash screen33
When Zoe is on a slow connection and is waiting for the website to load, she will see the icon of the conference, with an orange toolbar and a white background. (View large version34)

Customizing the Display Mode Link

With the display property35 in the manifest file, a developer can choose how they want the website to launch once it has been added to the home screen:

  • "display": "standalone" launches the website in full-screen mode, without any URL bar (currently supported in Chrome and Opera).
  • "display": "browser" launches the website in the conventional mode, with the URL bar visible.
Display standalone versus browser36
"display": "browser" is on the left and "display": "standalone" is on the right for two different websites. (View large version37)

The W3C also specifies fullscreen mode, which launches a website using the entirety of the available display area on a mobile device, and minimal-ui mode, which gives the user access to a minimal set of UI elements. Neither seems to be supported anywhere yet.

Developers can also force an orientation with "orientation": "landscape" or "orientation": "portrait", but unless you are building a video game, you might not want to use it.

Be Careful With meta name="apple-mobile-web-app-capable" on iOS Link

Display mode isn’t supported on iOS. The <meta name="apple-mobile-web-app-capable"> tag38 might look like it does the same thing, but it doesn’t. It will work on a web app with no links (AJAX-loaded content, for instance), but as soon as you use this on a traditional website, things get ugly. When the user launches the website from the launch icon, it will open full screen, but as soon as they tap on a link, it will open in a new tab in Safari. To prevent this, you will need some JavaScript to override the click event (which does not sound ideal).

on iOS39
By default, the launched page opens full screen, but any other URLs open in a new tab. (View large version40)

Changing the Color of the URL Bar Link

Another fun thing you can do to delight users is to change the color of the URL bar. To change it for every page, you can use the HTML meta tag:

<meta name="theme-color" content="#db5945"> 

Here in France, we have a nice website that sells socks… only socks — but it does it quite well. Part of its success is due to the wide range of sock colors. And the color of the URL bar on every page matches the color of the displayed socks. This is one of those little details that can delight users and contribute to a fun overall experience.

Archiduchesse41 matches the color of the browser’s tab to the color of the socks.

Using the manifest.json file, you can also provide a site-wide theme color: "theme_color": "#133742".

Users will see this color in the URL bar as well as in the Android bar at the top when the website is in browser mode. It will also be used for the top bar of the splash screen, as seen before, and when the tab is displayed in a stack of many other tabs in multitasking mode.

Orange theme color42
"theme_color": "#133742" gives a nice orange color theme to my website. (View large version43)

One Tool to Generate Them All Link

If you want to provide a nice experience, there’s a lot to do and to think about, including making a lot of different sizes of icons for different operating systems. Some nice person has built a cool little tool named RealFaviconGenerator44. Feed it your favicon, and you’ll get a nice interface to play with and to tweak all of the things just mentioned. Grab the ZIP file, and voilà!

Notification Access Link

Zoe checks the program before the conference. From the little icon next to each talk, she understands that she can add a talk that she wants to attend to her schedule. A subscription button appears under each talk’s description, with short text explaining that users who have subscribed to the talk will get a notification 10 minutes before the talk starts, even if their browser is closed. Users must allow access through a browser dialog.

notification dialog45
The first time Zoe clicks the notification button, the browser shows a dialog asking for access to send notifications for this domain. (View large version46)

Being Smart When Asking Permissions on Mobile Browsers Link

The Chromium team put out an interesting document titled “Best Practices for Push Notifications Permissions UX47.” Users need to understand what they will gain from giving you access to their notifications. Explain why you need this access, and put it in context. I’m seeing more and more websites and blogs asking to send notifications the first time a user arrives on the home page. As a user, I might have arrived on a blog by following a link on Twitter and might not know what the blog is about, so I’m going to need more context before accepting notifications (if I ever do accept them). In the browser, when a user denies access, the website will not be able to ask for it again (unless the user goes into the website settings). So, be smart about when and where you ask. This is a general rule for all permissions, by the way (media, notifications, geolocation, etc.).

Integrating Notifications in the OS Link

The conference day has finally arrived, and Zoe is getting a coffee when her phone vibrates. Even though the website and web app are closed, she has just gotten a notification directly on her locked phone, telling her that the first talk she has subscribed to will be starting in 10 minutes.

Notification example48
Example of website notifications on Android (View large version49)

Mobile browser notifications can compete with native notifications because they get integrated directly in the notification center of the operating system. This means that they will get displayed outside of the browser or web app, even if it is closed. It will appear in the operating system’s notification center and will be displayed on the lock screen of the phone as well. Notifications in Chrome can also be shown in the desktop notification center of Windows 10 and Mac OS X.

Meet the Push API and Service Workers Link

A service worker is JavaScript that runs in the background once installed. It acts as a sort of small proxy, pushing notifications to the browser. The Push API is part of the family of service worker technologies. Once activated on the page, the service worker receives the push message, and then it is up to you how to notify the user (for example, using push messages or one-page notifications). A the time of writing, service workers are supported50 in Chrome, Firefox, Opera, Android browser and Chrome for Android (it is under consideration for WebKit), and the Push API is supported51 only in Firefox, Chrome and Chrome for Android 51.

Service workers52
Service workers (View large version53)

In short, to make notifications work, you will need:

  • HTTPS on your server,
  • a declaration of a service worker,
  • the Push API,
  • the user’s acceptance.

That’s as far as my technical skill goes. If you want to go deeper, here are a few resources from people far more qualified on the topic than me:

Offline Access Link

Zoe might not have noticed, but the conference’s schedule was cached offline while she was browsing. This means that, even if she doesn’t always have an Internet connection during the conference, she can still visit the website.

Service worker and offline access62
(View large version63)

This magic happens again with service workers. A service worker can intercept the user’s request and provide cached files to display the page faster, with or without a connection. The browser will first look for the cached files, instead of requesting the ones on the server. It can then also check whether the files need to be updated by looking for file modifications in the background. You can use this to make your website work offline, but you can also use it to cache part of the website — the user interface, if you like — to make it load faster.

I imagined all kinds of scenarios for Zoe when I was preparing for the ConFoo conference in March 2016. I wanted to create a demo page, but then in June I saw that Google I/O implemented everything I imagined, so I’ll let you play with that demo instead. Open your mobile browser, go to events.google.com/io201664, navigate to the schedule, and add some events to your list (you might need to log in with a Google account first). Then, add the website to your home screen, close Chrome, and launch the website from the home screen icon. Keep on adding things to your list. Switch to airplane mode, and you should see a short explanation that the connection has been lost and that changes will be synchronized with the server once you are back online. Add some more talks to the list, go back online, and voilà!

Google I/O demo65
Google I/O 2016 website demo66 (View large version67)

There are two other demos I really like:

  • Pokedex.org68
    An online index of Pokemon characters (predating PokemonGo!).
  • 204869
    A fun game that has saved me from boredom during hours of air travel.

Again, open the website, load it to your home screen, switch to airplane mode, and then come back.

Offline website demo70
(View large version71)

If you want to go deeper in the code, I would recommend the following reading:

Going Full Steam: Progressive Web App Link

I’ve described how to enhance a website to add some native-like functionality. You could go one step further with a full-on progressive web app. In their article “Instant Loading Web Apps With an Application Shell Architecture75,” Addy Osmani and Matt Gaunt refer to a progressive web app as a web app that “can progressively change with use and user consent to give the user a more native-app-like experience.” They cite an article in which Alex Russell76 describes progressive web apps as “websites that took all the rights vitamins.”

According to Google’s documentation77, progressive web apps are:

  • Progressive

    They work for every user, regardless of browser choice, because they’re built with progressive enhancement as a core tenet. This bring us back to what I said at the beginning of this section: Make sure your website works even if all of this fancy new technology is not supported, and treat all of this as progressive enhancement.
  • Responsive

    They fit any form factor: desktop, mobile, tablet and whatever is next.
  • Connectivity-independent

    They can be enhanced with service workers to work offline or on a slow network.
  • Fresh

    They are always up to date, thanks to the service worker updating process.
  • Safe

    They must be served via HTTPS to prevent snooping and to ensure that content hasn’t been tampered with.
  • Discoverable

    They are identifiable as “applications” thanks to the manifest file and the service worker registration.scope, which allows search engines to find them (like any normal old-school website).
  • Re-engageable

    They make re-engagement easy through features such as push notifications. Again, for me, this is not mandatory, and you might want to be careful with it.
  • Installable

    They allow users to keep the apps they find most useful on their home screen, without the hassle of an app store.
  • Linkable

    They can easily be shared via a URL and do not require complex installation.
  • App-like

    They feel like an app to the user, with app-style interactions and navigation, because they’re built on the application shell model.

The last point about the application shell is where it gets really interesting and where progressive web apps bridge the gap between classic responsive websites and native apps. If you’ve created a native app, this should ring some bells. In a native app, the user would download the full UI (icons, fonts, etc.) when they install the app. Then, when they launch the app, the content is loaded from the server.

The concept of the application shell is pretty similar: It is the minimum HTML, CSS and JavaScript required to create your UI, the “chrome” of your interface. You would cache this to make the app load quickly. Then, the rest of the content would get dynamically loaded to populate the different views.

Explanation of application shell78
(Image: Addy Osmani and Matt Gaunt79) (View large version80)

Also, the people at Opera have put together a selection of progressive web apps81. If you want a taste of what progressive web apps can do, you’ll find demos and inspiration there.

With Great Power… Link

… comes great responsibility. There’s currently some82debate83 in the community about progressive web apps. Here are a few of the issues people are worrying about:

  • Is it really a good idea to hide URLs in a progressive web app? Developers have the choice, but it looked like Chrome was kind of in favor of standalone mode. And how are you supposed to share content? (Those awful share buttons might make a big comeback.)
  • A lot of current implementations seem to concentrate on the app part and forget the web part. Are we going to revert to dedicated mobile websites and desktop websites? I’m really looking forward to seeing more responsive and progressively enhanced demos.
  • Loading the application shell is like loading the chrome before the content, whereas many people want a “content-first” approach. Will users have to wait for your content to load even once the interface is already displayed?

If you ask me, not every website should be a progressive web app. For instance, transforming my portfolio84 into a progressive web app was pretty silly, but I did it for a demo; like many people in the industry, my portfolio is also a little playground. In truth, nobody (except maybe my mum) would install my portfolio as an app on their phone. And that’s totally fine, because let’s face it: My portfolio isn’t really app-ish.

So, I guess a progressive web app would be a great idea for websites that users visit on a regular basis, such as news websites and blogs (which is the criterion Chrome uses in determining whether to show the install banner), e-commerce and restaurant-delivery websites (from which users might order regularly), and anything task-oriented (i.e. app-ish). I would add social networks such as Facebook to the list, but building a progressive web app is far less interesting to those companies than building a native one — how are they supposed to collect and sell all of their users’ data if users can only access their services in the browser?

The thing about Facebook is that its mobile website works pretty well. But as soon as you try to view your messages, the website tries to open the Messenger app. Fun fact: Facebook has built a really nice responsive website for Messenger85 that works on desktop. You can shrink it to a mobile-ish size, and it still works. But as soon as you visit it on a mobile device (or with a mobile user agent), you get the mobile version of the website telling you that you need to install the app. So, when it comes to mobile apps versus progressive web apps (or responsive websites), even though we now have the tools and technology to build a lot of things in a mobile browser, there will always be different factors at play in the decisions of how to implement a service. The fact that you can’t access a phone’s address book from the browser is another piece of the puzzle.

To go deeper in this topic, you might want to read the following:

Part 3: Adapting The Website Or Web App To A User’s Current Needs And Context Link

Mobile devices are now equipped with a lot of different sensors that can get us a lot of information about our users (for best or worse). In this last part of the article, we will focus on how to enhance a website or web app for the user’s current needs, situation and context.

Ambient Light Detection Link

Back to Zoe for a moment. Thanks to the notification that popped up on her phone, she gets to the first talk in her schedule on time. She sits down in one of those comfortable theater chairs, and the room gets dark as the talk is about to start. She visits the conference website one last time before putting her phone away.

Website gets darker92
The website’s visual theme changes to a darker color, so that people aren’t disturbed by a bright screen while listening to the talk. (View large version93)

Using the light sensors on the device, we can adapt the luminosity or contrast of a website to the ambient light. Apart from making a website darker when the user is in a dark room, this could have a lot of practical applications. Many of the websites that my company builds get used in a private room (or on a couch), but that’s not the case for a lot of the professional products and interfaces I build. Those need to be used “in the field” — outside, inside, on rainy days, on sunny days, anything you can imagine.

For example, I was working on a crane-monitoring interface. The interface works in a Chrome browser on both desktop and tablet. The operator needs to see alerts when the wind is blowing too fast in order to change the cranes’ mode so that they don’t fall or collide with each other. The mobile device could be used in a really dark environment, or a lot of light might shine through the window directly onto the operator’s desk. Using ambient light sensors, we could maintain the contrast of the interface when there is too much light in the room, so that people monitoring the cranes will always be able to see alerts if something goes wrong.

In theory, there are two ways to do this. You could use the Ambient Light Sensor API94 to access the intensity level measured by the device’s light sensors. At the time of writing, this is supported95 only in Edge and Firefox for the desktop. A light-level query was expected in the “Media Queries Level 4” specification, but it seems to have been deferred to “Media Queries Level 596,” so this is not for us today.

A cool Codepen demo97 for the Ambient Light Sensor API

Enhance Conference Feedback Using Bluetooth URL Transfer Link

When a talk ends, it’s usually feedback time. When I was at ConFoo, the conference organizers had participants fill out a short form at the end of each talk. Then, a team would collect the forms, read them, scan them and send them to me with an average grade. This was awesome; I got all of the feedback one hour after my talk. But I’m guessing it was also a lot of work for the staff. Let’s see how we can enhance this using Bluetooth, URLs and smartphones, shall we?

ConFoo feedback paper98
The ConFoo survey given to participants after each talk. (View large version99)

The Physical Web Applied to Conference Feedback Link

This is a good time to meet the “physical web.” Google has launched an initiative100 to “enable quick and seamless interactions with physical objects and locations.” The idea is to take advantage of the power of the web — hence, the URLs to share content and to allow users to interact with objects and locations in their surroundings without having to install anything. If you must, you could think of this as QR codes on steroids. Bluetooth beacons will broadcast URLs, and users’ phones in the vicinity will be able to catch those URLs and directly open websites or web applications.

Back to Zoe and our conference. A Bluetooth low-energy (BLE) beacon supporting the Eddystone protocol specification is embedded in the conference poster next to the door.

URL broadcast101
The beacon is broadcasting. (View large version102)

A little notification tells Zoe that a URL is being broadcast nearby, which her browser can scan and display.

Device catches the URL103
The user gets a notification on their device. (View large version104)

Zoe opens the URL directly in her browser and fills in the feedback form online. Staff are no longer required to scan the forms, and the organizers can do this for every talk.

The browser opens the URL105
The URL opens in a browser. (View large version106)

For this to work, users need to activate the physical web in the browser and also enable Bluetooth. The physical web is not activated by default (for now). It can be activated on Chrome for both Android and iOS107. The physical web has been supported in Chrome for iOS since July 2015, and is available on Chrome for Android in version 49+ and on devices running Kit Kat (4.4) and above.

What Happens Next Is Simply the Web Link

The great thing about this is that you could integrate a beacon into almost anything: a street poster, a dog collar, a rental bike or a rental car. The idea is to use this for small interactions for which you would not really consider building a native app, but for which you could easily create a web page. In a video introduction to the physical web, Scott Jenson describes108 an interesting way to pay for a parking meter.

The physical web is about getting URLs to phones. What happens next is simply the web.

This is where things get exciting! In her talk “The Internet of Things Is for People109,” Stephanie Rieger explains how you can do a lot of useful stuff by combining a URL with a place (no need for geolocation — you’ve got a beacon here, remember) and a time (i.e. when the URL is triggered); for example, allowing the user to dig deeper into useful and relevant content. You have the exact context of the user; so, you can trigger a URL for content that adapts accordingly to the situation — an amazing, progressively enhanced experience tailored to the user’s needs. Bring service workers, WebRTC, notifications, progressive web apps and all of the technologies discussed earlier into the mix, and this, my dear designer and developer friends, is going to be powerful!

Another interesting example from Stephanie’s conference slides is Panic’s corporate sign in Portland110. The Panic team built an interactive sign for its building, and people can go to a website111 to change its color. How cool is that? The website is even a progressive web app. It’s fun to change the colors from where I live and imagine them changing on the building, but I’m a little far away. Many people walking around the area might not even be aware of this fun trick. With the physical web, we imagine that Panic could broadcast the URL of its fun little web app around the building, so that passersby can discover it.

If you are looking for more fun ideas for the physical web, check these out:

More Fun With the Web Bluetooth API Link

The physical web is but one attempt to play with Bluetooth and browsers. There’s also the Web Bluetooth API116, which will allow web applications and websites to access services exposed by devices. This means that in the future, we will be able to directly connect and control objects (watches, sensors, smart thermostats, etc.) to a browser through Bluetooth. I say “in the future” because browser support is pretty low117 at the moment: Chrome, with a flag. Eventually, we will be able to do really fun things directly in the browser, like change the colors and the mood of this cute little turtle using only a website and Bluetooth connection:

Geolocation And Battery Status Link

The conference ends a few hours later. Zoe is tired and decides to use the bike-rental service Velibre to get back to her hotel.

Adapting the Website to the User’s Location Link

Zoe arrives on Velibre’s website. A big button says “Find my location,” and a little snippet explains to Zoe that she will be able to find bike-rental stations nearby once she grants the website access to her location.

Geolocation dialog118
Zoe taps the button, a little dialog box appears at the bottom of the website, and she accepts. (View large version119)

With the Geolocation API120, we can access the user’s current static location and also monitor changes in location when they move. Basically, you could do a lot of geolocation-related things that native apps do, directly in the browser. This is pretty well supported in every mobile browser121 (except for Opera mini). Remember that, in the browser, users have to grant access first. So, you might want to make clear why you need their location. Asking it when the user first visits the website is not the best idea. Again, always ask in context, and explain what the user will gain.

And don’t forget to progressively enhance. A lot can go wrong with geolocation: The user might not see the dialog box (which I’ve seen with my own eyes in user-testing sessions), GPS might not be available, or the user simply might not grant access. Always provide a fallback. It could be as simple as a free-text input field that the user can fill in with their current (or desired) location. Also, don’t assume that users always want a given service at their current location; let them change the location. There was a cinema app that relied only on the user’s current location to provide a schedule of movies. This is great if the user wants to see something nearby, but it doesn’t work so well if they are looking for something to watch on a trip out of town. Don’t assume the user’s intention, and use these technologies as enhancements, not defaults.

Adapting to Battery Level Link

It was a really long day. Zoe used her phone a lot, and her battery is almost dead. She taps on Velibre’s button to ask for the closest bike station. The website detects that her battery is really low and loads a static map instead of an interactive one in order to save a bit of power.

Battery-saving map122
A little alert informs Zoe about the change to the static map and lets her choose the dynamic map if she wants. (View large version123)

The Battery Status API124 give you access to the battery level of the device. To be responsible, we could, say, propose fewer battery-consuming resources when the battery is low. This would be really useful for battery-draining functions such as GPS, peer-to-peer connections and animation. Codepen has a demo125 for you to play with. The API is currently supported126 in Chrome, Firefox and Opera for the desktop and in the latest version of Chrome for Android.

Conclusion Link

In this article, which is inspired by a talk I gave127, I wanted to present you with some APIs, some technologies and some of the cool things you can do with them to make your users’ lives easier. The future of the mobile browser is bright, shiny and fun. We can and will be able to build incredibly powerful things with web technologies.

In terms of mobile support for these technologies and APIs, it looks like the Android teams, followed by Firefox, Opera and Microsoft, are currently most focused on taking web apps to the next level and providing a more powerful experience for mobile browser users. iOS, on the other hand, is still far behind. Its lack of support for service workers might be the biggest issue here. If we truly want to be able to fill the gap between natives apps and mobile browsers, we need the notifications and offline functionality provided by service workers.

The big picture is complicated by more than just browser support. What would Apple gain by letting developers build web apps that don’t need to go in the App Store? Apple’s business model is tightly linked to iOS native applications? There’s an app for everything, right?

Is iOS holding us back? I don’t think so. We don’t need to embrace these new APIs and technologies as if they were supported everywhere. Building progressive web apps means building with performance in mind, while still providing a great mobile experience for users on all platforms and browsers. Make sure that users with devices that don’t support everything do not get frustrated with a blank page.

I’m just a designer, only one part of the whole chain. Now it’s your turn to build, to play, to share amazing websites and web apps!

(da, il, al)

Footnotes Link

  1. 1 https://apprtc.appspot.com/
  2. 2 https://www.smashingmagazine.com/wp-content/uploads/2016/11/webrtcchat-large-opt.jpg
  3. 3 https://www.smashingmagazine.com/wp-content/uploads/2016/11/webrtcchat-large-opt.jpg
  4. 4 http://w3c.github.io/webrtc-pc/
  5. 5 https://www.smashingmagazine.com/wp-content/uploads/2016/11/ptop-large-opt.jpg
  6. 6 https://www.smashingmagazine.com/wp-content/uploads/2016/11/ptop-large-opt.jpg
  7. 7 http://caniuse.com/#feat=rtcpeerconnection
  8. 8 https://www.w3.org/TR/mediacapture-streams/
  9. 9 http://caniuse.com/#feat=stream
  10. 10 https://www.smashingmagazine.com/wp-content/uploads/2016/11/media-upload-large-opt.jpg
  11. 11 https://www.smashingmagazine.com/wp-content/uploads/2016/11/media-upload-large-opt.jpg
  12. 12 http://www.wufoo.com/html5/attributes/20-accept.html
  13. 13 http://codepen.io/stephaniewalter/full/xZoxOb/
  14. 14 https://www.smashingmagazine.com/wp-content/uploads/2016/11/cssgram-large-opt.jpg
  15. 15 https://una.im/CSSgram/
  16. 16 https://www.smashingmagazine.com/wp-content/uploads/2016/11/cssgram-large-opt.jpg
  17. 17 https://guitar-tuner.appspot.com/
  18. 18 https://www.smashingmagazine.com/wp-content/uploads/2016/11/guitartuner-large-opt.jpg
  19. 19 https://www.smashingmagazine.com/wp-content/uploads/2016/11/guitartuner-large-opt.jpg
  20. 20 https://www.smashingmagazine.com/wp-content/uploads/2016/11/add-to-home-button-large-opt.jpg
  21. 21 https://www.smashingmagazine.com/wp-content/uploads/2016/11/add-to-home-button-large-opt.jpg
  22. 22 https://www.smashingmagazine.com/wp-content/uploads/2016/11/launch-icon-large-opt.jpg
  23. 23 https://www.smashingmagazine.com/wp-content/uploads/2016/11/launch-icon-large-opt.jpg
  24. 24 https://developers.google.com/web/updates/2015/03/increasing-engagement-with-app-install-banners-in-chrome-for-android
  25. 25 https://www.smashingmagazine.com/wp-content/uploads/2016/11/add-to-hom-large-opt.jpg
  26. 26 https://www.smashingmagazine.com/wp-content/uploads/2016/11/add-to-hom-large-opt.jpg
  27. 27 https://w3c.github.io/manifest/
  28. 28 https://manifest-validator.appspot.com/
  29. 29 https://developers.google.com/web/updates/2014/11/Support-for-installable-web-apps-with-webapp-manifest-in-chrome-38-for-Android#telling_the_browser_about_your_manifest
  30. 30 https://developer.mozilla.org/en-US/docs/Web/Manifest
  31. 31 https://developers.google.com/web/updates/2014/11/Support-for-installable-web-apps-with-webapp-manifest-in-chrome-38-for-Android#what_every_developer_should_do_today
  32. 32 https://developers.google.com/web/updates/2015/10/splashscreen
  33. 33 https://www.smashingmagazine.com/wp-content/uploads/2016/11/splashscreen-large-opt.jpg
  34. 34 https://www.smashingmagazine.com/wp-content/uploads/2016/11/splashscreen-large-opt.jpg
  35. 35 https://w3c.github.io/manifest/#dfn-display-mode
  36. 36 https://www.smashingmagazine.com/wp-content/uploads/2016/11/display-mode-large-opt.jpg
  37. 37 https://www.smashingmagazine.com/wp-content/uploads/2016/11/display-mode-large-opt.jpg
  38. 38 https://developer.apple.com/library/content/documentation/AppleApplications/Reference/SafariHTMLRef/Articles/MetaTags.html
  39. 39 https://www.smashingmagazine.com/wp-content/uploads/2016/11/apple-launch-large-opt.jpg
  40. 40 https://www.smashingmagazine.com/wp-content/uploads/2016/11/apple-launch-large-opt.jpg
  41. 41 http://www.archiduchesse.com/
  42. 42 https://www.smashingmagazine.com/wp-content/uploads/2016/11/theme-color-large-opt.jpg
  43. 43 https://www.smashingmagazine.com/wp-content/uploads/2016/11/theme-color-large-opt.jpg
  44. 44 http://realfavicongenerator.net/
  45. 45 https://www.smashingmagazine.com/wp-content/uploads/2016/11/notification-dial-large-opt.jpg
  46. 46 https://www.smashingmagazine.com/wp-content/uploads/2016/11/notification-dial-large-opt.jpg
  47. 47 https://docs.google.com/document/d/1WNPIS_2F0eyDm5SS2E6LZ_75tk6XtBSnR1xNjWJ_DPE/edit#heading=h.v5v9jr5n9i1w
  48. 48 https://www.smashingmagazine.com/wp-content/uploads/2016/11/notifications-large-opt.jpg
  49. 49 https://www.smashingmagazine.com/wp-content/uploads/2016/11/notifications-large-opt.jpg
  50. 50 http://caniuse.com/#feat=serviceworkers
  51. 51 http://caniuse.com/#feat=push-api
  52. 52 https://www.smashingmagazine.com/wp-content/uploads/2016/11/service-worker-large-opt.jpg
  53. 53 https://www.smashingmagazine.com/wp-content/uploads/2016/11/service-worker-large-opt.jpg
  54. 54 https://tests.peter.sh/notification-generator/
  55. 55 https://simple-push-demo.appspot.com/
  56. 56 http://goroost.com/try-web-push
  57. 57 http://www.html5rocks.com/en/tutorials/service-worker/introduction/
  58. 58 https://hacks.mozilla.org/2015/12/beyond-offline/
  59. 59 https://developers.google.com/web/fundamentals/engage-and-retain/push-notifications/
  60. 60 https://developer.mozilla.org/en-US/docs/Web/API/Push_API/Using_the_Push_API
  61. 61 https://jakearchibald.github.io/isserviceworkerready/
  62. 62 https://www.smashingmagazine.com/wp-content/uploads/2016/11/service-worker-offline-large-opt.jpg
  63. 63 https://www.smashingmagazine.com/wp-content/uploads/2016/11/service-worker-offline-large-opt.jpg
  64. 64 https://events.google.com/io2016/
  65. 65 https://www.smashingmagazine.com/wp-content/uploads/2016/11/google-io-large-opt.jpg
  66. 66 https://events.google.com/io2016/
  67. 67 https://www.smashingmagazine.com/wp-content/uploads/2016/11/google-io-large-opt.jpg
  68. 68 https://www.pokedex.org
  69. 69 https://2048-opera-pwa.surge.sh/
  70. 70 https://www.smashingmagazine.com/wp-content/uploads/2016/11/pwa-example-large-opt.jpg
  71. 71 https://www.smashingmagazine.com/wp-content/uploads/2016/11/pwa-example-large-opt.jpg
  72. 72 http://www.deanhume.com/Home/BlogPost/create-a-really–really-simple-offline-page-using-service-workers/10135
  73. 73 https://medium.com/dev-channel/offline-storage-for-progressive-web-apps-70d52695513c#.89q94e79i
  74. 74 https://css-tricks.com/serviceworker-for-offline/
  75. 75 https://medium.com/google-developers/instant-loading-web-apps-with-an-application-shell-architecture-7c0c2f10c73#.50aqnknm7
  76. 76 https://infrequently.org/2015/06/progressive-apps-escaping-tabs-without-losing-our-soul/
  77. 77 https://developers.google.com/web/progressive-web-apps/
  78. 78 https://www.smashingmagazine.com/wp-content/uploads/2016/11/application-shell-large-opt.jpg
  79. 79 https://medium.com/google-developers/instant-loading-web-apps-with-an-application-shell-architecture-7c0c2f10c73#.p9tdc6jg8
  80. 80 https://www.smashingmagazine.com/wp-content/uploads/2016/11/application-shell-large-opt.jpg
  81. 81 https://pwa.rocks/
  82. 82 https://adactio.com/journal/10708
  83. 83 https://www.kryogenix.org/days/2016/05/24/the-importance-of-urls/
  84. 84 https://www.stephaniewalter.fr/
  85. 85 https://www.messenger.com/
  86. 86 https://www.smashingmagazine.com/2016/08/a-beginners-guide-to-progressive-web-apps/
  87. 87 https://www.theguardian.com/info/developer-blog/2016/aug/19/how-we-made-the-riorun-progressive-web-app
  88. 88 http://nolanlawson.github.io/pwas-2016-05/#/
  89. 89 http://tech-blog.flipkart.net/2015/11/progressive-web-app/
  90. 90 http://www.wsj.com/articles/washington-post-unveils-lightning-fast-mobile-website-1473152456
  91. 91 https://cloudfour.com/thinks/designing-responsive-progressive-web-apps/
  92. 92 https://www.smashingmagazine.com/wp-content/uploads/2016/11/ambient-light-large-opt.jpg
  93. 93 https://www.smashingmagazine.com/wp-content/uploads/2016/11/ambient-light-large-opt.jpg
  94. 94 https://www.w3.org/TR/ambient-light/
  95. 95 http://caniuse.com/#feat=ambient-light
  96. 96 https://github.com/w3c/ambient-light/issues/12
  97. 97 http://codepen.io/WhatWebCanDo/pen/OyWZqY
  98. 98 https://www.smashingmagazine.com/wp-content/uploads/2016/11/confoo-survey-large-opt.jpg
  99. 99 https://www.smashingmagazine.com/wp-content/uploads/2016/11/confoo-survey-large-opt.jpg
  100. 100 https://google.github.io/physical-web/
  101. 101 https://www.smashingmagazine.com/wp-content/uploads/2016/11/pw-01-large-opt.jpg
  102. 102 https://www.smashingmagazine.com/wp-content/uploads/2016/11/pw-01-large-opt.jpg
  103. 103 https://www.smashingmagazine.com/wp-content/uploads/2016/11/pw-02-large-opt.jpg
  104. 104 https://www.smashingmagazine.com/wp-content/uploads/2016/11/pw-02-large-opt.jpg
  105. 105 https://www.smashingmagazine.com/wp-content/uploads/2016/11/pw-03-large-opt.jpg
  106. 106 https://www.smashingmagazine.com/wp-content/uploads/2016/11/pw-03-large-opt.jpg
  107. 107 https://google.github.io/physical-web/try-physical-web
  108. 108 https://youtu.be/1yaLPRgtlR0?t=1m26s
  109. 109 http://www.slideshare.net/yiibu/the-internet-of-things-is-for-people
  110. 110 https://panic.com/blog/the-panic-sign/
  111. 111 https://sign.panic.com/
  112. 112 https://www.hackster.io/agent-hawking-1/create-a-beacon-enabled-treasure-box-085314
  113. 113 https://www.hackster.io/eely22/physical-web-controlled-candy-machine-ce6711
  114. 114 http://www.technobuffalo.com/videos/disney-fun-wheel-challenge-world-of-color-hands-on/
  115. 115 http://www.slideshare.net/jeffprestes/physical-web-62013819
  116. 116 https://webbluetoothcg.github.io/web-bluetooth/
  117. 117 http://caniuse.com/#feat=web-bluetooth
  118. 118 https://www.smashingmagazine.com/wp-content/uploads/2016/11/gelocation-large-opt.jpg
  119. 119 https://www.smashingmagazine.com/wp-content/uploads/2016/11/gelocation-large-opt.jpg
  120. 120 https://www.w3.org/TR/geolocation-API/
  121. 121 http://caniuse.com/#feat=geolocation
  122. 122 https://www.smashingmagazine.com/wp-content/uploads/2016/11/battery-large-opt.jpg
  123. 123 https://www.smashingmagazine.com/wp-content/uploads/2016/11/battery-large-opt.jpg
  124. 124 https://www.w3.org/TR/battery-status/
  125. 125 http://codepen.io/WhatWebCanDo/pen/epvKNB
  126. 126 http://caniuse.com/#feat=battery-status
  127. 127 https://blog.stephaniewalter.fr/en/forget-apps-future-mobile-browser-nightlybuild-2016-conference/

↑ Back to topTweet itShare on Facebook