As web developers, we all approach our work very differently. And even when you take a look at yourself, you’ll notice that the way you do your work does vary all the time. I, for example, have not reported a single bug to a browser vendor in the past year, despite having stumbled over a couple. I was just too lazy to write them up, report them, write a test case and care about follow-up comments.
This week, however, when integrating the Internationalization API for dates and times, I noticed a couple of inconsistencies and specification violations in several browsers, and I reported them. It took me one hour, but now browser vendors can at least fix these bugs. Today, I filed two new issues, because I’ve become more aware again of things that work in one browser but not in others. I think it’s important to change the way we work from time to time. It’s as easy as caring more about the issues we face and reporting them back.
Web annotations5 are now a web standard6, with a defined data model, vocabulary, and protocol. Let’s hope many of the browser vendors (Microsoft Edge) and service platforms will adopt the standard soon. For us developers it’s a huge opportunity, too, to build standardized annotations that are interoperable and to communicate with each other.
Google Chrome now allows permitted site owners of a Chrome extension to override selected user settings12. This means that a browser extension vendor who verified their domain via Google Webmaster Tools can override user settings such as homepage or the default search provider via their website. After reading this attack scenario13, I fear this could take the DNS subdomain attack to a new level.
Sometimes it’s the small things that help you a lot. Did you know that you can save time and avoid confusion in CSS by using the :not(:last-of-type) selector instead of two different selectors, for example? Timothy B. Smith explains how this little trick works15.
The free Sustainable UX conference took place two weeks ago. To get some insights into how we can achieve sustainability in tech, you can now watch the conference talks for free18.
Douglas Crockford famously declared browsers to be “the most hostile software engineering environment imaginable,” and that wasn’t hyperbole. Ensuring that our websites work across a myriad of different devices, screen sizes and browsers our users depend on to access the web is a tall order, but it’s necessary. If our websites don’t enable users to accomplish the key tasks they come to do, we’ve failed them.
We should do everything in our power to ensure our websites function under even the harshest of scenarios, but at the same, we can’t expect our users to have the exact same experience in every browser, on every device. Yahoo realized this more than a decade ago and made it a central concept in its “Graded Browser Support1” strategy:
Support does not mean that everybody gets the same thing. Expecting two users using different browser software to have an identical experience fails to embrace or acknowledge the heterogeneous essence of the Web. In fact, requiring the same experience for all users creates an artificial barrier to participation. Availability and accessibility of content should be our key priority.
And that was a few years before the iPhone was introduced!
Providing alternate experience pathways for our core functionality should be a no-brainer, but when it comes to implementing stuff we’d rather not think about, we often reach for the simplest drop-in solution, despite the potential negative impact it could have on our business.
Consider the EU’s “cookie law.”2 If you’re unfamiliar, this somewhat contentious law3 is privacy legislation that requires websites to obtain consent from visitors before storing or retrieving information from their device. We call it the cookie law, but the legislation also applies to web storage4, IndexedDB5 and other client-side data storage and retrieval APIs.
Compliance with this law is achieved by:
notifying users that the website requires the ability to store and read information on their device;
providing a link to the website’s privacy statement, which includes information about the storage mechanisms being used and what they are being used for;
prompting users to confirm their acceptance of this requirement.
If you operate a website aimed at folks living in the EU and fail to do this, you could be subject to a substantial fine. You could even open yourself up to a lawsuit.
If you’ve had to deal with the EU cookie law before, you’re probably keenly aware that a ton of “solutions” are available to provide compliance. Those quotation marks are fully intentional because nearly every one I found — including the one provided by the EU6 itself — has been a drop-in JavaScript file that enables compliance. If we’re talking about the letter of the law, however, they don’t actually. The problem is that, as awesome and comprehensive as some of these solutions are, we can never be guaranteed that our JavaScript programs will actually run7. In order to truly comply with the letter of the law, we should provide a fallback version of the utility — just in case. Most people will never see it, but at least we know we’re covered if something goes wrong.
I stumbled into this morass while building the 10k Apart contest website8. We weren’t using cookies for much on the website — mainly analytics and vote-tracking — but we were using the Web Storage API9 to speed up the performance of the website and to save form data temporarily while folks were filling out the form. Because the contest was open to folks who live in the EU, we needed to abide by the cookie law. And because none of the solutions I found actually complied with the law in either spirit or reality — the notable exception being WordPress’ EU Cookie Law10 plugin, which works both with and without JavaScript, but the contest website wasn’t built in WordPress or even PHP, so I had to do something else — I opted to roll my own robust solution.
I’m a big fan of using interface experience (IX) maps11 to diagram functionality. I find their simple nature easy to understand and to tweak as I increase the fidelity of an experience. For this feature, I started with a (relatively) simple IX map that diagrammed what would happen when a user requests a page on the website.
This IX map outlines several potential experiences that vary based on the user’s choice and feature availability. I’ll walk through the ideal scenario first:
A user comes to the website for the first time. The server checks to see whether they have accepted the use of cookies and web storage but doesn’t find anything.
The server injects a banner into the HTML, containing the necessary messaging and a form that, when submitted, confirms acceptance.
The browser renders the page with the banner.
The user clicks to accept the use of cookies and web storage.
Client-side JavaScript sets the accepts cookie and closes the banner.
On subsequent page requests, the server reads the accepts cookie and does not inject the banner code. JavaScript sees the cookie and enables the cookie and web storage code.
For the vast majority of users, this is the experience they’ll get, and that’s awesome. That said, however, we can never be 100% guaranteed our client-side JavaScript code will run, so we need a backup plan. Here’s the fallback experience:
A user comes to the website for the first time. The server checks to see whether they have accepted the use of cookies and web storage but doesn’t find anything.
The server injects a banner into the HTML, containing the necessary messaging and a form that, when submitted, confirms acceptance.
The browser renders the page with the banner.
The user clicks to accept the use of cookies and web storage.
The click initiates a form post to the server, which responds by setting the accepts cookie before redirecting the user back to the page they were on.
On subsequent page requests, the server reads the accepts cookie and does not inject the banner code.
If JavaScript becomes available later, it will see the cookie and enable its cookie and web storage code.
Not bad. There’s an extra roundtrip to the server, but it’s a quick one, and, more importantly, it provides a foolproof fallback in the absence of our preferred JavaScript-driven option. True, it could fall victim to a networking issue, but there’s not much we can do to mitigate that without JavaScript in play.
Speaking of mitigating networking issues, the 10k Apart contest website uses a service worker14 to do some pretty aggressive caching; the service worker intercepts any page request and supplies a cached version if one exists. That could result in users getting a copy of the page with the banner still in it, even if they’ve already agreed to allow cookies. Time to update the IX map.
This is one of the reasons I like IX maps so much: They are really easy to generate and simple to update when you want to add features or handle more scenarios. With a few adjustments in place, I can account for the scenario in which a stale page includes the banner unnecessarily and have JavaScript remove it.
With this plan in place, it was time to implement it.
10k Apart’s back end is written in Node.js17 and uses Express18. I’m not going to get into the nitty-gritty of our installation and configuration, but I do want to talk about how I implemented this feature. First off, I opted to use Express’ cookie-parser19 middleware to let me get and set the cookie.
// enable cookie-parser for Express var cookieParser = require('cookie-parser'); app.use(cookieParser());
Once that was set up, I created my own custom Express middleware20 that would intercept requests and check for the approves_cookies cookie:
This code establishes a middleware function named checkCookie(). All Express middleware gets access to the request (req), the response (res) and the next middleware function (next), so you’ll see those accounted for as the three arguments to that function. Then, within the function, I am modifying the response object to include two local variables (res.locals) to capture whether the cookie has already been set (res.locals.approves_cookies) and the currently requested URL (res.locals.current_url). Then, I call the next middleware function.
With that written, I can include this middleware in Express:
app.use(checkCookie);
All of the templates for the website are Mustache21 files, and Express automatically pipes res.locals into those templates. Knowing that, I created a Mustache partial22 to handle the banner:
{{^approves_cookies}} <div role="alert"> <form action="/cookies-ok" method="post"> <input type="hidden" name="redirect_to" value="{{current_url}}"> <p>This site uses cookies for analytics and to track voting. If you're interested, more details can be found in <a href="{{privacy_url}}#maincookiessimilartechnologiesmodule">our cookie policy</a>.</p> <button type="submit">I'm cool with that</button> </form> </div> {{/approves_cookies}}
This template uses an inverted section23 that only renders the div when approves_cookies is false. Within that markup, you can also see the current_url getting piped into a hidden input to indicate where a user should be redirected if the form method of setting the cookie is used. You remembered: the fallback.
Speaking of the fallback, since we have one, we also need to handle that on the server side. Here’s the Node.js code for that:
var affirmCookies = function (req, res) { if ( ! req.cookies['approves_cookies'] ) { res.cookie('approves_cookies', 'yes', { secure: true, maxAge: ( 365 * 24 * 60 * 60 ) // 1 year }); } res.redirect(req.body.redirect_to); }; app.post('/cookies-ok', affirmCookies);
This ensures that if the form is submitted, Express will respond by setting the approves_cookies cookie (if it’s not already set) and then redirecting the user to the page they were on. Taken altogether, this gives us a solid baseline experience for every user.
Now, it’s worth noting that none of this code is going to be useful to you if your projects don’t involve the specific stack I was working with on this project (Node.js, Express, Mustache). That said, the logic I’ve outlined here and in the IX map is portable to pretty much any language or framework you happen to know and love.
OK, let’s switch gears and work some magic on the front end.
When JavaScript is available and running properly, we’ll want to take full advantage of it, but it doesn’t make sense to run any code against the banner if it doesn’t exist, so first things first: I should check to see whether the banner is even in the page.
var $cookie_banner = document.getElementById('cookie-banner'); if ( $cookie_banner ) { // actual code will go here }
In order to streamline the application logic, I’m going to add another conditional within to check for the accepts_cookies cookie. I know from my second pass on the IX map there’s an outside chance that the banner might be served up by my service worker even if the accepts cookie exists, so checking for the cookie early lets me run only the bit of JavaScript that removes the banner. But before I jump into all of that, I’ll create a function I can call in any of my code to let me know whether the user has agreed to let me cookie them:
function cookiesApproved(){ return document.cookie.indexOf('approves_cookies') > -1; }
I need this check in multiple places throughout my JavaScript, so it makes sense to break it out into a separate function. Now, let’s revisit my banner-handling logic:
var $cookie_banner = document.getElementById('cookie-banner'); if ( $cookie_banner ) { // banner exists but cookie is set if ( cookiesApproved() ) { // hide the banner immediately! } // cookie has not been set else { // add the logic to set the cookie // and close the banner } }
Setting cookies in JavaScript is a little convoluted because you need to set it as a string, but it’s not too ghastly. I broke out the process into its own function so that I could set it as an event handler on the form:
function approveCookies( e ) { // prevent the form from submitting e.preventDefault(); var cookie, // placeholder for the cookie expires = new Date(); // start building expiry date // expire in one year expires.setFullYear( expires.getFullYear() + 1 ); // build the cookie cookie = [ 'approves_cookies=yes', 'expires=' + expires.toUTCString(), 'domain=' + window.location.hostname, window.location.protocol == 'https:' ? 'secure' : '' ]; // set it document.cookie = cookie.join('; '); // close up the banner closeCookieBanner(); // return return false; }; // find the form inside the banner var $form = $cookie_banner.getElementsByTagName('form')[0]; // hijack the submit event $form.addEventListener( 'submit', approveCookies, false );
The comments in the code should make it pretty clear, but just in case, here’s what I’m doing:
Hijack the form submission event (e) and cancel its default action using e.preventDefault().
Use the Date object to construct a date one year out.
Assemble the bits of the cookie, including the approves_cookies value, the expiry date, the domain the cookie is bound to, and whether the cookie should be secure (so I can test locally).
Set document.cookie equal to the assembled cookie string.
Trigger a separate method — closeCookieBanner() — to close the banner (which I will cover in a moment).
With that in place, I can define closeCookieBanner() to handle, well, closing up the banner. There are actually two instances in which I need this functionality: after setting the cookie (as we just saw) and if the service worker serves up a stale page that still has the banner in it. Even though each requires roughly the same functionality, I want to make the stale-page cleanup version a little more aggressive. Here’s the code:
function closeCookieBanner( immediate ) { // How fast to close? Animation takes .5s var close_speed = immediate ? 0 : 600; // remove window.setTimeout(function(){ $cookie_banner.parentNode.removeChild( $cookie_banner ); // remove the DOM reference $cookie_banner = null; }, close_speed); // animate closed if ( ! immediate ) { $cookie_banner.className = 'closing'; } }
This function takes a single optional argument. If true (or anything “truthy”24) is passed in, the banner is immediately removed from the page (and its reference is deleted). If no argument is passed in, that doesn’t happen for 0.6 seconds, which is 0.1 seconds after the animation finishes up (we’ll get to the animation momentarily). The class change triggers that animation.
You already saw one instance of this function referenced in the previous code block. Here it is in the cached template branch of the conditional you saw earlier:
… // banner exists but cookie is set if ( cookiesApproved() ) { // close immediately closeCookieBanner( true ); } …
Because I brought up animations, I’ll discuss the CSS I’m using for the cookie banner component, too. Like most implementations of cookie notices, I opted for a visual full-width banner. On small screens, I wanted the banner to appear above the content and push it down the page. On larger screens I opted to affix it to the top of the viewport because it would not obstruct reading to nearly the same degree as it would on a small screen. Accomplishing this involved very little code:
Using the browser’s default styles, the cookie banner already displays block, so I didn’t really need to do much apart from set some basic text styles and colors. For the large screen (the “full-screen” version comes in at 60 ems), I affix it to the top of the screen using position: fixed, with a top offset of 0. Setting its left and right offsets to 0 ensures it will always take up the full width of the viewport. I also set the z-index quite high so it sits on top of everything else in the stack.
Here’s the result:
A video showing the browser viewport being enlarged from 240 to 960 pixels width. When the design hits the 60-em breakpoint, the banner becomes fixed-positioned.
Once the basic design was there, I took another pass to spice it up a bit. I decided to have the banner animate in and out using CSS. First things first: I created two animations. Initially, I tried to run a single animation in two directions for each state (opening and closing) but ran into problems triggering the reversal — you might be better at CSS animations than I am, so feel free to give it a shot. In the end, I also decided to tweak the two animations to be slightly different, so I’m fine with having two of them:
Not knowing how tall the banner would be (this is responsive design, after all), I needed it to animate to and from a height of auto. Thankfully, Nikita Vasilyev25 published a fantastic overview of how to transition values to and from auto26 a few years back. In short, animate max-height instead. The only thing to keep in mind is that the size of the non-zero max-height value you are transitioning to and from needs to be larger than your max, and it will also directly affect the speed of the animation. I found 20 ems to be more than adequate for this use case, but your project may require a different value.
It’s also worth noting that I used display: none at the conclusion of my cookie-banner-reverse animation (the closing one) to ensure the banner becomes unreachable to users of assistive technology such as screen readers. It’s probably unnecessary, but I did it as a failsafe just in case something happens and JavaScript doesn’t remove the banner from the DOM.
Wiring it up required only a few minor tweaks to the CSS:
This assigned the two animations to the two different banner states: The opening and resting state, cookie-banner, runs for one second after a one-second delay; the closing state, cookie-banner-reverse, runs for only half a second with no delay. I am using a class of closing, set via the JavaScript I showed earlier, to trigger the state change. Just for completeness, I’ll note that this code also stabilizes the dimensions of the banner with box-sizing: border-box and keeps the contents from spilling out of the banner using overflow: hidden.
One last bit of CSS tweaking and we’re done. On small screens, I’m leaving a margin between the cookie notice (#cookie-banner) and the page header (.banner). I want that to go away when the banner collapses, even if the cookie notice is not removed from the DOM. I can accomplish that with an adjacent-sibling selector:
It’s worth noting that I am setting the top margin on every element but the first one, using Heydon Pickering’s clever “lobotomized owl27” selector. So, the transition of margin-top on .banner will be from a specific value (in my case, 1.375 rem) to 0. With this code in place, the top margin will collapse over the same duration as the one used for the closing animation of the cookie banner and will be triggered by the very same class addition.
A video showing the final implementation on a wide screen, both with and without JavaScript.
What I like about this approach is that it is fairly simple. It took only about an hour or two to research and implement, and it checks all of the compliance boxes with respect to the EU law. It has minimal dependencies, offers several fallback options, cleans up after itself and is a relatively back-end-agnostic pattern.
When tasked with adding features we may not like — and, yes, I’d count a persistent nagging banner as one of those features — it’s often tempting to throw some code at it to get it done and over with. JavaScript is often a handy tool to accomplish that, especially because the logic can often be self-contained in an external script, configured and forgotten. But there’s a risk in that approach: JavaScript is never guaranteed28. If the feature is “nice to have,” you might be able to get away with it, but it’s probably not a good idea to play fast and loose with a legal mandate like this. Taking a few minutes to step back and explore how the feature can be implemented with minimal effort on all fronts will pay dividends down the road. Believe me29.
Social media is one of the dominant forms of interactions on the Internet. Leading platforms such as Facebook and Twitter count hundreds of millions of users each month. In this article, I will show you how social media is a rich vein of data for user researchers. I will argue that it would be an oversight for an organization to treat social media as nothing more than an opportunity for customer service enquiries, help requests and brand advocacy.
In the commercial sector, social media is a source of data about users that often gets ignored in favor of other more controlled user research activities, such as interviews and user testing. (Though, it is often used to recruit participants for these traditional methods.) Conversely, in the academic world, social media was immediately recognized as an interesting primary source of data. But it has been typically addressed with quantitative research methods, such as visualizing information flows between network members and graphing peaks of activity, which are not so relevant in most typical user research projects.
In recent years, a range of commercially available monitoring software tools have emerged to make it relatively easy to track a range of keywords and capture a wealth of tweets, posts and mentions on topics of interest. However, these tools are also principally set up to do sentiment analysis, such as whether brand mentions are broadly positive or negative. But these high-level insights come at the expense of the nuanced details that reside in the individual tweets, posts and mentions. So, how can we do useful user research with social media?
Social media platforms enable social listening. We can tap into the recent or “in the moment” experience of real issues in context, rather than asking people, for example, to recall experiences in a face-to-face interview that takes place a week afterwards. It is particularly well suited to researching instances of mundane, everyday activities (such as smartphone habits) that would otherwise be poorly remembered and inaccessible to the researcher in the lab or to popular services that have already been launched. And when we tap in, we get data in the users’ language, not the language of the researcher. This amounts to research gold, and all we need is to get a pan and jump into the river. (There are some things to be aware of, of course, which I will describe later.)
While working as a user researcher for Highways England, I created the user research with social media technique that I describe here. This was part of a wide-ranging user research project to make wholesale improvements to the Dart Charge service1. This is a highly used GOV.UK service that enables over 5 milion drivers to pay remotely to use a part of the UK’s M25 motorway network in outer London, called the Dartford Crossing, where the motorway crosses the River Thames. A key research challenge was to understand user needs around paying before or after using the Dartford Crossing. Many other typical user research methods were used on this project, including user testing sessions and interview studies, but the service team welcomed new ideas for gaining research insights, particularly those relating to routine activities such as driving, because it was felt these were not well captured by the other types of research being done.
The sources chosen were Facebook and Twitter on account of their popularity in the UK among the 5 million users of the Dart Charge service. Salesforce’s Radian 6 (now part of Social Studio) was chosen because it supports tracking of multiple keywords across multiple social networks. We selected the month of August 2015, mainly because it was the most recent full month and gathered around a thousand mentions. It was also felt to be the maximum amount of data the team could analyze in the time available.
Ultimately, this resulted in 39 insights, which were added to the product backlog at the time of the research. The four steps in this technique were:
This first step is about setting up the search query, or queries, that are going to be used. These could be user accounts, hash tags and phrases. A good place to start is to gather the project’s team together and collate all of the ways they think real people might refer to the product or situation of interest.
In the case of Highways England, we identified 10 target phrases, hash tags and accounts. Notably, some of these were official terms for the service, such as Dart Charge and Dartford Crossing, and some were unofficial but widely used, such as Dartford Tunnel and Dartford Toll. Examples of the phrases, hash tags and accounts we used are in the table below:
A variety of tools are available to gather social media data, including free tools and some very expensive one. A good place to start is with the search facilities within the social media networks themselves, because they provide the opportunity to gather data at no cost. These search tools have their drawbacks. For example, Facebook’s groups and privacy settings make it more difficult to search than Twitter, which is much more open. So, choose a social media network that your users, or prospective users, are using, and then start gathering data.
Once you are familiar with this research technique, you can come back to the decision of whether to spend money on other tools. Some, such as Hootsuite, Sprout Social, DiscoverText and IBM’s Watson Analytics, charge a monthly fee. Others, such as Salesforce’s Social Studio, Sysomos and Oracle’s Social Cloud, don’t even show the price. You have to email them for a demo and a quote. (It is a bit like being in a shop where the expensive clothes don’t have price tags on them!)
Once you have chosen a tool, gathering data is relatively straightforward. Let’s start with using the free search tool within Twitter. It is a process of running a search and saving the search results. But a few tips are worth bearing in mind.
First, you don’t even need a Twitter account. You can just head over to the Advanced Search tool2 and enter your keywords directly. Facebook is not so easy to access.
Secondly, defining the date range covered by your data sample is always smart (in case you, or others, want to repeat it). You can set a date range using the “since” and “until” commands in Twitter.
Thirdly, you can save a PDF of the search results via the print menu in your browser. This is worth doing because deleted tweets will disappear from results (when the user deletes them), so you would lose them otherwise. You will also need to manually expose conversations, because these are hidden by default (and will not be shown in your PDF).
There are many ways to analyze the qualitative data we have just gathered. In a nutshell, really, what we are doing at this stage is sense-making. We are asking, What does this piece of data really mean? More or less, it is a case of taking stock of any individual piece of data (for example, a tweet or post) and annotating it with additional words (sometimes called tags or codes) that encapsulate what is being meant. If there are items in the data sample that are hard to understand or incomplete or irrelevant, skipping over them is OK. (Likewise, skip any that appear to be from fake accounts or are the work of trolls.) Typically, only around 1 in 10 items in the data sample might actually be annotated with tags. Practically, this can be done by printing out the PDF data set and using a highlighter pen to mark up interesting pieces of data and writing the tags beside the data.
Once all of the interesting items in the data sample have been tagged, it is effective to pull out only the tagged items and group any related items together. This is a process of affinity-sorting. Again, practically, this can be done by cutting up the print-outs and spatially rearranging the affinity groups. Seeing different perspectives on the same issue helps to form a rounded insight, as we can see in these examples from our Highways England project. Some example tweets and how they were tagged are shown in the images below:
5 A tweet tagged with “warning,” “reminder” and “fine.”6 A tweet tagged with “forgetting” and “cost.”7 A tweet tagged with “forgetting” and “panic.”8 A tweet tagged with “forgetting” and “anger.”
Taking stock of just these four tagged data items, we can get to the following insights about user needs and values:
There is a user need to avoid forgetting to pay and to get a reminder.
There is a value to users in avoiding financial penalty and associated stress.
Ideally, the best way to do this sort of analysis is to have a fellow team member involved in the tagging, affinity-sorting and insight generation. If you see different things in the same piece of data, that is good, not bad, because a richer and more nuanced interpretation emerges. (Afterwards, long-term management of the analysis can be supported by transferring the data items and their associated tags into digital tools, such as NVivo or Reframer.)
Social media research offers many benefits to the user researcher, but there are some things to be aware of. Getting up and running is quick, and you don’t have to wait to recruit participants or need any prior hypotheses. Indeed, because the users are expressing themselves in public, they are not participants, so there are no data-protection issues to concern anyone. Nor are there any demand characteristics biases that would mean the participants are politely trying to please the researchers.
But these advantages do need to be balanced with the disadvantages. Is the data clear enough to understand? Are we interpreting the data to fit the questions we ask? Are we just sampling social media users and not everyone else? Are we getting only the most positive and negative voices (and none from the middle)? Are we seeing self-reported behavior, not real behavior? Are we prone to other cognitive biases in the data, such as researchers just seeing the things that are easiest to see (the availability bias) or participants overemphasizing the most intense or most recent aspects of their experience (the peak-end effect)? The answer is, of course, “Yes, but…!”
Ultimately, it is poor practice to rely on one research technique to answer any given question and lay yourself open to criticism of the shortcomings of that technique. It is always best to have multiple research techniques that address the same objective from different angles. This enables a team to notice the different biases at play in each research technique and to come to a rounded view of users’ needs and the best course of action in the design stage.
Social media provides a rich source of data for user researchers. It allows researchers to tap into the recent experience of people without the formality of interviewing or user testing. And while it is not without its disadvantages, it is illuminating, and you can get started for free. It helped Highways England realize the importance of the issue of forgetting to pay. So, why not add user research with social media to your toolbox and see what you find?
Sometimes all we need is a little inspiration kick to get our creative juices flowing. Maybe your secret is to go for a short walk, have a little chat with a colleague, or scroll through your favorite eye candy resources. Whatever it might be that helps you get new ideas, we, too, have something for you that could work just as good: desktop wallpapers.
To bring you a regular dose of unique and inspiring wallpapers, we embarked on our monthly wallpapers mission1 eight years ago. Each month, artists and designers from across the globe diligently contribute their works to it. And well, it wasn’t any different this time around. This post features their artwork for March 2017. The wallpapers all come in versions with and without a calendar. Time to freshen up your desktop!
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?
“A day, even a whole month aren’t enough to show how much a woman should be appreciated. Dear ladies, any day or month are yours if you decide so.” — Designed by Ana Masnikosa21 from Belgrade, Serbia.
“Early spring in March is for me the time when the snow melts, everything isn’t very colorful. This is what I wanted to show. Everything comes to life slowly, as this bear. Flowers are banal, so instead of a purple crocus we have a purple bird-harbinger.” — Designed by Marek Kedzierski64 from Poland.
“March the 2nd marks the birthday of the most creative and extraordinary author ever, Dr. Seuss! I have included an inspirational quote about learning to encourage everyone to continue learning new things everyday.” — Designed by Safia Begum149 from the United Kingdom.
“Don’t get me wrong, I like winter and snow, but in Austria where I live there was not much of it this year. It is still cold and moody, and I think by now I’m ready for spring!” — Designed by Izabela Grzegorczyk199 from Poland.
“Instead of focusing on St. Patrick’s day, I decided to feature my favorite March pun in textured handlettering. In this month – especially on the Fourth – it’s a great time time to grab life by the shamrocks and make it count. Now go march forth!” — Designed by Phil Scroggs212 from Seattle, WA, USA.
“Jīngzhé is the third of the 24 solar terms in the traditional East Asian calendars. The word 驚蟄 means ‘the awakening of hibernating insects’. 驚 is ‘to start’ and 蟄 means ‘hibernating insects’. Traditional Chinese folklore says that during Jingzhe, thunderstorms will wake up the hibernating insects, which implies that the weather is getting warmer.” — Designed by Sunny Hong255 from Taiwan.
“In the U.S., March is National Umbrella Month. Let this be a reminder to keep an umbrella handy with rain on the way.” — Designed by Karen Frolo274 from the United States.
“When we celebrate the achievements of women, of how far they have come, we’re actually celebrating the fact that no power on earth can rein a woman who can dream. Here’s to the women who with their lives are setting an example to the next generation of boys and girls what it means to be a woman. That femininity is not just about looking pretty but it is also about being bold, courageous and strong-willed. Happy Women’s Day.” — Designed by Acodez IT Solutions305 from India.
“Freedom should always be peaceful and respectful. Present your opinion peacefully through your art and let people see it and respect it.” — Designed by Hatim M. M. Yousif Al-Sharif348 from the United Arab Emirates.
“Just two weeks ago the world lost a wonderful artist and my beloved brother/sister, Ken/Kat – also known as ‘Psychedelic Rainbow KaTgirl Superstar DJ’. This wallpaper was created inspired by her designs – and for all those who miss her – that may she live on.” — Designed by Katherine Appleby512 from Australia.
“We must enjoy life and its many wonders whenever the opportunity presents itself and then accept whatever consequences may come with an equal amount of vigor and enthusiasm.” — Designed by Roxi Nastase584 from Romania.
“Since the month March is derivated from the planet Mars, I decided to make a wallpaper with the planet Mars in the universe. And when I heard that they discovered several new planets in our galaxy where there could be life, I chose to put a green marsian on the planet. Maybe one day we will all live on another planet.” — Designed by Melissa Bogemans627 from Belgium.
“In some parts of the world there is the beauty of nature. This is one of the best beaches in the world: Ponta Negra in the North East of Brazil” — Designed by Elisa de Castro Guerra668 from France.
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.
Typography is a primary element of composition. Being a designer, I pay a lot of attention to its quality. Operating Photoshop is easy for me; however, to level up my skills, I am always learning to work with letters, using my hands, without any computer programs.
The first time I took a calligraphy course was about a year ago, and the decision was quite hard. I was sure that it would be painstaking and that I would need excellent handwriting to learn this art. How mistaken I was!
Type is saying things to us all the time. Typefaces express a mood, an atmosphere. They give words a certain coloring.
– Rick Poynor (“Helvetica”, 2007)
Typefaces are always telling us something. We receive information through typography. Type influences us, adds coloring to words, sets a mood and atmosphere, assists, teaches, scares us, brings us joy and inspires us.
Typography is, foremost, an information medium. At the same time, it fulfils social functions and acts as an indicator of the age it belongs to. The contemporary world has its own rhythm, aesthetic and philosophy; while we are changing, everything is changing around us. In studying historical lettering in calligraphy, we can understand the character and potential of a writing instrument, and, as a result, we can manage its expressive means.
When I joined the calligraphy course, I heard students talking amongst themselves: “I’ll never manage to do it this way!” “I can’t write in such a beautiful way!”
To tell the truth, I felt the same way. But that was nonsense! And I say that as a master of Photoshop who couldn’t handwrite plain lines only a year ago.
Type is a visual language, which connects the writer and the reader.
– Erik Spiekermann
Our first lesson was to write simple strokes, the basis of all letters, with a flat paintbrush.
Tip: A lot of useful resources and online courses are on the Internet. However, I recommend starting by learning from professionals (in workshops, at calligraphy schools). A professional will help you to develop proper technique, answer your questions and prompt you in the nuances of the craft. Even something as seemingly simple as one’s posture and pen-holding technique will substantially influence the result.
Studying in a course had a positive outcome. Writing with different instruments and trying different techniques, I could figure out which instrument suits me best.
I learned the history of calligraphy, I learned how to customize my workplace, and I learned how to choose an instrument. I practiced Cyrillic ornamental script, textura quadrata, italic, English roundhand, modern calligraphy, brush pen lettering and chalk lettering. I also learned how to make my own calligraphy instruments.
Calligraphy is the most intimate, personal, spontaneous form of expression. Like a fingerprint or a voice, it is unique for each person.
Tip: I recommend devoting your initial lessons to writing with a flat paintbrush. Get accustomed to the instrument, and study the “skeleton” of letters (graphemes). Soon after that, practice Cyrillic ornamental script, textura quadrata and italic.
Write the alphabet, then start with words and continue on to sentences. Next, you could proceed to study the pointed nib and the typefaces that rely on it: English roundhand, modern calligraphy script, flourishing, Spencerian and other Copperplate styles.
With the development of an international exchange of information, there is a need for universal fonts. Today, Texture and other Gothic fonts are only used as a reminder of a bygone era, in particular, in newspaper logos.
– Erik Spiekermann
Each lesson was a meditation. Soon after a lesson, I felt relaxed, energetic and inspired. And I got a good result on paper! The craft is a remedy and exercise for the mind and soul.
Having fallen in love with calligraphy, I came to prefer a sketchbook to a camera while on vacation. At a conference in St. Petersburg this spring, I got inspired by various graphic designers’ presentations and by the talk by renowned calligrapher Pokras Lampas38. I wanted to put everything aside and write something. In such an inspired state, I signed a card to say hello to my friends from that wonderful city. Thus, a simple card began my project “Hello From.” The idea was to show the essence of a place through lettering; I would take a photo of the card with the city in the background.
Other photos from the project can be found below. You can stay up to date on my Instagram account43! There will be many interesting countries and medieval-aged cities soon!
Benefits: What Is The Use Of Calligraphy Lessons? Link
New skill
Calligraphy would be a great addition to any designer’s skill set. Postcards, posters, invitation cards, website banners, prints for t-shirts and many other design products would look more authentic and interesting in calligraphy and lettering.
44 (View large version45)
Pleasure
You will derive great pleasure from working with your hands.
Patience
Calligraphy is meditative. Diving into the world of letters and waltzing through the soft lines will make you more calm and serene.
Age not a factor
Banish the thought that you can’t start learning because of your age. At any age, learning has a positive effect on the brain and expands one’s worldview. It is also good to teach children calligraphy, which will improve their brain activity and develop their fine motor skills.
Quick progress
Your very first letter might be clunky, but I am sure that by the end of the first line it will get better. And I assure you that by the end of the first or second sheet of paper, the improvement will be noticeable!
46 (View large version47)
A sketchbook, not a camera, for vacation
I guarantee that you will see quick and steady progress and that you will want to take your sketchbook and pens with you wherever you go, to be able to write whenever you get inspired.
Attention to surroundings
You will become observant. You will find inspiration for new work everywhere, from building faces on the street to old books on the shelf.
Selfmade postcards
You will be able to easily decorate postcards, giftwrapping, invitation cards and holiday cards for family and friends. It is always heartwarming getting a postcard made with love and attention to detail.
48 Simple wedding calligraphy for my Italian friends. (View large version49)
Unique corporate identity
More and more companies are using calligraphy and lettering in their trademark style. It lends uniqueness and instills trust in the customer.
Manual dexterity
The skill has an influence on one’s thinking, memory, imagination, powers of observation, coordination and agility.
Inexpensive
Most of the tools can be found at an affordable price. And craft paper can be done with the help of coffee, paint, etc.
Monetization
Nowadays, calligraphy is especially popular for wedding invitations, holiday cards, logos and many other design elements.
Without sufficient knowledge, one might find it difficult to write with a nib. This could lead to tool damage, catching paper with the nib and, as a result, torn paper. A beginner might even give up because of such bad results.
Silence helps
Some people (though not everybody) might have a problem working when a lot of people are distracting their attention. I recommend training in silence, relaxed and concentrated.
Bad mood = bad result
You will not be able to draw soft, delicate lines in a state of anger. If you are in a bad mood, put the work aside.
As in sports and music, in calligraphy it is important to train every day, to be patient and to feel inspired.
Attend master classes and courses, study online, and participate in competitions.
Practice, practice, practice.
If you train every day, you won’t have to wait long for progress. Focus on sharpening your skill, don’t be afraid to experiment, and devote time to writing regularly.
50 (View large version51)
Practice by copying.
Choose projects you like and copy them to understand how the composition and contrast work.
Warm up.
Start with some warmup exercises before getting down to work. Clench and release your fingers, rub and move your hands in circles to warm them up. While writing, do eye exercises from time to time.
Start with basic strokes.
Once you master this skill, it will be easier to move to letters and words.
52 (View large version53)
Collect different styles of handwritings.
You can find these in postcards and old letters. Analyze them. These will help you to come up with new and interesting combinations of typefaces.
Try new things.
Write with different tools and on different kinds of paper. Conventional designs are only one benefit! I write on wallpapers, bookshelf stands and old notebooks. It’s enough to begin writing with ordinary tools everybody has at home (pencils, brushes, markers). If none are at your disposal, then you can get creative and even try writing with a carrot, for example.
Take care of your tools.
Wash and wipe dry your tools after each exercise. When I was a beginner, I rusted and damaged several nibs irrevocably because of untimely cleaning.
Show your work to professionals.
An objective review will help you to find and correct mistakes. Don’t be offended by criticism; treat it as a compliment.
Don’t worry about other people’s opinion.
Don’t give up, even if your progress is not as fast as you would like. Good results will come.
Mind your sitting posture.
This rule is key to beautiful handwriting. If you follow it, you will be able to work at the table for a long time without discomfort or hand pain.
Collect references.
A box of ideas is very helpful. When I’m not feeling inspired and need a creative punch, I close my eyes and take out two magazine cuttings; I’ll analyze them and try to combine their styles and play around with them.
Inspiration. From real life. I open my eyes and I travel and I look. And I read everything.
– Erik Spiekermann
It is hard to create something without experience. Therefore, I recommend collecting ideas. However, at the beginning, after looking through hundreds of beautiful pictures, I sometimes lose confidence and think, “I can’t do that!” Calm down. Before you panic, do the following:
Look around.
Perhaps you are sitting in a comfortable armchair near a bookcase. You might find diverse typefaces and cover designs in those books.
54 (View large version55)
Open the cabinet.
If you have a box of old postcards and magazines, look through them. Cut out worthwhile elements and put them in an ideas box (your personal, offline Pinterest).
Wander the city with a camera.
You will find a lot of bars and cafes with interesting logo designs, window designs and branding. These visuals will give you ideas for interesting compositions.
Hit the market.
Buy a couple of cheap vintage books and postcards from your local book market. Analyze the typefaces, text designs and color schemes.
Go on a field trip.
Nothing inspires me more than a new city, exploring its architecture, wayfinding marks, sign plates on houses, bookstores and markets. So cute! (Yes, I am hard to travel with. I often make stops to take photos.)
56 Logos in the streets of Vilnius and Moscow (View large version57)
Photograph building faces.
The diverse ornaments you’ll find will give you plenty of ideas for exquisite and vintage logos.
58 My version of a logo from an architectural carving found on Pinterest59. (View large version60)
Meet new people and share your experience.
Together, you can create new projects and get valuable feedback. Showing your work to others will enable you to find and correct mistakes more quickly. Collaborate with photographers and other creative people.
Follow trends.
Analyze what is in fashion now and what will be in fashion for the next couple of years. Constantly move forward.
Check in on Instagram, Pinterest or Google.
Here, you will find plenty of beautiful design work. However, be cautious, and don’t be overwhelmed. The less you look at readymade solutions on the Internet, the better. You want to give yourself the chance to create something completely unique.
Sure, you don’t have to buy everything in this photo! Consider your abilities and preferences. Below is a detailed list to give you a general idea of the tools you’ll need for different styles of writing:
In the beginning, ordinary notebooks, copy books, office paper and even old wallpaper will be enough for practice. Try to get paper with a smooth surface and a higher density than office paper; otherwise, the ink will not flow and the nib will not catch the paper. Rhobia and Fabriano paper are quite good, but try different variants to find the best one for you.
Unused wallpaper and draft work is perfectly suited to writing with brushes and brush pens. At a more advanced level, you could use texture paper and handmade paper, which is great for making postcards and wedding invitations.
This is mandatory: It is impossible to write letters at a proper height or write a line of text without positioning and marking the sheet of paper. The most handy solution would be to put a printed handwriting worksheet under the sheet of paper you’re writing on. The worksheet will show through the paper, guiding you on the height and incline of elements. A ruler and pencil might also help, but lining would take time.
Samples of alphabets will show you how to draw letters correctly. Print them out and put them under your sheet of paper as a guideline. Examples can be found and downloaded on Pinterest69.
I recommend writing each letter on a separate sheet of paper, to better remember the motion of letters and to train your hand. This will surely take more time, but after you’ve written a lot of drafts, your hand will move confidently without trembling, and you will remember how letters are drawn by heart. Let’s start!
Stores offer a great selection of calligraphy ink. Choose whatever you want — experiment! For an entry level, ordinary watercolor paint is quite enough.
Chinese ink is perfect for this work. But pay attention to the expiry date. Buy fresh ink, otherwise you risk getting clods, which will impede the flow of ink from the nib.
Dr. Ph. Martin’s ink is one of my favorites. The selection of colors and variants is quite extensive, but it is quite expensive.
Pearl ink looks beautiful on dark and high-contrast surfaces. I like Finetec’s dry golden palettes. Work done with it looks exquisite.
74 A quote from the book Shantaram: The Mountain Shadow in a modern calligraphy style (View large version75)
As mentioned, I first learned to write with a flat synthetic paintbrush. It’s a great choice for learning letter graphemes, and it is the most economical choice.
Brush pens are a good tool to learn brush calligraphy and lettering. They come with and without cartridges. Brushes have different quality levels, densities, sizes and shapes. Find one you are comfortable writing with.
Water brushes are handy because you can fill them with ink or watercolor yourself. The disadvantage is that if, used improperly, they can get dry or dirty. I prefer to put my water brushes in ink or paint but not to fill them in. This way, they last longer.
Pen holders can be straight and oblique. A straight pen holder is good for square-cut pens and for writing different typefaces (for example, rustic capitals, square capitals, uncials and artificial uncials, textura quadrata, italics, etc.).
At the same time, an oblique pen holder with a pointed pen better suits cursive writing. Due to its initial incline, you will not have to bend your hand so much. It can be adjusted for different pens or just one particular pen.
Oblique pen holders have a flange at the end of the handle — the metal part of the holder where the pen is put in. This helps to regulate the angle of incline.
I also have a straight holder that looks like a feather. It is more decorative and adds some atmosphere as I’m working, but it is not as comfortable as other holders. I use it mainly for photos.
Nibs are square cut or pointed. As suggested earlier, you’d better learn typefaces with a square-cut nib. These nibs are quite rough, which makes the work easier and which will train you for a pointed nib.
Tip: If you are left-handed, you just need to find a nib that bends from right to left.
Pointed nibs are specially designed for cursive. They come in different sizes and can be used for different line thicknesses and different writing styles. After trying several of them, you will find a favorite.
Tip: Take care of your writing tools. Wash and wipe dry your tools after each exercise.
These are wonderful pens with a square-cut nib! They are very firm and comfortable to use. Though they work with the original cartridges (which are quite expensive), the empty ones can be refilled with a syringe.
In these books, you will learn the history of calligraphy, find descriptions of diverse alphabets (written using the elements of handwriting worksheets), learn about tools, read tips on how to adjust your workspace, tutorials and more.
Many books recommend starting calligraphy by writing with two pencils (firmly bound together), training yourself to build letters this way. In any case, a pencil will be useful for sketches and draft text writing, which you can use as a basis for writing in ink.
A pair of compasses
For lining round objects in composition.
Pigma micron permanent pens
These pens are perfect for preliminary sketches and drawing out letters.
Writing desk
A wooden sketchboard can be adjusted at different angles against the table, and the sheet of paper would then be fixed on the surface.
A rubber and a kneaded rubber
I mostly use a kneaded rubber, because it doesn’t leave waste after cleaning.
Rulers
They are needed to mark up the sheet of paper and to set the height of letters. You could use a printed handwriting worksheet and put it under the sheet of paper instead.
Nowadays calligraphy is in fashion, which only makes me happier. In comparison to digital text, handwriting is a distinct art form, and its uniqueness is being valued more and more highly.
The art of beautiful handwriting shouldn’t be forgotten, and I thank everybody who supports and promotes it today.
I hope that I’ve managed to convince you that anyone can learn the art of calligraphy! All you need is daily practice, inspiration and belief in yourself. And I believe in you. Good luck!
To consolidate your knowledge, I suggest you draw a birthday card. Grab a brush, ink or paint and some cartridge paper. Line the paper, and write your text in the middle of the paper with a pencil. Feel free to add some decorative elements around the lettering according to your taste (balloons, flowers, confetti, etc.).
Make sure that the final composition is aligned and symmetrical. Now you can trace around the letters in ink. Not that difficult, right?
Attach your result in the comments. Can’t wait to see them!
Building an app, site or other digital experience? Book your spot now in the 2017 XAwards to compete for 3 prestigious awards and €30,000 worth of cash prizes.
Phew, what a week! Due to an HTML-parsing bug, Cloudflare experienced a major data leak, and the first practical collision for SHA-1 was revealed as well. We should take these events as an occasion to reconsider if a centralized front-end load balancer that modifies your traffic is a good idea after all. And it’s definitely time to upgrade your TLS-certificate if you still serve SHA-1, too. Here’s what else happened this week.
The fresh Safari Technology Preview 247 added support for PerformanceObserver and added <link preload> as an experimental feature. Furthermore, they implemented the dynamic JavaScript import operator and suspended SVG animations on hidden pages.
It was just a matter of time until browsers would stop accepting SHA-1 certificates. But this week, things took a sudden turn as Google researchers revealed the first practical collision for SHA-1, affirming the insecurity of the algorithm. As a result of this, starting from today, Mozilla will remote-update Firefox to not accept SHA-1 in certificates anymore8.
Joseph Zimmerman introduces us to Webpack10. What I really like about this article is that it’s not another article sharing pre-built sets of configurations but that it explains every detail step-by-step.
Oh shit, git!11 Don’t be afraid of git anymore thanks to this emergency guide that helps you solve the most common problems with the versioning system.
12 Something went wrong in Git, but you don’t know how to get yourself out of the mess? “Oh shit, git!13” has got your back.
Mitigating Cross-Site Request Forgery attacks has never been easy. Luckily, it seems that we now got a proper solution for it: Same-Site Cookies14. The only thing you need to do to make it work is adding SameSite to your existing Set-Cookie header. Of course, you should know how same-site cookies differ from “normal” cookies, but for most sites this should be easy to implement.
It’s not your computer that is the most vulnerable device, it’s your smartphone. In fact, for a small amount of money, everyone can easily buy spyware16 that works on most Android phones. For iOS, things look a bit better unless the device is jailbroken. But this doesn’t necessarily mean that spyware doesn’t exist for that system as well.
The Institute For Energy Efficiency’s computing solutions group has a couple of interesting projects and data to share. For example, they try to figure out solutions to selectively shut down unnecessary components while retaining access to critical data. This is only one of their ambitious projects and shows how much potential there is when it comes to improving energy efficiency in our networks22.
Besides the user’s needs, what’s another vital aspect of an app? Your first thought might be its design. That’s important, correct, but before you can even think about the design, you need to get something else right: the data. Data should be the cornerstone of everything you create. Not only does it help you to make more informed decisions, but it also makes it easier to account for edge cases, or things you might not have thought of otherwise.
The easiest way to work with real data in Sketch is the with Craft plugin from InVision. It provides a wealth of predefined content, such as names, dates, and addresses, lets you scour a website for the required information, and enables you to feed in a JSON file and work with the provided data. That’s exactly what we will do with our made-up Movie Finder app. You can use it to search for movies based on different terms, such as name, director and year. This data will be provided by a JSON file, an open-standard format that allows data to be stored with key-value pairs, such as "category": "Dramas".
1 This is the Movie Finder app we will be creating. All rights to the sample content are held by Netflix and their respective owners. (Large preview2)
Before we can start to pull in some data, we need to take care of the layout of the app. If you are just interested in the “content” part (i.e. how to populate the design with real data), you can download the Sketch file of the template3 and continue reading from the “From One to Many4” section onwards. Otherwise, follow along and let me show you how to create the entire app from A to Z. I won’t explain every bit in detail; you’ll need some basic knowledge of Sketch5. The finished design, filled with movie data, can be found on Dropbox6. In either case, you will need the free font Clear Sans87 from Intel.
I wanted to keep the app as universal as possible, without tying it to a certain platform, so I chose an artboard size of 360 × 640 pixels, and I renamed it to “Movie Finder.” This is a common Android size, but you can easily go to iPhone sizes from there. Select the checkbox “Background Color” in the Inspector panel to give it a white background. Now, press R (to select the Rectangle tool) and create a rectangle at the top for the header; it should be the full width of the artboard. Be sure to remove the default border by pressing B on the keyboard, and save this style for future shapes with “Edit” → “Set Style as Default” from the menu bar. The height of the rectangle doesn’t matter at the moment, but the layer name does, so please set it to “BG.” To simplify the process of laying out elements and deciding on their sizes, set up an 8-pixel grid from “View” → “Canvas” → “Grid Settings” in the menu bar. For the “Grid block size,” enter “8px”; for “Thick lines every,” use “0.” Everything else can be left alone.
The first time we will use this grid is for the height of the header. Drag the rectangle we just created to be 32 pixels high. Choose a color of your liking that has enough contrast with white text; I went for #D06002, which I also saved to the “Document Colors” in the color dialog with a click on the “+” button, for later reference. For the title, “Movie Finder,” create a new text layer (press T) with a size of 16 pixels and the color white, and center it in both dimensions to the background. My font of choice is Clear Sans87 by Intel due to its clean look, but also the good selection of weights. Choose the “Regular” weight for the title. Complete the header by moving all of the current elements into a “Header” group.
9 The header: An 8-pixel grid simplifies the placement and sizing of elements. Bottom right: Save the fill color to the “Document Colors” for later reference. (Large preview10)
The next task is the search field. Add another rectangle with dimensions of 344 × 32 pixels, and assign it rounded corners of “3,” a white background and a gray border (#B4B4B4). Rename it to “Field.” Move it 1 grid unit away from the header, and center it to the artboard (using the fourth icon at the top of the Inspector, or a right-click and then “Align Horizontally”). The placeholder consists of an icon and some text. For the former, I have used the plugin Icon Font11, which enables you to easily pull in different icons. It requires you to install the font bundle12, a package of the most popular fonts. In case you need some assistance with this multi-step process, have a look at the screencast13. Now, go to “Plugins” → “Icon Font” → “Grid Insert” → “Ionicons” in the menu bar and enter “search.” Click on the first icon to add it to the artboard, but change its font size to 16 pixels. Drag it over to the search field.
For the placeholder text, add a new text layer with T, set to the same font size, a “Regular” weight and the content “Movie name, director, year.” Also, make sure the “Clear Sans” font is used. Move it 3 pixels away from the icon, select both elements, and center them vertically with a right-click and “Align Vertically.” Set the color of both to #4A4A4A. Because this will be our default text color from now on, add it to the “Document Colors.” Create a new group from these elements (named “Placeholder”), which you can tone down to 50% opacity with 5 on the keyboard. Move it a little up afterwards with the arrow key for correct optical alignment. Select this new group together with the field itself, and center them in both dimensions (right-click → “Align Horizontally” and “Align Vertically”), and create a “Search field” group. In the layers list, it should be below the header group; move it there with Cmd + Alt + Ctrl + down arrow.
14 The search box consists of the field itself, an icon and the placeholder text. (Large preview15)
Now, duplicate the placeholder text for the search term below with Cmd + D, but move it down until its text box has a spacing of about 3 pixels from the border of the input field. This new layer doesn’t need to sit on a grid line (you can break this rule — not everything has to align perfectly). Use ‘You have searched for “ridley scott”‘ as the content. Also, drag it out of the groups in the layers list, below the “Search field” group, and center it to the artboard.
Right below the text layer, add a line to clearly distinguish the search results. This can be created with either a thin rectangle (1-pixel high) or a line (1-pixel thick). I prefer the former because it’s a tad easier to handle. Create it with the same width and spacing as the search field, and name it “Line.” Set the fill to #D4D4D4, and align it on top of a grid line (which should give it a spacing of about 7 pixels from the text layer above). Move it to the bottom of the layers list, together with the text layer.
16 Add another text layer that indicates the submitted search. (Large preview17)
Now we can finally turn to the search results. Each result consists of the poster of the movie, the name, the director, a short description, the year of release and the running time. It also shows the user rating at a glance. But instead of adding all of the information by hand, we will just create placeholders that will be filled with the actual content later!
18 The finished template for the search results we are going to create and fill with real content later. (Large preview19)
Let’s start with the poster. Add a rectangle of 72 × 104 pixels at the left edge, with a spacing of 2 grid units from the artboard’s edge and the line above. Name it “Poster.” A black shadow with the properties “0/4/6/0” (X/Y/blur/spread) and 30% opacity will give it a slightly raised appearance.
Right next to it, with another horizontal spacing of 2 grid units, add a text layer for the “Title” (use exactly that as the content). The font size should already be at 16 pixels. For the color, choose the same as the header’s background (get it from the “Document Colors” in the color dialog). Make it bold with Cmd + B, and move it so that the top of the text (not the text box) is at the same height as that of the poster. Use the arrow keys to fine-tune this position. Duplicate it for the “Director” (as above, use this as the content), move it down and align its baseline to a grid line. Once you have lowered the font size to 14 pixels, this should give it a spacing of about 2 pixels from the previous text layer. For the weight, use “Regular” again, and for the color, the black color we saved to the “Document Colors” earlier.
Continue with the description in the same fashion: Duplicate the previous text layer with Cmd + D, and move it down so that there’s spacing of about 2 grid units in between, after you have aligned its baseline to the grid. You just need to make sure that the filler text has two lines: Use the well-known placeholder “Lorem ipsum dolor sit amet, consectetuer adipiscing elit” as the content for now, but set the width of the text layer to 230 pixels in the Inspector panel. This will create a fixed text layer that automatically breaks at the right, creating two lines of text. Tighten the line spacing to 16 pixels in the Inspector panel, which will align both lines to the grid.
22 For the description, add a text layer, and manually set its width to 230 pixels in the Inspector panel. This will create a fixed text layer that breaks to two lines. (Large preview23)
Because these will be just the first two lines of the description, we will add a so-called “disclosure triangle” that indicates more text. Create a triangle (from “Insert” → “Shape” → “Triangle” in the toolbar) with dimensions of 8 × 6 pixels, and flip it vertically with a right-click and “Transform” → “Flip Vertical.” In case you have difficulty getting these measurements, switch off the grid temporarily with Ctrl + G and zoom in a bit with Cmd + +. Assign this triangle the same color as the text, and center it to the second line of the description (you can switch on the grid again now). To make it independent of the text length, move it to the right edge of the artboard, with a spacing of 2 grid units. Finally, rename it to “Disclosure,” and make sure that it is above the adjacent text layer in the layers list.
For the remaining two text layers — the year and running time — we can take the text layer of the “Director” as the base again. Duplicate it, move it down, so that there is another spacing of about 2 grid units from the description, but change the content to something like “2000” (so that we have a good indication of how long a typical year will be). As before, its baseline should align to the grid. Hold Alt, drag it to the right with the mouse to create another copy, and change this one to “|” to separate it from the year. You may also want to press Shift while dragging to keep it on the same line. Add the last layer in the same fashion, with “Running time” as the content. These text layers should have a horizontal spacing of about 4 pixels from each other.
24 Hold Alt (⌥) and drag the text layer of the year (“2000”) to the right, to make a copy for the separation line. Repeat to create the text layer for the running time.
The only thing we have to do before we can start pulling in some real content is the rating. First, it contains a circle with a diameter of 28 pixels (switch off the grid again) and the same fill color as the title of the movie. The second element is a white text layer (“9.9,” for example), with a font size of 14 pixels, a bold weight and center alignment (press Cmd + |). Changing the character spacing to “–0.8” will give it a tighter feel. Align these two layers to each other, but trust your own eyes for the optical alignment instead of Sketch’s functionality, because that will produce a better result.
After you have combined these into a “Rating” group, move it to the bottom right of the poster so that it sticks out about 10 pixels horizontally and 4 pixels vertically. Make sure that it is above the poster in the layer hierarchy. One last step: Duplicate the line from above so that it acts as a separator between the other search results we are going to create. Move it down until it has a spacing of 2 grid units from the poster and sits on top of a grid line.
25 The rating consists of a circle and a text layer. Create a group from these elements, and let it stick out 10 pixels horizontally and 4 pixels vertically from the poster. (Large preview26)
The design is ready. There are numerous ways in which we can fill it with real content (with the help of some plugins), but the best and easiest is Craft27. Apart from pulling in data, it also enables us to duplicate elements and vary their contents automatically. After you have installed the plugin, a handy panel next to the Inspector panel will appear (if not, open it with “Craft” → “Toggle Panel” from the menu bar), which will provide more functionality in Sketch. For us, the “data” section (third icon from the top) is of most interest and, in particular, the “JSON” tab.
28 After installing the Craft plugin, you will be presented with a handy panel. The “data” section (third icon from the top) is of particular interest; from it, navigate to the “JSON” tab. (Large preview29)
We will pull our data from the Netflix Roulette30 website, which provides an application programming interface (or an API, which is a way to access different parts of a service) for all shows on Netflix. Because we would like to get all movies from director Ridley Scott, we will use the “director” keyword with his name, which leads to the URL http://netflixroulette.net/api/api.php?director=Ridley%20Scott. Click on it to see the JSON file. The file might seem like a mess at first, but it’s just an unordered collection of the key-value pairs — i.e. the properties — of the movies, such as show_title, category and runtime. We will bring some order to this list shortly.
Take this exact URL and paste it in the input field of the “JSON” tab in the Craft panel that says “Type URL…”. Clicking on “Import” will bring up a list of (currently) seven entries, which you can extend with the arrow on the left.
31 Pasting the URL from the JSON file into the input field will bring up a list of (currently) seven movies. Expand one of them to see its properties, the key-value pairs. (Large preview32)
Start at 0, which should be the one for the movie Gladiator; a look at show_title confirms that. With a simple click on the key, you can assign its value (or any other from the JSON file) to layers on your artboard (for example, after selecting the “Title” text layer). Do the same for the “Director” text layer and the director key, as well as “Description” and summary. Unfortunately, the content from Netflix Roulette is much longer than what we have arranged for the text layer. Fix that by dragging the height of the text layer back to 34 pixels again (using the Inspector panel won’t work here).
33 Paste the URL from Netflix Roulette into the “Type URL…” field, expand the first entry (0), and assign the values to the layers on the artboard.
Now, continue with the remaining text layers. Select “2000” on the artboard, and assign the value from release_year, as well as “Running time” on the canvas and runtime from Craft. For the rating in the orange circle, use (you guessed it!) the rating field. Instead of using a URL for the JSON file, you can employ your own data: Delete the current source with the “x” icon next to the input field, and drag your JSON data to the appropriate field below (or simply click there and select it from the computer).
You can use Craft to fill not only text layers but also image layers. Unfortunately, selecting the “Poster” layer and clicking on the poster field in Craft won’t give us the desired result: it seems that the image path isn’t valid, so nothing more than the three dots (which usually act as a loading indicator) will be shown. Luckily, Craft can do even more: You can use the “Web” tab — which is basically just a browser — to navigate to a website and grab the poster from, say, IMBd. On the page for Gladiator35, scroll down and click on the movie poster, which will assign the correct image to the placeholder on the artboard (make sure that it is selected first). In case you want to follow a link, you need to hold Cmd before clicking.
36 Use the “Web” tab to navigate to the Gladiator page on IMDb, and click on the poster there to fill the layer with the image.
Now we have a search result that is fully filled with content about the Gladiator movie, without having typed a single value by hand. Magic!
But it doesn’t stop there. Getting to the other search results, all based on the same JSON file, is just a matter of a few clicks. As preparation, combine all of the layers of the search result into an “Item” group (including the line), and move it to the bottom of the layers list (you can use Ctrl + Alt + Cmd + down arrow). Now, click on “Duplicate content” in the Craft panel, which will bring you to the “Duplicate” section. This will let you lay out an element in both directions, with a certain count and spacing in between. We want “4” items in total, with a gutter of “10,” aligned vertically. Press “Duplicate Content” and watch the magic unfold.
37 Getting to the other search results is a matter of a few clicks: Use the “Duplicate” section, with a count of “4” and a gutter of “10.” This will give you three more entries, all based on the same JSON file.
We’ve gotten three new search results, all filled with more movie data. Craft was clever to use the other entries from the JSON file here. Alongside these additional entries, another new layer was created in the layers list: “Duplicate control.” This one’s really powerful: In case the new entries don’t align to the grid, you can use it to change the spacing on the fly. Just select the “Duplicate control” layer in the layers list, and drag the slider below the “Gutter” field in the Craft panel.
But it does even more. If you need more (or fewer) entries later on, you can resize the “Duplicate control” layer on the canvas, and the plugin will automatically adapt the number of search results! Just mind that plugins sometimes break with each new version of Sketch, so if something doesn’t work as expected, a fix might already be on the way.
The only thing that doesn’t perfectly work are the posters. They seem to be broken in general, so we need to use the “Web” tab again. Navigate to the respective detail pages on IMDb, and select the appropriate poster images. But that’s a small price to pay.
Basically, we are done now, but I want to show you one last trick. Though we have four similar elements, they aren’t tied to each other in any way. Changing one of the entries won’t affect the others. A symbol would help here.
Start by deleting all of the item groups except the first; remove the outer “Group” that Craft created with Shift + Cmd + G, as well as the “Duplicate control” layer, and select the remaining item. Now, click on “Create Symbol” in the toolbar, but don’t send it to the Symbols page. This will place the symbol next to the artboard, which will make modifications easier later because you can instantly see how all instances will be affected.
In contrast, if you select “Send Symbol to ‘Symbols’ Page,” the symbol will be created on a separate page38. While this is better for organization, it becomes much harder to see the direct correlation between the master symbol and its instances when you change it.
For the rest of the items, you can proceed in the same way as before. Select the first item, the instance of the symbol we just changed (not the master symbol next to the artboard), go to the “Duplicate” panel in Craft (the last icon), enter “4” for the count and “10” for the gutter, and you are done. Because all entries are tied to the same symbol now, you can try to change the size of the title, for example, and see how it adapts in every search result.
39 Create a symbol from the first entry with the appropriate icon in the toolbar, and it will act as the model for the other search results. (Large preview40)
The poster problem needs a slightly different approach, however. Selecting the poster of each search result isn’t possible anymore when using a symbol. Instead, click on the small thumbnail next to the “Choose Image” button in the “Overrides” section of the Inspector panel. Navigate to the appropriate IMDb page from the “Web” tab in the Craft panel again, and drag the poster to this thumbnail. This will apply it to the respective instance of the symbol. Goal achieved!
41 Select a search result, navigate to the appropriate page on IMDb in the “Web” tab of Craft, and drag the poster to the thumbnail in “Overrides” in the Inspector panel. This will apply the image to the selected item. (Large preview42)
I hope you’ve enjoyed this tutorial, in which I’ve shown how you can stop worrying about dummy content and start using real data with the help of the Craft plugin43. This could not only speed up your design process but also make you think more about edge cases, or how certain parts of a design can interact with each other.
Please feel free to post your questions or point out a different approach to a certain part of the tutorial. You can also contact me on Twitter (@SketchTips44) or visit my little side project (SketchTips45), where I provide more tips about Sketch. For the full package, have a look at The Sketch Handbook46 from Smashing Magazine, which will tell you everything you ever wanted to know about designing with Sketch.
When you examine the most successful interaction designs of recent years, the clear winners are those who provide an excellent functionality. While functional aspect of a design is key to product success, aesthetics and visual details are equally important — particularly how they can improve those functional elements.
In today’s article, I’ll explain how visual elements, such as shadows and blur effects, can improve the functional elements of a design. If you’d like to try adding these elements to your designs, you can download and test Adobe XD1for free and get started right away.
There’s a reason GUI designers incorporate shadows into their designs — they help create visual cues in the interface which tell human brains what user interface elements they’re looking at.
Since the early days of graphical user interfaces, screens have employed shadows to help users understand how to use an interface. Images and elements with shadows seem to pop off of a page, and it gives users the impression that they can physically interact with the element. Even though visual cues vary from app to app, users can usually rely on two assumptions:
Elements that appear raised look like they could be pressed down (clicked with the mouse or tapped with a finger). This technique is often used as a visual signifier for buttons.
Elements that appear sunken look like they could be filled. This technique is often used as a visual signifier for input fields.
You can see how the use of shadows and highlights help users understand which elements are interactive in this Windows 2000 dialog box:
2 Perceived possibility of action: notice how the buttons appear raised. (Large preview3)
Create a Visual Hierarchy and Impression of Depth Link
Modern interfaces are layered and take full advantage of the z-axis. The position of several objects in the z-axis act as important cues to the user.
4 The z-axis is perpendicularly aligned to the plane of the display, with the positive z-axis extending towards the viewer. Image credit: Material Design.5 (Large preview6)
Shadows help indicate the hierarchy of elements by differentiating between two objects. Also, in some cases, shadows help users understand that one object is above another.
Why is it so important to visualize the position of an element within three-dimensional space? The answer is simple — laws of physics.
Everything in the physical world is dimensional, and elements interact in three-dimensional space with each other: they can be stacked or affixed to one another, but cannot pass through each other. Objects also cast shadows and reflect light. The understanding of these interactions is the basis for our understanding of the graphical interface.
Let’s have a look at Google’s Material Design for a moment. A lot of people still call it flat design, but the key feature is that it has dimension — the use of consistent metaphors and principles borrowed from physics help users make sense of interfaces and interpret visual hierarchies in context.
10 The laws of physics are deeply integrated in our cognition: without a larger shadow, nothing indicates that the round yellow circle is separate from the background surface. Image credit: Google11 (Large preview12)
One very important thing about shadows is that they work in tandem with elevation. The elevation is the relative depth, or distance, between two surfaces along the z-axis. Measured from the front of one surface to another, an element’s elevation indicates the distance between surfaces and the depth of its shadow. As you can see from the image below, the shadow gets bigger and blurrier the greater the distance between object and ground.
13 Elevation in Material Design: z-depth = 1 is very close to the ground, z-depth = 5 is far away from the ground. (Large preview14)
Some elements like buttons have dynamic elevation, meaning they change elevation in response to user input (e.g., normal, focused, and pressed). Shadows provide useful clues about an object’s direction of movement and whether the distance between surfaces is increasing or decreasing. For users to feel confident that something is clickable or tappable, they need immediate reassurance after clicking and tapping, which elevation provides through visual cues:
15 An object’s elevation determines the appearance of its shadow. The values shown are for Android apps. Image credit: Behance
When Apple introduced iOS 8, it raised the bar for app design, especially when it came to on-screen effects. One of the most significant changes was the use of blur throughout, most notably in Control Center; when you swipe up from the bottom edge of a screen you reveal the Control Center, and the background is blurred. This blur occurs in an interactive fashion, as you control it completely with the movement of your finger.
Apple moved further in this direction with the latest version of iOS which uses 3D Touch for the flashlight, camera, calculator and timer icons. When a user’s hand presses on those icons, real-time blur effect takes place.
Blur technique has the following benefits for modern mobile interfaces: Link
Make User Flow Obvious
Blur effects allow for a certain amount of play within the layers and hierarchy of an interface, especially for mobile apps. It’s a very efficient solution when working with layered UI since it gives the user a clear understanding of a mobile app’s user flow.
The Yahoo Weather20 app for iOS displays a photo of each weather location, and the basic weather data you need is immediately visible, with more detailed data only a single tap away. Rather than cover the photo with another UI layer, the app keeps you in context after you tap — the detailed information is easily revealed, and the photo remains in the background.
21 Blur effect in Yahoo Weather provides contextual awareness to the user about where they are in the navigational hierarchy. (Large preview22)
Direct the User’s Attention
Humans have a tendency to pay attention to objects that are in focus and ignore objects that aren’t. It’s a natural consequence of how our eyes work, known as accommodation reflex23. App designers can use it to blur unimportant items on the screen in an effort to direct a user’s attention directly to the valuable content or critical controls. The Tweetbot24 app uses blur to draw users attention to what needs to be focused on; the background is barely recognizable, while the focus is on information about accounts and call to action buttons.
The purpose of text in your app is to establish a clear connection between the app and user, as well as to help your users accomplish their goals. Typography plays a vital role in this process, as good typography makes the act of reading effortless, while poor typography turns users off.
In order to maximize the readability of text, you need to create a proper contrast27 between the text and background. Blur gives designers a perfect opportunity to make overlaid text legible — they can simply blur a part of the underlying image. In the example below, you can see a restaurant feed which features the closest restaurants to the user. Immediately, your attention goes to the restaurant images as they feature a darkened blur with text overlay.
Blurred effect can seamlessly blend into the website design.
Decorative Background
Together with full-screen photo backgrounds, frequently used for website decorations, blur backgrounds have found their niche in modern website design. This decorative effect also has a practical value: by blurring one object, it brings focus to another. Thus, if you want to emphasize your subject and leave the background out of focus, the blurring technique is the best solution.
The website for Trellis Farm uses an iconic image of a farm to give visitors a sense of place for its website. For added interest, the photo is layered with a great typeface to grab a visitor’s attention. The blur is nice because it helps the visitor focus on the text and the next actions to take on the screen.
28 Blur backgrounds are able to focus attention on specified elements. (Large preview29)
Progressive Image Loading
As modern web pages load more and more images, it’s good to think of their loading process, since it affects performance and user experience. Using blur effect you can create a progressive image loading effect. One good example is Medium.com, which blurs the post image cover as well as images within the post content until the image is fully loaded. First, it loads a small blurry image (thumbnail) and then makes a transition to the large image.
It helps you serve different images sizes depending on the device that makes the requests, optimizing the weight of the page.
The thumbnails are very small (just a few kilobytes) which combined with the blurry effect allows for a better placeholder than a solid color, without sacrificing payload.
If you want to reproduce this effect on your site see the Resources and Tutorials section.
Testing Websites’ Visual Hierarchy
Blur effect can be used not only as visual design technique but also as a good testing technique for page visual hierarchy.
A blur test is a quick technique to help you determine if your user’s eye is truly going where you want it to go. All you need to do is, take a screenshot of your site and add a 5–10 px Gaussian blur in Photoshop. Look at a blurred version of your page (like the Mailchimp example below) and see what elements stand out. If you don’t like what’s projecting, you need to go back and make some revisions.
31 The blurring test is technique used to reveal a design’s focal point and visual hierarchy. (Large preview32)
Mailchimp’s homepage passes the blur test because the prominent items are the sign-up button and text copy which states the benefits of using the product.
Blur effect isn’t exactly free. It costs something — graphics performance and battery usage. Since blurring is a memory bandwidth and power intensive effect, it can affect system performance and battery life. Over-used blurs result in slower apps with largely degraded user experiences.
We all want to create a beautiful design, but at the same time, we can’t make users suffer from long loading or empty battery. Blur effects should be used wisely and sparsely — you need to find a balance between great appearance and the resource utilization. Thus, when using blur effects always check CPU, GPU, Memory and Power usage of your app (see section Resources and Tutorials for more information).
Blur Effect and Text Readability Issues
Another factor that you should remember — blurring is not as dynamic. If your image ever changes, make sure the text is always over the blurry bits. In the example below, you can see what happens when you forget this.
Blurred background can cause a problem when it is used for screens filled with a lot of content. You can compare two examples below. The screen on the left using blur effect looks dirty, and the text seems unreadable. The screen without blur effect is much clearer.
35 When we need to display more content on a page, blurring background may be not so great. Image credits: Tubik studio.36 (Large preview37)
In his article “How Medium Does Progressive Image Loading39,” José M. Pérez provides solutions on how to incorporate progressive image loading using blur effect using CSS filters or HTML canvas elements.
The article, “Creating A Blurring Overlay View40,” provides examples of applying the blur effect to images in Apple iOS 8+ using the UIVisualEffectView class, with both Objective-C and Swift code samples. This is a native API that has been fine-tuned for performance and great battery life.
Shadows and blur effects provide visual cues that allow users to better and more easily understand what is occurring. In particular, they allow the designer to inform users on objects’ relationships with each other, as well as potential interactions with these objects. When carefully applied, such elements can (and should) improve a functional aspect of design.
This article is part of the UX design series sponsored by Adobe. The newly introduced Experience Design app42 is made for a fast and fluid UX design process, as it lets you go from idea to prototype faster. Design, prototype and share — all in one app.
You can check out more inspiring projects created with Adobe XD on Behance43, and also visit the Adobe XD blog44 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 free45.
JavaScript module bundling has been around for a while. RequireJS had its first commits in 2009, then Browserify made its debut, and since then several other bundlers have spawned across the Internet. Among that group, webpack has jumped out as one of the best. If you’re not familiar with it, I hope this article will get you started with this powerful tool.
In most programming languages (including ECMAScript 2015+, which is one of the most recent versions of the standard for JavaScript, but isn’t fully supported across all browsers yet), you can separate your code into multiple files and import those files into your application to use the functionality contained in them. This wasn’t built into browsers, so module bundlers were built to bring this capability in a couple forms: by asynchronously loading modules and running them when they have finished loading, or by combining all of the necessary files into a single JavaScript file that would be loaded via a <script> tag in the HTML.
Without the module loaders and bundlers, you could always combine your files manually or load your HTML with countless <script> tags, but that has several disadvantages:
You need to keep track of the proper order in which the files should load, including which files depend on which other files and making sure not to include any files you don’t need.
Multiple <script> tags means multiple calls to the server to load all of your code, which is worse for performance.
Obviously, this entails a lot of manual work, instead of letting the computer do it for you.
Most module bundlers also integrate directly with npm or Bower to easily allow you to add third-party dependencies to your application. Just install them and throw in a line of code to import them into your application. Then, run your module bundler, and you’ll have your third-party code combined with your application code, or, if you configure it correctly, you can have all of your third-party code in a separate file, so that when you update the application code, users don’t need to download the vendor code when they need to update their cache of your application code.
Now that you have basic knowledge of the purpose of webpack, why should you choose webpack over the competition? There are a few reasons:
Its relative newness gives it a leg up because it is able to work around or avoid the shortcomings and problems that have popped up in its predecessors.
Getting started is simple. If you’re just looking to bundle a bunch of JavaScript files together without any other fancy stuff, you won’t even need a configuration file.
Its plugin system enables it to do so much more, making it quite powerful. So, it might be the only build tool you need.
I’ve seen only a few other module bundlers and build tools that can say the same thing, but webpack seems to have one thing over those: a large community that can help when you get stuck. Browserify’s community is probably just as big, if not larger, but it lacks a few of the potentially essential features that come with webpack. With all the praise I’ve given webpack, I’m sure you’re just waiting for me to move on and show some code, right? Let’s do that, then.
Before we can use webpack, we need to install it. To do that, we’re going to need Node.js and npm, both of which I’m just going to assume you have. If you don’t have them installed, then the Node.js website1 is a great place to start.
Now, there are two ways to install webpack (or any other CLI package, for that matter): globally or locally. If you install it globally, you can use it no matter what directory you’re in, but then it won’t be included as a dependency for your project, and you can’t switch between versions of webpack for different projects (some projects might need more work to upgrade to a later version, so they might have to wait). So, I prefer to install CLI packages locally and either use relative paths or npm scripts2 to run the package. If you’re not used to installing CLI packages locally, you can read about it in a post I wrote about getting rid of global npm packages3.
We’re going to be using npm scripts for our examples anyway, so let’s just forge ahead with installing it locally. First things first: Create a directory for the project where we can experiment and learn about webpack. I have a repository on GitHub4 that you can clone and whose branches you can switch between to follow along, or you can start a new project from scratch and maybe use my GitHub repository for comparison.
Once you’re inside the project directory via your console of choice, you’ll want to initialize the project with npm init. The information you provide really isn’t that important, though, unless you plan on publishing this project on npm.
Now that you have a package.json file all set up (npm init created it), you can save your dependencies in there. So, let’s use npm to install webpack as a dependency with npm install webpack -D. (-D saves it in package.json as a development dependency; you could also use --save-dev.)
Before we can use webpack, we should have a simple application to use it on. When I say simple, I mean it. First, let’s install Lodash5 just so that we have a dependency to load into our simple app: npm install lodash -S (-S is the same as --save). Then, we’ll create a directory named src, and in there we’ll create a file named main.js with the following contents:
var map = require('lodash/map'); function square(n) { return n*n; } console.log(map([1,2,3,4,5,6], square));
Pretty simple, right? We’re just creating a small array with the integers 1 through 6, then using Lodash’s map to create a new array by squaring the numbers from the original array. Finally, we’re outputting the new array to the console. This file can even be run by Node.js, which you can see by running node src/main.js, which should show this output: [ 1, 4, 9, 16, 25, 36 ].
But we want to bundle up this tiny script with the Lodash code that we need and make it ready for browsers, which is where webpack comes in? How do we do that?
The easiest way to get started with using webpack without wasting time on a configuration file is just to run it from the command line. The simplest version of the command for webpack without using a configuration file takes an input file path and an output file path. Webpack will read from that input file, tracing through its dependency tree, combining all of the files together into a single file and outputting the file at the location you’ve specified as the output path. For this example, our input path is src/main.js, and we want to output the bundled file to dist/bundle.js. So, let’s create an npm script to do that (we don’t have webpack installed globally, so we can’t run it directly from the command line). In package.json, edit the "scripts" section to look like the following:
Now, if you run npm run build, webpack should get to work. When it’s done, which shouldn’t take long, there should be a new dist/bundle.js file. Now you can run that file with Node.js (node dist/bundle.js) or run it in the browser with a simple HTML page and see the same result in the console.
Before exploring webpack some more, let’s make our build scripts a little more professional by deleting the dist directory and its contents before rebuilding, and also adding some scripts to execute our bundle. The first thing we need to do is install del-cli so that we can delete directories without upsetting the people who don’t use the same operating system as us (don’t hate me because I use Windows); npm install del-cli -D should do the trick. Then, we’ll update our npm scripts to the following:
We kept "build" the same as before, but now we have "prebuild" to do some cleanup, which will run prior to "build" every time "build" is told to run. We also have "execute", which uses Node.js to execute the bundled script, and we can use "start" to do it all with one command (the -s bit just makes it so that the npm scripts don’t output as much useless stuff to the console). Go ahead and run npm start. You should see webpack’s output, quickly followed by our squared array, show up in your console. Congratulations! You’ve just finished everything in the example1 branch of the repository I mentioned earlier.
As fun as it is to use the webpack command line to get started, once you start using more of webpack’s features, you’re going to want to move away from passing in all of your options via the command line and instead use a configuration file, which will have more capability but which will also be more readable because it’s written in JavaScript.
So, let’s create that configuration file. Create a new file named webpack.config.js in your project’s root directory. This is the file name that webpack will look for by default, but you can pass the --config [filename] option to webpack if you want to name your configuration file something else or to put it in a different directory.
For this tutorial, we’ll just use the standard file name, and for now we’ll try to get it working the same way that we had it working with just the command line. To do that, we need to add the following code to the config file:
We’re specifying the input file and the output file, just like we did with the command line before. This is a JavaScript file, not a JSON file, so we need to export the configuration object — hence, the module.exports. It doesn’t exactly look nicer than specifying these options through the command line yet, but by the end of the article, you’ll be glad to have it all in here.
Now we can remove those options that we were passing to webpack from the scripts in our package.json file. Your scripts should look like this now:
We have two primary ways to add to webpack’s capabilities: loaders and plugins. We’ll discuss plugins later. Right now we’ll focus on loaders, which are used to apply transformations or perform operations on files of a given type. You can chain multiple loaders together to handle a single file type. For example, you can specify that files with the .js extension will all be run through ESLint6 and then will be compiled from ES2015 down to ES5 by Babel7. If ESLint comes across a warning, it’ll be outputted to the console, and if it encounters any errors, it’ll prevent webpack from continuing.
For our little application, we won’t be setting up any linting, but we will be setting up Babel to compile our code down to ES5. Of course, we should have some ES2015 code first, right? Let’s convert the code from our main.js file to the following:
import { map } from 'lodash'; console.log(map([1,2,3,4,5,6], n => n*n));
This code is doing essentially the same exact thing, but (1) we’re using an arrow function instead of the named square function, and (2) we’re loading map from 'lodash' using ES2015’s import. This will actually load a larger Lodash file into our bundle because we’re asking for all of Lodash, instead of just asking for the code associated with map by requesting 'lodash/map'. You can change that first line to import map from 'lodash/map' if you prefer, but I switched it to this for a few reasons:
In a large application, you’ll likely be using a pretty large chunk of the Lodash library, so you might as well load all of it.
If you’re using Backbone.js, getting all of the functions you need loaded individually will be very difficult simply because there is no documentation specifying how much of it is needed.
In the next major version of webpack, the developers plan to include something called tree-shaking, which eliminates unused portions of modules. So, this would work the same either way.
I’d like to use it as an example to teach you the bullet points I just mentioned.
(Note: These two ways of loading work with Lodash because the developers have explicitly created it to work that way. Not all libraries are set up to work this way.)
Anyway, now that we have some ES2015, we need to compile it down to ES5 so that we can use it in decrepit browsers (ES2015 support8 is actually looking pretty good in the latest browsers!). For this, we’ll need Babel and all of the pieces it needs to run with webpack. At a minimum, we’ll need babel-core9 (Babel’s core functionality, which does most of the work), babel-loader10 (the webpack loader that interfaces with babel-core) and babel-preset-es201511 (which contains the rules that tell Babel to compile from ES2015 to ES5). We’ll also get babel-plugin-transform-runtime12 and babel-polyfill13, both of which change the way Babel adds polyfills and helper functions to your code base, although each does it a bit differently, so they’re suited to different kinds of projects. Using both of them wouldn’t make much sense, and you might not want to use either of them, but I’m adding both of them here so that no matter which you choose, you’ll see how to do it. If you want to know more about them, you can read the documentation pages for the polyfill14 and runtime transform15.
Anyway, let’s install all of that: npm i -D babel-core babel-loader babel-preset-es2015 babel-plugin-transform-runtime babel-polyfill. And now let’s configure webpack to use it. First, we’ll need a section to add loaders. So, update webpack.config.js to this:
We’ve added a property named module, and within that is the rules property, which is an array that holds the configuration for each loader you use. This is where we’ll be adding babel-loader. For each loader, we need to set a minimum of these two options: test and loader. test is usually a regular expression that is tested against the absolute path of each file. These regular expressions usually just test for the file’s extension; for example, /.js$/ tests whether the file name ends with .js. For ours, we’ll be setting this to /.jsx?$/, which will match .js and .jsx, just in case you want to use React in your app. Now we’ll need to specify loader, which specifies which loaders to use on files that pass the test.
This can be specified by passing in a string with the loaders’ names, separated by an exclamation mark, such as 'babel-loader!eslint-loader'. webpack reads these from right to left, so eslint-loader will be run before babel-loader. If a loader has specific options that you want to specify, you can use query string syntax. For example, to set the fakeoption option to true for Babel, we’d change that previous example to 'babel-loader?fakeoption=true!eslint-loader. You can also use the use option instead of the loader option which allows you to pass in an array of loaders if you think that’d be easier to read and maintain. For example, the last examples would be changed to use: ['babel-loader?fakeoption=true', 'eslint-loader'], which can always be changed to multiple lines if you think it would be more readable.
Because Babel is the only loader we’ll be using, this is what our loader configuration looks like so far:
If you’re using only one loader, as we are, then there is an alternative way to specify options for the loader, rather than using the query strings: by using the options object, which will just be a map of key-value pairs. So, for the fakeoption example, our config would look like this:
We need to set the presets so that all of the ES2015 features will be transformed into ES5, and we’re also setting it up to use the transform-runtime plugin that we installed. As mentioned, this plugin isn’t necessary, but it’s there to show you how to do it. An alternative would be to use the .babelrc file to set these options, but then I wouldn’t be able to show you how to do it in webpack. In general, I would recommend using .babelrc, but we’ll keep the configuration in here for this project.
There’s just one more thing we need to add for this loader. We need to tell Babel not to process files in the node_modules folder, which should speed up the bundling process. We can do this by adding the exclude property to the loader to specify not to do anything to files in that folder. The value for exclude should be a regular expression, so we’ll set it to /node_modules/.
Alternatively, we could have used the include property and specified that we should only use the src directory, but I think we’ll leave it as it is. With that, you should be able to run npm start again and get working ES5 code for the browser as a result. If you decide that you’d rather use the polyfill instead of the transform-runtime plugin, then you’ll have a change or two to make. First, you can delete the line that contains plugins: ['transform-runtime], (you can also uninstall the plugin via npm if you’re not going to use it). Then, you need to edit the entry section of the webpack configuration so that it looks like this:
entry: [ 'babel-polyfill', './src/main.js' ],
Instead of using a string to specify a single entry point, we use an array to specify multiple entry files, the new one being the polyfill. We specify the polyfill first so that it’ll show up in the bundled file first, which is necessary to ensure that the polyfills exist before we try to use them in our code.
Instead of using webpack’s configuration, we could have added a line at the top of src/main.js, import 'babel-polyfill;, which would accomplish the exact same thing in this case. We used the webpack entry configuration instead because we’ll need it to be there for our last example, and because it’s a good example to show how to combine multiple entries into a single bundle. Anyway, that’s it for the example3 branch of the repository. Once again, you can run npm start to verify that it’s working.
Let’s add another loader in there: Handlebars. The Handlebars loader will compile a Handlebars template into a function, which is what will be imported into the JavaScript when you import a Handlebars file. This is the sort of thing that I love about loaders: you can import non-JavaScript files, and when it’s all bundled, what is imported will be something useable by JavaScript. Another example would be to use a loader that allows you to import an image file and that transforms the image into a base64-encoded URL string that can be used in the JavaScript to add an image inline to the page. If you chain multiple loaders, one of the loaders might even optimize the image to be a smaller file size.
As usual, the first thing we need to do is install the loader with npm install -D handlebars-loader. If you try to use it, though, you’ll find that it also needs Handlebars itself: npm install -D handlebars. This is so that you have control over which version of Handlebars to use without needing to sync your version with the loader version. They can evolve independently.
Now that we have both of these installed, we have a Handlebars template to use. Create a file named numberlist.hbs in the src directory with the following contents:
<ul> {{#each numbers as |number i|}} <li>{{number}}</li> {{/each}} </ul>
This template expects an array (of numbers judging by the variable names, but it should work even if they aren’t numbers) and creates an unordered list with the contents.
Now, let’s adjust our JavaScript file to use that template to output a list created from the template, rather than just logging out the array itself. Your main.js file should now look like this:
import { map } from 'lodash'; import template from './numberlist.hbs'; let numbers = map([1,2,3,4,5,6], n => n*n); console.log(template({numbers}));
Sadly, this won’t work right now because webpack doesn’t know how to import numberlist.hbs, because it’s not JavaScript. If we want to, we could add a bit to the import statement that informs webpack to use the Handlebars loader:
import { map } from 'lodash'; import template from 'handlebars-loader!./numberlist.hbs'; let numbers = map([1,2,3,4,5,6], n => n*n); console.log(template({numbers}));
By prefixing the path with the name of a loader and separating the loader’s name from the file path with an exclamation point, we tell webpack to use that loader for that file. With this, we don’t have to add anything to the configuration file. However, in a large project, you’ll likely be loading in several templates, so it would make more sense to tell webpack in the configuration file that we should use Handlebars so that we don’t need to add handlebars! to the path for every single import of a template. Let’s update the configuration:
This one was simple. All we needed to do was specify that we wanted handlebars-loader to handle all files with the .hbs extension. That’s it! We’re done with Handlebars and the example4 branch of the repository. Now when you run npm start, you’ll see the webpack bundling output, as well as this:
Plugins are the way, other than loaders, to install custom functionality into webpack. You have much more freedom to add them to the webpack workflow because they aren’t limited to being used only while loading specific file types; they can be injected practically anywhere and are, therefore, able to do much more. It’s hard to give an impression of how much plugins can do, so I’ll just send you to the list of npm packages that have “webpack-plugin”16 in the name, which should be a pretty good representation.
We’ll only be touching on two plugins for this tutorial (one of which we’ll see later). We’ve already gone quite long with this post, so why be excessive with even more plugin examples, right? The first plugin we’ll use is HTML Webpack Plugin17, which simply generates an HTML file for us — we can finally start using the web!
Before using the plugin, let’s update our scripts so that we can run a simple web server to test our application. First, we need to install a server: npm i -D http-server. Then, we’ll change our execute script to the server script and update the start script accordingly:
… "scripts": { "prebuild": "del-cli dist -f", "build": "webpack", "server": "http-server ./dist", "start": "npm run build -s && npm run server -s" }, …
After the webpack build is done, npm start will also start up a web server, and you can navigate to localhost:8080 to view your page. Of course, we still need to create that page with the plugin, so let’s move on to that. First, we need to install the plugin: npm i -D html-webpack-plugin.
When that’s done, we need to hop into webpack.config.js and make it look like this:
The two changes we made were to import the newly installed plugin at the top of the file and then add a plugins section at the end of the configuration object, where we passed in a new instance of our plugin.
At this point, we aren’t passing in any options to the plugin, so it’s using its standard template, which doesn’t include much, but it does include our bundled script. If you run npm start and then visit the URL in the browser, you’ll see a blank page, but you should see that HTML being outputted to the console if you open your developer’s tools.
We should probably have our own template and get that HTML to be spitted out onto the page rather than into the console, so that a “normal” person could actually get something from this page. First, let’s make our template by creating an index.html file in the src directory. By default, it’ll use EJS for the templating, however, you can configure the plugin to use any template language18 available to webpack. We’ll use the default EJS because it doesn’t make much difference. Here are the contents of that file:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title><%= htmlWebpackPlugin.options.title %></title> </head> <body> <h2>This is my Index.html Template</h2> <div></div> </body> </html>
You’ll notice a few things:
We’re using an option passed to the plugin to define the title (just because we can).
There’s nothing to specify where the scripts should be added. This is because the plugin will add the scripts to the end of the body tag by default.
There’s a random div with an id in there. We’ll be using this now.
We now have the template we want; so, at the very least, we won’t have a blank page. Let’s update main.js so that it appends that HTML to that div, instead of putting it into the console. To do this, just update the last line of main.js to document.getElementById("app-container").innerHTML = template({numbers});.
We also need to update our webpack configuration to pass in a couple options to the plugin. Your config file should now look like this:
The template option specifies where to find our template, and the title option is passed into the template. Now, if you run npm start, you should see the following in your browser:
That brings us to the end of the example5 branch of the repository, in case you’re following along in there. Each plugin will likely have very different options and configurations of their own, because there are so many of them and they can do a wide variety of things, but in the end, they’re practically all added to the plugins array in webpack.config.js. There are also many other ways to handle how the HTML page is generated and populated with file names, which can be handy once you start adding cache-busting hashes to the end of the bundle file names.
If you look at the example project’s repository, you’ll see an example620 branch where I added JavaScript minification via a plugin, but that isn’t necessary unless you want to make some changes to the configuration of UglifyJS. If you don’t like the default settings of UglifyJS, check out the repository (you should only need to look at webpack.config.js) to figure out how to use the plugin and configure it. But if you’re good with the default settings, then all you need to do is pass the -p argument when you run webpack on the command line. That argument is the “production” shortcut, which is equivalent to using --optimize-minimize and --optimize-occurence-order arguments, the first of which minifies the JavaScript and the second of which optimizes the order in which the modules are included in the bundled script, making for a slightly smaller file size and slightly faster execution. The repository has been done for a while, and I learned about the -p option later, so I decided to keep the plugin example for UglifyJS in there, while informing you of an easier way. Another shortcut you can use is -d, which will show more debugging information from the webpack output, and which will generate source maps without any extra configuration. You can use plenty more command line shortcuts21 if that’s easier for you.
One thing that I really enjoyed with RequireJS and couldn’t quite get to work with Browserify (though it may be possible) is lazy-loading modules. One massive JavaScript file will help by limiting the number of HTTP requests required, but it practically guarantees that code will be downloaded that won’t necessarily be used by the visitor in that session.
Webpack has a way of splitting a bundle into chunks that can be lazy-loaded, and it doesn’t even require any configuration. All you need to do is write your code in one of two ways, and webpack will handle the rest. Webpack gives you two methods to do this, one based on CommonJS and the other based on AMD. To lazy-load a module using CommonJS, you’d write something like this:
require.ensure(["module-a", "module-b"], function(require) { var a = require("module-a"); var b = require("module-b"); // … });
Use require.ensure, which will make sure the module is available (but not execute it) and pass in an array of module names and then a callback. To actually use the module within that callback, you’ll need to require it explicitly in there using the argument passed to your callback.
Personally, this feels verbose to me, so let’s look at the AMD version:
require(["module-a", "module-b"], function(a, b) { // … });
With AMD, you use require, pass in an array of module dependencies, then pass a callback. The arguments for the callback are references to each of the dependencies in the same order that they appear in the array.
Webpack 2 also supports System.import, which uses promises rather than callbacks. I think this will be a useful improvement, although wrapping this in a promise shouldn’t be hard if you really want them now. Note, however, that System.import is already deprecated in favor of the newer specification for import(). The caveat here, though, is that Babel (and TypeScript) will throw syntax errors if you use it. You can use babel-plugin-dynamic-import-webpack22, but that will convert it to require.ensure rather than just helping Babel see the new import function as legal and leave it alone so webpack can handle it. I don’t see AMD or require.ensure going away any time soon, and System.import will be supported until version 3, which should be decently far in the future, so just use whichever one you fancy the best.
Let’s augment our code to wait for a couple seconds, then lazy-load in the Handlebars template and output the list to the screen. To do that, we’ll remove the import of the template near the top and wrap the last line in a setTimeout and an AMD version of require for the template:
import { map } from 'lodash'; let numbers = map([1,2,3,4,5,6], n => n*n); setTimeout( () => { require(['./numberlist.hbs'], template => { document.getElementById("app-container").innerHTML = template({numbers}); }) }, 2000);
Now, if you run npm start, you’ll see that another asset is generated, which should be named 1.bundle.js. If you open up the page in your browser and open your development tools to watch the network traffic, you’ll see that after a 2-second delay, the new file is finally loaded and executed. This, my friend, isn’t all that difficult to implement but it can be huge for saving on file size and can make the user’s experience so much better.
Note that these sub-bundles, or chunks, contain all of their dependencies, except for the ones that are included in each of their parent chunks. (You can have multiple entries that each lazy-load this chunk and that, therefore, have different dependencies loaded into each parent.)
Let’s talk about one more optimization that can be made: vendor chunks. You can define a separate bundle to be built that will store “common” or third-party code that is unlikely to change. This allows visitors to cache your libraries in a separate file from your application code, so that the libraries won’t need to be downloaded again when you update the application.
To do this, we’ll use a plugin that comes with webpack, called CommonsChunkPlugin. Because it’s included, we don’t need to install anything; all we need to do is make some edits to webpack.config.js:
Line 3 is where we import the plugin. Then, in the entry section, we use a different setup, an object literal, to specify multiple entry points. The vendor entry marks what will be included in the vendor chunk — which includes the polyfill as well as Lodash — and we put our main entry file into the main entry. Then, we simply need to add the CommonsChunkPlugin to the plugins section, specifying the “vendor” chunk as the chunk to base it on and specifying that the vendor code will be stored in a file named vendor.bundle.js.
By specifying the “vendor” chunk, this plugin will pull all of the dependencies specified by that chunk out of the other entry files and only place them in this vendor chunk. If you do not specify a chunk name here, it’ll create a separate file based on the dependencies that are shared between the entries.
When you run webpack, you should see three JavaScript files now: bundle.js, 1.bundle.js and vendor.bundle.js. You can run npm start and view the result in the browser if you’d like. It seems that webpack will even put the majority of its own code for handling the loading of different modules into the vendor chunk, which is definitely useful.
And that concludes the example8 branch, as well as the tutorial. I have touched on quite a bit, but it only gives you a tiny taste of what is possible with webpack. Webpack enables easy CSS modules23, cache-busting hashes, image optimization and much much more — so much that even if I wrote a massive book on the subject, I couldn’t show you everything, and by the time I finished writing that book, most (if not all) of it would be outdated! So, give webpack a try today, and let me know if it improves your workflow. God bless and happy coding!
Front page image credit: webpack24 (official site)
The mobile app market is growing faster than a beanstalk. The industry is huge and growing daily, and there is no end in sight. Expectedly, the mobile developer population has boomed, and the number of mobile apps in the market has hit new heights. The revenue generated by the global mobile app industry has skyrocketed.
Hybrid monetization models, such as in-app ads and in-app purchases, are quickly gaining popularity in the business world. Most studies show that in-app advertising is set to be a key driver of mobile growth over the coming years (see Statista’s1, IHS Markit’s2 and Forbes’s3 reports).
In this article, we’ll shed some light on the following questions:
On average, how much revenue does a mobile app generate?
Is the average revenue truly growing?
What are the biggest challenges facing the mobile app industry today?
What are the most popular monetization models in the market today? Which ones will be driving growth tomorrow? Which models have outlived their time?
I’ll try to present comprehensive answers, backed by statistical reports and expert opinion.
The Mobile App Market Still Has A Lot Of Room To Grow
App Annie reports8 that in 2015, the mobile app industry generated a whopping $41.1 billion in gross annual revenue and that this figure will rise to $50.9 billion. Gross annual revenue is projected to exceed $189 billion by 2020, according to Statista9. Though the figures differ somewhat between researchers, the overall picture is that the market is far from saturated. App Annie’s predictions corroborate reports from Forrester10 that only 46% of the world’s population will own smartphones by the end of 2016. This goes to show that the much-discussed mobile revolution is just starting.
According to another Forrester statistic11, there is a huge gap between leading companies that regard mobile devices as a catalyst to transforming their business and companies that consider mobile devices to be just another development channel. As of early 2016, only 18% of companies surveyed were in the first category. This number is expected to pass 25% by next year.
Consumers are evolving more rapidly than businesses. Today, the mobile Internet has clearly become a necessity for many users.
As for app popularity, aggregator apps12 are likely to move to the forefront. These are tools that pull content from multiple online sources and compile it into one easy-to-follow interface. The content could range from breaking news to niche subjects of interest. Aggregators are meant for those who don’t have the time or desire to visit numerous websites or install numerous apps. Some popular aggregator apps are Flipboard, News360, Feedly and IFTTT.
Aggregator apps tend to become user favorites when they are convenient or enhance the shopping experience. For instance, Facebook has done this with its Messenger app, which lets users read their feeds and order Uber rides.
Rich And Poor Platforms
Two mobile app giants, Android and iOS, dominate the global smartphone market. A study by Gartner13 found that by Q3 of 2016, 87.8% of smartphones sold worldwide were Android. This figure is 3.1% higher than a year ago. iOS’ market share is 11.5% — 2.5% less than in 2015. Though this figure is negligible for its already huge market share, this growth greatly decreased the positions of other market players. Windows, which accounted for 0.4% of all smartphones sold, came third in the mobile platform race, with its share decreasing 2.5%14 over the year.
Apple and Google have the largest and most popular app stores. For now, it seems as if no other competitor could dream of catching up to their variety of applications and number of developers.
InMobi estimates15 that 55% of app developers make less than $1,000. Moreover, a third of app developers worldwide haven’t managed to reach 10,000 total downloads of their products. Income stratification is more pronounced among Android developers, whereas income distribution is more balanced among iOS developers.
16 Two mobile app giants, Android and iOS, dominate the global smartphone market. (View large version17)
Since 2016, over 25% of iOS developers18 have generated over $5,000 in monthly revenue. Only 16% of Android developers have achieved a similar feat.
There are interesting statistics on the average monthly revenue earned by the mobile operating systems. Forbes estimates19 that iOS earned an average of $4,000 per month, pushing Android to second place with its $1,125. An outlier, Windows Phone came third with just $625.
However, this situation changed dramatically in 2016. According to Statista20, a Windows Phone app fetches $11,400 on average per month, whereas iOS app generates $8,100. Android makes $4,900 in average monthly revenue. However, about 75%21 of developers are most favorable to Android. They plan to boost their revenues by making Android-based products.
The Mobile App Spectrum
High-performance mobile CPUs, featuring powerful graphics, quality displays and fast Internet connection, have turned smartphones into gaming devices. According to reports by App Annie22, mobile games, which accounted for less than 50% of total mobile app revenue in 2011, generated 85% of mobile app market revenue in 2015. This figure represents a total of $34.8 billion worldwide.
23 The share of mobile games in the mobile app industry has grown impressively. (View large version24)
There has been a sharp increase in the time spent by users in different app categories. Non-gaming apps have overtaken games in the rapid rise of app usage. By late 2015, the mobile app market, according to Flurry Analytics Blog25, recorded the following new heights in app usage:
Customization apps, such as launchers, icons, wallpapers, and lock-screen and other device-customization apps, topped the list, with a staggering 332% rise in session usage.
Mobile versions of newspapers and magazines came in second, with a huge growth of 135%.
Productivity tools and apps came in third in the usage list, with a 125% rise.
Lifestyle and shopping solutions recorded an 81% growth and were ranked fourth.
Travel, sport, health and fitness utilities, along with messengers and social apps, gained from 53 to 54%.
Games turned out to be the only outlier, with a 1% decline in users’ time.
Monetization Models
Currently, there are six popular app monetization models.
If a paid app has not yet been purchased, then only screenshots, a description and a video will be available for preview. These items are meant to convince people to buy the app and show that they will get exactly what they see. However, this type of model makes it difficult for the user to make up their mind, which may have contributed to the disappointing statistic that no paid app is among the list of applications that have generated the highest revenues. Paid apps are the only ones rapidly losing the popularity battle, although they are still proving their worth in some cases.
Minecraft Pocket Edition26 is the most paid app in the Google Play Store. Officially released in 2011, Minecraft is a sandbox video game, and it goes for $6.99 per download.
Under the freemium model (a combination of “free” and “premium”), users get basic features at no cost and can access richer functionality for a one-time or subscription fee. Typically, the number of people willing to pay is relatively low. Consequently, apps using this model are focused on securing the highest possible number of downloads.
Heavily criticized for its potentially exploitative mechanisms, the freemium model performs remarkably when used thoughtfully. A perfect example is Clash of Clans4829.
The subscription model is similar to freemium. The difference is that users pay to access all of the content — not only certain features. This model generates predictable, long-term revenue flow for the owner by keeping customer loyalty high.
An excellent example of a subscription app is Lumosity32, which has over 50 different exercises designed by cognitive psychologists to train the brain. Lumosity offers both a monthly ($11.99 per month) and a yearly ($59.99 per year) subscription. With an average rating of five stars, coming from over 93,000 users, Lumosity is a phenomenal success in the subscription app sector.
Monetization through in-app purchases is especially common in mobile games, as well as various product catalog apps, which charge a service fee for every item sold. This model is so flexible that some games go too far in encouraging users to make purchases. As of February 2016, about 1.9% of mobile gamers made in-app purchases, as reported by Tech Times35, and this number is rising steadily.
An example is MeetMe36, a social app from which users can also buy certain goods and services. In MeetMe, you can pay a certain amount to increase your profile views. The developers generate decent income thanks to a clear sales model.
Crowdfunding is a relatively young monetization model. Developers present the idea for the app they want to develop on a popular online platform, such as Kickstarter or Indiegogo, requesting donations. Some interesting projects attract funding several times higher than the amount originally requested, whereas mediocre ones do not get anywhere near the desired amount.
Tech startup Shadow39 is an ideal example. The project achieved impressive crowdfunding success, with the developers generating $82,577 from 3,784 backers. Shadow approached this app-based crowdfunding challenge for its sleep- and dream-tracking software by adding a level of exclusivity to the rewards and project.
When delivered with the exclusive Shadow membership card, the app would have been free, but when the price rose to $8, it still fetched about $20,000 from this tier alone.
Sponsorship is a rather new monetization model. Users act as an advertising sponsor in exchange for a fee. A share from each fee goes to the developers. The model is still in its infancy, and the marketing strategy needs to be polished.
RunKeeper42, with a community of over 45 million users, is a great example of the sponsorship business model. It rewards users for covering a certain distance by running or riding a bicycle. Advertisers then pay the users. Credit here goes to the developer for not including any annoying ads.
This is the most popular45 monetization model and needs to be examined more closely. The reason behind its popularity is obvious: Users like to download free apps, and the higher the number of downloads, the greater the developer’s revenue. A report released by IHS Markit46 shows that, by 2020, in-app advertising will attract $53.4 billion in total revenue per year. That translates to almost 63% of mobile display advertising revenue.
As in other sectors, a few major developers of advertising-based apps are generating the bulk of the revenue. All other developers are forced to settle for leftovers. Klick Health47 reports that the indisputable leader is Facebook, with 44.3% of all mobile ads shown being in Facebook apps. Others in the ranking are, in order, Alibaba, Google, Tencent, Twitter, Pandora and Yahoo.
Companies that generate the highest advertising revenue often end up becoming major advertising sponsors. This trend is especially prominent in mobile games. The largest vendors, such as Rovio, Gameloft and Disney, employ hundreds of small indie studios, which advertise their own game products in less popular games.
The Bottom Line
As you can see, the explosive growth in the mobile app market isn’t stopping anytime soon. Despite increasingly strong competition in the industry, developers are applying new monetization methods and creating more interesting and useful solutions for users. At least two new monetization models have been shown to be very effective, gaining popularity in the last couple of years.
None of the models covered above could be described as inefficient. Rather, developers and publishers have gained skill in deploying these models in particular cases. For instance, the subscription model works only for certain niches but is the most profitable of all. At the same time, the freemium model, much criticized for being potentially unscrupulous, shows remarkable results when used thoughtfully, Clash of Clans4829 being a a perfect example. Paid apps are the only ones rapidly falling out of favor, although they are still proving their worth in some cases.
Hybrid monetization models, such as in-app ads and in-app purchases, are clearly gaining popularity in the business world. Most studies show that in-app advertising is set to be a key driver of mobile growth over the coming years.
Today, iOS and Android are the leading mobile operating systems, and tech giants Apple and Google own the biggest mobile app stores.
Time will tell how the mobile app market will develop. Market trends show that the market will continue to generate higher and higher revenue in the foreseeable future. So, it is quite clear that the much-discussed mobile app revolution is just beginning.
As web developers, we need to rely on our knowledge, and choosing solutions we’re already familiar with is often the most convenient approach to solving a problem. However, not only technology is evolving but also our knowledge of how to use it.
For a while, we thought it’s best to use base64 encoding for inlining assets into CSS files, for example, and that loading JavaScript asynchronously will make websites faster. With more evidence and research, however, we came to realize that we were wrong. We should take this as an occasion to remind ourselves to question our habits and from now on ask ourselves if the solution we have in mind for a given problem really is still the best one we could choose.
Jack Franklin explains context in ReactJS applications13 — something that’s discussed a lot in the community and often defined in many different ways. Jack explains why it exists, when to make use of it, and how you can avoid using it.
With all the talk about CSS in JavaScript and markup in JavaScript, we had quite some discussions lately. However, these topics were mostly discussed in the context of React applications. Now there’s a holistic approach to keeping everything in one place for vue.js15: your markup, your logic, your styles. An interesting concept that could be very useful for vue.js web applications.
So how can you be sure to not leak data from your phone or computer to authorities when you cross the border20? According to The Verge, the only reliable way is to delete it upfront. An interesting look at the options you have and why it can indeed make sense to delete your data on the phone and restore it later from the Cloud, if you want to avoid any hassle.
Have you ever dreamt of exploring the deep sea and getting up close to its fascinating, weird creatures? Or maybe you’ve dreamt of boarding a spacecraft to experience the beauty of our planet from above? The desire to leave the beaten tracks and explore unfamiliar terrain is human nature.
To celebrate mankind’s urge to explore, the creative folks at Vexels163 created a set of 30 adventurous icons that take you on a journey from the ground of the sea right up to outer space. The set offers all the building blocks you’ll need to create your own little universe and become an explorer yourself: Cute jellyfish, strange deep-sea fellows, a submarine, trees, a helicopter, hot air balloons, satellites, planets, meteors, and much more. Nature and technology beautifully united — I’m sure you’ll agree.
Please note that the set is released under a Creative Commons Attribution 3.0 Unported8. This means that you may modify the size, color and shape of the icons (more details in the readme.txt file). Attribution is required, so if you would like to spread the word in blog posts or anywhere else, please do remember to credit the designers and provide a link to this article.
Here’s a sneak peek of some of the icons:
9 The colors of the sky. Plenty of icons to fill it up just as you like. (Full preview1412102)11 Sweet submarine icon. Almost makes you want to sing along: “We all live in a yellow submarine, yellow submarine, yellow submarine”… (Full preview1412102)13 Look and listen closely. Can you hear that tropical bird song and the sounds of a small waterfall? (Full preview1412102)
“Nature is always inspiring. Whether it’s space, with its stars and Sun, or our home planet with its waterfalls and mountains, our design team is always motivated by what surrounds us. And that includes technology. From planes to submarines, we can explore our world with their help. We wanted to create a freebie that showed it so we made this elements set, called From Space to Earth.
It contains elements and icons with everything from rockets and asteroids to planes, fishes and even some dinosaur bones. We hope you get inspired to create some art of your own. Grab everything you need from this freebie and start creating!”
There’s a technique for improving one’s user interface design skills that is the most efficient way I know of expanding one’s visual vocabulary but that I’ve rarely heard mentioned by digital designers.
What’s going on here?
I’m talking about copywork. Copywork is a technique that writers and painters have been using for centuries. It is the process of recreating an existing work as closely as possible in order to improve one’s skill. In our case, this means recreating a user interface (UI) design pixel for pixel.
It’s not as pointless as it sounds, I promise. The trick is to pick a design that is better than what you are currently capable of. By copying something outside of your wheelhouse, you will be expanding your skills.
So, if you want to improve your use of color, copy something with some crazy gradients or a bold palette. If you want to get better at luxury branding, copy a preeminent website with a ritzy look and feel.
Obviously, this technique is not rocket science. Actually, it would be hard to think of a more mundane exercise. But it is the most effective way I know to improve my UI design skills.
I first heard about copywork on the blog The Art of Manliness4, where Brett McKay gives a long history of those who’ve used copywork to develop their writing skill.
Jack London copied swaths of Rudyard Kipling’s writing to adapt his forebear’s world-class cadence and phrasing.
Robert Louis Stevenson would meticulously study sections of writing he found particularly beautiful, then reproduce them word for word from memory.
Benjamin Franklin followed a variant of copywork, writing notes about each sentence in an essay and then, a few days later, trying to recreate the essay by reading his notes — and comparing the results.
The list goes on. I know that Raymond Chandler, the famous mystery writer, used a technique similar to Benjamin Franklin’s, rewriting a novelette from a detailed description, and then comparing his with the original to study the flow.
He actually wrote to the original author later in life, telling him how instructive the exercise was. Pay attention to his analysis:
I found out that the trickiest part of your technique was the ability to put over situations, which verged on the implausible but which in the reading seemed quite real. I hope you understand I mean this as a compliment. I have never even come near to doing it myself. Dumas had this quality in very strong degree. Also Dickens. It’s probably the fundamental of all rapid work, because naturally rapid work has a large measure of improvisation, and to make an improvised scene seem inevitable is quite a trick.
This is not a rote exercise. Chandler is extremely thoughtful about the differences between his work and the original and is well versed in the subtleties of style of many authors. Can you speak this articulately about UI design? If not, may I recommend copywork?
Just as a writer copying the greats before him unconsciously absorbs the tiniest choices those authors made — the word choice, phrasing, cadence and so on — a designer doing copywork also absorbs the subtlest choices in the designs they study — the spacing, layout, fonts, decorative elements. Therein lies its power.
Let’s take a quick look at copywork in one other art form, though, one with a remarkably long history.
Painters have an even longer history than writers of copying the masters. Leonardo da Vinci developed his art (one of his arts, anyhow) by copying his teacher, Andrea Del Verrocchio — a common practice among Renaissance apprentice artists. Da Vinci actually prescribed copywork as practice numero uno for art students:
The artist ought first to exercise his hand by copying drawings from the hand of a good master.
Why? Because copying directly from a master provides a controlled setting in which to train your eye.
When you’re painting a live scene, on the other hand, there’s a lot to worry about — the model will move, the wind will pick up, the sun will set. Until your brain can think naturally in shape and color, painting in the real world will be tough. But in the studio, you can take all the time you need to absorb the basics.
While UI designers do not model anything after a natural scene in the same way as painters, copywork provides a useful way to eliminate variables and distractions while honing your skill.
But although it was once a foundational exercise of some of the world’s greatest artists, copywork has fallen out of favor. Nowadays, it’s viewed as rote, uncreative and reeking of plagiarism.
The gist is this: When you recreate a design, pixel for pixel, you’re forced to remake every decision the original designer made. Which font? How big? How are things laid out? Which images and background and decorations? You immerse yourself in the small design decisions made by awesome designers.
You might argue that you’d be missing out on all of the choices the designer considered, and the rationale for why they picked what they did. Fair enough — but that’s missing the point. Done right, copywork exposes you to design decisions you simply wouldn’t have made on your own.
Let’s take an example. One of the most vocabulary-expanding pieces I’ve copied is Dann Petty’s wonderful Epicurrence10 website. I internalized three things from the header alone:
Insanely large font size
My copy of the original included the Hawaii initials “HI” in size 365 font. Never in my years of professional work had I even considered making text that big. Yet he uses it as a visual element, aligning it with the other header elements, even putting an image between the letters. Very cool.
Paint stroke as “shadow”
A watercolor smudge runs across the bottom of the seal, the header and the pineapple. It’s in the spot where a shadow might be, as if the shadow were painted on the page. Whoa — that’s not the usual way of doing it!
Uppercase type with generous letter-spacing
No doubt, that uppercase text adds a strong element of alignment, and pumping up the letter-spacing is a textbook way to add some classiness to type, but I find myself getting self-conscious about doing it much. It was cool to see that all of the text here is capitalized, and basically all of it has modified letter-spacing, too.
Now, I’d seen Dann Petty’s design before deciding to copy it. I thought, “Wow, this looks great.” And even as my eyes glossed over the design, it’s not like I immediately internalized every technique he used. Only when I copied it did I start to consciously adopt those things in my UI toolkit.
Here’s another example, the Skedio icon set14 by master icon designer Vic Bell. (Her originals are in blue, my copywork in red.)
This was a fascinating exercise for me, particularly because Vic’s icons are a step or two more detailed than most of what I make for the apps I work on. She added this complexity in two subtle ways:
A second, lighter shade of blue
Compare the fill color of the “Settings” icon (row 2, icon 1) to the outline color. Most icons I’ve designed are one color only.
A second, lighter line width
You can see it in the “text” of the “Tags” icon (row 1, icon 2) and in the arrow on the “Upgrades” icon (row 1, icon 3). I’ve lived by the rule that consistency is paramount in icon design, so seeing Vic’s use of 3-pixel accent lines in a primarily 4-pixel line set was fascinating.
But the strength of copywork is not just in seeing these details at a superficial level, but also in becoming intimately familiar with how they are used across the design.
Let’s take the idea of the second, lighter shade. It’s one thing to decide to use a second shade as an accent color. Here are four ways Vic has used the lighter shade in this icon set:
As a shadow
The trash can lid of the “Delete” icon (row 2, icon 3) has this secondary blue in its shadow. You can see a similar but even subtler shadow beneath the medallion in the “Upgrades” icon (row 1, icon 3).
As a gleam of light
The lighter shade is used as a reflection of light in the magnifying glass of the “Search” icon (row 3, icon 5).
For color contrast
Vic uses white and light blue as two contrasting colors in the life-preserver ring of the “Help and feedback” icon (row 1, icon 4). Same story with the pencil in the “Rename” icon below it (row 2, icon 4).
For visual weight contrast
This one was the subtlest for me. Notice how the background cards — but not the foreground card — of the “All sketches” icon (row 1, icon 1) and the “Layers” icon (row 3, icon 5) are light blue. The foreground card in both is white, giving it more contrast with the rest of the icon. If the background cards had white fills, then the sharp contrast between their borders and fills would have distracted the eye — as it is, the eye is directed straight to the front card.
These strategies are more detailed than any class on icons would get into. They’re one-off tips and techniques that go straight from the mind of a master to yours, if you’re willing to put the effort into doing copywork.
I saw Taylor Perrin’s Día de los Muertos design not long ago, and it blew me away. He does a fantastic job of using elements that I struggle with, such as beautiful photography, rich textures and panoramic layouts.
A lot of this is due to what I spend my time designing — mostly information apps for businesses. The look is clean and simple, the branding staid.
I’ve been a huge proponent of Sketch since day one, and I even teach a UI course based on Sketch19, but there are downsides to its simplicity. Namely, since switching from Photoshop to Sketch, my design reflexes have tended way towards everything being flat rectangles. In this exercise, I textured almost every background on the whole page, and it was a great reminder that a pass in Photoshop during the design process allows me much more versatility in style than simple colored rectangles.
Making decent assets shine
One of the first assets I had to track down and restyle was the illustration of the skeleton playing the horn. When I found it online20, I was underwhelmed. In fact, if I had been designing the original mockup and found that illustration, I probably would have passed it up. Yet it looked great in Perrin’s mockup. Comparing the original image to his mockup was a lesson in all of the cleanup work you can do with mediocre assets, and in envisioning their use beyond their immediate appearance.
Full-width layouts
Although it’s become popular to have panoramic layouts span the page’s width no matter how wide the screen gets, I’ve done very little of this myself. This exercise was a great confidence-booster for this type of layout. As I copied, I would try to guess certain details (such as the font size of a particular piece of copy) and see what felt right; then, I checked and adjusted. The next time I make a layout 1400 pixels wide, I won’t feel odd about headings being 60 pixels.
So, am I as good as Dann Petty or Vic Bell or Taylor Perrin now? I’m afraid that will take some time — they’re among the best UI designers in the game. But you better believe that every day I am pushing my set of skills and techniques to incorporate their know-how.
Copy something that pushes one of your skills beyond its current level. Copy something that exhibits a technique you’ve not honed.
21I use a Dribbble bucket to capture designs I’d like to copy.
For ideas, I love to browse Dribbble. I keep a Dribbble bucket of copywork images22 — things I’ve found from other designers that I want to copy (or already have).
I can also recommend a few designers who have carved out their own style and offer a lot to those who are still learning the basics:
Jonathan Quentin23 uses color and gradients really well. Check out his work to up your color chops.
Brijan Powell24 is the boss at making designs that are classy and upscale yet thoroughly masculine.
Tubik Studio25 is fantastic at everything bright, colorful and cheery.
Though I use Dribbble for copywork (it’s a great way to quickly browse and save high-quality images), live websites work great, too. For instance, Blu Homes26 is next on my list!
If you’re a professional designer, here are a few more ideas:
I sometimes copy my clients’ websites and apps if they want more UI work done in that style.
I sometimes copy my potential clients’ websites and apps, so that from the very first conversation, I have a deeper knowledge of their visual design language.
For instance, I did some design work for Soylent27, the meal-replacement company. As soon as they reached out to me, I put it on my to-do list to reproduce their home page. I wanted to be able to talk fluently about how they used color, typography and imagery.
28I copied Soylent’s home page in preparation for some work I did with them. This gave me a feel for how they used visuals, typography, etc. (View large version29)
I think copywork is subject to diminishing returns — so, no, you don’t have to copy perfectly. But (and this is important) you can’t copy it worse than the original. You have to achieve something that you view as equal or better, even if the details don’t totally line up.
You won’t always have access to the same fonts and resources, so slight differences are par for the course. I’ve found Identifont30 and WhatTheFont31 to be great resources for finding which fonts are used in images.
Do You Copy Multiple Images in Series to Improve a Certain Skill? Link
Copying five designs that demonstrate excellence in, say, typography is a great way to get better at that one skill. However, I much prefer to bounce around to whatever catches my eye. It’s a good counterbalance to what I’m working on at the time, and it keeps things interesting.
I copy in Sketch. I find that CSS is a poor medium for visual thinking, and copywork is a visual exercise. Writing CSS, I get bogged down thinking about the proper way to position each little element — which is exactly the kind of thing to worry about if you want to be a good CSS coder, but a terrible distraction if you’re trying to improve your visual design skill.
No, but here’s some great advice from designer Sean McCabe about avoiding plagiarism:
Soak up all the inspiration you want.
Sleep on it.
Produce your new work from memory.
Incidentally, copying from memory, rather than from the original right in front of you, is a variant of copywork that makes you far less prone to exact reproduction. However, I’d recommend this exercise for more advanced copiers. Working blind, you’ll be making both the low-level and high-level decisions without guidance. If you’re trying to reproduce something above your level, there’s plenty to be learned from direct copying.
There is remarkable consensus among artists and creative folk that creativity is fundamentally about mixing together what already exists. Nothing is entirely original.
Immature poets imitate; mature poets steal; bad poets deface what they take, and good poets make it into something better, or at least something different. The good poet welds his theft into a whole of feeling which is unique, utterly different from that from which it was torn; the bad poet throws it into something which has no cohesion.
– T.S. Eliot
I wanted to hear music that had not yet happened, by putting together things that suggested a new thing which did not yet exist.
– Brian Eno
All writing is in fact cut-ups. A collage of words read heard overheard. What else?
– William S. Burroughs
Copywork enables you to pick up inspiration and remix it into your own style. A casual glance at a great new design would only reveal the surface level of technique and style, but with copywork, you can go deep and really expand your skills.
Unless you’re known the world over for your inimitable style, then yes, you would probably benefit from it.
That covers the most frequent questions I get about copywork. It’s a simple practice but one that pays dividends. If you consistently copy pieces that impress you or are above your level, then you’ll pick up a handful — if not dozens — of techniques and tactics that you can apply to whatever you are working on. The rest of the art world has been doing this for centuries; it’s time for designers to catch up.
So, the next time you want to expand your visual vocabulary, open up a great design (for starters, you can browse my Dribbble copywork bucket32 for inspiration), put on some good music, and start cranking out the pixels.