Jump to Navigation

Smashing Magazine

Syndicate content
Recent content in Articles on Smashing Magazine — For Web Designers And Developers
Updated: 59 min 9 sec ago

Privacy UX: Better Notifications And Permission Requests

5 hours 58 min ago
Privacy UX: Better Notifications And Permission Requests Privacy UX: Better Notifications And Permission Requests Vitaly Friedman 2019-04-18T17:00:49+02:00 2019-04-18T19:36:01+00:00

Imagine you are late for one of those meetings that you really don’t want to be late to. You hastily put on your shoes and your coat and fetch your door keys and grasp for the door handle — just to head out in time. As you are stepping down the stairs, you reach into your pocket and pull out your mobile phone to check the subway schedule or order a cab.

A brief glance at the screen is enough to have you breaking out in a sweat: you realize you’ve forgotten to charge your phone overnight, and it’s proudly running on its remaining 2% battery charge. As you rush down the street, full of hope and faith, you dim the brightness of the screen and hunt down the right app icon across the home screen. Of course, at that exact moment a slew of notifications cascades down your screen, asking for your undivided attention for new followers, updates, reminders, and messages.

Chances are high that you know way too well what this feels like. How likely are you to act on the cascading stack of notifications in that situation? And how likely are you turn off notifications altogether as another reminder reaches you a few minutes later, just when you missed your connection? That’s one of those situations when notifications are literally getting in a way in the most disruptive way possible, and despite all the thoroughly crafted user flows and polished, precious pixels.

With so many applications and services and people and machines and chatbots fighting for our attention, staying focused is a luxury that needs to be savored and protected, and so no wonder notifications don’t enjoy a decent reputation these days. More than that, often they feel off the point and manipulative, too.

“They often appear at times when they are least relevant, and they create a false sense of urgency, diluting focus and causing frustration.”

Alex Potrivaev, Intercom

This goes for floating windows on the home screen as much as the almighty unread count in toolbars. This is also true for marketing messages masked as notifications, as well as social updates broken down in many small messages to permanently draw attention to the service.

All of these notifications demand immediate attention and feel incredibly invasive, playing on our desires not to miss out and stay connected with our social groups. In fact, they disrupt privacy in a way that no dark patterns can — by demanding and seizing attention unconditionally, no matter what the user is currently doing.

Can you spot anything weird in this particular design? It’s not common to see the notification count '0', as it’s done on MassGenie in the top-right corner. (Large preview)

However, it’s not the fault of notifications that they feel invasive; it’s that we design them such that they often get in the way. Users don’t want to miss important notifications and miss out on timely messages or limited sales, but they don’t want to feel pestered by a never-ending tide of noisy updates either. If the latter happens too frequently, users turn off notifications altogether, often with a bitter aftertaste towards the app and brand due to its “desperate begging for attention”, as one user put it. A single culprit can ruin it for everybody else, and that despite the fact that no notification is like another.

The Many Faces Of Notifications

Notifications are distractions by nature; they bring a user’s attention to a (potentially) significant event they aren’t aware of or might want to be reminded of. As such, they can be very helpful and relevant, providing assistance, and bringing structure and order to the daily routine. Until they are not.

In general, notifications can be either informational (calendar reminders, delay notifications, election night results) or encourage action (approve payment, install an update, confirm a friend request). They can stream from various sources, and can have various impacts:

  • UI notifications appear as subtle cards in UIs as users interact with the web interface — as such, they are widely accepted and less invasive than some of their counterparts.
  • In-browser push notifications are more difficult to dismiss, and draw attention to themselves even if the user isn’t accessing the UI.
  • In-app notifications live within desktop and mobile apps, and can be as humble as UI notifications, but can take a more central role with messages pushed to the home screen or the notifications center.
  • OS notifications such as software updates or mobile carrier changes also get in the mix, often appearing together with a wide variety of notes, calendar updates, and everything in between.
  • Finally, notifications can find their way into email, SMS, and social messaging apps, coming from chatbots, recommendation systems, and actual humans.

You can see how notifications — given all their flavors and sources — could become overwhelming at some point. It’s not that we pay exactly the same amount of attention to every notification we receive, though. For the vast majority of users, it can take weeks until they eventually install a software update prompted by their OS notification, whereas it usually doesn’t take more than a few hours to confirm or decline a new LinkedIn or Facebook request.

Not every notification is equal, and the level of attention users grant them will depend on their nature, or, more specifically, how and when notifications are triggered.

In his article on “Critical Analysis of Notification Systems”, Shankar Balasubramanian has done remarkable research breaking down notification triggers into a few groups:

Event-triggered notifications News updates, recommendations, state changes OS-triggered notifications Low battery, software update, or an emergency alert Self-triggered notifications Reminders or alarms Many-to-one messaging notifications Group messages from Slack or WhatsApp One-to-one messaging notifications Personal email from a friend or a relative

We can’t deduce that one group of triggers is always more effective than another, but some notifications from every group tend to be much better at capturing attention than others:

  • People care more about new messages from close friends and relatives, notifications from selected colleagues during working hours, bank transactions and important alerts, calendar notifications, scheduled events, alarms, and any actionable and awaited confirmations or releases.
  • People care less about news updates, social feed updates, announcements, new features, crash reports, web notifications, informational and automated messages in general.

Unsurprisingly, users tend to attend to low battery notifications or payment confirmations immediately; also, calendar reminders, progress updates (e.g. package delivery ETA) and one-to-one messages matter more than other notifications. In fact, in every single conversation we’ve had with users, a message from another human being was valued much higher than any automated notification. The priorities might change slightly, of course, if a user is impatiently awaiting a notification, but only few people would ever leave everything behind in a desperate rush to check the 77th like on their photo.

So notifications can be different, and different notifications are perceived differently; however, the more personal, relevant, and timely notifications are, the higher engagement we should expect. But what does it all mean for the design of notifications, and how can we make them less intrusive and more efficient?

Don’t Rely On Generic Defaults: Set Up Notification Modes

There is usually a good reason why customers have chosen to sign up for a service. Not many people wake up in the morning hoping to create a new account that day. In fact, they might feel like your service might help them in their daily tasks, or could improve their workflow. Hopefully they don’t need notifications to understand how a service works, but they might need to receive notifications to understand the value the service provides.

Perhaps they’ve received an important message from a potential employer, or perhaps there is a dating profile match that’s worth looking at. They might not want to miss these messages just because they’ve forgotten to check into the service for a while. As designers, we need to sprinkle just the right pinch of notifications into the mix to keep the customer motivated, while delivering only relevant and actionable pointers to them.

Unfortunately, with most services it’s not uncommon to sign up, only to realize a few moments later that the inbox is filling up with all kinds of messages (mostly purely informational), often sent immediately after another, and rarely actionable. Email notifications especially are often switched on by default, with the user’s consent implied by agreeing to lengthy and unmanageable terms and conditions. Nobody loves being bombarded with a stream of unsolicited messages, and that holds true for spam emails as much as for unwanted notifications.

Instead of setting up a default notification frequency for all customers by default, we could start sending just a few curated notifications very infrequently. As the customer keeps using the interface, we could ask them to decide on the kind of notifications they’d prefer and their frequency. The same goes for cookie consent prompts: we could provide predefined recommended options with a “calm mode” (low frequency), a “regular mode” (medium frequency), and a “power-user mode” (high frequency).

We could be more granular even than this, though. Basecamp, for example, has introduced “Always On” and “Work Can Wait” options as a part of their onboarding experience, so new customers can select if they wish to receive notifications as they occur (at any time), or choose specific time ranges and days when notifications can be sent. Or, the other way around, we could ask users when they don’t want to be disturbed, and suspend notifications at that time. Not every customer wants to receive work-related notifications outside of business hours or on the weekend, even if their colleagues might be working extra hours on Saturday night on the other side of the planet.

On Basecamp, new customers can select if they wish to receive notifications as they occur, or choose specific time ranges and days when notifications can be sent. (Large preview)

As time passes, the format of notifications might need adjustments as well. Rather than having notifications sent one by one as events occur, users could choose a “summary mode,” with all notifications grouped into a single standalone message delivered at a particular time each day or every week.

That’s one of the settings that Slack provides when it comes to notifications; in fact, the system adapts the frequency of notifications over time, too. Initially, as Slack channels can be quite silent, the system sends notifications for every posted message. As activities become more frequent, Slack recommends reducing the notification level so the user will be notified only when they are actually mentioned.

Another feature Slack offers is allowing users to highlight a selection of words so that the users only get notified when a topic they care about has been mentioned:

With this feature, it’s still important to remain selective about your choice of highlighted words in order to avoid getting too many notifications. (Image source: Slack) (Large preview)

It might sound like the frequency of notifications is receiving too much attention at this point, but when asked about common pain points with notifications, the most common issue was, by far, their high frequency, even if the messages were relevant or actionable.

The bottom line is: start sending notifications slowly but steadily; set up notification modes, and provide granular options such as a choice of triggers and the format of notifications. Better send too little than too much: you might not get another chance should the customer wish to opt out from numerous notifications that are getting on their nerves at just the wrong time.

Pick Timing Carefully

We might not like to admit it, but for many of us, the day doesn’t start with a peaceful, mindful greeting of the rising sun; instead, it starts with a tedious, reflexive glance at the glowing screen of our mobile phones. More specifically, the first thing we see every morning isn’t even the current time or our loved ones, but the stack of notifications that piled up tirelessly while we slept.

That state of mind isn’t necessarily the best opportunity to remind users of an updated privacy policy, shiny new features, or outstanding expenses that need finalizing. Personal notifications like new social shares and reactions from social circles might be way more relevant, though, just like upcoming appointments and to-dos for the day.

Timing matters, and so do timely notifications. You probably don’t want to disturb your customers in the middle of the night as they arrive at a remote destination with heavy jet lag. Therefore, it’s a good idea to track the change of time zones and local time, and adjust the delivery of notifications accordingly. On the other side, customers won’t be particularly happy about an important notification appearing when it’s no longer relevant, so if they are tracking an important event or announcement, you’ll have to decide if the event is critical enough to disturb them at an uncomfortable time.

Your analytics will tell you when your users are likely to act on your notifications, so it’s a good idea to study and track responses based on time, and trigger the dispatch of notifications around that time. For example, if a customer is most receptive to sharing a message in the mornings, hold off notifications until just the right moment at the local morning time.

There are many ways to present a notification. Most common notifications are displayed within a designated area, usually in the right top corner of the screen. It is the format we are used to from apps such as Facebook, Airbnb or Dropbox. (Image source) (Large preview) Avoid Stressful Situations By Design

With notifications, timing is not the only important attribute to consider. Remember the poor character hoping to catch their connection from the beginning of this section? Unleashing a deck of notifications at a critically low battery level isn’t a good idea, and it’s just as counterproductive when the user is struggling with connectivity or is focused on a task like driving a car. If you can assess the battery level and the quality of connection, it’s a good idea to avoid sending notifications when a user’s conditions are suboptimal. Of course, notifications also have to be relevant, so if you can assess user’s location too, avoid sending location-dependent notifications that are not applicable at all.

Sometimes it’s difficult to hold notifications as they might be critical for the user’s current activity. If the user is driving a car, following directions in a navigator app, you might need to provide a more persistent and humble notification about the recommended change of route due to an accident on the road. In that case, just like other critical notifications, we could display a floating button “New updates available. Refresh.” It’s much less invasive than a notification blocking access to the content, but it’s as effective in indicating that the page or state of the page might be outdated and new information is available.

In fact, instead of sending out notifications at specific default times, even if it’s based on the user’s past behavior, you could explore the other side of the coin and tap into happy and successful moments instead. A money transfer service, TransferWise, displays notifications when the customer receives a payment — and isn’t that wonderful timing to ask for an app review on App Store? We could track important milestones and notify users about advanced features as they are reached, just-in-time, as Luke Wroblewski calls them.

Reduce Frequency By Grouping Notifications

There is no golden rule for just the right amount of notifications on a given day. Just like every notification differs, so do the preferences and motivations of every customer. To keep a user’s engagement, you might need to gradually release blocks of notifications depending on the customer’s reach or preferences. That’s where gradual grouping comes into place, as explained in the article “Designing Smart Notifications” by Alex Potrivaev, product designer at Intercom.

The idea is simple. If you know your customers get less than five reactions per post on average, it might be a good idea to provide a unique notification for each of them. You might also trigger a notification if a message is coming from important events, such as a message from close friends, family, or influential people. Besides, as we know that notifications triggered by an action from another human being are valued more than automated notifications, prioritize and focus primarily on personal ones, for that particular customer.

Once the volume of notifications has increased, we can start grouping them and provide compact summaries at an appropriate time. For example, Facebook summarizes notifications in non-intrusive blocks, with every line highlighting exactly one type of event, such as reactions to a particular message (“Stoyan Stefanov and 48 other people reacted to your post…”). LinkedIn, on the other hand, seems to trigger almost every single event one by one (“Stoyan Stefanov commented on your post”), hence polluting the stream of notifications and making them difficult to scan and use.

The quality of notifications matters. While Facebook provides a compact summary view of notifications, on Quora they are lengthy and verbose, making scanning difficult. (Image source: Designing Smart Notifications) (Large preview)

Of course, based on a user’s history, we could customize more than just grouping of notifications. Once we know how a user reacts to new photo likes, whether they briefly glance at them or dive deep into each and every notification, we can provide better notifications next time. As Alex concludes:

“Based on the way you usually interact with content, better wording and structure choices could be offered, and depending on the default behavior you may see notifications structured differently.”

This, of course, also requires continuous feedback loops.

Allow Users To Snooze Or Pause Notifications

Hardly any company will dismiss the value of data about their customers. In fact, we can gain valuable long-term insights by introducing feedback loops; that is, continuously offering customers options to “See more” or “See fewer” notifications of a particular kind. But just like we tend to perceive disability as an on/off condition (you either have a disability or don’t), we often feel that we can accurately predict the user’s behavior based on their past behavior alone.

The reality, however, is rarely black and white. Our users might be temporarily hindered while holding a baby in one arm, or because of a recent unfortunate accident, and the conditions in which they find themselves can fluctuate in the same way. Quick actions such as snoozing in response to an incoming notification can help alleviate the issue, albeit temporarily.

The user’s context changes continuously. If you notice an unusual drop in engagement rate, or if you’re anticipating an unusually high volume of notifications coming up (a birthday, wedding anniversary, or election night, perhaps), consider providing an option to mute, snooze, or pause notifications, perhaps for the next 24 hours.

This might go very much against our intuition, as we might want to re-engage the customer if they’ve gone silent all of a sudden, or we might want to maximize their engagement when important events are happening. However, pressing on with the frequency of notifications is just too dangerous most of the time. It’s easy to reach a point when a seemingly harmless notification will steer a customer away, potentially even in the long term. There might be good reasons why the user hasn’t been or doesn’t want to be active for a while, and more often than not, it has nothing to do with the service at all.

Another option would be to suggest a change of medium used to consume notifications. Users tend to associate different levels of urgency with different channels of communication. In-app notifications, push notifications, and text messages are considered to be much more intrusive than good ol’ email, so when frequency exceeds a certain threshold, you might want to nudge users towards a switch from push notifications to daily email summaries.

In the article “Designing Notifications For Apps”, Shashank Sahay explores different notification models and when to use which, e.g. notification center, with a few guidelines and recommendations along the way. (Large preview) Set Thresholds And Build Up A Notifications Decision Tree

The thresholds aren’t easy to set properly, though. Important events should trigger immediate notifications to be received in time. Less important events could wait, but it might be useful to draw the customer’s attention to the service. Potentially irrelevant notifications have to be filtered out relentlessly to leave time and space for important notifications to be cherished and valued.

In general, shorter notifications, such as messages from friends and colleagues, are best suited as UI notifications if they aren’t urgent, or push notifications if they are. Lengthier notifications are better off as emails — whether they’re urgent or not. This rule of thumb would vary from service to service, so you could build up a notifications decision tree to track which medium works best for particular kinds of notification based on their urgency, length, and frequency. Additionally, you could define thresholds and trigger a prompt for snoozing or adjusting the settings if a threshold is reached.

Make Opting In And Opting Out Obvious

These days it’s almost expected for a service to go to extremes in making it ridiculously difficult for a customer to opt out from almighty notifications. Obscure wording and obscure labels skillfully hidden in remote corners of the interface are not uncommon. Few other design considerations can be more harmful and damaging for a brand. When users can’t adjust settings easily, they apply heavy artillery, marking email notifications as spam, or blocking notifications in OS settings or browser settings. For a website or an app, there is no easy way to recover from that, except begging for subscriptions yet again.

A much simpler way out is to provide very granular control over notifications, including their content, format, frequency, and do-not-disturb times. We could provide an option to reply to a recent notification with “Fewer emails” or “Stop” to change the frequency, bypassing website log-ins or app sign-ins (Notion.so does that). For apps, provide notification preferences integrated into the app rather than relying on OS native settings. There, you could also explain what the user can expect from every kind of notification, perhaps even with examples of how they would look.

In practice, many users will search for notification settings in both places if they really need to, but the longer it takes them to find that nebulous setting, the less patient they’ll be. In reality, most users seek a way of turning off notifications at the moment when they are actually frustrated or annoyed by recent notifications. That’s not a pleasant state of mind to be in, and as a service, you probably don’t want to unnecessarily extend that state of mind at the expense of feeling nagged and confused by your paying customers.

Don’t forget to explore the other side of the coin as well, though. Identify parts of the user journey when a user is more likely to subscribe to notifications; for example, once an order in an online shop has been successfully placed, or a flight booking has been confirmed. In both cases, notifications can help customers track delays or retrieve boarding passes in time. That’s also a good time to suggest real-time push notifications, which also means first asking the customer’s permission to send those reminders. And that topic deserves a separate conversation.

Asking For Permission, The Humble Way

Some websites are quite a character, aren’t they? Self-indulgent, impolite at heart, and genuinely unlikeable too. How often do you stumble on a seemingly modest, unpretentious page just to be greeted with a wondrous permissions prompt begging to send you notifications? You haven’t read a single word yet, but there it is, already asking for a long-term commitment — and frankly, quite an invasive one.

In terms of user experience, displaying a permission prompt on load is probably the best way to make a poor first impression, and in most cases an irreversible mistake. Starting from January 2019, Chrome has changed the options displayed when a native prompt is triggered. While users might be able to dismiss a notification to react to it later, now they have to choose whether they’d like to either “Accept” or “Block” notifications. The latter results in web notifications being permanently blocked for the entire site, unless the user finds their way through the wilderness of browser settings to grant access after all. No wonder the vast majority of users block such prompts right away, without reading their contents at all.

Strategically, it’s better to ask permission only when there is a high chance a user would actually accept. For that to happen, we need to explain to the customer why we actually need their permission, and what value we can provide them in return. In practice, this strategy is often implemented in form of the ‘double request pattern.’ Instead of asking for permission immediately, we wait for a certain amount of engagement first: perhaps a couple of page visits, a few interactions, a certain amount of time spent on the site. Eventually, we can highlight the fact that a user could subscribe to notifications and how they might be valuable, or that we need their permission for more accurate, location-aware search results. Sometimes the context of the page is enough, like when an interface would like to ask for geolocation when the user visits the store locator page.

In all of these cases, a prominent call-to-action button would wait for the moment when a user is most receptive to act on it. If the user chooses to tap on the button, we can assume they are likely to proceed with the action. So, once clicked, the button would prompt an actual native permission request.

Essentially, we are breaking down the permission prompt into two requests:

  1. A request built into the UI,
  2. A native request at the browser level.

As Adam Lynch notes, should the user still revoke permission, perhaps due to a mis-tap or mis-click in the native browser prompt, we need to display a fallback page that explains how to manually enable the permission via their browser settings (or link to an explanation). Obviously, it doesn’t make sense to display a request for notifications if the user has already granted permission. We can use the Permissions API to query the status of any permission through a single asynchronous interface and adjust the UI accordingly.

The same strategy could be applied to any kind of permission request, such as access to geolocation, camera, microphone, Bluetooth, MIDI, WebUSB, and so on. The wording and appearance of UI notification prompts is of critical importance here, though, so it’s a good idea to track engagement and acceptance ratios for each permission or feature, and act on them accordingly. And that brings us to the king of them all — tracking major metrics for your notifications.

Track Metrics For Notifications

Usually notifications aren’t sent for the sheer purpose of informing customers about an occurring or upcoming event. Good notifications are useful and actionable, helping both customers and businesses achieve their goals. For that, relevant metrics have first to be discovered and defined.

As a bare minimum, we might need to know if the notifications we send are relevant in the first place.

  • Do the wording, format, and frequency of notifications drive the desired action that we aim to achieve (be it social shares, time spent on the site, or purchases)?
  • What kind of notifications matter more than others?
  • Do the notifications actually bring users back to the application?
  • How much time passes between sending the notification and the user’s return to the site or app?
  • How much time is spent on average between the clickthrough notification and the user leaving the site?
Track whether notifications actually work by exploring if they prompt a desired action, and if yes, when. (Image source: Designing Smart Notifications) (Large preview)

Experiment with wording, length, dispatch times, and grouping and frequency of notifications for different levels of user involvement — beginner, regular user, and power user. For example, users tend to be more receptive to conversational messages that feel more casual and less like system notifications. Mentioning the names of actual human beings whose actions triggered a notification might be useful as well.

It’s never a bad idea to start sending notifications slowly to track their potential negative impact as well — be it opt-outs or app uninstalls. By sending a group of notifications to a small group first, you still have a chance to “adjust or cancel any detrimental notification campaigns before it’s too late,” as Nick Babich remarks in “What Makes A Good Notification”.

All these efforts have the same goal in mind: avoiding significant disruption and preventing notifications fatigue for our customers, while informing them about what they want to know at about the time they need to know it. However, if cookie prompts are just annoying, and frequent notifications are merely a disturbance, when it comes to the security of personal data and how it’s managed, customers tend to have much more pressing concerns.

It’s worth noting that there are significant differences in how notifications are requested, grouped, and displayed on Android and iOS, so if you are designing a native or a hybrid app, you’ll need to examine them in detail. For example, on iOS, users don’t set up app notifications until onboarding or a later usage of the app, while Android users can opt-out from notifications during installation, with the default behavior being opt-in. Push notifications sent by a PWA will behave like native notifications on a respective OS.

Admittedly, these issues will not be raised immediately, but as customers keep using an interface and contribute more and more personal data, doubts and concerns start appearing more frequently, especially if more people from their social circles are involved. Some of these issues are easy refinements, but others are substantial and often underestimated blockers.

In the final article of the series, we’ll be looking into notifications UX and permission requests, and how we can design the experience around them better, with the user’s privacy in mind.

Useful Resources And References (yk, il)
Categories: Around The Web

Optimizing Performance With Resource Hints

Wed, 04/17/2019 - 6:30am
Optimizing Performance With Resource Hints Optimizing Performance With Resource Hints Drew McLellan 2019-04-17T12:30:16+02:00 2019-04-18T19:36:01+00:00

Modern web browsers use all sorts of techniques to help improve page load performance by guessing what the user may be likely to do next. The browser doesn’t know much about our site or application as a whole, though, and often the best insights about what a user may be likely to do come from us, the developer.

Take the example of paginated content, like a photo album. We know that if the user is looking at a photo in an album, the chance of them clicking the ‘next’ link to view the following image in the album is pretty high. The browser, however, doesn’t really know that of all the links on the page, that’s the one the user is most likely to click. To a browser, all those links carry equal weight.

What if the browser could somehow know where the user was going next and could fetch the next page ahead of time so that when the user clicks the link the page load is much, much faster? That’s in principal what Resource Hints are. They’re a way for the developer to tell the browser about what’s likely to happen in the future so that the browser can factor that into its choices for how it loads resources.

All these resource hints use the rel attribute of the <link> element that you’ll be familiar with finding in the <head> of your HTML documents. In this article we’ll take a look at the main types of Resource Hints and when and where we can use them in our pages. We’ll go from the small and subtle hints through to the big guns at the end.

DNS Prefetching

A DNS lookup is the process of turning a human-friendly domain name like example.com into the machine-friendly IP address like that is actually needed in order to fetch a resource.

Every time you type a URL in the browser address bar, follow a link in a page or even load a resource like an image from a different domain, the browser needs to do a DNS lookup to find the server that holds the resource we’ve requested. For a busy page with lots of external resources (like perhaps a news website with loads of ads and trackers), there might be dozens of DNS lookups required per page.

The browser caches the results of these lookups, but they can be slow. One performance optimization technique is to reduce the number of DNS lookups required by organizing resources onto fewer domains. When that’s not possible, you can warn the browser about the domains it’s going to need to look up with the dns-prefetch resource hint.

<link rel="dns-prefetch" href="https://images.example.com">

When the browser encounters this hint, it can start resolving the images.example.com domain name as soon as possible, even though it doesn’t know how it’ll be used yet. This enables the browser to get ahead of the game and do more work in parallel, decreasing the overall load time.

When Should I Use dns-prefetch?

Use dns-prefetch when your page uses resources from a different domain, to give the browser a head start. Browser support is really great, but if a browser doesn’t support it then no harm done — the prefetch just doesn’t happen.

Don’t prefetch any domains you’re not using, and if you find yourself wanting to prefetch a large number of domains you might be better to look at why all those domains are needed and if anything can be done to reduce the number.


One step on from DNS prefetching is preconnecting to a server. Establishing a connection to a server hosting a resource takes several steps:

  • DNS lookup (as we’ve just discussed);
  • TCP handshake A brief “conversation” between the browser and server to create the connection.
  • TLS negotiation on HTTPS sites This verifies that the certificate information is valid and correct for the connection.

This typically happens once per server and takes up valuable time — especially if the server is very distant from the browser and network latency is high. (This is where globally distributed CDNs really help!) In the same way that prefetching DNS can help the browser get ahead of the game before it sees what’s coming, pre-connecting to a server can make sure that when the browser gets to the part of the page where a resource is needed, the slow work of establishing the connection has already taken place and the line is open and ready to go.

<link rel="preconnect" href="https://scripts.example.com"> When Should I Use preconnect?

Again, browser support is strong and there’s no harm if a browser doesn’t support preconnecting — the result will be just as it was before. Consider using preconnect when you know for sure that you’re going to be accessing a resource and you want get ahead.

Be careful not to preconnect and then not use the connection, as this will both slow your page down and tie up a tiny amount of resource on the server you connect to too.

Prefetching The Next Page

The two hints we’ve looked at so far are primarily focussed on resources within the page being loaded. They might be useful to help the browser get ahead on images, scripts or fonts, for example. The next couple of hints are concerned more with navigation and predicting where the user might go after the page that’s currently being loaded.

The first of these is prefetching, and its link tag might look like this:

<link rel="prefetch" href="https://example.com/news/?page=2" as="document">

This tells the browser that it can go ahead and fetch a page in the background so that it’s ready to go when requested. There’s a bit of a gamble here because you have to preempt where you think the user will navigate next. Get it right, and the next page might appear to load really quickly. Get it wrong, and you’ve wasted time and resources in downloading something that isn’t going to be used. If the user is on a metered connection like a limited mobile phone plan, you might actually cost them real money.

When a prefetch takes place, the browser does the DNS lookup and makes the server connection we’ve seen in the previous two types of hint, but then goes a step further and actually requests and downloads the files. It stops at that point, however, and the files are not parsed or executed and they are in no way applied to the current page. They’re just requested and kept ready.

You might think of a prefetch as being a bit like adding a file to the browser’s cache. Instead of needing to go out to the server and download it when the user clicks the link, the file can be pulled out of memory and used much quicker.

The as Attribute

In the example above, you can see that we’re setting the as attribute to as="document". This is an optional attribute that tells that browser that what we’re fetching should be handled as a document (i.e. a web page). This enables the browser to set the same sort of request headers and security policies as if we’d just followed a link to a new page.

There are lots of possible values for the as attribute by enabling the browser to handle different types of prefetch in the appropriate way.

Value of as Type of resource audio Sound and music files video Video Track Video or audio WebVTT tracks script JavaScript files style CSS style sheets font Web fonts image Images fetch XHR and Fetch API requests worker Web workers embed Multimedia <embed> requests object Multimedia <object> requests document Web pages

The different values that can be used to specify resource types with the as attribute.

When Should I Use prefetch?

Again prefetch has great browser support. You should use it when you have a reasonable amount of certainty of the user might follow through your site if you believe that speeding up the navigation will positively impact the user experience. This should be weighed against the risk of wasting resources by possibly fetching a resource that isn’t then used.

Prerendering The Next Page

With prefetch, we’ve seen how the browser can download the files in the background ready to use, but also noted that nothing more was done with them at that point. Prerendering goes one step further and executes the files, doing pretty much all the work required to display the page except for actually displaying it.

This might include parsing the resource for any subresources such as JavaScript files and images and prefetching those as well.

<link rel="prerender" href="https://example.com/news/?page=2">

This really can make the following page load feel instantaneous, with the sort of snappy load performance you might see when hitting your browser’s back button. The gamble is even greater here, however, as you’re not only spending time requesting and downloading the files, but executing them along with any JavaScript and such. This could use up memory and CPU (and therefore battery) that the user won’t see the benefit for if they end up not requesting the page.

When Should I Use prerender?

Browser support for prerender is currently very restricted, with really only Chrome and old IE (not Edge) offering support for the option. This might limit its usefulness unless you happen to be specifically targeting Chrome. Again it’s a case of “no harm, no foul” as the user won’t see the benefit but it won’t cause any issues for them if not.

Putting Resource Hints To Use

We’ve already seen how resource hints can be used in the <head> of an HTML document using the <link> tag. That’s probably the most convenient way to do it, but you can also achieve the same with the Link: HTTP header.

For example, to prefetch with an HTTP header:

Link: <https://example.com/logo.png>; rel=prefetch; as=image;

You can also use JavaScript to dynamically apply resource hints, perhaps in response to use interaction. To use an example from the W3C spec document:

var hint = document.createElement("link"); hint.rel = "prefetch"; hint.as = "document"; hint.href = "/article/part3.html"; document.head.appendChild(hint);

This opens up some interesting possibilities, as it’s potentially easier to predict where the user might navigate next based on how they interact with the page.

Things To Note

We’ve looked at four progressively more aggressive ways of preloading resources, from the lightest touch of just resolving DNS through to rending a complete page ready to go in the background. It’s important to remember that these hints are just that; they’re hints of ways the browser could optimize performance. They’re not directives. The browser can take our suggestions and use its best judgement in deciding how to respond.

This might mean that on a busy or overstretched device, the browser doesn’t attempt to respond to the hints at all. If the browser knows it’s on a metered connection, it might prefetch DNS but not entire resources, for example. If memory is low, the browser might again decide that it’s not worth fetching the next page until the current one has been offloaded.

The reality is that on a desktop browser, the hints will likely all be followed as the developer suggests, but be aware that it’s up to the browser in every case.

The Importance Of Maintenance

If you’ve worked with the web for more than a couple of years, you’ll be familiar with the fact that if something on a page is unseen then it can often become neglected. Hidden metadata (such as page descriptions) is a good example of this. If the people looking after the site can’t readily see the data, then it can easily become neglected and drift out of date.

This is a real risk with resource hints. As the code is hidden away and goes pretty much undetected in use, it would be very easy for the page to change and any resource hints to go un-updated. The consequence of say, prefetching a page that you don’t use, means that the tools you’ve put in place to improve the performances of your site are then actively harming it. So having good procedures in place to key your resource hints up to date becomes really, really important.

Resources (il)
Categories: Around The Web

The User’s Perspective: Using Story Structure To Stand In Your User’s Shoes

Tue, 04/16/2019 - 10:00am
The User’s Perspective: Using Story Structure To Stand In Your User’s Shoes The User’s Perspective: Using Story Structure To Stand In Your User’s Shoes John Rhea 2019-04-16T16:00:16+02:00 2019-04-18T19:36:01+00:00

Every user interaction with your website is part of a story. The user—the hero—finds themselves on a journey through your website on the way to their goal. If you can see this journey from their perspective, you can better understand what they need at each step, and align your goals with theirs.

My first article on websites and story structure, Once Upon a Time: Using Story Structure for Better Engagement, goes into more depth on story structure (the frame around which we build the house of a story) and how it works. But here’s a quick refresher before we jump into implications:

The Hero’s Journey

Most stories follow a simple structure that Joseph Campbell in his seminal work, Hero with a Thousand Faces, called the Hero’s Journey. We’ll simplify it to a hybrid of the plot structure you learned in high school and the Hero’s Journey. We’ll then take that and apply it to how a user interacts with a website.

Once upon a time… a hero went on a journey. (Large preview) Ordinary World The ordinary world is where the user starts (their every day) before they’ve met your website. Inciting Incident/Call To Adventure Near the beginning of any story, something will happen to the hero that will push (or pull) them into the story (the inciting incident/call to adventure). It will give them a problem they need to resolve. Similarly, a user has a problem they need to be solved, and your website might be just the thing to solve it. Sometimes though, a hero would rather stay in their safe, ordinary world. It’s too much cognitive trouble for the user to check out a new site. But their problem — their call to adventure — will not be ignored. It will drive the user into interacting with your site. Preparation/Rising Action They’ve found your website and they think it might work to solve their problem, but they need to gather information and prepare to make a final decision. The Ordeal/Climax In stories, the ordeal is usually the fight with the big monster, but here it’s the fight to decide to use your site. Whether they love the video game news you cover or need the pen you sell or believe in the graphic design prowess of your agency, they have to make the choice to engage. The Road Back/Falling Action Having made the decision to engage, the road back is about moving forward with that purchase, regular reading, or requesting the quote. Resolution Where they apply your website to their problem and their problem is *mightily* solved! Return With Elixir The user returns to the ordinary world and tells everyone about their heroic journey. The User’s Perspective

Seeing the website from the user’s perspective is the most important part of this. The Hero’s Journey, as I use it, is a framework for better understanding your user and their state of mind during any given interaction on your site. If you understand where they are in their story, you can get a clearer picture of where and how you fit in (or don’t) to their story. Knowing where you are or how you can change your relationship to the user will make a world of difference in how you run your website, email campaigns, and any other interaction you have with them.

Numerous unsubscribes might not be a rejection of the product, but that you sent too many emails without enough value. Great testimonials that don’t drive engagement might be too vague or focused on how great you are, not what solutions you solve. A high bounce rate on your sign up page might be because you focused more on your goals and not enough on your users’ goals. Your greatest fans might not be talking about you to their friends, not because they don’t like you, but because you haven’t given them the opportunity for or incentivized the sharing. Let’s look at a few of these problems.

Plan For The Refusal Of The Call To Adventure

Often the hero doesn’t want to engage in the story or the user doesn’t want to expend the cognitive energy to look at another new site. But your user has come to your site because of their call to adventure—the problem that has pushed them to seek a solution—even if they don’t want to. If you can plan for a user’s initial rejection of you and your site, you’ll be ready to counteract it and mollify their concerns.

Follow up or reminder emails are one way to help the user engage. This is not a license to stuff your content down someone’s throat. But if we know that one or even seven user touches aren’t enough to draw someone in and engage them with your site, you can create two or eight or thirty-seven user touches.

Sometimes these touches need to happen outside of your website; you need to reach out to users rather than wait for them to come back to you. One important thing here, though, is not to send the same email thirty-seven times. The user already refused that first touch. The story’s hero rarely gets pulled into the story by the same thing that happens again, but rather the same bare facts looked at differently.

So vary your approach. Do email, social media, advertising, reward/referral programs, and so on. Or use the same medium with a different take on the same bare facts and/or new information that builds on the previous touches. Above all, though, ensure every touch has value. If it doesn’t, each additional touch will get more annoying and the user will reject your call forever.

Nick Stephenson is an author who tries to help other authors sell more books. He has a course called Your First 10K Readers and recently launched a campaign with the overall purpose of getting people to register for the course.

Before he opened registration, though, he sent a series of emails. The first was a thanks-for-signing-up-to-the-email-list-and-here’s-a-helpful-case-study email. He also said he would send you the first video in a three-part series in about five minutes. The second email came six minutes later and had a summary of what’s covered in the video and a link to the video itself. The next day he emailed with a personal story about his own struggles and a link to an article on why authors fail (something authors are very concerned about). Day 3 saw email number four… you know what? Let’s just make a chart.

Day Value/Purpose Email # 1 Case Study 1 1 Video 1 of 3 2 2 Personal Story and Why Authors Fail Article 3 3 Video 2 of 3 4 4 Honest discussion of his author revenue and a relevant podcast episode 5 5 Video 3 of 3 6 6 Testimonial Video 7 7 Registration Opens Tomorrow 8 8 Registration Info and a pitch on how working for yourself is awesome 9

By this point, he’s hooked a lot of users. They’ve had a week of high quality, free content related to their concerns. He’s paid it forward and now they can take it to the next level.

I’m sure some people unsubscribed, but I’m also sure a lot more people will be buying his course than with one or even two emails. He’s given you every opportunity to refuse the call and done eight different emails with resources in various formats to pull you back in and get you going on the journey.

I’ve Traveled This Road Before

It takes a lot less work to follow a path than to strike a new one. If you have testimonials, they can be signposts in the wilderness. While some of them can and should refer to the ordeal (things that might prevent a user from engaging with you), the majority of them should refer to how the product/website/thing will solve whatever problem the user set out to solve.

“This article was amazing!” says the author’s mother, or “I’m so proud of how he turned out… it was touch-and-go there for a while,” says the author’s father. While these are positive (mostly), they aren’t helpful. They tell you nothing about the article.

Testimonials should talk about the road traveled: “This article was awesome because it helped me see where we were going wrong, how to correct course, and how to blow our competitor out of the water,” says the author’s competitor. The testimonials can connect with the user where they are and show them how the story unfolded.

This testimonial for ChowNow talks about where they’ve been and why ChowNow worked better than their previous setup.

“I struggled with the same things you did, but this website helped me through.” (Large preview)

So often we hear a big promise in testimonials. “Five stars”, “best film of the year,” or “my son always does great.” But they don’t give us any idea of what it took to get where they are, that special world the testifier now lives in. And, even if that company isn’t selling a scam, your results will vary.

We want to trumpet our best clients, but we also want to ground those promises in unasterisked language. If we don’t, the user’s ordeal may be dealing with our broken promises, picking up the pieces and beginning their search all over again.

The Ordeal Is Not Their Goal

While you need to help users solve any problems preventing them from choosing you in their ordeal, the real goal is for them to have their problem solved. It’s easy to get these confused because your ordeal in your story is getting the user to buy in and engage with your site.

Your goal is for them to buy in/engage and your ordeal is getting them to do that. Their goal is having their problem solved and their ordeal is choosing you to solve that problem. If you conflate your goal and their goal then their problem won’t get solved and they won’t have a good experience with you.

This crops up whenever you push sales and profits over customer happiness. Andrew Mason, founder of Groupon, in his interview with Alex Bloomberg on the podcast “Without Fail”, discusses some of his regrets about his time at Groupon. The company started out with a one-deal-a-day email — something he felt was a core of the business. But under pressure to meet the growth numbers their investors wanted (their company goals), they tried things that weren’t in line with the customer’s goals.

Note: I have edited the below for length and clarity. The relevant section of the interview starts at about 29:10.

Alex: “There was one other part of this [resignation] letter that says, ‘my biggest regrets are the moments that I let a lack of data override my intuition on what’s best for our company’s customers.’ What did you mean by that?”

Andrew: “Groupon started out with these really tight principles about how the site was going to work and really being pro customer. As we expanded and as we went after growth at various points, people in the company would say, ‘hey why don’t we try running two deals a day? Why don’t we start sending two emails a day?’ And I think that sounds awful, like who wants that? Who wants to get two emails every single day from a company? And they'd be like, ‘Well sure, it sounds awful to you. But we’re a data driven company. Why don’t we let the data decide?’ ...And we’d do a test and it would show that maybe people would unsubscribe at a slightly higher rate but the increase in purchasing would more than make up for it. You'd get in a situation like: ‘OK, I guess we can do this. It doesn’t feel right, but it does seem like a rational decision.’ ...And of course the problem was when you’re in hypergrowth like [we were] ...you don’t have time to see what is going to happen to the data in the long term. The churn caught up with [us]. And people unsubscribed at higher rates and then before [we] knew it, the service had turned into… a vestige of what it once was.”

Without Fail, Groupon's Andrew Mason: Pt. 2, The Fall (Oct. 8, 2018) Tools For The Return With The Elixir

Your users have been on a journey. They’ve conquered their ordeal and done what you hoped they would, purchased your product, consumed your content or otherwise engaged with you. These are your favorite people. They’re about to go back to their ordinary world, to where they came from. Right here at this pivot is when you want to give them tools to tell how awesome their experience was. Give them the opportunity to leave a testimonial or review, offer a friends-and-family discount, or to share your content.

SunTrust allows electronic check deposit through their mobile app. For a long while, right after a deposit, they would ask you if you wanted to rate their app. That’s the best time to ask. The user has just put money in their account and are feeling the best they can while using the app.

“Money, money, money! Review us please?” (Large preview)

The only problem was is that they asked you after every deposit. So if you had twelve checks to put in after your birthday, they’d ask you every time. By the third check number, this was rage inducing and I’m certain they got negative reviews. They asked at the right time, but pestered rather than nudged and — harkening back to the refusal of the call section — they didn’t vary their approach or provide value with each user touch.

Note: Suntrust has since, thankfully, changed this behavior and no longer requests a rating after every deposit.

Whatever issue you’re trying to solve, the Hero’s Journey helps you see through your user’s eyes. You’ll better understand their triumphs and pain and be ready to take your user interactions to the next level.

So get out there, put on some user shoes, and make your users heroic!

(cc, il)
Categories: Around The Web

Design At Scale: One Year With Figma

Mon, 04/15/2019 - 7:30am
Design At Scale: One Year With Figma Design At Scale: One Year With Figma Paul Hanaoka 2019-04-15T13:30:48+02:00 2019-04-18T19:36:01+00:00

This article will be about how large teams can benefit from using more open, collaborative tooling and how to make adoption and migration feasible and pleasant. Also, in case you didn’t guess from the title of the article just yet, a lot of it will be about Figma and how we succeeded at adopting this design tool in our team.

The intended audience is experienced designers working in larger teams with design systems, developers or product managers looking to improve the way cross-functional teams work in their organization.

I’ve been using design tools in a professional setting for over ten years and am always trying to make teams I’m serving work more efficiently and more effectively. From scripting and actions in Photoshop, to widget libraries in Axure, to Sketch plugins, and now with Figma — I’ve helped design teams stay on the cutting edge without leaving developers or product managers behind.

The State of Design Tools 2015. (Large preview)

Basic knowledge of design systems and tools will be helpful, but not necessary as I hope to share specific examples and also “high level” concepts and methods that you can adapt for your team or context.

Our Design Workflow Circa 2015

Our primary tool in 2015 was Sketch, and that’s pretty much where the commonalities stopped. We all had different methods of prototyping, exporting, and sharing designs with stakeholders (InVision, Axure, Marvel, Google Slides, and even the antiquated Adobe PDF) and developers (Avocode, Zeplin, plugins without standalone apps like Measure). On rare occasions, we could send files directly to the engineers who were lucky enough to have the rare combination of a MacBook and a Sketch license.

When InVision released the Craft plugin, we were overjoyed — being able to prototype and upload screens from Sketch into InVision, sharing components and styles in nascent libraries across files — it was the designer’s dream come true.

A peek into our InVision projects. (Large preview)

Eventually, we all converged on the InVision platform. We created and documented the processes that helped reduce much of the friction in stakeholder collaboration and developer handoff. Yet, due to the complex permissions structure, InVision remained a closed ecosystem — if you weren’t a designer, there was an approval chain that made it difficult to get an InVision account, and once you got an account, you had to be added to the right groups.

Manually managing versions and files, storing and organizing them in a shared drive, and dealing with sync conflicts were just a few of the things that caused us many headaches.

Getting Started in Figma. (Large preview)

Could we really have an all-in-one tool that had all the best features of Sketch and InVision, with the real-time collaboration and communication features found in Google Docs? In addition to reducing overhead from context switching, we could also potentially simplify from three tool subscriptions (for mockups, prototyping, and developer handoff), to only one.

The Process

The first designers from our team to adopt Figma started experimenting with it when the first Figma beta was released in 2016. The features were limited but covered 80% of what we needed. Sketch import was buggy, but we still found immense value in being able to collaborate in real-time and most importantly, we could do 90% of the design work for a project inside a single tool. Stakeholder feedback, revisions, and developer handoff improved exponentially.

By 2017, we had a few designers using it for most of their work, and one of the Lexicon designers (Liferay’s design system), Emiliano Cicero, was quickly becoming an evangelist — which turned out to be a key factor in convincing the rest of the team to make the switch.

When Figma 2.0 debuted in the summer of 2017 with prototyping features added and huge improvements to the developer handoff capabilities, we knew this could be a viable tool for our global team. But how do you convince 20+ designers to abandon tools and workflows they love and have used comfortably for years?

I could write a series on that subject, but I’ll summarize by saying the two biggest things were: starting small, and creating a solid infrastructure.

Starting Small

In the fall of 2017, we started our first trial of Figma with a product team distributed between the United States and Brazil. We were fortunate to have a week-long kickoff together in our Los Angeles office. Designing flows and wireframes together in Figma was so much faster and more efficient. We were able to divide up tasks and share files and components without having to worry about constantly syncing a folder or a library.

At our global gathering in January 2018, we formulated a plan to slowly adopt Figma, using this team’s experiences to help form the infrastructure we’d need for the rest of the organization so that migration would be as seamless as possible.

The biggest challenge we faced was a tight deadline — it didn’t make any sense for us to rework our review and handoff process due to the scale of the project with multiple engineering teams and product managers distributed around the world. Even though the end result would have been better, the timing wasn’t right. Another factor was Figma’s lack of a reliable offline design experience (more on that later), and for these reasons, the team decided to use Sketch and Figma for wireframes and mockups, but any prototyping or review had to be done in InVision.

A DAM presentation from Design Week 2018. (Large preview) Creating a solid Figma structure

One of the first steps was formulating rough guidelines for the project, file, and component organization. The foundation for these things was started by two junior (at the time) designers, Abel Hancock and Naoki Hisamoto, who never developed the bad layer-naming habits that seem to come from designers who cut their teeth in Photoshop. This method for organization, coupled with a year spent developing a small library of components for Liferay.com properties, was critical to setting the rest of the global team up for success.

An early organizational improvement created by one of our Liferay.com designers, inspired by Ben’s tweet, was our system of covers.

Figma project covers, by Abel Hancock. (Large preview)

We’ve made this file available if you’d like to copy it, otherwise it’s a pretty straightforward hack:

  1. Create a single frame in the first page of your file that’s 620×320.
  2. Add your design. If you have text, we found that the minimum size is ~24, the titles in our examples are set at 48.
  3. Enjoy!

Note: There will always be a slight margin around your cover, but if you set the page canvas the same color as the card, it will reduce the appearance of this margin.

This helped transform our library, not just for designers, but for project and product managers and engineers who are trying to find things quickly. The search functionality was already really good, but the covers helped people narrow things down even faster, plus it allowed us to instantly communicate the status of any given file.

Sparking Joy with Figma Covers (Large preview)

Prior to using Figma, in addition to a ‘Master’ design system Sketch file, most designers had base files they had developed over time with things like wireframing elements and basic components. As we coalesced into a single pattern, we started to combine everything and refined them into a single library. Since we were doing wireframes, mockups, and prototypes in Figma, we also started to abandon flow apps like Lucidchart, instead of making our own task flow components in Figma.

Other utilities that we developed over time were redline components for making precise handoff specs, sticky notes for affinity diagrams (and just about anything), and flow nodes.

Liferay Design’s redline, flow, and affinity components. (Large preview)

One of the biggest benefits of doing this in Figma, was that improvements to any of these components that any designer made could easily be pulled into the library and then pushed out to all instances. Having this in a centralized place also makes maintenance a lot easier, as anyone on the team can contribute to improvements with a relatively simple process.

A redline document is for making it easier for the developer to know the dimensions, visual specs, and other properties of a UI component or a set of components. If you’re interested in the topic, you can also check Dmitriy Fabrikant’s article about design blueprints.

Some recommendations to keep in mind when creating components:

  1. Use of overrides and masters for powerful base components (more on that here);
  2. Establish a consistent pattern for naming (we use the atomic model);
  3. Document and label everything — especially layers.

With the advanced styling features released at the beginning of June 2017, the systems team finished a complete version of our Lexicon library in between our big product releases in July and the ramp-up in August. This was the final piece we needed to support the global team. Designers working in Marketing and other departments had already been using Figma for some time, but by last Fall almost all of the other product teams had finalized the move over to Figma.

As of today, most of the product designers are only using Figma, there are also a couple of designers that are working in legacy systems with lots of existing, complicated Sketch prototypes that aren’t worth importing to Figma. Another exception is a few designers that occasionally use apps like Principle or Adobe After Effects for more advanced animation that wouldn’t make sense to do in Figma. We even have a few designers exploring Framer X for even more robust prototypes, especially with work that requires leveraging any kind of data at scale. While there are some designers using multiple tools on a semi-regular basis, 80% of our product designers are using Figma for all of their design and prototyping work.

Continuous Improvements

We’re always working on ways to work more effectively, and one of the current things we’re iterating is best practices for naming pages. At first, we named pages according to the page name, but that proved problematic, plus, as we improved our libraries, the need for larger files with multiple pages was reduced.

Currently, we’re using a numbering system within files, with the top-most page being what’s delivered to the developers. The next phase we’re discussing nowadays is making the versions more meaningful with explicit labels (wireframes, mockups, breakpoints, etc.) and making better use of Figma’s built-in versioning, establishing best practices for when and how to save versions.

The evolution of page organization within a Figma file. (Large preview) Final_Final_Last_2 — No More!

I generally hate to use the term ‘game-changer’, but when Figma released naming/annotating to the version history last March, it dramatically changed the way we organized our files. Previously, we all had different ways of saving iterations and versions.

Usually we would create new pages within a single file, sometimes with large files we would duplicate them and add a letter at the end of the filename to signal an iteration. If you were going to make drastic changes, then you might create a new file and append a version number. This was very natural, coming from the Photoshop/Sketch paradigm of managing multiple files for everything.

Version history timeline view (Large preview)

The ability to work, periodically pausing to name and annotate a point in time will be very familiar for anyone who has used a version control like Git before. You can even look at the whole file history, and go into past snapshots, pick one out and name and annotate it.

If you want to go back and revert to a past version, you can restore it and work on that file from that point in the history. The best part is that you didn’t lose any of the work because the version you ‘restored’ wasn’t deleting anything; it was simply copying that state and pasting it at the top.

Git it? (Large preview)

In this illustration, the designer arrives at final 3.0 after restoring final 1.1, but the file version history is still completely visible and accessible.

In cases where you’re starting a new project, or want to make some really dramatic changes to the file, it can be necessary for you to ‘fork’ the file. Figma allows you to duplicate a file at any given point in the history, but it’s important to note that the file history will not be copied.

We’ve found that a good way to work in this versioned system is to use your file history in a similar way to how a developer uses git — think of a Figma version as a commit or pull-request, and name and annotate them as such. For more, smarter thoughts on this, I recommend Seth Robertson’s Commit Often, Perfect Later, Publish Once: Git Best Practices — this is a good general philosophy for how to work in a version-controlled ecosystem. Also, Chris Beams’s How to Write a Git Commit Message is a great guide to writing meaningful and useful notes as you work.

Some practical tips we’ve discovered:

  1. Keep titles to 25 characters or less.
    Longer titles are clipped and you have to double-click on the note in the version history to open up the ‘Edit Version Information’ modal to read it.
  2. Keep your description to 140 characters or less.
    The full description is always shown, so keeping it to the point helps keep the history readable.
  3. Use the imperative mood for the title.
    This gives the future you a clearer idea of what will happen when you click on that point in time, e.g. “changing button colors to blue” vs. “change buttons to blue.”
  4. Use the description to explain ‘what’ and ‘why’ versus ‘how’.
    Answering the ‘why’ is a critical part of any designers job, so this helps you focus on what’s important as you’re working as well as provide better information for you in the future.
Working Offline

Disclaimer: This is based on our own experience, and a lot of it is our best guess as to how it works.

As I mentioned before, offline support in Figma is tenuous. If you already have a file open before going offline, you can continue working on the file. It seems like each change you make is timestamped. In the case of someone else working on the same file while you were offline, then the latest change will be the one rendered once you do come back online.

When Cat came back online, her button position change was made, and merged with the Nerd’s color changes. (Large preview)

In this simple example, it doesn’t seem like too big of a deal — but in real life, this can get really messy, really fast. In addition to the high possibility of someone overriding your work, frames and groups could get stacked on top of one another.

Our workflow is to duplicate the page before (or after) going offline, and then do your work in that copy. That way it will be untouched when you come back online, and you can do any necessary merges manually.

“F” Is For Future

Adopting a new tool is never easy, but in the end, the benefits may far outweigh the costs.

The biggest areas of improvement our team has experienced are:

  • Collaboration
    It’s much easier to share our work and improvements with the team and community.
  • Transparency
    A system that is open by default is naturally more inclusive to people outside of the field of design.
  • Evolution
    Removing the “layers” between designers and engineers, enabling us to take the next step in design maturity.
  • Operations
    Adopting a single tool for wireframes, mockups, prototypes, and developer handoffs makes life easier for accounting, IT, and management.

Reducing the overall number of subscriptions was really helpful for our team, but as costs can vary from ‘free’ to over $500 per year this might not make sense for your specific context and needs. For a full breakdown, see Figma’s pricing page.

Grow And Get Better

Of course, no tool is perfect, and there’s always room for improvements. Some things that were missing from previous tools we used are:

  1. No plugin ecosystem.
    Sketch’s extensibility was a huge factor in making the switch from Photoshop a no-brainer. Figma does have a web API, but currently, there is no ‘write’ functionality. For now, Sketch remains the market leader with its vibrant community of extensions and plugins. (Of course, things might change in the future in case Figma opens the stage for plugin development as well.)
  2. Importing web, or JSON data in prototypes.
    It would be a lot easier for us to design with real data. Sketch recently introduced a “Data” feature in v.52, InVision’s Craft plugin is still very much the gold standard when it comes to easily addxing large amounts of different data — and for now, we’re stuck manually populating text fields.
  3. More motion.
    The Principle integration is nice (if you have Principle), but having basic animation and advanced prototyping features in Figma would be a lot better.
  4. A smoother offline experience
    As mentioned previously, as long as you have the Figma file open before going offline, you’re fine. This is probably OK for most people — but if you like to shut down your computer every night, it can be painful when you open it in the morning on a train or airplane and realize you forgot to leave Figma open.
Open-Source Design

A few months ago, the always controversial Dann Petty recently tweeted about developers having GitHub, photographers having Unsplash — but designers not having a platform for sharing things for free. Design Twitter™️ swooped in and he deleted his tweet before I could get a screengrab, but one thing I’d like to mention is that what we’re very passionate about at Liferay, is open source. To that end, we’ve created a Figma project for resources to share with the design community.

Open sourced files from Liferay.Design. (Large preview)

To access any of these files, check out liferay.design/resources/figma, and stay tuned as we grow and share more!

Further Reading Other Resources (mb, yk, il)
Categories: Around The Web

Monthly Web Development Update 4/2019: Design Ethics And Clarity Over Style

Fri, 04/12/2019 - 8:44am
Monthly Web Development Update 4/2019: Design Ethics And Clarity Over Style Monthly Web Development Update 4/2019: Design Ethics And Clarity Over Style Anselm Hannemann 2019-04-12T14:44:48+02:00 2019-04-18T19:36:01+00:00

‘Ethics’ and Ethics” is more than a typical article. It’s a detailed essay exploring what the term ‘ethics’ really means, how its meaning changed in recent times, and how diffusion of responsibility makes it hard to address and fix problems in big organizations.

Implementing design ethics, tech ethics, or business ethics as individual responsibilities might seem like a quick and easy solution, however, it’s not a very effective one as they all lack context when they don’t have support from other people who provide the foundation for their work. Only if a company’s business analysts, bookkeepers, investors, PR, marketing and sales people, as well as the CEO themself all contribute to building an ethical product, it will become successful. And because such an undertaking requires so many people to be on board, it’s rarely seen out in the wild.

How much effort and good will it takes to build a company that follows an ethical approach, is illustrated in the book It doesn’t have to be crazy at work by Basecamp’s Jason Fried and David Heinemeier Hansson. It helps us understand why it’s so much easier to build a non-ethical company and why even if a couple of people in a team strive for better ethics, the product or company won’t reflect this individual path yet. To help us do better, Oliver Reichenstein, the author of the article which I mentioned in the beginning, also shares a very interesting approach: designers might want to start to consider philosophy to encourage ethical thinking and advocate for values and ethics in their everyday work.

  • We heard the announcement some months ago, and now the first builds are out: Microsoft’s new Chromium-based Edge browser is here. So what does that mean for front-end developers?
  • Safari 12.1 is included in macOS Mojave 10.14.4 and iOS 12.2 and with it, all users get Dark Mode for the Web, Intelligent Tracking Prevention 2.1, Payment Request API improvements, WebRTC improvements, Intersection Observer support, Web Share API, color input, and <datalist> support.
  • Firefox 66 has been released. From now on, autoplaying sounds will be blocked by default, and the Touch Bar on macOS is supported, too.
  • Humane by Design is an essential resource about focusing your design decisions on user well-being. It provides ideas and helpful resources about transparency, empowering people, fostering inclusiveness, showing respect, and making thoughtful decisions. A valuable website for any project or product you are in charge of or work on.
  • What does it look like when you try to use a browser just ten years old today? The browser’s start page returns a 404 error, Google works but returns a no-script version — not deliberately but because JavaScript errors out —, YouTube doesn’t work without even showing an error, and creating accounts at any of the big services isn’t a pleasant experience at all. This article is not only enlightening but also reveals a lot of details we can take care of to make our web projects more sustainable and available for more people, regardless of which browser they use.
UI/UX When designing a product, there are quite some pitfalls that can make a simple task overly complicated. Taras Bakusevych summarized what you need to watch out for. (Image credit) Web Performance
  • Chrome 73 now supports imagesrcset and imagesizes attributes on link rel=preload elements.
  • Spectral is a flexible open-source JSON linter with out-of-the-box support for the OpenAPI specification and, as such, promotes consistency in API designs.
  • This article explains why all your Alexa traffic is analyzed and probably listened to by someone who works on the product software to help the voice-activated assistant respond to commands.
JavaScript JavaScript can be a performance liability and, thus, we need to use it responsibly. Jeremy Wagner shares tips for doing so. (Image credit) Work & Life Going Beyond…
  • It’s impossible to reach everyone, even for giants like Google or Facebook. Seth Godin on why reaching almost no one is fine if you ask yourself which no one. Your smallest viable audience holds you to account. It forces a focus and gives you nowhere to hide.
  • Google Maps is one of the products most of us use daily. And yet it’s the one product by Google that doesn’t make money — yet. As it seems, its makers are now trying to include ads into Maps to bring more profits to Alphabet.
  • George Monbiot wrote an article on “how the media let malicious idiots take over”. To make it clearer, let me quote the following paragraph: “If our politics is becoming less rational, crueller and more divisive, this rule of public life is partly to blame: the more disgracefully you behave, the bigger the platform the media will give you. If you are caught lying, cheating, boasting or behaving like an idiot, you’ll be flooded with invitations to appear on current affairs programmes. If you play straight, don’t expect the phone to ring.”
  • Mallen Baker explains why the environment is too important to leave to environmentalists and what we can do to make our lives worth living and create a surrounding that works for humans.
  • It’s hard to believe in theory, but in practice, it’s very easy to make unethical choices, deliberately. This article asks what drives people to make unethical choices. Sticking to your own ethical beliefs is hard when society is embracing something different — at least that’s what we tend to see from the filtered media and social media bubble. However, if we talk to people directly, I think it’s different. Many people share the same ethical beliefs and would condemn unethical behavior if it would be transparent and public. The private/unseen is what makes it easier for people to go beyond their values, supercharged by the allurement of money or getting a higher status and reputation in society.
Categories: Around The Web

Art Direction For The Web Using CSS Shapes

Thu, 04/11/2019 - 7:30am
Art Direction For The Web Using CSS Shapes Art Direction For The Web Using CSS Shapes Andrew Clarke 2019-04-11T13:30:16+02:00 2019-04-18T19:36:01+00:00

Last year, Rachel Andrew wrote an article that took a new look at CSS Shapes in which she reintroduced readers to the basics of using CSS Shapes. For anyone keen to understand how to use properties like shape-outside, shape-margin, and shape-image-threshold, Rachel’s is the ideal primer.

I’ve seen many examples of using the properties, but very few go beyond Basic Shapes, including circle(), ellipse(), inset(). Even examples using polygon() shapes rarely go far beyond them. Considering the creative opportunities CSS Shapes offer, this is disappointing. But, I’m sure that with a little inspiration and imagination, we can make more distinctive and engaging designs. So, I’m going to show you how to use CSS Shapes to create the following five different types of layout:

  1. V-shapes
  2. Z-patterns
  3. Curved shapes
  4. Diagonal shapes
  5. Rotated shapes
A Little Inspiration

Sadly, you won’t find many inspiring examples of websites which use CSS Shapes. That doesn’t mean that inspiration isn’t out there — you just have to look a little further afield at advertising, magazine, and poster design. However, it would be foolish for us to merely mimic work from a previous era and medium.

You can find inspiration in surprising places, such as these vintage advertisements.

For the past few years, I’ve filled Dropbox folders with inspiration and I really ought to move those examples to Pinterest. Fortunately, Kristopher Van Sant has been more diligent than me in compiling a Pinterest board full of inspiring ‘Shapes Of Text’ examples.

Shapes add energy to design, and this movement draws people in. They help to connect an audience with your story and make tighter connections between your visual and written content.

When you need content to flow around a shape, use the shape-outside property. You must float an element left or right for shape-outside to have any effect.

img { float: <values>; shape-outside: <values>; }

NB: When you flow content around shapes, be careful not to allow any lines of text to become too narrow and fit only one or two words.

It often needs surprisingly little markup to develop dynamic and original layouts. My HTML for this series of five designs consists only of a header and main elements, figures, and images, and is often no more complicated than this:

<header role="banner"> <h1>Mini Cooper</h1> </header> <figure> <img src="mini.png" alt="Mini Cooper"> </figure> <main> … </main> 1. V-Shapes

For me, one of the most incredible aspects of modern-day CSS is that I can create a shape from the alpha channel of a partially transparent image with no need to draw a polygon path. I only need to create an image, and then a browser will take care of the rest.

I think this is one of the most exciting additions to CSS and it makes developing art direction for the web more straightforward, especially if you work with a content management system and dynamically generated content.

Left: Without CSS Shapes, this design feels dull and lifeless. Right: Creating v-shapes makes this design more distinctive and engaging.

To develop shapes from images, they must have an alpha channel which is either entirely or partially transparent. I needn’t draw a polygon to enable content to flow between the triangular shapes either side of my content in this first design; instead, I need only specify the URL of an image file as the shape-outside value:

[src*="shape-left"], [src*="shape-right"] { width: 50%; height: 100%; } [src*="shape-left"] { float: left; shape-outside: url('alpha-left.png'); } [src*="shape-right"] { float: right; shape-outside: url('alpha-right.png'); } Watch out for CORS (cross-origin resource sharing) when using images to develop your shapes. You must host images on the same domain as your product or website. If you use a CDN, make sure it sends the correct headers to enable shapes. It’s also worth noting that the only way to test shapes locally is to use a web server. The file:// protocol simply won’t work. Generated Content

As Rachel explained in her article:

“You could also use an image as the path for the shape to create a curved text effect without also including the image on the page. You still need something to float, however, and so for this, we can use Generated Content.”

As an alternative to alpha channel, I can use Generated Content — applied to two pseudo-elements — one for a polygon triangle on the left, the other for the right. My running text will now flow between the two generated shapes:

main::before { content: ""; display: block; float: left; width: 50%; height: 100%; shape-outside: polygon(0 0, 0 100%, 100% 100%); } main p:first-child::before { content: ""; display: block; float: right; width: 50%; height: 100%; shape-outside: polygon(100% 0, 0 100%, 100% 100%); }

NB: Bennett Feely’s CSS clip-path maker is a fabulous tool for working out coordinate values for use with CSS Shapes.

Adjusting the width of alpha images at several breakpoints allows the shape of this running text to best suit its viewport. 2. Z-Patterns

A Z-pattern is a familiar path our eyes follow when reading content from left–right, top–bottom. By placing content along the hidden lines which form a Z, these patterns help guide a reader along this path, from where we’d like them to start reading towards a destination such as a call-to-action. Z-patterns can be either discreet — implied by focal points or elements with higher visual weight — or made obvious using CSS Shapes.

The z-pattern created by driving a narrow column of running text between two shapes suggests speed and the fun people will have when driving this iconic little car.

In this next design, a discreet z-pattern is formed as:

  1. The large image spans the full page width, the end-point emphasised with a right aligned headline.
  2. A block of running text is formed by two CSS Shapes.
  3. The thick top border on a figure acting as a footer completes the Z.

There’s no need for complicated markup to implement this design and my simple HTML includes just three elements:

<header role="banner"> <h1>Mini Cooper:icon of the ’60s</h1> <img src="banner.png" alt="Mini Cooper"> </header> <main> <img src="placeholder-left.png" alt="" aria-hidden="true"> <img src="placeholder-right.png" alt="" aria-hidden="true"> … </main> <figure role="contentinfo"> … </figure>

My page-width spanning header and figure needs no explanation, but flowing text between two triangular shapes is a little more complicated. To implement this z-pattern design, I choose to include two tiny 1×1px placeholder images onto which I apply two larger, shape-forming images using shape-outside. By attaching an aria-hidden attribute to these images, a screen reader won’t describe them.

After giving the two shape images the same dimensions, I float one image left and the other to the right, which allows my running text to run between them:

[src*="placeholder-left"], [src*="placeholder-right"] { display: block; width: 240px; height: 100%; } [src*="placeholder-left"] { float: left; shape-outside: url('shape-right.png'); } [src*="placeholder-right"] { float: right; shape-outside: url('shape-right.png'); } Left: A presentable but predictable design which lacks energy. Right: CSS Shapes suggest fun and speed.

The iconic Mini Cooper was fast and fun to drive. While my design would be perfectly presentable without a z-pattern formed by CSS Shapes, this layout looks predictable and lacks energy. The z-pattern created by driving a narrow column of running text between two shapes suggests speed and the fun people will have when driving this iconic little car.

3. Curved Shapes

One of the most fascinating aspects of CSS Shapes is how I can create elegant shapes using the alpha channel from a partially transparent image. This shape can be anything I imagine. I only need to create the image, and a browser will flow content around it.

While confining content to within a shape has been proposed in the CSS Shapes Module Level 2 specification, there’s currently no way to know if and when this might be implemented in browsers. But while shape-inside isn’t available (yet!), that doesn’t mean I can’t create similar results using shape-outside.

Left: Another presentable, but predictable design. Right: A more distinctive look created by using CSS Shapes.

By confining my content within a curved image floated right, I can easily add a distinctive look to this next design. To create the shape, I again use the shape-outside property, this time with the value being the same URL as my visible image:

[src*="curve"] { float: right; width: 400px; height: 100vh; shape-outside: url('curve.png'); }

To put some distance between my shape and the content flowing around it, the shape-margin property draws a further shape outside the contours of the first one. I can use any CSS absolute length unit — millimeters, centimeters, inches, picas, pixels, and points — or relative units (ch, em, ex, rem, vh, and vw):

[src*="curve"] { shape-margin: 3rem; } More Margins

Adding movement to this curved design relies on more than CSS Shapes. Using viewport width units, I give my headline, image, and running text a different left margin, each one proportional to the width of the viewport. This creates a diagonal from the back of my headline to the front of the car:

h1 { margin-left: 5vw; } img { margin-left: 10vw; } p { margin-left: 20vw; } 4. Diagonal Shapes

Angles can help make layouts look less structured and feel more organic. The absence of clear structure encourages the eye to roam freely around a composition. This movement also causes an arrangement to feel energetic.

I see designs set around horizontal and vertical axes every day, but rarely anything based on a diagonal. Every once in a while, I spot an angled element — perhaps a banner graphic with its bottom sloping — but it’s rarely essential to a design.

It’s common to see content flowing around shapes in print design, but this was impossible to achieve on the web before CSS Shapes.

Even though CSS Grid involves setting columns and rows, there’s no reason why it can’t be used to create dynamic diagonals. This next design needs just a header and main element:

<header role="banner"> <h1>Mini Cooper</h1> <img src="banner.png" alt="Mini Cooper"> </header> <main> <img src="shape.png" alt=""> … </main>

To create the diagonal detail in this design, I again flow content around a shape image which itself is floated left. Again I use the shape-outside property with the same URL value as my visible image and a shape-margin to put distance between my shape and the content flowing around it:

[src*="shape"] { float: left; shape-outside: url('shape.png'); shape-margin: 3rem; }

Given that responsiveness is one of the web’s intrinsic properties, we can rarely predict how content will flow, but we avoid designs like this one. When there’s too little space for all my running text to fit above the shape, the fact that each shape is floated means that content will flow into space below the shape.

5. Rotated Shapes

Why settle for just using CSS Grid and Shapes when adding Transforms to the mix can enable layouts which were unimaginable only a few years ago? In this final example, flowing text around the cars in this image, while at the same time rotating the entire composition needed a combination of all those properties.

Why settle for using only CSS Grid and Shapes?

As the image of these cars has no transparent alpha channel, flowing text around the shapes, it contains needs a second image which includes only alpha channel information.

Implementing this design requires two images; one visible, the other proving alpha channel information.

This time, I float the visible image right and apply the shape-outside property with a URL value which matches my alpha channel image:

[src*="shape"] { float: right; width: 50%; shape-outside: url('alpha.png'); shape-margin: 1rem; }

You may have noticed that both my images contain elements which I rotated clockwise by ten degrees. With those images in place, I can rotate the entire layout ten degrees in the opposite direction to give the illusion that my images are upright:

body { transform: rotate(-10deg); } I rotate this layout just enough to make the design more appealing, without sacrificing readability. Bonus Example: Polygon Shapes Sculpt Columns

An extract from ‘Art Direction for the Web’ available from 26th March 2019.

You can create strong, structural shapes with nothing more than type. Combining polygon() shapes and pseudo-elements, you can sculpt shapes from solid blocks of running text, in the style of Alexey Brodovitch and his influential work for Harper’s Bazaar.

Left: These beautiful numerals are almost too lovely to hide. They’re also perfect for carving into those columns. Right: When I use invisible pseudo-elements with no background or borders to develop polygon shapes, the result is two unusually shaped columns.

I formed these columns from two article elements, i.e. with a gutter between them and a maximum width, which help maintain a comfortable measure:

body { display: grid; grid-template-columns: 1fr 1fr; grid-gap: 2vw; max-width: 48em; }

Because there are two article elements and I also specified two columns for my grid, there’s no need to be specific about the position of those articles. I can let a browser place them for me, and all that remains for me is to apply shape-outside to a generated pseudo-element in each column:

article:nth-of-type(1) p:nth-of-type(1)::before { content: ""; float: left; width: 160px; height: 320px; shape-outside: polygon(0px 0px, 90px 0px, [...]); } article:nth-of-type(2) p:nth-of-type(2)::before { content: ""; float: right; width: 160px; height: 320px; shape-outside: polygon(20px 220px, 120px 0px, [...]); } The Pay-Off

Now that Firefox has released a version which supports CSS Shapes, and has launched a Shape Path Editor inside its Developer Tools, there’s now only Edge without support for Shapes. This situation will soon change now that Microsoft has announced a change from their own EdgeHTML rendering engine to Chromium’s Blink, the same engine as Chrome and Opera.

Tools like CSS Shapes now give us countless opportunities to use art direction to capture readers’ attention and keep them engaged. I hope by now you’re as excited about them as I am!

Editorial’s Note: Andy’s new book, Art Direction for the Web (pre-order your copy today), explores 100 years of art direction and how we can use this knowledge and the newest web technologies to create better digital products. Read an excerpt chapter to get a taste of what the book has to offer.

Further Resources (mr, ip, il)
Categories: Around The Web

Privacy UX: Better Cookie Consent Experiences

Wed, 04/10/2019 - 9:00am
Privacy UX: Better Cookie Consent Experiences Privacy UX: Better Cookie Consent Experiences Vitaly Friedman 2019-04-10T15:00:49+02:00 2019-04-18T19:36:01+00:00

With the advent of the EU General Data Protection Regulation (GDPR) in May 2018, the web has turned into a vast exhibition of consent pop-ups, notifications, toolbars, and modals. While the intent of most cookie-related prompts is the same — to get a user’s consent to keep collecting and evaluating their behavior the same ol’ way they’ve been doing for years — implementations differ significantly, often making it ridiculously difficult or simply impossible for customers to opt out from tracking.

On top of that, many implementations don’t even respect users’ decisions anyway and set cookies despite their choices, assuming that most people will grant consent regardless.

Admittedly, they aren’t entirely wrong. In our research, the vast majority of users willingly provide consent without reading the cookie notice at all. The reason is obvious and understandable: many customers expect that a website “probably wouldn’t work, or the content wouldn’t be accessible otherwise.” Of course, that’s not necessarily true, but users can’t know for sure unless they try it out. In reality, though, nobody wants to play ping-pong with the cookie consent prompt, and so they click the consent away by choosing the most obvious option: “OK.”

Note: It’s important to understand that cookies and consent mechanisms discussed in this article go beyond GDPR. In Europe, they are addressed by a separate piece of legislation, the ePrivacy Directive, which is currently in draft for a revamp (as of April 2019). It may be finalized by summer 2019. We do not know what its final form will take, but it will determine the future of cookie consent prompts.

Now, with this common behavior online, what might come across is that cookie prompts aren’t particularly useful, and that’s partly true. But they certainly helped raise awareness about privacy and data collection on the web. In fact, users now know that websites track their data, which they weren’t aware of a few years ago. But they often see it as a necessary evil in exchange for accessing the content “for free.”

It’s not that users always happily share their personal data, but they don’t really feel that revoking consent is a viable alternative. To many of them, the only reasonable option is to provide consent while opting in for an ad-blocker extension or any other tracking blocker in their browser.

Cookie consent pop-ups don’t have to be tiny and unreadable. We could try to integrate them into our overall experience too. Case in point: Oreo, with an Oreo’s cookie displayed as a cookie consent prompt. (Large preview)

Since cookie consent prompts always stand in the way of the content, they are often dismissed almost instinctively, not unlike carousels during onboarding. Hence, from the designer’s perspective, spending weeks refining that one-of-a-kind prompt might be a waste of time. (Sorry for crushing your dreams at this point.)

Iamsterdam.com allows visitors to adjust cookie settings and explains the different types of cookies, with an option to easily opt out from certain ones. (Large preview)

Since many websites heavily rely on collecting data, running A/B tests, and serving users with targeted advertising, often the design of the cookie consent notice is heavily influenced by business requirements and business goals. Is it acceptable for the business to allow users to quickly dismiss all tracking? Which cookies are (apparently) required for the site to work, and which ones are optional? Which cookies should be selected for approval by default, and which ones would require a manual opt-in? Should the customer be able to easily revoke the consent once it’s provided, and if so, how exactly would it be done if they don’t have an account on the site?

These business decisions have a major impact on design decisions, although from the user’s side, the optimal design would be quite obvious: no cookie consent at all. That would mean, for example, that users could define privacy settings in their browsers, and choose what cookies they’d like to provide consent to. The browser would then send a hint to each website a user chooses to visit and automatically opt-in or opt-out cookie settings, depending on the provided preferences.

Users now know that websites track their data, which they weren’t aware of a few years ago. But they often see it as a necessary evil in exchange for accessing the content “for free.”

In fact, a Do Not Track (DNT) header is already implemented and widely supported by browsers (although it was removed from Safari to prevent potential use for fingerprinting), yet there is no established mechanism for transforming this preference into a granular selection of accepted cookie groups. It shouldn’t be very surprising that most advertisers wouldn’t be particularly happy about this pattern gaining traction either, but perhaps it could be a slightly better way forward, as preferred by users, to no cookie consent at all.

Admittedly, users sometimes find a way around anyway. Some users who already use an ad-blocker are using a cookie prompt blocker as well. The latter, however, usually grants full consent on user’s behalf by default. Obviously, it goes against the very purpose of the cookie prompt in the first place, and ideally such extensions would automatically opt in only for essential cookies while opting out for everything else (if it’s possible at all).

As designers, though, we have a legal obligation to explain what happens to a user’s data and how it will be stored within the mandate of provided business requirements. As Geoffrey Keating mentioned in his article, “The Cookie Law and UX,” focusing specifically on legislation in Ireland, according to the Office of the Data Protection Commissioner, “the minimum requirement is clear communication to the user as to what he/she is being asked to consent to in terms of cookies usage and a means of giving or refusing consent.”

It’s worth noting that consent has to be “unambiguous” and “freely given,” as it must “leave no doubt as to the data subject’s intention, should be an active indication of the user’s wishes and can only be valid if the data subject is able to exercise a real choice.” Hence, silent, pre-ticked checkboxes or inactivity shouldn’t constitute consent.

This might sound obvious, but some solutions explore the uncharted legal territory that’s left for interpretation. For instance, sometimes the website visitor “automatically submits a cookie consent by clicking a link on the website”, and sometimes you can choose which actions are “obvious enough” for you to perceive them as a silent consent. Obviously, this isn’t an informed decision and such technique rightly belongs to the realm of mischievous culprits that should be avoided at all costs.

With this in mind, there are a couple of options we could consider:

Avoid Optional Cookies And Keep Only Functional Ones: No Prompt Required

It might appear that every single website needs to display a cookie consent notice to their European visitors, but if your website doesn’t collect, track, and evaluate any personal data from users, or it collects only anonymous data, you may not need one. In fact, one of the fundamental principles of the Privacy by Design framework is that non-essential cookies should be off by default and the user needs to actively opt in.

Now, cookies might be required for maintaining the logged-in state or user preferences, for example, and according to EU regulations you don’t need explicit consent for that. That’s also why many prompts have functional cookies enabled by default, without an option to disable them. And some sites, like GOV.UK, merely inform users about cookies, not requiring any input at all, but also not providing a choice to opt out from the optional Google Analytics cookie.

GOV.UK stores at least 18 cookies, and many of them are required for better experience; e.g. to track progress when applying for a licence, multivariate testing, making secure connections to websites, YouTube videos, email subscription updates. However, only one cookie is optional: Google Analytics (anonymized). (Large preview) Nudging Users Towards Implicit Consent

Not every website can get away without ad-related third-party cookies, though. One seemingly light way out would be to add a plain notification such as “By using our website, you are consenting to our use of cookies.” But this alone isn’t enough. As we need an active indication of the user’s consent, we have to require some sort of unambiguous action. For that reason, some sites add a “close” icon, making the consent box appear as a notification that can be dismissed. To ensure a more obvious acknowledgement, it’s a good idea to replace the “close” icon with a button. In many implementations, the button would simply say “Close” or “Save” or “Continue,” although “Accept and continue” is more clear.

In most cases, the notification doesn’t disappear until it is acted upon, hence being the very first thing that users see when visiting any page on the website. Do you need user consent on every page, though? You could be more selective and ask for the cookie consent only when it’s actually required; for example, when the user is setting up an account or wants to save their settings.

Twitter informs its visitors about the cookies used, but there is no option to adjust cookie preferences. The prompt will be clicked away by clicking on the ‘×’ in the top-right corner. Beware, however: some people see it as consent, while others see it as postponing the decision for a later time, similar to snoozing notifications. (Large preview) JetBrains chose to display a plain text-only prompt as if it were in a terminal window. There are balanced options to opt in or opt out of cookie consent. (Large preview) Allowing Users To Adjust Privacy Settings

While the previous option dictates complete obedience or complete lock-out, you could be more empathetic to the user’s intent. The user might have strong feelings about the exposure of their personal data, so providing a way out — not dissimilar to the personal questions we mentioned earlier — could keep them on the site. To achieve that, we could add an option to change settings, followed by an overview of different groups of cookies, with some of them being required for the site to function flawlessly, and others being optional.

The grouping could relate to the purpose of cookies such as advertising, analytics and statistics, or testing. It could also be much broader, allowing users to choose between “I am OK with personalized ads” or “I do not want to see personalized ads”. It’s also a good idea to explain to the user which features on the site will be unavailable once a certain group of cookies is blocked. TrustArc does that with a slider, allowing for a number of privacy levels, from allowing only required cookies to functional cookies to advertising cookies, while also showing its impact on the overall functionality of the site.

On Nielsen Norman group, all cookies are grouped. Necessary cookies can’t be opted out of, but all other groups can be dismissed with a few taps. Ideally, there’d be a way to opt out from all optional ones at once. (Large preview) Tabbed groups for cookies on MailChimp. (Large preview) (Large preview) The Guardian provides clear options which have equal weight on the 'Your privacy' page (not in the initial prompt, though). The modal on the front page is large but it provides clear options. (Large preview) The Daily Mash provides an option to adjust privacy settings (albeit de-emphasized), and in the settings panel visitors can easily reject or accept all cookies. Also, 'Save & Exit' is a very clear label for a button at the bottom. The experience might not be delightful, but it’s pretty clear. (Large preview) MyFitnessPal, powered by TrustArc, displays a slider which explains which functionality is allowed or disallowed with every group of cookies. (Large preview) A fantastic pattern on how a cookie settings dashboard could be designed to improve transparency. A mock-up by Matthias Ott and Joschi Kuphal built at the last @indiewebcamp in Dusseldorf. You can also download the Adobe XD source file, kindly provided by the authors. (Large preview) A Subtle Or Prominent Display Of The Request For Consent

In terms of layout, the prompt could be subtle and hardly noticeable, or obvious and difficult to ignore. We could place it in the header of the page, or at the bottom of the viewport, or we could also position it in the center of the page as a modal. All of these options could be floating and persistent as the user scrolls the page, thereby blocking access to a portion of the content (or entire content) until consent is granted.

De Telegraaf, for example, places a verbose cookie consent in the middle of the page, blurring out the content underneath, literally hijacking the page and standing in the way. It shouldn’t be a big revelation that from all the options we’ve tested, this one seems to be the most annoying one to users. In general, subtle prompts should be preferred, and the less space they need to be displayed, the better the overall user’s reaction has been.

It’s becoming common to blur out the content while displaying a cookie consent prompt. This technique brings focus to the prompt, but it also makes visitors more likely to click it away, often trading privacy for access to content. A slightly more subtle prompt would be more effective and helpful as users might browse around and leave without committing. Example: Telegraaf.nl. (Large preview) Blurring out the content is rarely a good idea. Also, there’s a very clear primary action and secondary action in play here. It doesn’t look like a fair choice between the two options. Example: Pathe.nl. (Large preview) Can you spot the cookie? A little notification in the bottom-right corner asks for the user’s consent on Empirebio.dk. (Large preview) On HoistGroup, there is no way to dismiss cookies — they are required, and there is no way out. (Large preview) On Zeit Online, there is no way to dismiss cookies — they are required, and there is no way out. (Large preview) Ticketveiling.nl displays a cookie prompt at the bottom, but also a chat widget. Only one interviewed person expected that the chat was here to provide help with the cookie settings. It’s probably a good idea to not display the widget alongside the cookie display prompt, though. (Large preview) Appearance And Wording On Buttons

We also need to give some thought to the appearance of the consent form, especially to the design of buttons and the wording on those buttons. Wording such as “Just proceed” or “Save and Exit” or “Continue using the site” nudges users to move on with a default option, and in fact, many users are likely to do just that. It’s more respectful to have two buttons, a primary one for granting consent, and a secondary one for adjusting settings, with both buttons having neutral microcopy such as “Accept” and “Reject,” or “Okay” and “No, thanks.” That’s the path we’ve chosen with Smashing Magazine.

Accept or dismiss. It shouldn’t be harder than that. (Large preview) NHS provides very clear options to accept cookies or 'Turn cookies off'. (Large preview) Large radio buttons to select what kind of cookies the visitor accepts. A fantastic example of privacy settings designed in an honest and transparent way. The only missing bit is to opt out from all optional cookies by default. Example: NHS. (Large preview) Accept or reject with a single tap, although both options don’t have the same weight. Example: Fandom.com. (Large preview)

It shouldn’t be surprising that of all the options, users feel surprisingly pleased and appreciative of the option to reject all cookies with a single click on a button. Some users were surprised that this option was even provided, and while a majority chose to grant consent, every fifth user refused consent. By doing so, they assumed the website would be fully functional without cookies, and rightfully so.

Adjusting Cookie Preferences

Not many users would consider revoking or adjusting cookie settings after granting consent, but when asked to do so, they expected to find the options in the header or the footer of the website, either in the privacy policy or in the cookie policy. It’s not very surprising, and of course that’s where we need to place the options to adjust settings should the user wish to do so.

(Large preview) By default, all options on the Jamie Oliver website are off, with an option to turn them on. However, the main call-to-action button is 'Accept recommended settings', which turns all toggles to on. The option to proceed without cookies is positioned at the very bottom of the page, with a subtle 'Close'. It’s probably not obvious enough, and another button on the top would be more helpful. (Large preview) Users Understand When They Are Being Tricked

So far, the entire experience should be quite straightforward, right? Well, if a business model heavily relies on collecting and tracking data, you might be forced into shady areas when selecting anything but the easiest option is confusing and generates a lot of work. In our interviews, users could easily see through the companies’ agendas, even saying something along the lines of “Ah, I see what you did there.” Some things were less obvious than others, though.

Whenever the cookie consent suggested an option to review cookies or adjust cookie settings, users expected to see an overview of all cookies and be able to adjust which cookies should be allowed to be set and which not. In terms of interface design, usually it’s done with tabbed sections within a cookie consent widget, with some groups selected by default. It’s common to see functional cookies, analytics cookies, advertising cookies, and website settings cookies. This level of granular control isn’t often expected but it’s considered to be helpful and friendly, and as such preferred — however, only if the entire category of cookies could be unselected at once, with a single tap on a single checkbox.

Oddly enough, some implementations go to extremes, providing users with an overwhelming overview of every single cookie set by third parties. It’s not uncommon for all of them to be opted in by default, and opting out requires a tap on every single one of them, one by one. It might not seem like a big deal with five cookies, but it’s a monstrosity with over 250 cookies generously provided by dozens of trackers on the site. In such cases, many users gave up after a few opt-outs, providing full access to their data and moving on.

What would you expect to happen when clicking on the 'close' icon? How is a click on a button different from a click on the cross? Is there a difference? On Kayak, users were confused during the test. (Large preview)

Unfortunately, that’s just scratching the surface. Imagine a cookie settings prompt with a “Close ×” button. What behavior would you expect from clicking “Close”? Would you expect the prompt to be dismissed and then eventually reappear? Or would you expect all tracking scripts to be opted out by default? Opted in? Unsurprisingly, most users weren’t even thinking that far — they just wanted the pop-up to disappear. Nobody expected the trackers to be opted out by default, yet many users felt that it was a “temporary thing” that would show up again “at some point.” In practice, almost all of the time, closing the prompt was perceived by website owners as user consent and, in fact, all cookies were stored to their full extent. That’s not necessarily what the user was expecting.

A slightly confusing experience on Speisekarte.de, with an option to accept or ‘deselect all’ options in the top-left corner, in the same color, with a delimiter > in between. Also, the wording ‘Agree and Proceed’ or ‘Learn more’ isn’t obvious. (Large preview)

The wording on buttons and links caused major confusion for users. On Speisekarte.de, you can either “Agree and Proceed” (primary, large green button) or “Learn more” (subtle grey link, not even underlined). What would you expect to appear after clicking “Learn More”? While many users expect a privacy policy to appear, the action actually prompts the management of cookies, with 405 ad selection, delivery, and reporting partners, 446 information storage and access partners, 274 content selection, delivery, and reporting partners, 372 measurement partners and 355 personalization partners. “Agree and Proceed” grants access to the storage and evaluation of customers’ personal data for 1,852 partners. That’s not too shabby, isn’t it?

It’s not obvious that the listing area for all those partners is scrollable at all, and there is no obvious way to unselect all of them. Would you find it enjoyable to manually opt out 1,852 toggles, one by one? Probably not. As it turns out, you can “deselect all” partners in the top-left corner of the window — however, this option is conveniently presented in a way that resembles breadcrumb navigation rather than a button. And, of course, all partners are opted in by default. That’s deceptive, dishonest, and disrespectful.

Once you get into the habit of rejecting cookies by default, you can find a number of shady and questionable practices that seem to be widespread. Sometimes companies place Facebook and Twitter tracking cookies in the “Necessary” category. Sometimes the option to reject cookies is conveniently hidden behind an extra “Manage” option. And sometimes there is an option to opt out from analytics, but a user is automatically opted in for “Anonymous analytics.”

Some companies go beyond that, inventing new ways of making business should the user wish to avoid tracking. Sometimes it shows up with a “Premium EU Subscription” without on-site advertising and tracking scripts, and sometimes with a website being unavailable, or an “EU experience” (which, frankly, is much faster and lightweight than its non-EU counterpart). Not a single person accessing the site appreciated either of these options. That shouldn’t be a big revelation, but there is a significant amount of users who, being confronted with such treatment, have nothing left but to leave the site in search for alternatives.

USA Today provides an EU experience which happens to be much cleaner and faster than the original one. For EU visitors, the 'site does not collect personally identifiable information or persistent identifiers from, deliver a personalized experience to, or otherwise track or monitor persons reasonably identified as visiting our Site from the European Union.' (Large preview) The Washington Post has introduced a 'Premium EU Subscription' that doesn’t contain any on-site advertising or third-party ad tracking. (Large preview) For a while, Los Angeles Times displayed a message stating that the website was unavailable in most European countries. (Large preview) Guidelines And Strategies For Better Design

According to the EU regulation, each cookie, its provider, purpose, expiry date, and type should be explained and elaborated in detail in a privacy policy, and many services such as TrustArc, IAB Consent Framework, Cookiebot, OneTrust, Cookie Consent, and many others provide this feature out of the box. They also provide an option to customize which groups of cookies should be presented as choices to the user, and while the default experience is decent, often it can be used to make it unnecessarily difficult for the customer to adjust their settings.

(Large preview) (Large preview) Clear options, honest experience, transparent interface. A great example on Sourceforge. (Large preview)

At the end of the day, we need to provide good experiences while also achieving our business goals. We can do that with a series of steps:

  1. We need to audit and group all cookies required on the site;
  2. We need to decide how each of these groups would be labelled, which ones would be required, and which would be optional;
  3. We need to understand what impact disabling a group of cookies would have on the functionality of the site, and communicate each choice to the user;
  4. Last but not least, we need to decide what settings should be selected by default, and what customization options we want to present to the user.

The simplest design pattern seems to be obvious. If you need user consent, display a narrow notification notice in the header or at the bottom of the viewport. No need to blur out or darken the content to make the notification noticeable; just make sure it doesn’t blend in with the rest of the site. If possible, allow users to accept or reject cookies with two obvious buttons: “Okay” and “No, thanks.” Otherwise, provide an option to adjust settings, following an overview of cookie categories. There, you have to make obvious the consequences each choice has on the website functionality, and enable users to “Approve all” or “Reject all” cookies at once — for the entire site, and for each category.

Where to place the notification notice? The position doesn’t seem to really matter — it didn’t make any difference in decision-making. The overlay covering half of the page, however, was perceived as the most annoying option — and it shouldn’t be too surprising as it literally blocks a large portion of the content on the page. Most users almost instinctively know what they are presented with, and they also know what action they’d prefer to take to get on with the site, so lengthy explanations are ignored or dismissed as swiftly as push notifications or permission requests.

In the next article of the series, we’ll look into notifications UX and permission requests, and how we can design the experience around them better — and with user’s privacy in mind.

A kind thank you to Heather Burns for reviewing this article before publication.

(yk, il)
Categories: Around The Web

Understanding Subresource Integrity

Tue, 04/09/2019 - 6:30am
Understanding Subresource Integrity Understanding Subresource Integrity Drew McLellan 2019-04-09T12:30:59+02:00 2019-04-18T19:36:01+00:00

If you’ve ever used a CDN-hosted version of a JavaScript library, you may have noticed a strange looking integrity attribute on the script tag. This attribute contains seemingly endless alphanumeric junk that you may be tempted to strip out in the quest for cleaner code.

All that junk is actually a really useful security feature called Subresource Integrity (SRI) that can help to defend your site against certain types of hacks and compromises. In this article, we’ll take a look at what SRI is, how it can help protect you, and how you can start using it in your own projects, not just for files hosted on CDNs.

A Bit Of History

Way back in the days when JavaScript was very much the poorer cousin to HTML and CSS, we didn’t need to think too much about how our scripts could be used as an attack vector for our websites. Most sites were all hosted on a single physical server somewhere on our own hosting infrastructure, and it was the server we thought about defending when it came to security best practices.

As browsers became more capable and net connections got fatter, we started to use more and more JavaScript, and eventually, reusable JavaScript libraries began to spring up. In those early days, libraries like script.aculo.us, Prototype and eventually jQuery began to gain adoption amongst developers looking to add more interactivity into their pages.

With these added libraries and subsequent plugins came added page weight, and before long we were starting to think seriously about front-end performance. Resources like Content Delivery Networks (CDNs) that had previously been the reserve of giant corporations were becoming commonplace for everyday folk building snappy websites.

Along the way, some bright spark noticed that sites were all requesting their own copies of common libraries — things like the latest jQuery — and if there was a common CDN version of those libraries that could be used by every site, then the user wouldn’t need to keep downloading the same file. They’d take the hit for the first site to use the file, but then it would sit in their local browser cache and downloads could be skipped for each subsequent site. Genius!

This is why you’ll see CDN links for your favorite libraries using URLs like jsdelivr.com — they’re making use of a common CDN to host the files so that their users see the performance benefits.

What Could Go Wrong?

This remains a good, practical way to work, but it does introduce a potential vector for attack. Let’s imagine that it’s 2012 and everyone is using the brand new jQuery 1.8. Back with the traditional way of doing things, everyone would have their own jQuery 1.8 file hosted as part of their own website on their own server.

If you were some kind of evil actor — like some sort of jQuery-based Hamburglar — and had figured out a sneaky way to hack the library for your own evil gains, you’d have to target every website individually and compromise their servers to have any impact. That’s a lot of effort.

But that’s not how things are now, as everyone is using jQuery loaded from a common CDN. And when I say everyone, I don’t mean hundreds of web pages. I mean millions of web pages. Suddenly that one file has become a very attractive target for our shady hacker. If they can compromise that one file, they can very quickly have code running in millions of web pages across the globe.

It doesn’t matter what that code is. It could be a prank to deface pages, it could be code to steal your passwords, it could be code to mine cryptocurrency, or it could be sneaky trackers to follow you around the web and make a marketing profile. The important thing is that the innocent file that the developer added to a page has been changed and you now have some evil JavaScript running as part of your site. That’s a big problem.

Enter Subresource Integrity

Rather than rolling back the clocks and abandoning a useful way to use code, SRI is a solution that adds a simple level of security on top. What SRI and the integrity attribute does is make sure that the file you linked into a page never changes. And if it does change, then the browser will reject it.

Checking that code hasn’t changed is a very old problem in computer science and thankfully it has some very well established solutions. SRI does a good job of adopting the simplest — file hashing.

File hashing is the process of taking a file and running it through an algorithm that reduces it to a short string representation, known as a hash or checksum. Without getting into the weeds, the process is either repeatable or reversible, so much that if you were to give someone else a file along with the hash they’d be able to run the same algorithm to check that the two match. If the file changes or the hash changes, then there’s no longer a match and you know something is wrong and should distrust the file.

When using SRI, your webpage holds the hash and the server (CDN or anywhere) holds the file. The browser downloads the file, then quickly computes to make sure that it is a match with the hash in the integrity attribute. If it matches the file is used, and if not it is blocked.

Trying It Out

If I go to getbootstrap.com today to get a CDN link to a version of Bootstrap, I’m given a tag that looks like this:

<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>

You can see that the src attribute is as we’re used to, and the integrity attribute holds what we now know to be a hash.

The hash is actually in two parts. The first is a prefix to declare which hashing algorithm to use. In this case, it’s sha384. This is followed by a dash and then the hash itself, encoded with base64.

You may be familiar with base64 as a way of encoding inline files like images into pages. It’s not a cryptographic process — it’s just a fast and convenient way to encode potentially messy data in a way that translates neatly to ASCII. This is why it’s used a lot on the web.

On seeing this, the browser will download bootstrap.min.js. Before executing it, it will base64 decode the hash and then use the sha384 hashing algorithm to confirm that the hash matches the file it’s just downloaded. If it matches, the file is executed.

I can test this out by putting that tag in a page, and then flipping to the Network tab in my browser tools to see that the file has been loaded.

(Large preview)

I can see that bootstrap.min.js (and also the jQuery file it needs) have loaded successfully.

Let’s see what would happen if I update the hash to be something I know to be incorrect.

<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-SmashingMagazineIsCoolForCats" crossorigin="anonymous"></script> (Large preview)

As you can see, the hash that’s specified in my page no longer matches the file, so the file gets blocked.

Using SRI In Your Own Projects

Having this capability for libraries on a CDN is great, and if you see the option to use an embedded file with an integrity attribute then you should definitely favor that option. But it’s not limited to big projects on CDNs, you can use this yourself for your own sites.

It’s not at all far fetched to imagine a scenario where a hacker manages to get access to just a few files on your site. I think most of us have see a client, colleague or friend who has at some point had a WordPress site compromised with a load of nasty junk that they didn’t even realise was there.

SRI can protect you from this too. If you generate integrity hashes for your own files, then you can have your site reject any changes just as it would for a remotely hosted file.

Generating Hashes

You can, as you’d expect, run some commands at your computer’s terminal to generate a hash for a file. This example of how to do so comes from the MDN Subresource Integrity page:

cat FILENAME.js | openssl dgst -sha384 -binary | openssl base64 -A

That’s getting the content of FILENAME.js and passing it as input to openssl to create a digest using sha384, which is then passed as input into another openssl command to base64 encode the result. Not only is that complicated and obscure, but it’s also not the sort of thing you want to be doing by hand every time your JavaScript file changes.

More usefully, you’ll want to integrate this somehow into your site’s build process, and as you’d imagine, there are plenty of ready-made options there. The exact implementation is going to vary wildly based on your project, but here are some building blocks.

If you use Gulp to build your sites, there’s gulp-sri which will output a JSON file with a list of your files and their hashes. You can then make use of this in your site. For example, for a dynamically rendered site, you might create a template plugin to read that file and add the hashes to your templates where needed.

If you’re still with Gulp but have a static site (or a statically generated site) you might use gulp-sri-hash which will actually run through your HTML pages and modify the pages to add hashes where needed, which is very handy.

If you’re using Webpack, there’s webpage-subresource-integrity which in true Webpack style is more complex than any human might expect it to be, but does appear to work.

For those using the Handlebars templating engine, there appear to be options available to you, and if your build process is just basic JavaScript, there are simple solutions there too.

If you’re using a CMS like WordPress, I found a plugin that appears to make it easy, although I’ve not tried it myself. Googling for your own platform of choice with SRI or Sub Resource Integrity will likely point you in the right direction.

You essentially want to hook your hashing in after your JavaScript files have been minified and then make that hash available in some way to whatever part of your system outputs the <script> tags. One of the wonders of the web platform is that it’s so technically diverse, but that sadly leaves me unable to give you good implementation instructions!

Other Things To Note

In this article, I’ve talked a lot about JavaScript files because that’s really where it makes the most sense to defend against hacking attacks. SRI also works with CSS, and so you can use it in exactly the same way there. The risk for malicious CSS is much lower, but the potential to deface a site still exists and who knows what browser bugs could also lead to CSS inadvertently exposing your site to a hacker. So it’s work using SRI there too.

Another interesting thing you can do is use a Content Security Policy to specify that any script (or styles) on your page must use SRI, and of course that SRI must validate.

Content-Security-Policy: require-sri-for script;

This is a way to ensure that SRI is always used, which could be useful on sites worked on by multiple team members who may or may not be fully up to speed with how to do things. Again, a good place to read more about this is the always-great MDN docs for Subresource Integrity.

The last thing that’s worth talking about is browser support for SRI. Support in modern browsers is broad, with the main exception being Internet Explorer. Due to the backwards-compatible way the specification has been implemented, however, it’s safe to use immediately. Browsers that understand the integrity attribute will use the hash and check integrity, and older browsers will just carry on as they always have and keep working. Of course, you’ll not get the added protection in those older browsers, but you will in the browsers that do offer support.


We’ve seen not only what those weird hashes in the integrity attributes do, but how we can use them to defend against certain types of attacks on our website. Of course, there’s no one silver bullet that will defend our sites against every type of exploit, but Subresource Integrity is a really useful tool in the chain.

Exploiting a security flaw is often about getting multiple small pieces to line up. If A is in place, and you can make B happen, then a bug in C makes D possible. Browser features like SRI give us a good way to tie things down just a little bit more and potentially break that chain and prevent a hacker from getting what they want. What’s more, if you can integrate it into your build process or CMS, it’s something you should be able to set up once and then forget about and it won’t cause you day to day inconvenience.

As such, I’d really recommend taking a serious look at Subresource Integrity and implementing it on your sites if you can.

(yk, il)
Categories: Around The Web

Digging Into The Display Property: The Two Values Of Display

Mon, 04/08/2019 - 7:00am
Digging Into The Display Property: The Two Values Of Display Digging Into The Display Property: The Two Values Of Display Rachel Andrew 2019-04-08T13:00:59+02:00 2019-04-18T19:36:01+00:00

A flex or grid layout starts out with you declaring display: flex or display: grid. These layout methods are values of the CSS display property. We tend not to talk about this property on its own very much, instead concentrating on the values of flex or grid, however, there are some interesting things to understand about display and how it is defined that will make your life much easier as you use CSS for layout.

In this article, the first in a short series, I’m going to take a look at the way that the values of display are defined in the Level 3 specification. This is a change to how we defined display in earlier versions of CSS. While it may seem unusual at first for those of us who have been doing CSS for many years, I think these changes really help to explain what is going on when we change the value of display on an element.

Block And Inline Elements

One of the first things we teach people who are new to CSS are the concepts of block and inline elements. We will explain that some elements on the page are display: block and they have certain features because of this. They stretch out in the inline direction, taking up as much space as is available to them. They break onto a new line; we can give them width, height, margin as well as padding, and these properties will push other elements on the page away from them.

We also know that some elements are display: inline. Inline elements are like words in a sentence; they don’t break onto a new line, but instead reserve a character of white space between them. If you add margins and padding, this will display but it won’t push other elements away.

The behavior of block and inline elements is fundamental to CSS and the fact that a properly marked up HTML document will be readable by default. This layout is referred to as “Block and Inline Layout” or “Normal Flow” because this is the way that elements lay themselves out if we don’t do anything else to them.

Inner And Outer Values Of display

We understand block and inline elements, but what happens if we make an item display: grid? Is this something completely different? If we look at a component on which we have specified display: grid, in terms of the parent element in the layout it behaves like a block level element. The element will stretch out and take up as much space in the inline dimension as is available, it will start on a new line. It behaves just like a block element in terms of how it behaves alongside the rest of the layout. We haven’t said display: block though, or have we?

It turns out that we have. In Level 3 of the Display specification, the value of display is defined as two keywords. These keywords define the outer value of display, which will be inline or block and therefore define how the element behaves in the layout alongside other elements. They also define the inner value of the element — or how the direct children of that element behave.

This means that when you say display: grid, what you are really saying is display: block grid. You are asking for a block level grid container. An element that will have all of the block attributes — you can give it height and width, margin and padding, and it will stretch to fill the container. The children of that container, however, have been given the inner value of grid so they become grid items. How those grid items behave is defined in the CSS Grid Specification: the display spec gives us a way to tell the browser that this is the layout method we want to use.

I think that this way of thinking about display is incredibly helpful; it directly explains what we are doing with various layout methods. If you were to specify display: inline flex, what would you expect? Hopefully, a box that behaves as an inline element, with children that are flex items.

There are a few other things neatly explained by thinking about display in this new way, and I’ll take a look at some of these in the rest of this article.

We Are Always Going Back To Normal Flow

When thinking about these inner and outer display properties, it can be helpful to consider what happens if we don’t mess around with the value of display at all. If you write some HTML and view it in a browser, what you get is Block and Inline Layout, or Normal Flow. The elements display as block or inline elements.

See the Pen Block and Inline Layout by Rachel Andrew.

See on Codepen

The example below contains some markup that I have turned into a media object, by making the div display: flex (the two direct children) now become flex items, so the image is now in a row with the content. If you see in the content, however, there is a heading and a paragraph which are displaying in normal flow again. The direct children of the media object became flex items; their children return to normal flow unless we change the value of display on the flex item. The flex container itself is a block box, as you can see by the fact the border extends to the edge of its parent.

See the Pen Block and Inline Layout With Flex Component by Rachel Andrew.

See on Codepen

If you work with this process, the fact that elements on your page will lay themselves out with this nice readable normal flow layout, rather than fighting against it and trying to place everything, CSS is much easier. You are also less likely to fall into accessibility issues, as you are working with the document order, which is exactly what a screen reader or a person tabbing through the document is doing.

Explaining flow-root And inline-block

The value of inline-block is also likely to be familiar to many of us who have been doing CSS for a while. This value is a way to get some of the block behavior on an inline element. For example, an inline-block element can have a width and a height. An element with display: inline-block also behaves in an interesting way in that it creates a Block Formatting Content (BFC).

A BFC does some useful things in terms of layout, for example, it contains floats. To read about Block Formatting Contexts in more detail see my previous article “Understanding CSS Layout And The Block Formatting Context.” Therefore saying display: inline-block gives you an inline box which also establishes a BFC.

As you will discover (if you read the above-mentioned article about the Block Formatting Context), there is a newer value of display which also explicitly creates a BFC. This is the value of flow-root. This value creates a BFC on a block, rather than an inline element.

  • display: inline-block gives you a BFC on an inline box.
  • display: flow-root gives you a BFC on a block box.

You are now probably thinking that is all a bit confusing: why do we have two completely different keywords here, and what happened to the two-value syntax we were talking about before? This leads neatly into the next thing I need to explain about display, i.e. the fact that CSS has a history we need to deal with in terms of the display property.

Legacy Values Of Display

The CSS2 Specification detailed the following values for the display property:

  • inline
  • block
  • inline-block
  • list-item
  • none
  • table
  • inline-table

Also defined were the various table internal properties such as table-cell which we are not dealing with in this article.

We then added to these some values for display, to support flex and grid layout:

  • grid
  • inline-grid
  • flex
  • inline-flex

Note: The specification also defines ruby and inline-ruby to support Ruby Text which you can read about in the Ruby specification.

These are all single values for the display property, defined before the specification was updated to explain CSS Layout in this way. Something very important about CSS is the fact that we don’t go around breaking the web; we can’t simply change things. We can’t suddenly decide that everyone should use this new two-value syntax and therefore every website ever built that used the single value syntax will break unless a developer goes back and fixes it!

While thinking about this problem, you may enjoy this list of mistakes in the design of CSS which are less mistakes in many cases as things that were designed without a crystal ball to see into the future! However, the fact is that we can’t break the web, which is why we have this situation where right now browsers support a set of single values for display, and the specification is moving to two values for display.

The way we get around this is to specify legacy and short values for display, which includes all of these single values. This means that a mapping can be defined between single values and new two keyword values. Which gives us the following table of values:

Single Value Two-Keyword Values Description block block flow Block box with normal flow inner flow-root block flow-root Block box defining a BFC inline inline flow Inline box with normal flow inner inline-block inline flow-root Inline box defining a BFC list-item block flow list-item Block box with normal flow inner and additional marker box flex block flex Block box with inner flex layout inline-flex inline flex Inline box with inner flex layout grid block grid Block box with inner grid layout inline-grid inline grid Inline box with inner grid layout table block table Block box with inner table layout inline-table inline table Inline box with inner table layout

To explain how this works, we can think about a grid container. In the two-value world, we would create a block level grid container with:

.container { display: block grid; }

However, the legacy keyword means that the following does the same thing:

.container { display: grid; }

If, instead, we wanted an inline grid container, in the two-value world we would use:

.container { display: inline grid; }

And if using the legacy values:

.container { display: inline-grid; }

We can now go back to where this conversation began and look at display: inline-block. Looking at the table, you can see that this is defined in the two-value world as display: inline flow-root. It now matches display: flow-root which in a two-value world would be display: block flow-root. A little bit of tidying up and clarification of how these things are defined. A refactoring of CSS, if you like.

Browser Support For The Two-Value Syntax

As yet, browsers do not support the two-value syntax for the display property. The implementation bug for Firefox can be found here. Implementation — when it happens — would essentially involve aliasing the legacy values to the two-value versions. It’s likely to be a good while, therefore, before you can actually use these two-value versions in your code. However, that really isn’t the point of this article. Instead, I think that looking at the values of display in the light of the two-value model helps explain much of what is going on.

When you define layout on a box in CSS, you are defining what happens to this box in terms of how it behaves in relation to all of the other boxes in the layout. You are also defining how the children of that box behave. You can think in this way long before you can explicitly declare the values as two separate things, as the legacy keywords map to those values, and it will help you understand what happens when you change the value of display.

Categories: Around The Web

How We Used WebAssembly To Speed Up Our Web App By 20X (Case Study)

Fri, 04/05/2019 - 6:00am
How We Used WebAssembly To Speed Up Our Web App By 20X (Case Study) How We Used WebAssembly To Speed Up Our Web App By 20X (Case Study) Robert Aboukhalil 2019-04-05T12:00:29+02:00 2019-04-18T19:36:01+00:00

If you haven’t heard, here’s the TL;DR: WebAssembly is a new language that runs in the browser alongside JavaScript. Yes, that’s right. JavaScript is no longer the only language that runs in the browser!

But beyond just being “not JavaScript”, its distinguishing factor is that you can compile code from languages such as C/C++/Rust (and more!) to WebAssembly and run them in the browser. Because WebAssembly is statically typed, uses a linear memory, and is stored in a compact binary format, it is also very fast, and could eventually allow us to run code at “near-native” speeds, i.e. at speeds close to what you’d get by running the binary on the command line. The ability to leverage existing tools and libraries for use in the browser and the associated potential for speedup, are two reasons that make WebAssembly so compelling for the web.

So far, WebAssembly has been used for all sorts of applications, ranging from gaming (e.g. Doom 3), to porting desktop applications to the web (e.g. Autocad and Figma). It is even used outside the browser, for example as an efficient and flexible language for serverless computing.

This article is a case study on using WebAssembly to speed up a data analysis web tool. To that end, we’ll take an existing tool written in C that performs the same computations, compile it to WebAssembly, and use it to replace slow JavaScript calculations.

Note: This article delves into some advanced topics such as compiling C code, but don’t worry if you don’t have experience with that; you will still be able to follow along and get a sense for what is possible with WebAssembly.


The web app we will work with is fastq.bio, an interactive web tool that provides scientists with a quick preview of the quality of their DNA sequencing data; sequencing is the process by which we read the “letters” (i.e. nucleotides) in a DNA sample.

Here’s a screenshot of the application in action:

A screenshot of fastq.bio in action (Large preview)

We won’t go into the details of the calculations, but in a nutshell, the plots above provide scientists a sense for how well the sequencing went and are used to identify data quality issues at a glance.

Although there are dozens of command line tools available to generate such quality control reports, the goal of fastq.bio is to give an interactive preview of data quality without leaving the browser. This is especially useful for scientists who are not comfortable with the command line.

The input to the app is a plain-text file that is output by the sequencing instrument and contains a list of DNA sequences and a quality score for each nucleotide in the DNA sequences. The format of that file is known as “FASTQ”, hence the name fastq.bio.

If you’re curious about the FASTQ format (not necessary to understand this article), check out the Wikipedia page for FASTQ. (Warning: The FASTQ file format is known in the field to induce facepalms.)

fastq.bio: The JavaScript Implementation

In the original version of fastq.bio, the user starts by selecting a FASTQ file from their computer. With the File object, the app reads a small chunk of data starting at a random byte position (using the FileReader API). In that chunk of data, we use JavaScript to perform basic string manipulations and calculate relevant metrics. One such metric helps us track how many A’s, C’s, G’s and T’s we typically see at each position along a DNA fragment.

Once the metrics are calculated for that chunk of data, we plot the results interactively with Plotly.js, and move on to the next chunk in the file. The reason for processing the file in small chunks is simply to improve the user experience: processing the whole file at once would take too long, because FASTQ files are generally in the hundreds of gigabytes. We found that a chunk size between 0.5 MB and 1 MB would make the application more seamless and would return information to the user more quickly, but this number will vary depending on the details of your application and how heavy the computations are.

The architecture of our original JavaScript implementation was fairly straightforward:

The architecture of the JavaScript implementation of fastq.bio (Large preview)

The box in red is where we do the string manipulations to generate the metrics. That box is the more compute-intensive part of the application, which naturally made it a good candidate for runtime optimization with WebAssembly.

fastq.bio: The WebAssembly Implementation

To explore whether we could leverage WebAssembly to speed up our web app, we searched for an off-the-shelf tool that calculates QC metrics on FASTQ files. Specifically, we sought a tool written in C/C++/Rust so that it was amenable to porting to WebAssembly, and one that was already validated and trusted by the scientific community.

After some research, we decided to go with seqtk, a commonly-used, open-source tool written in C that can help us evaluate the quality of sequencing data (and is more generally used to manipulate those data files).

Before we compile to WebAssembly, let’s first consider how we would normally compile seqtk to binary to run it on the command line. According to the Makefile, this is the gcc incantation you need:

# Compile to binary $ gcc seqtk.c \ -o seqtk \ -O2 \ -lm \ -lz

On the other hand, to compile seqtk to WebAssembly, we can use the Emscripten toolchain, which provides drop-in replacements for existing build tools to make working in WebAssembly easier. If you don’t have Emscripten installed, you can download a docker image we prepared on Dockerhub that has the tools you’ll need (you can also install it from scratch, but that usually takes a while):

$ docker pull robertaboukhalil/emsdk:1.38.26 $ docker run -dt --name wasm-seqtk robertaboukhalil/emsdk:1.38.26

Inside the container, we can use the emcc compiler as a replacement for gcc:

# Compile to WebAssembly $ emcc seqtk.c \ -o seqtk.js \ -O2 \ -lm \ -s USE_ZLIB=1 \ -s FORCE_FILESYSTEM=1

As you can see, the differences between compiling to binary and WebAssembly are minimal:

  1. Instead of the output being the binary file seqtk, we ask Emscripten to generate a .wasm and a .js that handles instantiation of our WebAssembly module
  2. To support the zlib library, we use the flag USE_ZLIB; zlib is so common that it’s already been ported to WebAssembly, and Emscripten will include it for us in our project
  3. We enable Emscripten’s virtual file system, which is a POSIX-like file system (source code here), except it runs in RAM within the browser and disappears when you refresh the page (unless you save its state in the browser using IndexedDB, but that’s for another article).

Why a virtual file system? To answer that, let’s compare how we would call seqtk on the command line vs. using JavaScript to call the compiled WebAssembly module:

# On the command line $ ./seqtk fqchk data.fastq # In the browser console > Module.callMain(["fqchk", "data.fastq"])

Having access to a virtual file system is powerful because it means we don’t have to rewrite seqtk to handle string inputs instead of file paths. We can mount a chunk of data as the file data.fastq on the virtual file system and simply call seqtk’s main() function on it.

With seqtk compiled to WebAssembly, here’s the new fastq.bio architecture:

Architecture of the WebAssembly + WebWorkers implementation of fastq.bio (Large preview)

As shown in the diagram, instead of running the calculations in the browser’s main thread, we make use of WebWorkers, which allow us to run our calculations in a background thread, and avoid negatively affecting the responsiveness of the browser. Specifically, the WebWorker controller launches the Worker and manages communication with the main thread. On the Worker’s side, an API executes the requests it receives.

We can then ask the Worker to run a seqtk command on the file we just mounted. When seqtk finishes running, the Worker sends the result back to the main thread via a Promise. Once it receives the message, the main thread uses the resulting output to update the charts. Similar to the JavaScript version, we process the files in chunks and update the visualizations at each iteration.

Performance Optimization

To evaluate whether using WebAssembly did any good, we compare the JavaScript and WebAssembly implementations using the metric of how many reads we can process per second. We ignore the time it takes for generating interactive graphs, since both implementations use JavaScript for that purpose.

Out of the box, we already see a ~9X speedup:

Using WebAssembly, we see a 9X speedup compared to our original JavaScript implementation. (Large preview)

This is already very good, given that it was relatively easy to achieve (that is once you understand WebAssembly!).

Next, we noticed that although seqtk outputs a lot of generally useful QC metrics, many of these metrics are not actually used or graphed by our app. By removing some of the output for the metrics we didn’t need, we were able to see an even greater speedup of 13X:

Removing unnecessary outputs gives us further performance improvement. (Large preview)

This again is a great improvement given how easy it was to achieve—by literally commenting out printf statements that were not needed.

Finally, there is one more improvement we looked into. So far, the way fastq.bio obtains the metrics of interest is by calling two different C functions, each of which calculates a different set of metrics. Specifically, one function returns information in the form of a histogram (i.e. a list of values that we bin into ranges), whereas the other function returns information as a function of DNA sequence position. Unfortunately, this means that the same chunk of file is read twice, which is unnecessary.

So we merged the code for the two functions into one—albeit messy—function (without even having to brush up on my C!). Since the two outputs have different numbers of columns, we did some wrangling on the JavaScript side to disentangle the two. But it was worth it: doing so allowed us to achieve a >20X speedup!

Finally, wrangling the code such that we only read through each file chunk once gives us >20X performance improvement. (Large preview) A Word Of Caution

Now would be a good time for a caveat. Don’t expect to always get a 20X speedup when you use WebAssembly. You might only get a 2X speedup or a 20% speedup. Or you may get a slow down if you load very large files in memory, or require a lot of communication between the WebAssembly and the JavaScript.


In short, we’ve seen that replacing slow JavaScript computations with calls to compiled WebAssembly can lead to significant speedups. Since the code needed for those computations already existed in C, we got the added benefit of reusing a trusted tool. As we also touched upon, WebAssembly won’t always be the right tool for the job (gasp!), so use it wisely.

Further Reading (rb, ra, il)
Categories: Around The Web

Privacy UX: Common Concerns And Privacy In Web Forms

Thu, 04/04/2019 - 10:30am
Privacy UX: Common Concerns And Privacy In Web Forms Privacy UX: Common Concerns And Privacy In Web Forms Vitaly Friedman 2019-04-04T16:30:49+02:00 2019-04-18T19:36:01+00:00

Many conversations in our industry tend to circle around strong opinions and universal answers. Choosing a shiny new technical stack or sticking to an old-school paradigm; betting on a trendy framework or building a custom light framework of your own; using an attention-grabbing pop-up or sticking to calmer, less annoying solutions. We tend to have strong opinions about design and development, and so we agree and disagree, and argue endlessly, trying to protect and explain our views. Sometimes (and maybe a bit too often) to the point that conversations escalate and result in annoyingly disgruntled camps not agreeing on anything.

It’s not the stubbornness that brings us there, though. It’s the simple fact that we all have different backgrounds, expectations, and experiences. But sometimes we end up debating answers that are all acceptable and seeking the ultimate truth in a place where it really can’t exist. This pattern shows up for the usual suspects: accessibility, performance, tooling, workflows, and naming conventions. It also repeats itself with topics that are often considered to be ephemeral: ethics and privacy.

In the past, these topics could be spotted sporadically on the remote fringes of Twitter threads and blog posts. These days we’ve become very aware of the frightening dimensions that collection and use of personal data have gradually and silently gained. So we’ve started fighting back. Fighting back by publicly complaining about privacy-related dark patterns, unsolicited emails, shady practices, strict legal regulations, and ad-blocker wars against disruptive ads from hell. Of course, these are all important conversations to have and raising awareness is important; but we also need an applicable, pragmatic approach for designing and building ethical and respectful interfaces within our existing, well-established processes. We could use a few established patterns to bake in privacy-aware design decisions into our interfaces by default.

As a part of Smashing consultancy and teaching at universities and schools, over the last several months I was privileged to run interviews with 62 customers of various ages and experiences in Belgium, the Netherlands, Germany, Ukraine, USA, Serbia, Bosnia-Herzegovina, Austria, and Canada. My objective was to ascertain the role privacy plays for users these days, and how the interfaces we so thoroughly craft are perceived when it comes to various touchpoints. The findings from these interviews are the foundation of this article series.

In this four-part series, we’ll explore some of the respectful ways to approach privacy and data collection, and how to deal with notorious GDPR cookie consent prompts, intrusive push notifications, glorious permission requests, malicious third-party tracking, and offboarding experience:

Why Aren’t Privacy-Aware Interfaces a Default?

Imagine a beautiful, authentic historical street, paved with half-broken cobble stones, tiny vintage stores, and flourishing flowers randomly placed across the pathway. Sauntering along such charming streets is a wonderful experience, full of smells and sounds of the city that aren’t easy to capture in the daily stream of mundane tasks.

Now imagine the very same street packed with lookalike merchandise farms stacked right next to each other, plastered with promotional posters, blinking advertising, loud music, and repeating marketing messages fighting for your attention over and over and over again. Compared with the previous experience, that’s very different, and most likely much less enjoyable.

Unfortunately, in both of the scenarios above, the more often we walk down that same street, the more we become accustomed to what’s happening, and in the end these experiences become normal — and even expected — along that path. Over time, we tend to get used to the way things appear and function, and especially when it comes to advertising, over time we’ve learned fairly well how to dismiss the marketing messages streaming endlessly and loudly our way.

Not all marketing messages are ineffective, of course; in fact, most people are receptive to them, mostly because they are literally everywhere, often heavily personalized and hence relevant. We see them as an unnecessary evil that enables and finances our experience, be it reading an article, playing a game or watching a video. What came along with it, though, isn’t just visual noise and a substantial performance footprint of adverts, but also ever-increasing tracking, collection, and ongoing evaluation of private data.

If you’ve wondered why a product you looked up in a search engine one day keeps showing up in all your social channels over and over just a few hours later, that’s the power of data collection and retargeting at play.

As a result, many of the online experiences we attend to on a daily basis feel more broken and frustrating than refreshing and inspiring. Over years of daily training on the websites we love and hate so much, we’ve got used to it — and many of us no longer notice how distracting, invasive, and disrespectful the websites have become.

While boring pop-ups and annoying blinking ads might be easy to ignore or dismiss, sneaky push notifications, ambiguous copywriting, shady backdoors in seemingly friendly apps, and deceptive ads camouflaged as parts of the UI are nothing but a notorious, well-executed hustle. Not many website owners would willingly impose this kind of experience on their customers, and not many customers would knowingly return to a website that shared their private data for retargeting or reuse. With such experiences, trust and loyalty are at stake, and these days they are extremely rare and precious values that are hard to reacquire once they are lost.

Pop-ups are rarely friendly and respectful, as they interrupt the experience. However, Medium goes to extremes when trying to make the interruption friendly and humble with strong, thoughtful microcopy. (Large preview)

If we ask ourselves why honest interfaces haven’t made a breakthrough yet, bypassing and pushing away all the culprits out there, it’s not easy to find an answer at first. It’s not that designers want to manipulate customers, or that developers want to make experiences slower, or that marketeers are happy to endlessly frustrate and confuse users’ experience for the sake of one-off campaigns.

In a world where every brand demands immediate and uninterrupted attention, attention has become incredibly scarce, and so competing against loud guerrilla campaigns with a subtle, humble marketing message might feel remarkably inferior. Clever, subtle campaigns can be effective, but they need to be constantly invented anew to remain interesting — and there is no guarantee they actually will work. On the other hand, it’s much easier to rely on solutions that worked well in the past — they are predictable, easy to measure, and not too difficult to sell to clients.

In fact, we tend to rely on predictable A/B tests that give us clear answers for measurable, quantifiable insights. But when it comes to ethics and the long-term impact of an interface on loyalty and trust, we are out there in the blue. What we are missing is a clear, affordable strategy for meeting business requirements without resorting to questionable practices that proved to be effective in the past.

In most conversations I’ve had with marketing teams over the years, the main backlash against all the UX-focused, customer-protective changes in marketing was the simple fact that marketing teams didn’t believe for a second that they could be as competitive as good ol’ workhorse techniques. So while, of course, calm, ethical, and privacy-aware interfaces would benefit the user, moving away from the status quo would massively hurt business and make companies less competitive.

Sadly enough, they might be right. Most of us use well-known services and websites that have all the despicable practices we so love to hate. Tracking, and collection and manipulation of data are at the very core of their business models, which allow them to capitalize on it for advertising and selling purposes. In fact, they succeed, and for many users, trading privacy is an acceptable cost for all the wonderful benefits that all those giants provide for nothing. Beyond that, moving away from these benefits is remarkably hard, time-consuming, and just plain painful, so unless a company hurts its users on a level that goes way beyond harvesting and selling data, they are very unlikely to leave.

'Confirmshaming', one of the dark patterns used too frequently on the web. Image source: confirmshaming.tumblr. Many dark patterns are collected by Harry Brignull on darkpatterns.org. (Large preview)

Many of you might remember the golden days when the first mobile interfaces were clunky and weird and slow, and when everything seemed to be out of place, and we were desperately trying to fill all those magical rectangles on shiny new mobile phones with adaptive and pixel-perfect layouts.

Despite good intentions and wondrous ideas, many of our first interfaces weren’t great — they just weren’t good executions of potentially great ideas. As time passed, these interfaces slowly disappeared, replaced by solutions that were designed better, slowly carved out of thorough efforts in research and testing, and gradual, ongoing refinements. It’s rare we see and regularly use some of those old interfaces today. Sometimes they remain locked up in app ecosystems, never updated or redesigned, but the competition pushed them away hastily. They just aren’t competitive enough, because they weren’t comfortable enough to enable users to reach their goals.

I wonder if the same will happen with the new wave of privacy- and ethics-aware applications. Well-designed, small applications that do simple tasks very well, with a strong focus on ethical, respectful, and honest pixels, without shady backdoors and psychological tricks. We can’t expect giants to change overnight, but once these alternative solutions start succeeding, they might be forced to refine their models in response. I strongly believe that taking good care of users’ data can be a competitive advantage and a unique selling proposition that no other company in your niche has.

For that to happen, though, we need to understand common pain points that users have, and establish interface patterns that designers and developers could easily use. We’ll start with common privacy concerns and seemingly obvious interface components: privacy-related issues often raised in web forms.

Eliminating Privacy Concerns

So you designed a wonderful new feature: an option to connect your customers with their friends by importing contacts from Facebook, LinkedIn, Twitter, or perhaps even their contact list. Imagine the huge impact on your sign-ups if only a fraction of your existing customers choose to use the feature, connecting with dozens and hundreds of their friends on your wonderful platform! Unfortunately, the feature is likely to have difficulties taking off, not because it isn’t designed well, but because of the massive abuse of privacy that users have been exposed to over the years.

Remember that awkward conversation with a few friends wondering about an unusual invitation they received from you the other day? You didn’t mean to annoy your friends, of course, but the service you’ve just signed up to was happy to notify your friends on your behalf, without your explicit permission. Perhaps recommended default settings during installation contained a few too many checkboxes with ambiguous labels, or perhaps the app just wouldn’t work correctly otherwise. You didn’t think anything at the time, but you’ll definitely think twice next time, before leaving all of those checkboxes opted-in.

In general, when asked about what kinds of privacy issues customers seem to be worried about, the following concerns have been raised, in order of magnitude or severeness:

  1. Tracking and evaluating user preferences, location, etc.
  2. Convoluted privacy policy changes
  3. Lack of trust for free or freemium services
  4. Disturbing and annoying advertising in apps or on websites
  5. Targeting with commercial and political messages
  6. Unwanted notifications and marketing emails
  7. No proper control of personal data
  8. Exposing personal preferences to third parties
  9. Difficulty to delete personal details
  10. Difficulty to cancel or close account
  11. Safety of stored data on servers
  12. Uploading a photo of a credit card or passport scan
  13. Use of personal data for commercial purposes
  14. Exposing private messages and emails publicly
  15. Exposing search history publicly
  16. Social profiling by potential employers
  17. An app posting on user’s behalf
  18. Difficulty to export personal data
  19. Difficulty to cancel a subscription
  20. Hidden fees and costs not explicitly mentioned
  21. Importing contact details of friends
  22. Trolling and stalking online
  23. Data breach of login, password, and credit card details
  24. Hacked Gmail, Facebook, Twitter, or Instagram accounts

It’s quite astonishing to see how many concerns our humble interfaces raise, producing doubt, uncertainty, and skepticism in our customers.

They don’t come out of nowhere, though. In fact, conversations about privacy often share a common thread: dreadful previous experiences that users had to learn from — the hard way. Usually it’s not those password input nightmares or frustrating CAPTCHAs; instead, it’s credit card fraud after an online purchase, and never-ending emails from companies trying to lure you in; and unsolicited posts, check-ins, and recommendations graciously posted on user’s behalf. So it shouldn’t be very surprising that for most customers the default behavior and response for pretty much any request of personal data is “Block,” unless the app makes a strong, comprehensible case of why the permission should be granted.

This goes for importing contacts as much as for signing in with a social login: nobody wants to spam their friends with random invitations or have an app polluting their profile with automated check-in messages. On the other hand, anonymous data collection always wins. Whenever the word “anonymous” made its appearance in privacy policies, security updates, or web forms, customers were much less reluctant to share their personal data. They understood that the data is collected for marketing purposes, and wouldn’t be used to target them specifically, so they had no issues with it at all across the board. So if you need to gather some data, but don’t need to target every individual customer, you are likely to cause fewer concerns with your customers.

One of the most dreadful features out there: importing contacts from other social networks. Very often, customers associate this feature with nothing but annoying and irreversible spam. (Large preview)

In our interviews, users often spoke about “being burned in the past,” which is why they tend to be careful when granting permissions for any kind of data or activities online. Some users would have a dedicated credit card for online purchases, heavily protected with 2-factor authorization via their phone; others would have dedicated spam or throwaway email address for new accounts and registration, and yet others would never share very personal information in social networks. However, all these users were in a small minority, and most of them changed their attitude after they had experienced major privacy issues in the past.

We have to design our interfaces to relieve or eliminate these concerns. Obviously, this goes very much against dubious practices for tricking customers into posting, sharing, engaging, and adding value to our platforms, hence exposing their personal data. This might also work against the business goals of the company that is heavily dependent on advertising and maximizing customer fees. However, there is a fine line between techniques used to keep users on the site and exploiting their privacy. We need to eliminate privacy concerns, and there are a few straightforward ways of doing so.

Privacy In Web Forms

While it’s been a good practice to avoid optional input fields and ask only for the information required to complete the form, in the real world web forms are often poisoned with seemingly random questions that appear absolutely irrelevant in the user’s context.

The reason for this isn’t necessarily malicious in intent, but rather technical debt, as the site might be using a site-wide component for all forms, and it simply doesn’t allow for enough flexibility to fine-tune the forms appropriately. For example, when asking the user for their name, we’ve become accustomed to breaking a full name into first name and family name in our forms, sometimes with a middle name in between.

From a technical perspective, it’s much easier to save structured data this way, but when asking for a person’s name in a real-life conversation we hardly ever ask specifically for their first name or last name — instead we ask for their name. In some countries, such as Indonesia, the last name is very uncommon, and in others a middle name is extremely rare. Hence, combining the input into a single “Full name” input field seems most plausible, yet in most web forms out there, it’s rarely the case.

That means that in practice, seemingly random questions have to be asked at times, even though they aren’t really required. On the other hand, marketing teams often need personal information about their customers to be able to capture and present the reach and specifics of the audience to their potential advertisers. Gender, age, preferences, habits, purchasing behavior and everything in between falls under this category. And that’s not the kind of data that users are happy to willingly hand over without a legitimate reason.

When running interviews with users, we’ve identified a few common privacy-related data points that were considered to be of a “too private, too intrusive” nature. Obviously, it heavily depends on the context too. Shipping address is perfectly acceptable at a checkout, but would be out of place in an account sign-up form. Gender would be inappropriate in an anonymous donation form, but would make perfect sense on a dating website.

In general, users tend to raise concerns when asked about the following details (in order of magnitude or severeness):

  • Title
  • Gender
  • Age
  • Birthday
  • Phone number
  • Personal photo
  • Credit card or bank details
  • Signature
  • Passport details
  • Social security number

Admittedly, only a few users would abandon a form just because it’s asking for their title or gender. However, if the questions are framed in an inappropriate way, or many of the questions seem to be irrelevant, all these disturbances start to add up, raising doubt and uncertainty at the point when we, as designers, want to ensure clarity and get all potential disturbances out of the way. To avoid that, we need to explain why we need a user’s data, and provide a way out should the customer want to keep the data private.

Explain Why You Need A User’s Data

With numerous data breaches, scam mails, and phishing websites permanently reminding users of the potential implications of data misuse, they rightfully have doubts and concerns about sharing private information online. We rarely have second thoughts when asked to add a few seemingly harmless radio buttons and input fields to a form, but the result is often not only a decrease in conversion, but a long-lasting mistrust of customers towards the brand and its products.

As a result, you might end up with people submitting random data just to “pass through the gates,” as one interviewer called it. Some people would creatively fight back by providing random answers to “mess up the results.” When asked for a phone number, some would type in the correct number first (mostly because they expect the input to be validating the correct format of the phone number), and then modify a few digits to avoid spam calls. In fact, the more personal data a website is attempting to gather, the more likely the input is to be purposefully incorrect.

Just-in-time explanations with the info tooltip in forms. Explaining why you need a user’s data matters. Image source: Claire Barrett. (Large preview)

However, customers rarely have concerns when they fully understand why particular private information is required; the doubts occur when private information is required without an adequate explanation. While it might be obvious to the company why it needs particular details about its users, it might not be obvious to users at all. Instead, it might appear suspicious and confusing — mostly owing to the simple lack of understanding of why it’s actually needed and if it might be misused.

As a rule of thumb, it’s always a good idea to explain exactly why the private data is required. For example, a phone number might be required to contact the customer in case a package can’t be delivered. Their birthday might be required to customize a special gift for a loyal customer. Passport details might be required for identity verification when setting up a new bank account.

All these reasons have to be explicitly stated as a hint next to the input field; for instance, revealed on tap or click behind an info icon, to avoid confusion and misunderstanding. For the same reason, if you’re aware that some questions might feel weird for a particular set of customers, make them optional and indicate they can be skipped if they seem to be not applicable.

It’s also a good idea to reassure the user that you take their privacy seriously, and that their data will be protected and, most importantly, will not be used for any targeted marketing purposes nor shared with third parties. Surprisingly, the latter seemed to be even more important to a large number of users than the former, as they didn’t want their data to “end up in random, inconvenient, places.”

Always Provide A Way Out

We have all been there: the reality is rarely a set of straightforward binary choices, and more often than not, it’s a spectrum of possibilities, without an obvious set of predefined options. Yet isn’t it ironic that our interfaces usually expect a single, unambiguous answer for reasonably ambiguous questions?

When designing the options for title and gender, we tend to think in common patterns, providing a strict set of predictable options, basically deciding how a person should identify themselves. It’s not our place to do so, though. Not surprising, then, that for some users the options felt “patronizing and disrespectful.” A common area where this problem occurs frequently is the framing and wording of questions. Gender-neutral wording is less intrusive and more respectful. Instead of referring to a specific gender, you could keep the tone more general; for instance, asking for the age of a spouse rather than wife or husband.

The world is rarely binary. Always provide a way out when specifying gender. Check the article on inclusive form design for gender diversity. Also, askingaboutgender.tumblr.com collects good UX practices for collecting and displaying information about gender. (Large preview)

To avoid lock-in, it’s a good strategy to always provide a way out should the customer want to specify input on their own, or not want to share that data. For title and gender it might be as easy as providing an additional input field that would allow customers to specify a custom input. A checkbox with “I’d rather not say” or “I’d like to skip this question” would be a simple way out if customers prefer to avoid the question altogether.

Always Ask For Exactly What You Need, Never More

What question seems to be more personal to you: your age or your birthday? In conversations with users, the former was perceived much less personal than the date of birth, mostly because the former is more broad and general. In reality, although companies rarely need a specific date of birth, the required input contains masks for the day, month, and year.

There are usually three reasons for that. On the one side, marketing teams often want to know the age of the customer to understand the demographics of the service — for them, a specific date of birth isn’t really necessary. On the other side, when a company wants to send out custom gifts to a customer on their birthday, they do need the day and the month — but not necessarily the year.

Never ask more than you need. For its age prompt, Carlsberg used to ask only the year of birth, and ask for month and day only if necessary to verify that the customer is over 18 years old. (Large preview)

Finally, depending on local regulations, it might be a legal requirement to verify that a website visitor is over a certain age threshold. In that case, it might be enough to ask the customer if they are over 18 rather than asking them for their date of birth, or ask them only for the year of birth first. If they are definitely younger than 18, they might not be able to access the site. If they are definitely older than 18, they can access the site. The prompts for the month should appear only if the user might be just below or just above 18 (born 18 years ago). Finally, the day input would appear only if it’s absolutely necessary to check if the user is old enough to enter the site.

When designing an input for age or date of birth, consider the specific data points that you need and design the form accordingly. Try to minimize the amount of input required, and (again) explain why for what purpose you need that input.

When Asking For Sensitive Details, Prepare Customers Ahead Of Time

While users can find a way to “pass through the gates” with title, gender, age, birthday, and even phone number input, they will have a very difficult time finding a way out when asked for their photo, signature, credit card, passport details, or social security number. These details are very personal and customers tend to spend a disproportionate amount of time filling in these input fields, slowing down massively as they do so. Often this area would be where the users would spend most of their time, and also where they abandon most frequently.

When asked to type in this kind of data, customers would often linger around the interface, scanning it from top to bottom and right to left or scrolling up and down — almost hoping to detect a reassuring confirmation that their data will be processed securely. Almost nobody would mindlessly load their personal photo or type in their passport details without a brief reassurance phase, both on mobile and on desktop.

There are a few strategies to alleviate the concerns users might have at this point. Because users slow down significantly in their progress, always provide an option to save and finish later, as some users might not have the details to hand. You could ask for their phone number or email to send a reminder a few hours or days later. Additionally, consider reassuring users with a noticeable hint or even pop-up that you take their privacy seriously and that you would never share details with third party.

It might also be a good idea to prepare the customer for the required input ahead of time. You could ask them to prepare their passport and bank account details before they even start filling in the form, just to set the right expectations.

The more sensitive private details are, the less room for amusing remarks there should be. The voice and tone of accompanying copywriting matter a lot, just like the copy of error messages, which should be adaptive and concise, informing the user about a problem and how it could be fixed.

Don’t Expect Accurate Data For Temporary Accounts

You’ve been here before: you might be having a quick bite in a coffee shop, or waiting for your spouse in a shopping mall, or spending a few layover hours at an airport. It probably won’t take you long to discover a free Wi-Fi hotspot and connect to it. Suddenly, a gracious pop-up window makes its glorious appearance, informing you about 15 free minutes of Wi-Fi, along with a versatile repertoire of lengthy text passages, auto-playing video adverts, painfully small buttons, tiny checkboxes, and miniature legal notices. Your gaze goes straight to where it matters most: the sign-up area prompting you to sign in with Facebook, Twitter, Instagram, SMS, or email. Which option would you choose, and why?

Throughout our interviews, we’ve noticed the same behavior over and over again: whenever customers felt that they were in a temporary place or state (that is, they didn’t feel they might be returning any time soon), they were very unlikely to provide accurate personal data. This goes for Wi-Fi in airports as much as in restaurants and shopping malls. Required sign-ups were usually associated with unsolicited marketing emails, mostly annoyingly irrelevant. After all, who’d love to receive notifications from Schiphol Airport if they’ve only flown from it once?

Every time a temporary account requires email, expect a throwaway email to be entered. Such forms just don’t work, so it’s about time to stop designing them. More examples of such interfaces can be found here. (Large preview)

In fact, users were most unlikely to log in with Facebook, Twitter, or Instagram, because they were worried about third-party services posting on their behalf (we’ll cover these issues in a bit more detail later in this series). Many customers just didn’t feel comfortable letting an unknown third party into what they consider to be their “private personal sphere.” Both SMS and email were perfectly acceptable, yet especially when traveling, many customers didn’t know for sure if they’d be charged for text messages or not, and referred email instead. Hence, it’s critical to never enforce a social sign-in and provide a way out with an SMS confirmation or an email sign-up.

With the email option chosen, however, only a few people would actually provide their active personal or business emails when signing up. Some people keep a trash email, used for new accounts, quick confirmations, random newsletters and printing documents in a print shop around the corner. That email is hardly ever checked, and often full of spam, random newsletters, and irrelevant marketing emails. Chances are high that your carefully crafted messages will be enjoying the good company of these messages, usually unopened and unread.

Other people, when prompted to type in their email, provide a random non-existent @gmail.com account, hoping that no verification will be required. If it is required after all, they usually return and provide the least important email account, often a trash email.

What happens if the service tries to ensure the validity of the email by requiring user to retype their email one more time? A good number will try to copy-paste their input into the email verification input field, unless the website blocks copy-paste or the email input is split into two inputs, one for the segment before the @ symbol, and one after it. It shouldn’t be too surprising that not a single customer was particularly thrilled about these options.

Users seem to highly value a very strict separation between things that matter to them and things that don’t matter to them — especially in their email inbox. Being burned with annoying marketing emails in the past, they are more cautious of letting brands into their private sphere. To get their attention, we need to give customers a good reason to sign up with an active email account; for example, to qualify for free shipping, or auto-applied discounts for loyal customers, or an immediate discount for next purchases, or a free coffee for the next visit. One way or another, we need to deserve their trust, which is not granted by default most of the time.

Don’t Store Private Data By Default

When setting up an account, it’s common to see interfaces asking for permission to store personal data for future use. Of course, sometimes the reason for it comes from the objective to nudge customers into easy repurchasing on future visits. Often it’s a helpful feature that allows customers to avoid retyping and save time with the next order. However, not every customer will ever have a second order, and nobody will be amused by an unexpected call from the marketing department about a brand new offering.

Customers have no issues with storing gender and date of birth once they’ve provided it, and seem to be likely to allow phone numbers to be stored, but they are less likely to store credit card details and signature and passport details.

Some customers would even go as far as taking the time to write a dedicated email requesting passport details to be removed after a successful identity verification.

Hence, it’s plausible to never store private data by default, and always ask users for permission, unchecking the checkbox by default. Also, consider storing details temporarily — for a few weeks, for example — and inform the user about this behavior as they are signing up.

In general, the more private the required information is, the more effort should be spent to clearly explain how this information will be processed and secured. While a subtle text hint might be enough when asking for a phone number, passport details might need a larger section, highlighting why they are required along with all the efforts put into protecting user’s privacy.

Users Watch Out For Privacy Traps

The more your interface is trying to get silent consent from customers — be it a subscription to email, use of personal data, or pretty much anything else — the more customers seem to be focused on getting this done, their way. It might seem like a tiny mischievous checkbox (opted-in by default) might be overlooked, yet in practice customers go to extremes hitting that checkbox, sometimes as far as tapping it with a pinky finger on their mobile phones.

With a fundamental mistrust of our interfaces, customers have become accustomed to being cautious online. So they watch out for privacy traps, and have built up their own strategies to deal with malicious and inquisitive web forms. As such, on a daily basis, they resort to temporary email providers, fake names and email addresses, invalid phone numbers, and random postal codes. In that light, being respectful and humble when asking for personal data can be a remarkably refreshing experience, which many customers don’t expect. This also goes for a pattern that has become quite a nuisance recently: the omnipresent cookie settings prompt.

In the next article of the series, we’ll look into these notorious GDPR cookie consent prompts, and how we can design the experience around them better, and with our users’ privacy in mind.

(og, yk, il)
Categories: Around The Web

Going Serverless With Cloudflare Workers

Thu, 04/04/2019 - 9:00am
Going Serverless With Cloudflare Workers Going Serverless With Cloudflare Workers Leonardo Losoviz 2019-04-04T15:00:34+02:00 2019-04-18T19:36:01+00:00

(This is a sponsored article.) It is a truth universally acknowledged, that a website in pursuit of success must be in want of speed. And so, it goes serverless.

At its core, serverless is a strategy for a website’s architecture, based on deploying static files (the good old HTML, CSS and image files) on cloud-based hosting, and augmenting the website’s capabilities by accessing cloud-based, charge-per-use dynamic functionality. There is nothing mystical or mysterious about serverless: its end result is simply a website or application.

In spite of its name, “serverless” doesn’t mean “without a server”. It simply means “without my own server”. This means that my site is still hosted on some server, but by offloading this responsibility to the cloud services provider, I can devote all my energies to developing my own product (the website) and not have to worry about the infrastructure.

Serverless is very appealing for several reasons:

  • Low-cost
    You only pay for what you use. Hosting static files on the cloud can cost just a few cents a month (or even be free in some cases).
  • Fast
    Static files can be delivered to the user from a Content Delivery Network (CDN) located near the user.
  • Secure
    The cloud provider constantly keeps the underlying platform up-to-date.
  • Easy to scale
    The cloud provider’s business is to scale up the infrastructure on demand.

Serverless is also becoming increasingly popular due to the increasing availability of services offered by cloud providers, simple-yet-powerful template-based static site generators (such as Jekyll, Hugo or Gatsby) and convenient ways to feed data into the process (such as through one of the many git based CMS’s).

The Network Is The Computer: Introducing Cloudflare Workers

Cloudflare, one of the world’s largest cloud network platforms, is well versed in providing the benefits we are after through serverless: for some time now they have made their extensive CDN available to make our sites fast, offered DDoS protection to make our sites secure, and made their DNS service free so we could afford having privacy on the Internet, among many other services.

Their new serverless offering, Cloudflare Workers (or simply “Workers”), runs on the same global cloud network of over 165 data centers that powers those services. Cloudflare Workers is a service that provides a lightweight JavaScript execution environment to augment existing applications or create new ones.

Being stacked on top of Cloudflare’s widespread network makes Cloudflare Workers a big deal. Cloudflare can scale up its infrastructure based on spikes in demand, serving a serverless application from locations on five continents and supporting millions of users, making our applications fast, reliable, and scalable.

The Cloudflare network is powered by 165 data centers around the world. (Large preview)

On top of that, Cloudflare Workers provides unique features that make it an even more compelling service. Let’s explore these in detail.

Architecture Based On V8 For Fast Access And Low Cost

The Cloudflare engineers went out of their way to architect Workers, as they proudly explain in depth. Whereas almost every provider offering cloud computing has an architecture based on containers and virtual machines, Workers uses “Isolates”, the technology that allows V8 (Google Chrome’s JavaScript engine) to run thousands of processes on a single server in an efficient and secure manner.

Compared to virtual machines, Isolates greatly reduce the overhead required to execute user code, which translates into faster execution and lower use of memory.

Isolates allow thousands of processes to run efficiently on a single machine (Large preview)

Cloudflare Workers is not the first serverless cloud computing platform in operation: for instance, Amazon has offered AWS Lambda and Lambda@Edge. However, as a consequence of the lower overhead produced by Isolates, Cloudflare claims that when executing a similar task, Workers beats the competition where it matters most: speed and money.

Lower Price

While a Worker offering 50 milliseconds of CPU costs $0.50 per million requests, the equivalent Lambda costs $1.84 per million. Hence, running Workers ends up being around 3x cheaper than Lambda per CPU-cycle.

Faster Access

The Cloudflare team ran tests comparing Workers against AWS Lambda and Lambda@Edge, and came to the conclusion that Workers is 441% faster than a Lambda function and 192% faster than Lambda@Edge.

This chart shows what percentage of requests to Lambda, Lambda@Edge, and Cloudflare Workers were faster than a given number of milliseconds. (Large preview)

The better performance achieved by Cloudflare Workers is confirmed by the third-party site serverless-benchmark.com, which measures the performance of serverless providers and provides continuously updated statistics.

Statistics for Overhead (the time from request to response without the actual time the function took) and Cold start (the latency it takes a function to respond to the event) for Cloudflare Workers and its competitors. (Large preview) Coded In JavaScript, Modeled On The Service Workers API

Because it is based on V8, programming for Workers is done in those languages supported by V8: JavaScript and languages that support compilation to WebAssembly, such as Go and Rust. V8’s code is merged into Workers at least once a week, so we can always expect it to support the latest implemented flavor of ECMAScript.

Workers are modeled on the Service Workers available in modern web browsers, and they use the same API whenever possible. This is significant: Because Service Workers are part of the foundation to create a Progressive Web App (PWA), creating Workers is done through an API that developers are already familiar with (or may be in the process of learning) for creating modern web applications.

In addition, relying on the Service Workers API allows developers to boost their productivity since it allows isomorphism of code, i.e. the same code that powers the Service Worker can be used for a Cloudflare Worker. Even though this is not always feasible because of the different contexts (while a Service Worker runs in the browser, the Cloudflare Worker runs in the network), certain use cases could apply to both contexts.

For instance, among the Service Workers recipes described in serviceworke.rs, recipes for API Analytics, Load Balancer, and Dependency Injection can be implemented on both the client side and the network using the same code (or most of it). And even when the functionality makes sense only on either the client-side or the network, it can be partly implemented using chunks of code that are context-agnostic and can be conveniently reused.

Furthermore, using the same API for Service Workers and Cloudflare Workers makes it easy to provide progressive enhancement. An application can execute a Service Worker whenever possible, and fall back on a Cloudflare Worker when the user visits the site for the first time (when the Service Worker is still not installed on the client), or when Service Workers are not supported (for instance, when the browser is old, or it is just Opera mini).

Finally, relying on a unique API simplifies the overall language stack, once again making it easier for the developer to get more work done. For instance, defining a caching policy for the CDN in Varnish is done through the Varnish Configuration Language, which has its own syntax. Cloudflare Workers, though, enables develpers to code the same tasks through, you guessed it, the Service Workers API.

It Leverages The Modern Toolbox

In addition to Workers not requiring developers to learn any new language or API, it follows modern conventions and provides integration with popular technologies, allowing us to use our current toolbox:

Let’s See Some Practical Examples

It’s time to have fun! Let’s play with some Workers based on common use cases to see how we can augment our sites or even create new ones.

Cloudflare makes available a browser-based testing tool, the Cloudflare Workers Playground. This tool is very comprehensive and easy to use: simply copy the Worker script on the left-side panel, execute it against the URL defined on the top-right bar, see the results on the ‘Preview‘ tab and the source code on the ‘Testing‘ tab (from where we can also add custom headers), and execute console.log inside the script to bring the results on the DevTools on the bottom-right. To share (or also store) your script, you can simply copy your browser’s URL at that point in time.

The Playground allows us to test-drive our Cloudflare Workers (Large preview)

Starting with the Playground will take you far, but, at some point, you will want to test on the actual Cloudflare network and, even better, deploy your scripts for production. For this, your site must be set up with Cloudflare. If you already are a Cloudflare user, simply sign in, navigate to the ‘Workers’ tab on the dashboard, and you are ready to go.

If you are not a Cloudflare user, you can either sign up, or you can request a workers.dev subdomain, under which you will soon be able to deploy your Workers. The workers.dev site is currently accepting reservations of subdomains, so hurry up and reserve yours before it is taken by someone else!

workers.dev is currently accepting reservations of subdomains (Large preview)

The recipes below have been taken from the Cloudflare Workers Recipe cookbook, from the examples repository in Github, and from the Cloudflare blog. Each example has a link to the script code in the Playground.

Static Site Hosting

The most straightforward use case for Workers is to create a new site, dynamically responding to requests without needing to connect to an origin server at all. So, hello world!

addEventListener('fetch', event => { event.respondWith(new Response('<html><body><p>Hello world!</p></body></html>')) })

See code in Playground

Instead of printing the HTML output in the script, we can also host static HTML files with some hosting service, and fetch these with a simple Worker script. Indeed, the Worker script can retrieve the content of any file available on the Internet: While the domain under which the Worker is executed must be handled by Cloudflare, the origin website from which the script fetches content does not have to. And this works not just for HTML pages, but also for CSS and JS assets, images, and everything else.

The script below, for instance, renders a page that is hosted under DigitalOcean Spaces:

addEventListener('fetch', event => { event.respondWith(handleRequest(event.request)) }) async function handleRequest(request) { const parsedUrl = new URL(request.url) let path = parsedUrl.pathname let lastSegment = path.substring(path.lastIndexOf('/')) if (lastSegment.indexOf('.') === -1) { path += '/index.html' } return fetch("https://cloudflare-example-space.nyc3.digitaloceanspaces.com" + path) }

See code in Playground

Building APIs

A prominent use case for Workers is creating APIs. For instance, the script below powers an API service that states if a domain redirects to HTTPS or not:

addEventListener('fetch', event => { event.respondWith(handleRequest(event.request)) }) /** * Fetch a request and follow redirects * @param {Request} request */ async function handleRequest(request) { let headers = new Headers({ 'Content-Type': 'text/html', 'Access-Control-Allow-Origin': '*' }) const SECURE_RESPONSE = new Response('secure', {status: 200, headers: headers}) const INSECURE_RESPONSE = new Response('not secure', {status: 200, headers: headers}) const NO_SUCH_SITE = new Response('website not found', {status: 200, headers: headers}) let domain = new URL(request.url).searchParams.get('domain') if(domain === null) { return new Response('Please pass in domain via query string', {status: 404}) } try { let resp = await fetch(`http://${domain}`, {headers: {'User-Agent': request.headers.get('User-Agent')}}) if(resp.redirected == true && resp.url.startsWith('https')) { return SECURE_RESPONSE } else if(resp.redirected == false && resp.status == 502) { return NO_SUCH_SITE } else { return INSECURE_RESPONSE } } catch (e) { return new Response(`Something went wrong ${e}`, {status: 404}) } }

See code in Playground

Workers can also connect to several origins in parallel and combine all the responses into a single response. For instance, the script below powers an API service that simultaneously retrieves the price for several cryptocurrency coins:

addEventListener('fetch', event => { event.respondWith(fetchAndApply(event.request)) }) /** * Make multiple requests, * aggregate the responses and * send it back as a single response */ async function fetchAndApply(request) { const init = { method: 'GET', headers: {'Authorization': 'XXXXXX'} } const [btcResp, ethResp, ltcResp] = await Promise.all([ fetch('https://api.coinbase.com/v2/prices/BTC-USD/spot', init), fetch('https://api.coinbase.com/v2/prices/ETH-USD/spot', init), fetch('https://api.coinbase.com/v2/prices/LTC-USD/spot', init) ]) const btc = await btcResp.json() const eth = await ethResp.json() const ltc = await ltcResp.json() let combined = {} combined['btc'] = btc['data'].amount combined['ltc'] = ltc['data'].amount combined['eth'] = eth['data'].amount const responseInit = { headers: {'Content-Type': 'application/json'} } return new Response(JSON.stringify(combined), responseInit) }

See code in Playground

Making the API highly dynamic by retrieving data from a database is covered too! Workers KV is a global, low-latency, key-value data store. It is optimized for quick and frequent reads, and data should be saved sparingly. Then, it is a sensible approach to input data through the Cloudflare API:

curl "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/storage/kv/namespaces/$NAMESPACE_ID/values/first-key" \ -X PUT \ -H "X-Auth-Email: $CLOUDFLARE_EMAIL" \ -H "X-Auth-Key: $CLOUDFLARE_AUTH_KEY" \ --data 'My first value!'

And then the values can be read from within the Worker script:

addEventListener('fetch', event => { event.respondWith(handleRequest(event.request)) }) async function handleRequest(request) { const value = await FIRST_KV_NAMESPACE.get("first-key") if (value === null) return new Response("Value not found", {status: 404}) return new Response(value) }

At the time of writing, KV is still in beta and released only to beta testers. If you are interested in testing it out, you can reach out to the Cloudflare team and request access.


Cloudflare detects the origin IP of the incoming request and appends a two-letter country code to header ‘Cf-Ipcountry’. The script below reads this header, obtains the country code, and then redirects to the corresponding site version if it exists:

addEventListener('fetch', event => { event.respondWith(fetchAndApply(event.request)) }) async function fetchAndApply(request) { const country = request.headers.get('Cf-Ipcountry').toLowerCase() let url = new URL(request.url) const target_url = 'https://' + url.hostname + '/' + country const target_url_response = await fetch(target_url) if(target_url_response.status === 200) { return new Response('', { status: 302, headers: { 'Location': target_url } }) } else { return fetch(request) } }

See code in Playground

A similar approach can apply to implement load balancing, choosing from among multiple origins to improve speed or reliability.

Enhanced Security

The scripts below add security rules and filters to block unwanted visitors and bots.

Ignore the POST and PUT HTTP requests:

addEventListener('fetch', event => { event.respondWith(fetchAndApply(event.request)) }) async function fetchAndApply(request) { if (request.method === 'POST' || request.method === 'PUT') { return new Response('Sorry, this page is not available.', { status: 403, statusText: 'Forbidden' }) } return fetch(request) }

See code in Playground

Deny a spider or crawler:

addEventListener('fetch', event => { event.respondWith(fetchAndApply(event.request)) }) async function fetchAndApply(request) { if (request.headers.get('user-agent').includes('annoying_robot')) { return new Response('Sorry, this page is not available.', { status: 403, statusText: 'Forbidden' }) } return fetch(request) }

See code in Playground

Prevent a specific IP from connecting:

addEventListener('fetch', event => { event.respondWith(fetchAndApply(event.request)) }) async function fetchAndApply(request) { if (request.headers.get('cf-connecting-ip') === '') { return new Response('Sorry, this page is not available.', { status: 403, statusText: 'Forbidden' }) } return fetch(request) }

See code in Playground

A/B Testing

We can easily create a Worker to control A/B tests:

addEventListener('fetch', event => { event.respondWith(fetchAndApply(event.request)) }) async function fetchAndApply(request) { const name = 'experiment-0' let group // 'control' or 'test', set below let isNew = false // is the group newly-assigned? // Determine which group this request is in. const cookie = request.headers.get('Cookie') if (cookie && cookie.includes(`${name}=control`)) { group = 'control' } else if (cookie && cookie.includes(`${name}=test`)) { group = 'test' } else { // 50/50 Split group = Math.random() < 0.5 ? 'control' : 'test' isNew = true } // We'll prefix the request path with the experiment name. This way, // the origin server merely has to have two copies of the site under // top-level directories named "control" and "test". let url = new URL(request.url) // Note that `url.pathname` always begins with a `/`, so we don't // need to explicitly add one after `${group}`. url.pathname = `/${group}${url.pathname}` request = new Request(url, request) let response = await fetch(request) if (isNew) { // The experiment was newly-assigned, so add a Set-Cookie header // to the response. We need to re-construct the response to make // the headers mutable. response = new Response(response.body, response) response.headers.append('Set-Cookie', `${name}=${group}; path=/`) } return response }

See code in Playground

Serving Device-Based Content

The script below delivers different content based on the device being used:

addEventListener('fetch', event => { event.respondWith(fetchAndApply(event.request)) }) async function fetchAndApply(request) { let uaSuffix = '' const ua = request.headers.get('user-agent') if (ua.match(/iphone/i) || ua.match(/ipod/i)) { uaSuffix = '/mobile' } else if (ua.match(/ipad/i)) { uaSuffix = '/tablet' } return fetch(request.url + uaSuffix, request) }

See code in Playground

Conditional Routing

By passing custom values through headers, we can fetch most-specific content:

addEventListener('fetch', event => { event.respondWith(fetchAndApply(event.request)) }) async function fetchAndApply(request) { let suffix = '' //Assuming that the client is sending a custom header const cryptoCurrency = request.headers.get('X-Crypto-Currency') if (cryptoCurrency === 'BTC') { suffix = '/btc' } else if (cryptoCurrency === 'XRP') { suffix = '/xrp' } else if (cryptoCurrency === 'ETH') { suffix = '/eth' } return fetch(request.url + suffix, request) }

See code in Playground

Enhanced Performance

Workers makes available a Cache API through which we can save computationally intensive data and have it ready for immediate use from then on:

async function handleRequest(event) { let cache = caches.default let response = await cache.match(event.request) if (!response) { response = doSuperComputationallyHeavyThing() event.waitUntil(cache.put(event.request, response.clone())) } return response }

For instance, through the Cache API we can store GraphQL requests whose results have not changed:

async function handleRequest(event) { let cache = caches.default let response = await cache.match(event.request) if (!response){ response = await fetch(event.request) if (response.ok) { event.waitUntil(cache.put(event.request, response.clone())) } } return response } Many Others

The list of useful applications goes on and on. Below are links to several additional examples:

Wrapping Up: “The Network Is The Computer”

Because speed matters, websites are going serverless. Cloudflare Workers is a new offering that enables this transition. It blurs the boundaries between the computer and the network, enabling developers to deploy apps globally that run on the fabric of the Internet itself, leveraging Cloudflare’s worldwide network of servers to run our code near where our users are located. It is fast, cheap, and secure, and it scales as much as we need it.

If you want to find out more, check it out or ask the community.

Categories: Around The Web

Managing Z-Index In A Component-Based Web Application

Wed, 04/03/2019 - 8:00am
Managing Z-Index In A Component-Based Web Application Managing Z-Index In A Component-Based Web Application Pavel Pomerantsev 2019-04-03T14:00:08+02:00 2019-04-18T19:36:01+00:00

If you’ve done any complex web UI development, you must have at least once furiously tried driving an element’s z-index up to thousands, only to see that it’s not helping position it on top of some other element, whose z-index is lower or even not defined at all.

Why does that happen? And more importantly, how to avoid such issues?

In this article, I’ll recap what z-index actually is and how you can stop guessing whether it might work in any specific case and start treating it just like any other convenient tool.

The Hierarchy Of Stacking Contexts

If you imagine the webpage as having three dimensions, then z-index is a property that defines the z coordinate of an element (also called its “stacking order”): the larger the value, the closer the element is to the observer. You can also think of it as a property affecting paint order, and this will in fact be more correct since the screen is a two-dimensional grid of pixels. So, the larger the z-index value, the later the element is painted on the page.

There is, however, one major complication. The z-index value space is not flat — it’s hierarchical. An element can create a stacking context which becomes the root for z-index values of its descendants. It would be best to explain the concept of stacking contexts by using an example.

The document body has five div descendants: div1, div2, div3, div1-1, and div2-1. They’re all absolutely positioned and overlap with each other. div1-1 is a child of div1, and div2-1 is a child of div2.

See the Pen stacking-contexts by Pavel Pomerantsev.

See on Codepen

Let’s try to understand why we see what we see. There are quite elaborate rules to determine paint order, but here we only need to compare two things:

  • z-index Values
    If an element has a higher z-index, it’s painted later.
  • Source Order
    If z-index values are the same, then the later it’s in the source, the later it’s painted.

So if we don’t take stacking contexts into account, the order should be as follows:

  • div1
  • div2
  • div3
  • div1-1
  • div2-1

Note that div2-1 is in fact overlapped by div3. Why is that happening?

If an element is said to create a stacking context, it creates a basis for its children’s z-index values, so they’re never compared with anything outside the stacking context when determining paint order. To put it another way, when an element creating a stacking context is painted, all its children are painted right after it and before any of its siblings.

Going back to the example, the actual paint order of body’s descendant divs is:

  • div1
  • div2
  • div3
  • div1-1

Notice the absence of div2-1 in the list — it’s a child of div2 which creates a stacking context (because it’s an absolutely positioned element with a z-index other than the default value of auto), so it’s painted after div2, but before div3.

div1 doesn’t create a stacking context, because its implicit z-index value is auto, so div1-1 (its child) is painted after div2 and div3 (since its z-index, 10, is larger than that of div2 and div3).

Don’t worry if you didn’t fully grasp this on first reading. There’s a bunch of online resources that do a great job in explaining these concepts in more detail:

Note: It’s also great to be familiar with general paint order rules (which are actually quite complex).

The main point of this piece, however, is how to deal with z-index when your page is composed of dozens and hundreds of components, each potentially having children with z-index defined.

One of the most popular articles on z-index proposes grouping all z-index values in one place, but comparing those values doesn’t make sense if they don’t belong to the same stacking context (which might not be easy to achieve in a large application).

Here’s an example. Let’s say we have a page with header and main sections. The main section for some reason has to have position: relative and z-index: 1.

See the Pen z-index-step1 by Pavel Pomerantsev.

See on Codepen

We’re using a component architecture here, so CSS for the root component and every child component is defined in dedicated sections. In practice, components would live in separate files, and the markup would be generated using a JavaScript library of your choice, like React, but for demonstration purposes it’s fine to have everything together.

Now, imagine we’re tasked with creating a dropdown menu in the header. It has to be stacked on top of the main section, of course, so we’ll give it a z-index of 10:

See the Pen z-index-step2 by Pavel Pomerantsev.

See on Codepen

Now, a few months later, in order to make something unrelated work better, we apply the translateZ hack to the header.

See the Pen z-index-step3 by Pavel Pomerantsev.

See on Codepen

As you can see, the layout is now broken. An element with z-index: 1 sits on top of an element with z-index: 10, in the absence of any other z-index rules. The reason is that the header now creates a stacking context — it’s an element with a transform property whose value is anything other than none (see full rules) and its own z-index (0 by default) is lower than that of the main section (1).

The solution is straightforward: give the header a z-index value of 2, and it’ll be fixed.

See the Pen z-index-step4 by Pavel Pomerantsev.

See on Codepen

The question is, how are we supposed to come to this solution if we have components within components within components, each having elements with different z-indices? How can we be sure that changing z-index of the header won’t break anything else?

The answer is a convention that eliminates the need for guesswork, and it’s the following: changing z-indices within a component should only affect that component, and nothing else. To put it differently, when dealing with z-index values in a certain CSS file, we should ideally only concern ourselves with other values in that same file.

Achieving it is easy. We should simply make sure that the root of every component creates a stacking context. The easiest way to do it is to give it position and z-index values other than the default ones (which are static and auto, respectively).

Here’s one of the ways to structure the application. It uses more elements than the previous one, but computation associated with extra DOM elements is cheap whereas developer’s time (a lot of which can sometimes be spent on debugging stacking issues) is definitely not.

See the Pen z-index-step5 by Pavel Pomerantsev.

See on Codepen
  • header__container and main__container both have position: relative and z-index: 0;
  • header__overlay now has z-index: 1 (we don’t need a large value since it’s only going to compete for stacking order with other elements within the header);
  • root__header now has z-index: 2, whereas root__main keeps its z-index: 1, and this is what makes the two siblings stack correctly.

(Note also that both have position: relative since z-index doesn’t apply to statically positioned elements.)

If we look at the header code now, we’ll notice that we can remove the z-index property from both the container and the overlay altogether because the overlay is the only positioned element there. Likewise, the z-index is not required on the main container. This is the biggest benefit of the proposed approach: when looking at z-indices, it’s only the component itself that matters, not its context.

See the Pen z-index-step6 by Pavel Pomerantsev.

See on Codepen

Such an architecture is not without its drawbacks. It makes the application more predictable at the expense of some flexibility. For example, you won’t be able to create such overlays inside both the header and the main section:

See the Pen z-index-step7 by Pavel Pomerantsev.

See on Codepen

In my experience, however, this is rarely a problem. You could make the overlay in the main section go down instead of up, in order for it to not intersect with the header. Or, if you really needed it to go up, you could inject the overlay HTML at the end of the body and give it a large z-index (“large” being whatever’s larger than those of other sections at the top level). In any case, if you’re not in a competition to build the most complicated layout, you should be fine.

To recap:

  • Isolate components in terms of z-index values of elements by making the root of each component a stacking context;
  • You don’t have to do it if no element within a component needs a z-index value other than auto;
  • Within a component’s CSS file, maintain z-index values any way you like. It might be consecutive values, or you could give them a step of 10, or you can use variables — it all depends on your project’s conventions and the size of the component (although making components smaller is never a bad thing). Preferably, only assign z-index to sibling elements. Otherwise, you may inadvertently introduce more stacking contexts within a component, and you’re faced with the same issue again, luckily on a smaller scale;
  • Debugging becomes easy. Find the first ancestor component of the two elements that are not stacked correctly, and change z-indices within that component as necessary.

This approach will hopefully bring back some sanity to your development process.

(dm, ra, il)
Categories: Around The Web

Design System: What It Is And How To Create One Using Indigo.Design

Tue, 04/02/2019 - 6:30am
Design System: What It Is And How To Create One Using Indigo.Design Design System: What It Is And How To Create One Using Indigo.Design Nick Babich 2019-04-02T12:30:58+02:00 2019-04-18T19:36:01+00:00

(This is a sponsored article.) Design is about scaling. Digital products are becoming more and more complex, and it is evident that product teams need to adapt their approach when designing them. To deliver well-designed products to the market, many organizations have started taking a more systematic approach to design, experimenting with style guides and pattern libraries in order to create design systems.

While product teams might face various problems in creating and incorporating a design system into their design process, one of the most common problems is integrating the different tools a team uses. Even if a team has a pixel-perfect visual design with properly handled components, they could face trouble in the design handoff and coding, all because their tools do not work properly with each other.

Indigo.Design attempts to solve this problem by introducing a unified platform for visual design, UX prototyping, code generation and app development. Using this platform increases the chances that you will create a design system that takes root and becomes an essential part of the organization. In this article, we’ll focus on just one aspect of this tool: using a design system in a visual design. But before that, it’s important to define what a design system is.

What Is A Design System?

A design system is a collection of elements that can be combined and reused to build products. This definition might give the wrong impression that it’s a single design deliverable, such as a Sketch library with UI components or a style guide. In fact, a design system is much more than that. Think of it as a process and a set of deliverables that create a shared language that everybody on the team will use when creating a product.

A design system is about communication. A well-crafted design system establishes a common shared language among team members, and this language allows the team to collaborate more effectively. Thus, the ultimate goal in creating a design system is to create both a single source of truth that can be referred to during product design and an effective shared language that all team members can use when working on a product.

What Problems Does A Design System Solve For Team Members?

Perhaps the most crucial thing that a design system brings to a product team is a different approach — members start approaching a design with a system in mind. Here are a few everyday tasks that a design system can help a team member with:

  • Quickly find and use the right component, pattern or style option (color, typeface, icon, etc.);
  • Reuse a component or pattern (either in the same product or in another product);
  • Know how to use a component or pattern properly (product creators will now have this guidance when creating products);
  • Reassure yourself that the components you are using are up to date.
What Can Motivate A Team To Think About A Design System?

There are a few powerful motivators for a team to think about a design system:

  • Design debt.
    As products and teams age, they accumulate design and development debt. Non-reusable conventions, inconsistent styles and legacy code are the most common sources of design and technical debt. Debt prevents a team from moving quickly. A design system helps an organization to reduce its debt.
  • Collaboration and communication problems.
    In large companies, a few different teams will usually work on a single project. Even with a team that communicates regularly, it’s quite common for their work to overlap (such as by creating similar components or UX patterns). A design system can build bridges between teams and make it easier to reuse work.
  • Repetitive work.
    A design system frees up time from repetitive work so that the team can focus on solving more interesting problems. The fact that team member won’t need to worry about which icon or button to choose in a particular situation not only saves valuable time, but also helps them to focus on the big picture: thinking more about how the user will use the product.
  • Consistency within a product family.
    Large companies need to design for multiple platforms and have a consistent experience across all platforms (both in behavior and interaction). Considering that an individual team is responsible for creating a design for a particular platform, this isn’t a simple task. A design system makes it much easier to design a consistent experience across all platforms.
The Key Qualities Of A Well-Functioning Design System

Regardless of the technologies and tools behind it, an effective design system has the following characteristics:

  • It should be adopted by the team.
    The system should fit the culture of the team. It should become a natural part of the design process and evolve gradually with the team’s products.
  • It should be balanced.
    The system should give team members enough freedom to contribute yet stay within parameters.
  • It should be consistent.
    The different parts of the system work well together.
  • It should be well-documented.
    The quality of documentation has a direct impact on the system’s adoption. If something is not documented, it doesn’t exist. That’s why the documentation should always be up to date.
  • It should be robust.
    Whatever the product or platform to which a design system is applied, the final product should have minimal flaws.
  • It should be highly reusable.
    All components of the system should be able to be reused in many contexts.
  • Last but not least, it should be cost-effective.
    An effective system can make the design process more cost-effective.
How Does Indigo.Design Simplify The Process Of Building A Design System?

Starting a design system can feel daunting. It’s evident that a great design system cannot be built overnight; there are too many things to consider. Even with all its benefits, it’s hard to get buy-in from the teams involved in design and development, mainly because the system will influence the way designers and developers work. Let’s see how Indigo.Design can improve this process.

The key thing that differentiates Indigo.Design from any other tool is that it’s a unified platform for visual design, UX prototyping, code generation and app development. Usually, design systems are created by product companies for their own products.

As a result of the significant number of user requests and expertise in building UI controls, the Indigo team has identified the component and pattern needs of a great number of clients from various industries. Thanks to this knowledge, Indigo.Design’s system goes beyond regular design systems that are created for specific product needs; rather, it is a ready-to-use design system that can be easily adjusted to the needs of a particular team. Users can use Indigo.Design’s Sketch UI kit as a starting point to build their own system using the premade components and patterns.

Indigo.Design consists of three parts: components, patterns and styling. All three parts are integrated as Sketch libraries and are perfectly synced. They will appear in the ‘Symbols’ section in Sketch.


Components are the building blocks of user interfaces. Think of components as LEGO blocks that you can use to create a product. Avatars, cards and dialogs are just a few examples of components.

Components range in complexity, from simple components such as a “Submit” button to more complex components such as interactive cards. Usually, the more complex a component, the fewer the scenarios to which it can be applied.

Component-based design and development bring a lot of benefits to the design process, reducing technical overhead by making design and code reusable.

Because components are designed and built in code, for each component, it’s vital to describe both:

  • visual language (visual appearance),
  • functional behavior (code).

Indigo.Design provides a flexible way of working with components:

  • The design library has over 50 components:
A robust array of components are available in Indigo.Design. (Large preview)
  • Indigo allows you to modify everything about a component in a structure way. Individual properties, such as size, styling, icons, fonts and events, can be modified in the Overrides section of a component. For example, for avatars, we can select a different shape of the object, changing it from a circle to a square. With overrides, it’s possible to create unlimited design combinations to drive your team’s productivity.
  • The components of a design system are interdependent. When we introduce a change in one place, the change will be inherited throughout the system.
  • Indigo makes it easier to translate design into code. All components map to the Ignite UI for Angular components. Data from the DataProperty field will be passed through to the code generator.

Below, you can see a layout with an input component. Sketch’s Overrides section contains the properties of the selected component. Modifying each property in a structured way is easy; basically, everything from styling options to events can be easily adjusted.

Each component can have a different list of Overrides based on its capabilities. For example, for the input field, we notice a DataProperty field, which can be translated directly to a code generator.

Use Overrides to modify the properties of a component. (Large preview) Patterns

Many designers think that patterns and components are the same things. They are not. The idea of a design pattern was introduced by architect Christopher Alexander. In his book A Pattern Language, Alexander gives the following description:

“Each pattern describes a problem which occurs over and over again in our environment, and then describes the core of the solution to that problem, in such a way that you can use this solution a million times over, without ever doing it the same way twice.”

Similarly to architecture, we use patterns in interface design to solve common problems. For example, many apps have contact lists. It’s possible to create a contact list using components, by pairing avatars and text sections.

Create a contact list using Indigo.Design’s avatar and text component sections. (Large preview)

But there is a much easier approach — use a pattern called ‘List’.

Use Indigo.Patterns’ list for people. (Large preview)

Patterns empower designers, allow people to use their previous experience when interacting with a product. Because many design patterns are familiar to users, they will enable a design to be understood intuitively.

Components and patterns form the language of a product’s interface. But a design system should contain not only patterns, but also techniques and practices for using and iterating on those patterns. For many companies, a pattern library typically lives in a wiki, which means it’s difficult to keep up to date. What makes things worse is that patterns are also shaped by the conventions of platforms (for example, iOS and Android).

Indigo.Design solves these common problems by providing easily customizable UX patterns for a brand’s needs.

Adding elevation for the article details pattern (Large preview)

With the last release of Indigo.Design, it’s become much easier to customize styling options: You can apply your styling options for the entire design all at once using the Theme plugin.

Indigo.Design’s Theme plugin allows you to apply style settings for all elements in a design. (Large preview) Styling

A style is something we use to create a certain kind of aesthetic and to strengthen the emotional connection between a product and its users. Indigo.Design makes it really easy to create an elegant design that matches your brand.

Indigo-Styling.sketch is a representation of the theming engine. It is separated into two parts, represented as different pages in the library:

  • Icons are a collection of over a hundred Material icons that you can easily extend.
  • Colors are a rich collection of primary, secondary and special colors, as well as shades of gray and levels of opacity.
(Large preview)

The styling library allows you to do custom branding (changing colors, fonts, etc.), and it is also inherited by the design. With just a few clicks, you can create and reuse a theme.

Change the text color of a form’s active elements to the product’s primary color using Overrides. (Large preview) (Large preview)

Indigo.Design’s Theme functionality lets you take care of most of your styles in a systematic way.


Design systems have changed the way we design and build applications. They are quickly becoming a cornerstone of an organization’s digital product strategy. And it’s extremely important to select tools that allow you to set a solid cornerstone for your product’s design process. Indigo.Design offers a ready-to-use design system that can be adapted to your individual needs.

(ms, al, il)
Categories: Around The Web

How To Use Spaces In Web Design With Gestalt Principles

Mon, 04/01/2019 - 7:30am
How To Use Spaces In Web Design With Gestalt Principles How To Use Spaces In Web Design With Gestalt Principles Ayesha Ambreen 2019-04-01T12:30:41+01:00 2019-04-18T19:36:01+00:00

Human brains are hardwired to connect the dots and make sense out of everything the eyes see. Design is a creative field where forms and space intermingle to lend us a variety of experiences. Whatever design we come across, our brains are hardwired to transform that piece into simpler components made up of basic shapes and forms that are at play with the spaces. Our minds flood with memories and — thanks to our experiences — we recognize the patterns easily.

Space — both positive and negative — plays a pivotal role in unifying the design elements. As a result, we see a uniform pattern (or not). When the elements are arranged in an orderly manner, the intelligent use of spaces draws our eye to the most noticeable space — be it positive or negative.

The positive space poses as the flesh or the meat of the design; it’s the part where you see the shapes, colors, patterns and so on. The negative space, on the other hand, is the background or the hyped white space (most of the times).

“The Starry Night” by Vincent van Gogh

As much as the positive space seems to dominate the negative counterpart, both are used in equilibrium to tell a harmonious, coherent, and a seamlessly complete story.

In balanced compositions, the positive parts and negative space of the design work together and complement each other to form a seamless, aesthetically pleasing whole. Unbalanced compositions, on the contrary, can cause discomfort to the audience and convey an incomplete, rather distorted story.

But what kind of story do spaces tell in web design?

In the midst of the spaces, the success and failure of web design is determined more by the utility and the usability. Just consider that if you have poor design skills, the overall efficacy and the presentation of the web design will be disturbed. Content is king, but from an alternative point of view, the content will take its toll on your website if the spaces are not used appropriately.

If you think your developing skills rock but your design skills could need some more improvement, you’ve just hit the jackpot. In this article, we’re going to cover:

  • Positive versus negative space relationship, importance and implementation;
  • The connection between spaces and cognitive perception;
  • The Gestalt principles and their implication in web design.

We’re also going to discuss some real-world web design examples with each Gestalt principle and creative use of spaces.

Without further ado, let’s begin.

Positive Versus Negative Space: Relationship, Importance And Implementation

Spaces comprise of two main dimensions: positive and negative. The positive is the element and the negative is the no element. As mentioned before, the positive is object, negative is the negligible space behind it. Where one is the focus, other serves as the background. Where the former moves and motivates, the latter remains stationary and obscure. Where one is the moon, the other is the dark sky surrounding it.

In web design, the spaces interact with each other to maintain the idea of holistic composition. Visual hierarchy is only created when both the spaces are differentiated with contrast and yet tend to the bigger picture (think of yin and yang).

“Yin and yang”, a concept of dualism in ancient Chinese philosophy. (Large preview)

We differentiate between the positive and the negative space at the meeting point. The negative occurs mainly as the white space that complements the positive to make it pop out.

It might seem that the positive space takes the lead, the negative space is equally important for a myriad of benefits. Some of these benefits are:

  • It creates an easy-to-follow visual hierarchy;
  • Sets the focus of attention as well as reduces distraction;
  • Helps establish the scale and lets the focus appear bigger;
  • It improves page scan-ability;
  • Makes the flow on the page appear natural;
  • It clarifies the relationship between the visual elements without the need for additional aids;
  • It helps de-clutter the page;
  • Enhances the style and look of the webpage.

Negative space in design isn’t that negative if you ask me. However, both space types perform great when used in a balanced ratio. Unfortunately, chaos strikes only when either one dominates the other and gives an ‘overcrowded’ or a ‘lacking’ impression. In both cases, the audience is unable to process such complex information, and hence, the motive of using space creatively for web design falls apart.

Here’s a web template with misplaced content or ‘chaos’ space:

Unconsidered ‘chaotic’ space (Large preview) Space discrepancies shown in black and white (Large preview) Fixed space to show how space can spark clarity and uniformity when used in proportion (Large preview) The effective use of space in web design (Large preview)

As fascinating as the concept and arrangement of space occurs, doubt begins to fog the area.

  • Is the positive space surrounded by the negative one or is the negative space eaten up by the positive one?
  • How is the proportion of each space type determined?
  • Which one should validate as the focal object?
  • Is it mandatory to highlight one and eclipse the other to communicate your intended perception to the audience?
  • How would I achieve ‘design nirvana’ with the communion of positive and negative spaces?

Questions like these can only be answered with a clear understanding of the basics. And as per the golden rule of thumb: simplicity is the best policy (we made that up because it fits!).

We mentioned in the beginning that web design is all about creating a simple user interface that helps you and your audience kill more than two birds with one stone, or in literal terms, helps increase the visual desirability of the website design as well as making it effective and easier to use — yes, with an incredible power over the use of spaces.

The Connection Between Spaces And Cognitive Perception

Since our minds are always playing the detective for finding hidden clues and missing links between the spaces, it compares present visuals with the ones experienced before as a part of the cognitive process. In order to become an efficient web designer, you must first understand how the brain pays attention to its surroundings. It may help you pin the particular use of visual elements and use them to influence the viewer’s perception.

“Great designers understand the powerful role that psychology plays in visual perception. What happens when someone’s eye meets your design creations? How does their mind react to the message your piece is sharing?”

Laura Busche, Brand Content Strategist at Autodesk

You must now have a clear idea of how visual design and psychology are linked and have the power to influence each other. In other words, the main idea of developing a simple user-centric interface and using space for its design is by considering the Gestalt principles. These can help you understand and control the visual-psychological connection.

Recommended reading: Improve Your Designs With The Principles Of Similarity And Proximity

Gestalt Principles In Web Design

Gestalt is German for ‘forms’. It is more of a concept than a word, which states that:

“The whole is other than the sum of the parts.”

— Kurt Koffka

A collection of individual units appears as a group to us when they’re unified in some way. We see the elements as a group despite their individuality. This concept or theory applies fundamentally to all the design mediums: We don’t see text, colors, and shapes as separate elements, but instead a whole webpage as a collective entity. The same applies to a forest: we don’t only see a bunch of trees, just the same way we don’t see water drops when looking at an ocean.

The Gestalt principles describe how the human mind perceives visual components when certain terms and conditions are applied. It helps the brain create imagery of the visual. Hence, the Gestalt principles are based on six main categories:

  1. Figure And Ground
  2. Proximity
  3. Symmetry And Order
  4. Similarity
  5. Closure
  6. Continuity
Figure And Ground

The ‘figure’ is the object that is intuitively as well as visibly separated from the ground.

Grail Cup (Large preview)

The most classic example that exists is that of the grail cup — the vase between two mirroring face silhouettes. When you first come across this image, your eyes are drawn to the most focally visual object that comes into your notice immediately, which might be the faces opposing each other or the vase. While your mind is adjusting your focus, the ground or the vase is blurred out and at that moment, your mind intuitively crops out the negative or the ground in the image.

After a while, you get to notice the vase in the background and realize it was there in the first place. As ambiguous as the Figure and Ground principle seems, designers usually create visually appealing surreal and illusionary art and web designs.

Figure-ground relationship (Large preview)

Sometimes, the relationship between figure and ground is stable, which makes both distinguishable from one another. This relationship is sometimes unstable, meaning that the figure and ground are indistinguishable from each other. Due to the ambiguousness of this relationship, the viewers confront perceptual confusion.

To give you a clear idea of how the figure-ground relationship influences web design, let’s discuss a few examples in detail. Each of these examples focus on three main areas of the figure-ground relationship: You can add explicit visual cues by using contrast, boxes, and shadows for your web design. These techniques are used to distinguish the color, size, and level of detail, to separate the content, and to add depth to the respective object of focus.

In the first example below, Trellis uses a ‘hero image’ (images with clear CTAs) with a figure-ground relationship that clearly indicates the level of detail, color, and size.

Trellis (Large preview) (Image source)

The text is the figure here in a large cursive font in the center of the page, making it stand out as compared to the image in the background. The white text over the contrasting grayscale image draws the focus of attention, which makes the text visible over it. From another perspective, the background is blurred so that the text pops out as the figure. All of these aspects show that the text here is prioritized as the figure or the positive space, while the blurred image is used as background or the negative space, hence strongly implying the concept of figure and ground.

Next comes the content in boxes. Ocean Health Index makes a smart use of boxed content to separate the figure from the background. This is what you see when you come across their website:

Ocean Health Index (Large preview) (Image source)

Which part of it jumps at you when you first view this web page? If you ask me, it’s the main text in white in the upper right-hand side and the two boxes with contrasting color and text. The bold white text on the top is obviously the figure. (Notice how it’s placed over the darker image to stand out.) The boxes down below are also part of the figure, due to the contrast they offer to the ground image. The other aspect of this figure is the second contrast that is placed inside the boxes in the form of contrastive-colored text.

The background uses subtle shades that help the figures appear sharply, showing a pattern of detail here. The boxes are also overlapping the background image, bringing them in clear view over the image.

Some websites also exhibit the figure-ground relationship by adding drop shadows to the figure, in order to give a feeling that the figure is placed over the background. Here’s a screenshot from Seriously Unsweetened:

Seriously Unsweetened (Large preview) (Image source)

Seriously Unsweetened’s landing page uses more than one technique to maintain that figure-ground relationship in a balanced manner. There are bright colors and shadows. The ground remains white, making it easier for the figure to appear accurately above the ground. In the positive space, the objects in the figure are presented under an illusion as of being ‘on the top’ of the background. The shadow game is played inside the primary figure, making us notice that there is another figure-ground relationship within the main figure. A clever one!


Proximity refers to the closeness of elements in a page. Different elements in webpages can be grouped together to create a bigger association. Apart from being similar, the closeness of these elements with each other than other page elements will automatically be paired in the viewer’s mind.

Proximity in design (Large preview)

From images to texts and navigation bars to web forms, the Proximity principle applies heavily to web design. When you group similar content together, it creates a seamless relationship between the elements and delivers a better visual experience to the viewer.

Here is an example of proximity as displayed in the navigation of the Mashable website:

Mashable (Large preview) (Image source)

In the snapshot above, you can clearly notice how the elements of the same category are placed together to show the relation with the main menu type. The users’ eyes are automatically drawn to the subtypes under the main heading — also thanks to the use of colors and text size. You can see that the items that are unrelated are set apart with the help of a line, which serves as the users’ guide in relating and separating the items as per the principle of proximity.

Besides delineating the navigation bar, the grid-based content also complies with the golden rule of Proximity. Amazon’s product listing is the best example:

Amazon Products (Large preview) (Image source)

Proximity complies with similarity, which is yet to be discussed. As you can see, similar products in the positive space are grouped and separated using narrow white space. This instructs the user to sort their preferred item from the list of similar products. Moreover, the principle of closure also comes into action among the list of similar items.

Now, we’ll take a closer look at the Basecamp web form which displays yet another ideal case for proximity in web design:

Basecamp Web Form (Large preview) (Image source)

You can notice how the form is divided into two main segments: personal details and ID generation. The first section is implied as the most important field, followed by a lesser important requirement. The headings for both the sections vary as shown by the difference in color and font size. In this web form, proximity is an indicator that places and prioritizes grouping of information from highest to lowest importance.

Symmetry and Ordery

Symmetry refers to the exact reflection or the mirror image of the two opposing planes. It can be regarded as the balance that divides an object into two equal halves. Real-world examples of symmetry include geometrical images like equilateral triangles, circles, and squares and so on.

Symmetry versus asymmetry (Large preview)

The human mind desires to find the ‘balance’ in human faces, which it finds aesthetically pleasing. The mind also tends to find symmetry in other objects, such as images because symmetry creates harmony and allows the viewers to be at comfort while viewing the image.

Below is a great example of symmetry in web design as exhibited by HvD Fonts:

HvD Fonts (Large preview) (Image source)

Not only does this webpage show a typical figure-ground relationship, but also displays great symmetry. The page is dissected into four equal halves with fonts of similar size and color. The background in each of the four sections runs along the same theme with a grayscale effect. You can also notice that the negative space isn’t necessarily white; it’s the image in the background.

The idea of symmetry gives rise to another notion: asymmetry can be confusing and must be used with great care when used in web design. Many websites use asymmetry as the main balancing element for spacing, where the unconventional positive space is balanced with a neutral background and vice versa. And as per the concept of asymmetry, Xplode Marketing prompts asymmetry with unique aesthetics pleasing the eyes.

Xplode Marketing (Large preview) (Image source)

This webpage immediately grabs the eye using optical illusions as well as asymmetry. The positive space objects are placed in an unusual pattern over the negative space that creates the appeal. The color is the main indicator of harmony between both the spaces and develops a natural connection for the viewers to notice. There is also a strong balance of left-hand graphics with the strong and dominant wings on the right. What do you think?


The reason that proximity works closely with the principle of similarity is the quality of shared attributes among the similarly-grouped objects. Whether it be color, shape, posture, size, shape, orientation or any other property, connectedness will prevail when one or more of these are shared in all the objects displayed in proximity.

Similarity in Design (Large preview)

Even if the positive space elements do not look visibly connected, these will stand apart from the negative one due to the principle of similarity.

Just look at these UrbanDecay palettes list for a moment:

Urban Decay (Large preview) (Image source)

The positive spaces aka the figures are different from each other but do share some similarity in various aspects, such as their position, color, product layout and mode of presentation. The only dissimilar object is the ad for the eye shadow primer that stands out uniquely in the line of the similar-product category. This is obviously a marketing tactic that is intended to draw attention without hurting the overall symmetry and beauty of the page. Another point to consider here is that similarity in size sets the other image apart from the similar product category.

Other than just product display, the positive space can be employed with the similarity in conjunction with the negative space.

Let’s take a look at the influenster landing page:

Influenster’s front page(Large preview) (Image source)

The similarity in the above example shows clearly aligned boxes. Though the products in each positive space are different, the perception of similarity is conveyed by the consistent text fields in the overall page. The genre, layout, and the theme all are similar, hence delivering a seamless effect to the vision.


Did you ever come across an image that seems close but is open? That is because of the principle of closure. Our brains tend to ‘close’ the gaps in the incomplete objects and use our visual perception to complete the figure, seeing it as a whole.

Closure in design (Large preview)

The positive and negative spaces close in to form a whole. The best example is that of the hidden shapes and forms in the negative space in and outside the design, which demands an intelligent assessment of message within the design. Using both the spaces creatively in the closure can give rise to an interesting yet simplified design.

Take a look at the screenshot from Magu Kambucha below:

Magu Kambucha (Large preview) (Image source)

In this example, you can see that closure is kept intact with the principle of the figure-ground relationship. The bottles and the bold text behind are obviously the figure, where the background is solid soft pink. Where’s the closure? See the text behind the bottles? You can’t see it completely, but still know it’s ‘Kambucha’. Except for the first ‘K’ and the last ‘A’, other letters are half hidden, which are intuitively completed and the whole form begins to take shape and consequently, the meaning. This, my friend, is one good example of closure we have here!

Take a look at the screenshot from Cult below:

CULT Website (Large preview) (Image source)

Even though the text is not spelled out quite clearly, our minds can easily read the word CULT. The arrangement and alignment of the text made it easy to decipher, even when the words are incomplete.


Finally, as per the general Gestalt principles, continuity follows the pattern by leading the eyes to follow a consistent path and establishing a linear pattern from object to object. It can best be understood by the example of a positive space line with a curved over the negative space. The colors of both lines indicate that the lines bent by each other, but the pattern of continuity suggests otherwise.

Continuity in design (Large preview)

In the image above, the viewers are more inclined to see a straight line despite the color degradation. This leads us to believe that the principle of Continuity guides the perception better than the power of color. This concept flows smoothly through both kinds of spaces. When we insert a subject in the negative space, our eyes tend to draw the line of distinction between the positive space and the negative one.

The imaginary line of continuity is what we tend to introduce in the design to guide our perception when differentiating between the positive and the negative space.

Let’s take our cue from the Crypton Trading website down below:

Crypton Trading (Large preview) (Image source)

See the perfect continuation of design in the right half of the page? Regardless of the light and dark hue in the background, the pattern is pretty much obvious on the page. And when you scroll down, you will see how the pattern as well the color change in a continuous and seamless motion. The shift in tones is negligible here and all we see is a continued pattern of lines and dots.

Another good example is the OscilloScope website:

OscilloScope Website (Large preview) (Image source)

The website uses the law of Continuity to take web visitors to a 360-degree view of the studio where they can navigate their way to the desired section.

Cargo the movie (Large preview) (Image source)

The film Cargo has a landing page that also uses the law of continuity: it get its text float across the website in a linear motion using the scroll-only navigation. Since the half-visible logo was shown vertically, the viewer has to scroll down to get a full view of it. As the page is scrolled down, the static logo starts floating along with the chunks of text running parallel to it. The navigation leads the user through different levels of experience without interfering the darkness lurking below.

Since our eyes usually follow the smoothest path, graphic designers can use such examples to make them follow the desired path and position the elements along a line.

Summing It Up

In this article, we covered the Gestalt principles in relation to positive and negative spaces in websites. We also made sure we include some real-life examples to give you a clear idea of how you can employ simple yet effective techniques to influence your audience’s perception. The key here is to use these principles to create a web design that appears more than the sum of its parts.

We humans think in terms of our perception — mainly based on visuals. According to the Gestalt principles in relation to positive and negative spaces, we tend to see the bigger picture rather than individual elements at first glance.

Positive and negative spaces help us differentiate, help us recall our experiences, and recognize the patterns. With the help of the Gestalt principles, we are better able to visualize how well we can use spaces in web design to create appealing pieces. Since spaces can appear as a tangled affair for any designer, the best way is to keep intact your Gestalt principles. This is the only way you can truly realize the importance, usage, and effectiveness of spaces in your designs and effortlessly become an effective contributor in the web design domain.

Want to add something else? Don’t forget to share your ideas. We’d love to receive the feedback!

Further Reading

Here are a few design sources to help you understand the Gestalt principles:

Don’t forget to check out the related recommended tutorials:

Categories: Around The Web

Blooming Colors And April Adventures (2019 Wallpapers Edition)

Sun, 03/31/2019 - 3:14am
Blooming Colors And April Adventures (2019 Wallpapers Edition) Blooming Colors And April Adventures (2019 Wallpapers Edition) Cosima Mielke 2019-03-31T09:14:59+02:00 2019-04-18T13:35:27+00:00

Starting off the new month with an inspiration boost, that’s the idea behind our monthly wallpapers series which has been going on for more than nine years already. What makes it special: the wallpapers are created by the community for the community, and everyone who has an idea for a wallpaper design is welcome to submit it — no matter if they are experienced designers or aspiring artists.

For this April edition, people from across the globe once again took on the creative challenge to cater for some variety on your screens. The result: a colorful collection of unique and inspiring wallpapers dedicated to the big and small joys of April. All wallpapers come in versions with and without a calendar and can be downloaded for free. Thank you to everyone who participated!

As a bonus goodie, you’ll also find a little April best-of at the end of this post. Please note that these wallpapers come from our archives, and, thus, are only available without a calendar. Enjoy!

Please note that:

  • All images can be clicked on and lead to the preview of the wallpaper,
  • You can feature your work in our magazine by taking part in our Desktop Wallpaper Calendar series. We are regularly looking for creative designers and artists to be featured on Smashing Magazine. Are you one of them?

Further Reading on SmashingMag:


“The moment when you just walk and your imagination fills up your mind with thoughts.” — Designed by Gal Shir from Israel.

Inspiring Blossom

“‘Sweet spring is your time is my time is our time for springtime is lovetime and viva sweet love’, wrote E. E. Cummings. And we have a question for you. Is there anything more refreshing, reviving, and recharging than nature in blossom? Don’t wait. Go outside and enjoy this lovely flourishing season. Let it inspire us all to rise up, hold our heads high, and show the world what we are made of. It’s time to bloom!” — Designed by PopArt Studio from Serbia.

April Showers

Designed by Ricardo Gimenes from Sweden.

Gentle Blooming

“After so many months of grey winter weather, I can’t wait to feel the warmth of sun rays on my skin, to see and smell the flavor of blooming flowers and trees… Thinking about all this inspired me to create these blooming flowers in gentle warm colors.” — Designed by Yuliia Bahniuk from Ukraine.

Spring Serenity

“My inspiration was the arrival of spring that transmits a sense of calmness and happiness through its beautiful colors.” — Designed by Margarida Granchinho from Portugal.

Egg Hunt In Wonderland

“April is Easter time and I wanted to remind us that there’s a child inside all of us. My illustration is based on the story that fills our imagination since childhood, Alice in Wonderland, and joined to one of the most traditional customs in America at this time of year, the egg hunt. That’s how we get an ‘egg hunt in wonderland’.” — Designed by Patrícia Garcia from Portugal.

Wonderful Things

“If you need to find anything beautiful, there is no better place than nature. Everything in nature is unique and beautiful in its own way!” — Designed by Dental Expression from Lee’s Summit, Missouri.

In The River

“Spring is here! Crocodiles search the hot and stay in the river.” — Designed by Veronica Valenzuela from Spain.


“My choice to represent the month of April was the 25th of April in 1974 in Portugal, also known as the great revolution for freedom (‘Revolução dos Cravos’). It started with a political and social movement, which deposed the dictatorial regime of the New State. This date will always inspire us and remind us that freedom is worth fighting for and that people united are stronger than any kind of tyranny. For this reason, my project is called Freedom.” — Designed by Mirella Damasceno from Portugal.


Designed by Tatiana Campos from Portugal.

Happy Easter!

“Celebrated all around the world in Christian tradition, April is the month of Easter. For kids Easter is about bunnies and painted eggs. Because April is also the month of early spring I chose joyful colours to give life to this lovely Easter illustration.” — Designed by Joana Duarte from Portugal.


“Every year around April, the cherry blossom marks the beginning of spring in Japan. There is a tradition of watching this phenomenon which the locals refer to as ‘Hanami’ — flower viewing. This event occurs for a short time because of the cherry blossom’s short lifespan. The concept of Hanami reminds us that we should appreciate and even celebrate life in all its beauty and fragility while we can.” — Designed by Tetyana Malakhova from Portugal.


“Every month of our calendar is named after a god or goddess. The month of April is named after Aphrodite, the Greek goddess of love.” — Designed by Rita Falé from Portugal.

From The Archives

A lot of things have inspired the community to create their April wallpapers in the past few years — be it a tasty bowl of soup on a rainy day or grabbing their bike and exploring new places. Below you’ll find some of these almost forgotten favorites. Please note that they don’t come with a calendar.

April Is The Nicest Month

“T.S. Eliot wrote in 1922 that ‘April is the cruelest month,’ but we quite disagree. April is the month when spring has finally come so nature starts blooming, providing us with more time to go out into nature and enjoy nice weather, long walks, and riding a bike. This is our message to you: go out and play. We surely will.” — Designed by PopArt Studio from Serbia.

Wildest Dreams

“We love the art direction, story and overall cinematography of the ‘Wildest Dreams’ music video by Taylor Swift. It inspired us to create this illustration. Hope it will look good on your desktops.” — Designed by Kasra Design from Malaysia.

No Winter Lasts Forever

“Here comes spring, breathing new life into the world around us.” — Designed by Norjimm Pvt Ltd from India.

April Insignia

“April — its first day reminds us that laughter makes life better. Nature also laughs, but it does so in daisies!” — Designed by Ana Masnikosa from Belgrade, Serbia.

Once Upon A Time

“April is the month of spring but also the month of books. ‘A book is a proof that humans are capable of doing magic.’ (Carl Sagan)” — Designed by Verónica Valenzuela from Spain

Nikes On My Feet

“We got inspired by the song ‘Nikes on My Feet’ by Mac Miller, which was perfect for the upcoming month of April and the warm weather that spring brings. As Mac Miller said, ‘All I really need is some shoes on my feet…” — Designed by PopArt Web Design from Serbia.

Colors Of April

“My daughter was born in April so this month reminds me of that colorful, bright and precious moment.” — Designed by Izabela Grzegorczyk from Poland.

Bad Bunny

“This bad bunny is just waiting for Easter.” — Designed by Izabela from Poland.


“It’s spring already, my favourite season! You can smell it, you can see it, you can feel it in the air. Trees blossom, the grass is smiling at the sun, everything is so eager to show itself.” — Designed by Vane Kosturanov from Macedonia.

Rainy Day

Designed by Xenia Latii from Berlin, Germany.

Spring Fever

“I created that mouse character for a series of illustrations about a poem my mom often told me when I was a child. In that poem the mouse goes on an adventure. Here it is after the adventure, ready for new ones.” — Designed by Anja Sturm from Germany.

Citrus Passion

Designed by Nathalie Ouederni from France.

Sweet April Showers Do Bring May Flowers

“Discover the seasonal fruits and vegetables in April: artichoke and beans walking in the rain!” — Designed by Vitaminas Design from Spain.

Ipoh Hor Fun

“Missing my hometown’s delicious ‘Kai See Hor Fun’ (in Cantonese), that literally translates to ‘Shredded Chicken Flat Rice Noodles’. It is served in a clear chicken and prawn soup with chicken shreds, prawns, spring onions and noodles.” — Designed by Lew Su Ann from Brunei.

Noisy Neighbors

Designed by Katerina Bobkova from Ukraine.

Jean-Cloud Van Damme

“Hope that this little cloud will make you laugh. Happy Fools’ Day everybody.” Designed by Marika Smirnova from Russia.

Umbrella Season

“In my neck of the woods, April means a lot of rain, and therefore a lot of umbrellas. I’ve noticed a lot of pretty unique umbrellas out there, especially when I walked to class in college. Happy Umbrella Season!” — Designed by Angelia DiAntonio from Ohio, USA.

Join In Next Month!

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.

Thank you to all designers for their participation. Join in next month!

Categories: Around The Web

Rundown Of Gen Z: What Does This Mean For Mobile Designers?

Fri, 03/29/2019 - 7:30am
Rundown Of Gen Z: What Does This Mean For Mobile Designers? Rundown Of Gen Z: What Does This Mean For Mobile Designers? Suzanne Scacca 2019-03-29T12:30:08+01:00 2019-04-17T09:35:41+00:00

Just a few years ago, design blogs were all abuzz with tips on how to build websites for the millennial consumer. At this point, however, that’s old news. We know what millennials want from the online experience and have, for the most part, been able to meet their expectations.

But now we have a new generation of consumers to worry about: Generation Z.

Are they all that different from millennials?

As an old millennial myself, I can tell you that this next generation is one I don’t feel much of a connection to. I can remember a time when the most exciting part of my day was when my mom got off the phone and I was able to finally connect to the Internet with our dial-up AOL account.

This next generation doesn’t understand any of that. They weren’t caught between worlds the way many millennials were, which means they have a whole different set of expectations when it comes to the technology they interact with on a daily basis.

Consider this your quick and dirty guide to designing mobile websites for Gen Z.

What You Need to Know About Designing Mobile Web for Gen Z

According to Reality Bytes, a report published by WP Engine and The Center For Generational Kinetics, Gen Z cannot live without Internet access. More specifically:

  • 55% won’t go more than five hours without it.
  • 27% won’t go more than one.

Now, what’s really interesting about this particular generation is that, despite their attachment to the Internet, 61% of them prefer to shop on websites instead of mobile apps.

Considering how long they’ve had smart devices in their hands, it’s surprising that they’d gravitate towards browsers over native applications. That just goes to show you that native apps aren’t necessarily the best way to reach a mobile audience (especially if you want to make money from your app).

But all this is good news for you. Mobile apps are expensive to build and time-consuming to maintain. Plus, it’s quite difficult to convert users on mobile apps. If you were nervous about having to make the leap into mobile app development, or about losing money to those working in that field, don’t be. Generation Z wants your clients’ websites.

Now that you know which experience Gen Z is more likely to lean towards, it’s time to discuss designing for it.

Entertain Them

Before you do anything else, think about how to engage Gen Z visitors with entertainment.

According to Reality Bytes, entertainment is the primary reason why they visit the Internet:

Generation Z overwhelmingly prefers to be entertained online over anything else. (WP Engine) (Large preview)

Until now, the primary reason why consumers flocked to the Internet was for informational purposes. But that’s not all bad news for you as it means you have an excuse to reach out to older clients and say:

“Hey, times are changing! Here’s what’s on trend now and what your website needs in order to reach these new consumers.”

Just be careful: even for the most relaxed and youthful company, you don’t want to go over the top with adding entertaining elements into a mobile website. Just because 66% of Generation Z consumers name gaming as their #1 hobby doesn’t mean you need to build a mobile game and put it on your site. (Leave that to the gaming app developers.)

Instead, look at subtle ways to surprise Generation Z with something unexpected and engaging.

The first place to start? Video.

KFC has a great example of this right on its home page:

KFC shares its well-known and hilarious video ads on its home page. (Source: KFC) (Large preview)

There’s a number of reasons why this video example is so awesome.

First, every visitor to the website — both on desktop and mobile — will see it right away. On mobile, visitors can’t even scroll down the home page. What you see above is what you get.

Next, this ensures your visitors get a taste of the brand’s humor and personality. Whereas content-driven sites or blogs can do that with GIFs and memes, Gen Z might not take the time to read content. Video makes sure they won’t miss out.

Also, this video is totally on brand, showcasing KFC’s humor in video form.

Even if you don’t have a humorous mascot to trot around, show off your client’s CEO or other engaging brand ambassador. Video is a great way to quickly suck Gen Z visitors in and let them know this is not going to be a dry or unmemorable experience.

If you don’t have video to play with, that’s okay. Think about adding humor as you educate visitors. Old Spice demonstrates:

Old Spice’s informative, yet funny Ingredients pages. (Source: Old Spice) (Large preview)

Old Spice is another company that’s known for its entertaining video ads. However, their website also contains some humorous gems where you’d least expect them:

In the Ingredients section.

Visitors that are concerned about the ingredients within their deodorant can visit this page to learn more about what goes into each of the products. But read those descriptions closely. Not only are they transparent about what’s inside, but they also do it in a casual and playful way which says:

“Hey, we’re taking your concerns seriously. But don’t sweat it. We got you.”

Another way you can appeal to the entertainment-loving Generation Z is to add a social component to your site.

Don’t worry about building your own social network, community or forum either. Gen Z is going to flock to their favorite social platforms for that purpose: YouTube, Snapchat, Instagram, etc.

Instead, think about what it is that makes those environments so engage-worthy. Here’s an example from the Gymshark Central blog:

Gymshark uses social media-like reactions to improve blog engagement. (Source: Gymshark) (Large preview)

The blog post looks like any other. However, at the bottom of each post is this emoji reaction system. That’s pretty unique, right? Plus, this type of engagement doesn’t require much work from the reader. Simply click on the recognizable and well-labeled emoji and let the writer know what you thought of the content.

Another reason why this works so well is because Gymshark actively targets Gen Z customers. If you look on their website, you’ll see a section where they give discounts to college students.

So, if your client’s website needs to reach a younger audience, take a lesson from Gymshark. There’s no need to do a complete overhaul and convert an otherwise well-designed website into a superficial social network. Instead, add the most engaging elements from social networks and encourage your Gen Z visitors to interact more.

Personalize It

Think about what makes video games and social media so attractive to Gen Z. There’s obviously the fun aspect of it, but there’s another force at play that keeps users returning time and time again:

And that’s personalization.

This is something you should already be designing your mobile websites for as you target millennial consumers. However, if you haven’t bothered to add personalized touches to your sites, yet, you’re going to need to take this more seriously now.

Forbes Agency Council and YPulse worked together to find out what Generation Z really wants in terms of personalized experiences. Here’s a snippet from their findings:

“71% of the 3,000 respondents ages 14–29 said they prefer to receive offers that are customized to their location. In the same survey, 80% said they expect tailored onscreen experiences that not only target location but also recognize their interests and habits — who they are and how they self-identify.”

With 44% of Gen Z more likely to give up their personal data than other generations, you can’t afford to ignore this one.

One way to deliver a personalized experience based on what Gen Z visitors want is through push notifications. The only problem is, whether you have a mobile website or a progressive web app, push notifications are not supported on iOS devices.

While you can still use them to connect with Android users, consider other means for personalization that will help you connect with 100% of them.

Take, for instance, something as seemingly simple as what Amazon does with data:

About ¾ of the Amazon mobile home page contains personalized information. (Source: Amazon) (Large preview)

As you can see here, Amazon has saved a whole bunch of information about me:

  • My name and account information;
  • My cart items (which were not put there on this shopping trip);
  • My delivery location.

I also happen to own a Fire TV Stick, so this top ad is super relevant to me. Overall, I’m quite pleased with how tailor-made this first step inside the mobile website feels.

If you’re building a registration or membership system into your client’s website, make sure you’re leveraging user data to provide a personalized experience for them.

And if you don’t have a reason to ask mobile visitors to log in, that’s okay. You can still gather information by placing simply designed email subscription forms on the mobile website — preferably above the fold or at the very bottom. And most definitely on the home page.

Here’s a nice example from inkbox:

inkbox uses a subscription form to start collecting information on visitors. (Source: inkbox) (Large preview)

inkbox has done a nice job with this subscription form. Even if mobile users scroll past the content on the page, they’re likely to see that white box screaming back at them, begging them to sign up.

Because there’s such a low commitment compared to the potential for such valuable rewards (like information on new products and access to exclusive discounts), Generation Z visitors will love this. Like I said earlier, they’re more than willing to give you their personal data if you can make it worth their while.

For mobile websites with a brick-and-mortar presence, geolocation features are non-negotiable. Generation Z shoppers often use their mobile devices while in-store, so this would definitely take their experience to the next level.

One of the easiest ways to implement this is with geolocation sensors like the ones used by The North Face:

The North Face auto-populates search parameters based on the user’s location. (Source: The North Face) (Large preview)

The above screenshot is what happens when I use the Find a Store feature on the mobile website. What’s great about this is it detected my location (which is currently Boston) and it auto-populated my search query with a nearby store.

Mobile users don’t have time to waste and Gen Z certainly won’t take kindly to a website that forces them to do all the work. Take what you know about your user — even if all you can detect is a location — and make their job of connecting with you easier.

Make Them Feel Special

Now, there’s a difference between adding personal touches to a website and taking it up a notch so that Generation Z visitors feel special. They’re going to need you to make them feel like their money and opinions and faces are worth more than anyone else’s.

You have to remember, this is the generation that grew up with reality TV and smartphone cameras pointed at their faces. That’s why it’s no surprise they’re known as the “influencer” generation.

On a related note, this makes Generation Z much more likely to build a relationship with brands as there’s the hope that, someday, they’ll reward their loyalty with a public-facing partnership.

Your clients will ultimately have to decide how far they want to take this. After all, affiliate partnerships and influencer marketing won’t make sense for everyone. That said, there are other ways to reap the advantages of having a generation of consumers willing to “help” a brand out.

According to data from the IBM Institute for Business Value and the National Retail Federation, 44% of Generation Z consumers said they’d be happy to share ideas for product design. That makes sense as that level of contribution will make them feel like they have more invested in the relationship with the company.

While your clients need to decide if consumers have any say in the shaping of their offering, you can do something about this from the web design side of things.

Check out what the Panera website is doing to solicit visitors for feedback:

Panera calls attention to its redesign and asks visitors for feedback. (Source: Panera) (Large preview)

These “Feedback” tabs are a somewhat new feature on the web, but more and more websites are certainly taking advantage of it. With this intro pop-up from Panera, it’s looking as though they want to make sure their visitors take notice, too.

This is a smart move in terms of trying to appeal to a younger audience. You let them know, straight out the gate, “We made some changes!” and then ask them to provide feedback. But that’s not all. Panera is saying: “Thanks for your help.” This implies that they want customers to take a greater part in shaping both the online experience and the brand itself.

There are other ways to make Generation Z feel like they’re more than just the average customer.

Sephora has created something called the “Rewards Bazaar” to layer on top of its more traditional BeautyInsider loyalty program:

Rewards Bazaar is Sephora’s point-based rewards system that can be used to buy products and experiences. (Source: Sephora) (Large preview)

The Rewards Bazaar program works similarly to credit card points or airline miles programs. In other words, the more money customers spend with Sephora, the more points they accumulate.

And points don’t just buy them more Sephora goods. Points buy them experiences, like an Algenist R&R sleep retreat in Tucson, Arizona. They can also get “swag” bundles full of makeup and body products, clothes, artwork and more.

Sephora is rewarding their loyalty with celeb-like treats.

If you want to go crazy and actually encourage Gen Z customers to act like the influencers they so desire to be, take inspiration from this American Eagle example:

American Eagle asks customers to become unofficial influencers with AE x ME. (Source: American Eagle) (Large preview)

Generation Z customers already have their cameras ready to snap the next Insta-worthy photo, so why not give them a reason to put it to good use?

American Eagle has created an influencer-like program called AE x ME. Really, this is nothing more than a brilliant ploy to ask customers for user-generated content that American Eagle can then use on its website and beyond.

Whereas brands usually have to dig around for these types of photos or videos featuring their products in action, American Eagle is saying:

“You’re going to take pictures of your awesome new duds anyway. Why not let us show them off to a much larger audience for you?”

That’s not the only reward American Eagle dangles in front of influencers. While most of the people featured get a unique URL that features their Instagram handle and some information about them, there’s a profile at the bottom of this page that suggests there might be a greater opportunity here.

American Eagle turned a customer into a campaign model. (Source: American Eagle) (Large preview)

Daevin tagged American Eagle in one of his posts and then was flown out to become one of the faces in an upcoming campaign for the famous clothing brand. If that’s not living the dream for Gen Z influencer wannabes, I don’t know what is.

Keep It Real

One last thing to keep in the back of your minds as you design websites for Generation Z is the “keep it real” component. Anyone else remember this Dave Chappelle gem?

Dave Chappelle struggles to keep it real, long before Gen Z had a say in it. (Source: Giphy)

Gen Z has very high standards when it comes to the authenticity of a company. And, not only that, they expect brands to be socially good, too.

Reality Bytes reports that:

  • 79% of Gen Z consumers respect brands more if they keep their images Photoshop-free.
  • 84% of them trust companies that put real customers in their ad campaigns (see American Eagle’s example above).
  • 69% of them will buy from companies that give money to and support good causes.

Really, what all of this data points to is this:

Generation Z wants to know that they’re engaging with genuinely good and honest people; not just a brand name.

That’s why, if your clients have a strong mission and values, their websites need to have one page specifically dedicated to them.

One way to do this is with a partnership highlight page like eos has:

eos touts its recycling initiatives and partnership with TerraCycle. (Source: eos) (Large preview)

The eos website actually has two pages dedicated to this recycling cause. The first is called “Social Responsibility” where the company discusses its mission to build clean products. The second is called “TerraCycle” where it goes more into the recycling partnership.

For consumers looking to buy from companies that take causes like this seriously, these landing pages may be all they need to convince them to convert.

Samsung does something similar on its About Us page, except the key difference is that it calls out social responsibility and sustainability as part of its core company values:

Samsung makes it its mission to make the environment a priority. (Source: Samsung) (Large preview)

This way, it’s not just Samsung telling customers where their products come from or where they end up. Instead, their entire identity becomes synonymous with this mission to create a better world.

When you compare them to companies that prioritize profit before anything else or who have been accused of being dishonest for the purposes of driving up their bottom line, Samsung stands out as a shining example of what to do.

Another way to stand out with this concept of social goodness is by showing customers how they’re contributing to a good cause by giving their business to them.

The Giving Keys is a brand that’s built its entire concept around this.

The Giving Keys highlights customer stories. (Source: The Giving Keys) (Large preview)

The Giving Keys isn’t just a website to buy jewelry from. This is a place where consumers can make a difference in more ways than one. It works like this:

  • Customers purchase a piece of jewelry and add a personalized inscription to the key charm.
  • They then give the inspirational message jewelry to someone who needs it. (The website features a section where customers can “Share Your Story” to talk about who they gave it to and why.)
  • In turn, the company uses a portion of the sale to help create jobs for the homeless.

This is the kind of thing that makes Generation Z stop and think twice about giving their money to a money-hungry mega brand instead of a smaller company that backs a good cause.

Wrapping Up

It’s an interesting thing, isn’t? Raise kids in a certain timeframe and environment and they’ll turn out to be completely different shoppers than the generations before them.

Thankfully, the same kinds of technologies that have powered Generation Z’s lives are the ones we can use to learn more about them. And we’ve certainly learned a lot. As you go about designing websites for clients in the future, don’t forget to bring up the Gen Z question to them. Even if they’re not selling to them now, someday in the not-so-distant future, they will.

Further Reading on SmashingMag: (ra, yk, il)
Categories: Around The Web

How To Align Things In CSS

Thu, 03/28/2019 - 7:30am
How To Align Things In CSS How To Align Things In CSS Rachel Andrew 2019-03-28T12:30:41+01:00 2019-04-16T13:35:27+00:00

We have a whole selection of ways to align things in CSS today, and it isn’t always an obvious decision which to use. However, knowing what is available means that you can always try a few tactics if you come across a particular alignment problem.

In this article, I will take a look at the different alignment methods. Instead of providing a comprehensive guide to each, I’ll explain a few of the sticking points people have and point to more complete references for the properties and values. As with much of CSS, you can go a long way by understanding the fundamental things about how the methods behave, and then need a place to go look up the finer details in terms of how you achieve the precise layout that you want.

Aligning Text And Inline Elements

When we have some text and other inline elements on a page, each line of content is treated as a line box. The property text-align will align that content on the page, for example, if you want your text centered, or justified. Sometimes, however, you may want to align things inside that line box against other things, for example, if you have an icon displayed alongside text, or text of different sizes.

In the example below, I have some text with a larger inline image. I am using vertical-align: middle on the image to align the text to the middle of the image.

See the Pen Vertical Alignment example by Rachel Andrew.

See on Codepen The line-height Property And Alignment

Remember that the line-height property will change the size of the line-box and therefore can change your alignment. The following example uses a large line-height value of 150px, and I have aligned the image to top. The image is aligned to the top of the line box and not the top of the text, remove that line-height or make it less than the size of the image and the image and text will line up at the top of the text.

See the Pen Vertical Alignment and line-height by Rachel Andrew.

See on Codepen

It turns out that line-height and indeed the size of text is pretty complicated, and I’m not going to head down that rabbit hole in this article. If you are trying to precisely align inline elements and want to really understand what is going on, I recommend reading “Deep Dive CSS: Font Metrics, line-height And vertical-align.”

When Can I Use The vertical-align Property?

The vertical-align property is useful if you are aligning any inline element. This includes elements with display: inline-block. The content of table cells can also be aligned with the vertical-align property.

The vertical-align property has no effect on flex or grid items, and therefore if used as part of a fallback strategy, will cease to apply the minute the parent element is turned into a grid or flex Container. For example, in the next pen, I have a set of items laid out with display: inline-block and this means that I get the ability to align the items even if the browser does not have Flexbox:

See the Pen inline-block and vertical-align by Rachel Andrew.

See on Codepen

In this next pen, I have treated the inline-block as a fallback for Flex layout. The alignment properties no longer apply, and I can add align-items to align the items in Flexbox. You can tell that the Flexbox method is in play because the gap between items that you will get when using display: inline-block is gone.

See the Pen inline-block flex fallback by Rachel Andrew.

See on Codepen

The fact that vertical-align works on table cells is the reason that the trick to vertically center an item using display: table-cell works.

Now that we do have better ways to align boxes in CSS (as we will look at in the next section), we don’t need to employ the vertical-align and text-align properties in places other than the inline and text elements for which they were designed. However, they are still completely valid to use in those text and inline formats, and so remember if you are trying to align something inline, it is these properties and not the Box Alignment ones that you need to reach for.

Box Alignment

The Box Alignment Specification deals with how we align everything else. The specification details the following alignment properties:

  • justify-content
  • align-content
  • justify-self
  • align-self
  • justify-items
  • align-items

You might already think of these properties as being part of the Flexbox Specification, or perhaps Grid. The history of the properties is that they originated as part of Flexbox, and still exist in the Level 1 specification; however, they were moved into their own specification when it became apparent that they were more generally useful. We now also use them in Grid Layout, and they are specified for other layout methods too, although current browser support means that you won’t be able to use them just yet.

Therefore, next time someone on the Internet tells you that vertical alignment is the hardest part of CSS, you can tell them this (which even fits into a tweet):

.container { display: flex; align-items: center; justify-content: center; }

In the future, we may even be able to dispense with display: flex, once the Box Alignment properties are implemented for Block Layout. At the moment, however, making the parent of the thing you want centering a flex container is the way to get alignment horizontally and vertically.

The Two Types Of Alignment

When aligning flex and grid items, you have two possible things to align:

  1. You have the spare space in the grid or flex container (once the items or tracks have been laid out).
  2. You also have the item itself inside the grid area you placed it in, or on the cross axis inside the flex container.

I showed you a set of properties above, and the alignment properties can be thought of as two groups. Those which deal with distribution of spare space, and those which align the item itself.

Dealing With Spare Space: align-content And justify-content

The properties which end in -content are about space distribution, so when you choose to use align-content or justify-content you are distributing available space between grid tracks or flex items. They don’t change the size of the flex or grid items themselves; they move them around because they change where the spare space goes.

Below, I have a flex example and a grid example. Both have a container which is larger than required to display the flex items or grid tracks, so I can use align-content and justify-content to distribute that space.

See the Pen justify-content and align-content by Rachel Andrew.

See on Codepen Moving Items Around: justify-self, align-self, justify-items And align-items

We then have align-self and justify-self as applied to individual flex or grid items; you can also use align-items and justify-items on the container to set all the properties at once. These properties deal with the actual flex or grid item, i.e. moving the content around inside the Grid Area or flex line.

  • Grid Layout You get both properties as you can shift the item on the block and inline axis as we have a defined Grid Area in which it sits.
  • Flex Layout You can only align on the cross axis as the main axis is controlled by space distribution alone. So if your items are a row, you can use align-self to shift them up and down inside the flex line, aligning them against each other.

In my example below, I have a flex and a grid container, and am using align-items and align-self in Flexbox to move the items up and down against each other on the cross axis. If you use Firefox, and inspect the element using the Firefox Flexbox Inspector, you can see the size of the flex container and how the items are being moved vertically inside of that.

Aligned flex items with the flex container highlighted in Firefox (Large preview)

In grid, I can use all four properties to move the items around inside their grid area. Once again, the Firefox DevTools Grid Inspector will be useful when playing with alignment. With the grid lines overlaid, you can see the area inside which the content is being moved:

Aligned grid items with the Grid highlighted in Firefox (Large preview)

Play around with the values in the CodePen demo to see how you can shift content around in each layout method:

See the Pen justify-self, align-self, justify-items, align-items by Rachel Andrew.

See on Codepen Confused By align And justify

One of the cited issues with people remembering the alignment properties in Grid and Flexbox, is that no one can remember whether to align or to justify. Which direction is which?

For Grid Layout, you need to know if you are aligning in the Block or Inline Direction. The Block direction is the direction blocks lay out on your page (in your writing mode), i.e. for English that is vertically. The Inline direction is the direction in which sentences run (so for English that is left to right horizontally).

To align things in the Block Direction, you will use the properties which start with align-. You use align-content to distribute space between grid tracks, if there is free space in the grid container, and align-items or align-self to move an item around inside the grid area it has been placed in.

The below example has two grid layouts. One has writing-mode: horizontal-tb (which is the default for English) and the other writing-mode: vertical-rl. This is the only difference between them. You can see that the alignment properties which I have applied work in exactly the same way on the block axis in both modes.

See the Pen Grid Block Axis Alignment by Rachel Andrew.

See on Codepen

To align things in the inline direction, use the properties which begin with justify-. Use justify-content to distribute space between grid tracks, and justify-items or justify-self to align items inside their grid area in the inline direction.

Once again, I have two grid layout examples so that you can see that inline is always inline — no matter which writing mode you are using.

See the Pen Grid Inline Alignment by Rachel Andrew.

See on Codepen

Flexbox is a little trickier due to the fact that we have a main axis which can be changed to row or column. So, let’s first think about that main axis. It is set with the flex-direction property. The initial (or default) value of this property is row which will lay the flex items out as a row in the writing mode currently in use — this is why when working in English, we end up with items laid out horizontally when we create a flex container. You can then change the main axis to flex-direction: column and the items will be laid out as a column which means they are laid out in the block direction for that writing mode.

As we can do this axis switching, the most important factor in Flexbox is asking, “Which axis is my main axis?” Once you know that, then for alignment (when on your main axis) you simply use justify-content. It doesn’t matter if your main axis is row or column. You control space between the flex items with justify-content.

See the Pen justfy-content in Flexbox by Rachel Andrew.

See on Codepen

On the cross axis, you can use align-items which will align the items inside the flex container or flex line in a multi-line flex container. If you have a multi-line container using flex-wrap: wrap and have space in that container, you can use align-content to distribute the space on the cross axis.

In the example below, we are doing both with a flex container displayed as a row and a column:

See the Pen Cross axis alignment in Flexbox by Rachel Andrew.

See on Codepen When justify-content Or align-content Do Not Work

The justify-content and align-content properties in Grid and Flexbox are about distributing extra space. So the thing to check is that you have extra space.

Here is a Flex example: I have set flex-direction: row and I have three items. They don’t take up all of the space in the flex container, so I have spare space on the main axis, the initial value for justify-content is flex-start and so my items all line up at the start and the extra space is at the end. I am using the Firefox Flex Inspector to highlight the space.

The spare space at the end of the container (Large preview)

If I change flex-direction to space-between, that extra space is now distributed between the items:

The spare space is now between the items (Large preview)

If I now add more content to my items so they become larger and there is no longer any additional space, then justify-content does nothing — simply because there is no space to distribute.

There is now no space to distribute (Large preview)

A common question I’m asked is why justify-content isn’t working when flex-direction is column. This is generally because there is no space to distribute. If you take the above example and make it flex-direction: column, the items will display as a column, but there will be no additional space below the items as there is when you do flex-direction: row. This is because when you make a Flex Container with display: flex you have a block level flex container; this will take up all possible space in the inline direction. In CSS, things do not stretch in the block direction, so no extra space.

The column is only as tall as needed to display the items (Large preview)

Add a height to the container and — as long as that is more than is required to display the items — you have extra space and therefore justify-content will work on your column.

Adding a height to the container means we have spare space (Large preview) Why Is There No justify-self In Flexbox?

Grid Layout implements all of the properties for both axes because we always have two axes to deal with in Grid Layout. We create tracks (which may leave additional space in the grid container in either dimension,) and so we can distribute that space with align-content or justify-content. We also have Grid Areas, and the element in that area may not take up the full space of the area, so we can use align-self or justify-self to move the content around the area (or align-items, justify-items to change the alignment of all items).

Flexbox does not have tracks in the way that Grid layout does. On the main axis, all we have to play with is the distribution of space between the items. There is no concept of a track into which a flex item is placed. So there is no area created in which to move the item around in. This is why there is no justify-self property on the main axes in Flexbox.

Sometimes, however, you do want to be able to align one item or part of the group of items in a different way. A common pattern would be a split navigation bar with one item being separated out from the group. In that situation, the specification advises the use of auto margins.

An auto margin will take up all of the space in the direction it is applied, which is why we can center a block (such as our main page layout) using a left and right margin of auto. With an auto margin on both sides, each margin tries to take up all the space and so pushes the block into the middle. With our row of flex items, we can add margin-left: auto to the item we want the split to happen on, and as long as there is available space in the flex container, you get a split. This plays nicely with Flexbox because as soon as there is no available space, the items behave as regular flex items do.

See the Pen Alignment with auto margins by Rachel Andrew.

See on Codepen Flexbox And Micro-Components

One of the things I think is often overlooked is how useful Flexbox is for doing tiny layout jobs, where you might think that using vertical-align is the way to go. I often use Flexbox to get neat alignment of small patterns; for example, aligning an icon next to text, baseline aligning two things with different font sizes, or making form fields and buttons line up properly. If you are struggling to get something to line up nicely with vertical-align, then perhaps try doing the job with Flexbox. Remember that you can also create an inline flex container if you want with display: inline-flex.

See the Pen inline-flex example by Rachel Andrew.

See on Codepen

There is no reason not to use Flexbox, or even Grid for tiny layout jobs. They aren’t just for big chunks of layout. Try the different things available to you, and see what works best.

People are often very keen to know what the right or wrong way to do things is. In reality, there often is no right or wrong; a small difference in your pattern might mean the difference between Flexbox working best, where otherwise you would use vertical-align.

Wrapping Up

To wrap up, I have a quick summary of the basics of alignment. If you remember these few rules, you should be able to align most things with CSS:

  1. Are you aligning text or an inline element? If so, you need to use text-align, vertical-align, and line-height.
  2. Do you have an item or items you want to align in the center of the page or container? If so, make the container a flex container then set align-items: center and justify-content: center.
  3. For Grid Layouts, the properties that start with align- work in the Block direction; those which start with justify- work in the inline direction.
  4. For Flex Layouts, the properties that start with align- work on the Cross Axis; those which start with justify- work on the main axis.
  5. The justify-content and align-content properties distribute extra space. If you have no extra space in your flex or grid container, they will do nothing.
  6. If you think you need justify-self in Flexbox, then using an auto margin will probably give you the pattern you are after.
  7. You can use Grid and Flexbox along with the alignment properties for tiny layout jobs as well as main components — experiment!

For more information about alignment, see these resources:

Categories: Around The Web

Plesk VPS Hosting For Better Website Outcomes

Thu, 03/28/2019 - 5:30am
Plesk VPS Hosting For Better Website Outcomes Plesk VPS Hosting For Better Website Outcomes Suzanne Scacca 2019-03-28T10:30:39+01:00 2019-04-15T10:35:42+00:00

(This is a sponsored article.) In early discussions you have with clients about the website you’re tasked with designing, does the topic of web hosting ever come up? My guess is that it’s not something your clients give much thought to, waving it away with:

“Just give me the cheapest, no-frills hosting.”

I get why they’d think that way. For starters, they’re paying you a large sum of money to design the site. Of course, they’re going to look to other areas to offset those costs. Because server technology is rarely understood by the people who own websites, it’s easy for them to mistakenly think they can save money there.

Here’s the problem though:

As a website grows in authority and expands its reach, security and performance problems will arise if the hosting configuration isn’t prepared to handle it.

In the following article, I’m going to show you why clients need the power of VPS hosting behind the websites you design for them. And why you — the administrator — need a tool like the Plesk control panel to manage it.

The Web Designer’s Connection to Web Hosting

In many cases, people get stuck being the go-to person for one highly specialized task at the companies they work for. This person handles the marketing. This person manages inventory. This person coordinates client meetings.

One of the things I love about working with websites is that there are so many new things to learn about and other areas to branch out to. If you don’t want to be relegated to building website after website, day in and day out, there are ways to expand your offering and become the total end-to-end solution provider for clients.

In my opinion, web hosting is one of the areas you should look to for expansion. Now, I’m not saying you should become a reseller of hosting or anything like that. All I mean is that it would be beneficial to understand how the technology behind a website affects the outcomes of what you’ve built.

For example:

  • An underpowered hosting plan fails to handle influxes of traffic, which leads to slower page speeds and a drop in conversion rates.
  • Occasional downtime on the website leaves visitors wondering if it’s even worth going to the site if its availability is unreliable.
  • There’s a high demand for the inventory sold on the site, but potential customers are too nervous to pull the trigger since security seems to be non-existent.

Even if you’re not the one responsible for the server technology your client’s site sits on, you can see how this sort of thing could have a negative effect on your business. You build an amazing website that aims to do exactly what your client wanted, but the server technology is holding it back.

Who do you think the client is going to blame in that case?

Rather than let it get that far, I’d suggest you engage your clients early on in conversations about their web hosting. As we move on, I’m going to present you with specific arguments you should be prepared to make regarding the hosting as well as how it’s managed.

An Introduction To VPS Hosting

When it comes to choosing the right hosting for your clients’ websites, there’s a lot to think about:

Who Should You Entrust Your Website To?

There are thousands of web hosting companies to choose from. But in terms of reliability? That list could easily be narrowed down to less than a hundred.

HostGator has been a web hosting company I’ve recommended to clients for years, especially ones who need a powerful hosting solution like Plesk VPS hosting. If your client doesn’t have a strong preference of provider, start here.

What Type Of Web Hosting Will Serve Your Website And Audience Best?

This is what you need to know about the different kinds of web hosting:

Shared Hosting

This is the cheapest form of hosting available and probably the one your clients will be most inclined to purchase.

The hosting provider designates a section of a web server to a number of clients who will then share the resources. This means there are strict limitations set on how much bandwidth and storage a website can use, but very little you can do to control any of it — especially if another website in the shared server space hogs the resources.

It’s this last point that’s especially problematic on shared hosting. Although your hosting plan might indicate you get X amount of memory, it’s actually a cap on how much you might have access to if no one else is using resources from the server at the same time. In reality, it’s very likely you’ll run into lack of memory errors due to this limitation quite frequently.

Shared hosting is fine for small, personal blogs or private websites. Not for serious businesses.

Cloud Hosting

This is similar to shared hosting except that it’s more secure and stable.

Rather than relegate a website to one specific segment of a web server, the site is hosted across a number of servers. That way, if one server experiences an outage or another website compromises the performance of others around it, your website can safely be hosted elsewhere.

That said, there are still a number of limitations that come from cloud hosting. If your website is for a growing business, but you don’t expect a lot of traffic to it (say, if it were a simple portfolio), cloud hosting would be a good choice.

Dedicated Hosting

This is the most robust form of web hosting, which also makes it the most expensive.

As the name indicates, your hosting company will lease you an entire server to host your website. So, think of this like shared hosting, but on steroids. As you can imagine, when you have your own server environment, it greatly reduces the risk of anyone else compromising the performance of your website.

That said, there is a lot more work involved in managed a dedicated hosting account and the website on it. This is really only best for large enterprises, social networks, e-commerce sites and others that require this type of extreme web hosting.

VPS Hosting

This stands for “virtual private server”. The name alone should give you a good idea of how this differs from the other kinds of hosting already mentioned.

In sum, a virtual private server is like a scaled-back version of dedicated hosting. Instead of having an entire server to yourself, the web hosting company carves out a dedicated portion of the server and personalizes its settings for you. Although you share the server with other VPS clients, you don’t share the resources with anyone else. You get exactly what you pay for.

Here are some other highlights of VPS hosting:

  • It’s faster and more secure than shared or cloud hosting.
  • It’s cheaper than dedicated hosting.
  • It’s custom-tailored to your needs, but still allows you to take more control over your server configuration.

Bottom line: VPS is an overall better hosting solution for growing businesses.

How Will You Manage Your Web Hosting Account?

There’s one more question you have to ask yourself before you commit to a new hosting provider and plan.

Because VPS hosting is more complex and requires a greater degree of management than a set-it-and-forget-it type of hosting like shared or cloud, you need a control panel you can rely on.

So, let’s explore the Plesk panel and take a look at what you can do to maximize the management of your new website with it.

An Exploration Of Plesk VPS Hosting

This is the Plesk website:

Large preview

It won’t take long to realize that Plesk is not like other control panel solutions. The website will help clarify some of this for you, but I’d like to give you an inside look at the control panel so you can see for yourself.

A Universally Friendly Control Panel

Plesk is one of those tools you step inside of and immediately realize you made the right choice. With a very short learning curve, Plesk is a highly intuitive control panel solution that’s great for anyone:

Plesk is a universally user-friendly platform. (Image source: Large preview)

In all honesty, I don’t know how much time your clients will spend inside the control panel. When I’ve managed and built websites for clients in the past, just asking for login credentials to their hosting account tended to be a real chore.

“What’s hosting? Is that WordPress? I don’t think I need that.”

Regardless of whether they want or know what to do with a control panel, Plesk provides a user-friendly experience regardless of who the user is as well as their level of comfort with website management. I’ll show you why in this next example.

Words cannot describe how frustrating it is to ask clients to complete simple tasks. (Source) Great Interface For Clients And Other End Users

If you’ve ever tried to use cPanel to manage hosting and domain services, you know how overwhelming it can be to use.

If you’re not familiar with it, this is typically what cPanel looks like upon first logging in:

This is how the cPanel interface (meant for end users) looks like. (Image source: cPanel) (Large preview)

If you plan on reselling or managing hosting for your cPanel clients, then you'll need to use a separate dashboard called WHM:

cPanel’s user interface (Image source: cPanel) (Large preview)

There’s a navigation and sub-navigation bar at the top, which makes management options seem simple enough.

Then, you’re presented with individual actions you can take to manage hosting, your website or email accounts within the control panel itself. This is just too much — even for technically-minded clients who know what the heck they’re looking for.

Now, check out the Plesk interface for power users:

The Plesk power user home page. (Source: Plesk) (Large preview)

This is insanely well-organized and clearly labeled. If your clients or other novice users were to step inside of Plesk, they’d instantly know where to go as well as which actions they could possibly take from the sidebar alone.

It gets better within each of the individual modules. For instance:

An example of the clean layout of the Plesk UI. (Source: Plesk) (Large preview)

This is what the Tools & Settings page looks like. As you can see, it’s not bogged down by a barrage of icons for each setting. Instead, it presents options in a succinct and well-organized manner, which will greatly reduce friction that might otherwise exist in a tool of this nature.

Great Interface For Designers And Developers

Plesk offers an alternative “service provider” view for web developers and designers:

A look at the Plesk service provider interface for developers. (Source: Plesk) (Large preview)

It looks a lot like the power user view, except you can see that the sidebar is broken up into different modules. What I like about this is that it encourages developers to manage more of their business from one tool instead of a variety of business management tools.

From within Plesk, you can:

  • Add new customer accounts and manage them from one dashboard.
Adding and managing customers in Plesk is easy. (Source: Plesk) (Large preview)
  • Customize what they do and see in their “power user” view of Plesk. This helps keep server and website management under control.
Managing customers in Plesk is easy. (Source: Plesk) (Large preview)
  • Create hosting plans that you can, in turn, sell to customers as subscriptions.
Managing hosting plans in Plesk is easy. (Source: Plesk) (Large preview)
  • Move non-Plesk customers over to Plesk with a simple-to-use migration tool.
The Plesk Migrator extension. (Source: Plesk) (Large preview)
  • Customize nearly every aspect of your clients’ server configurations. Like disk space:
It’s easy to configure your server with Plesk. (Source: Plesk) (Large preview)
  • Manage the essentials to ensure the server runs in tip-top shape. For instance, here are some of the PHP settings for security and performance:
Security and performance controls are a priority in Plesk. (Source: Plesk) (Large preview)
  • Manage things like plugins, themes and more if you build websites with WordPress.
Plesk users can control various WordPress settings and tools inside of the control panel. (Source: Plesk) (Large preview)

If you’ve ever been frustrated with the management piece of your business or felt that your ability to control things was lacking, Plesk is the solution. Plus, you can use Plesk extensions to really open this tool up. Add business management features like invoicing and site-builder tools to improve your offering, streamline your workflow and make more money.

Last but not least, you can white label it with your branding. That way, when clients step inside, they’re reminded that they have a trusted website pro like you to properly manage their server and website.

Flexible Workflows

Another developer-friendly feature of Plesk is its flexibility.

One of the issues with letting clients make decisions about their web hosting and server management is that they don’t understand the amount of work that goes into it behind the scenes. They might think:

“You’re the developer. Why can’t you work with whatever I give you?”

But you and I know it’s not that simple.

For starters, there’s your level of comfort in using the command line. For some developers, that level of comfort is low, so having a flexible solution like Plesk that removes the need for programming is great.

That said, you can still use the CLI if you prefer. Plesk provides you with full root access, so you won’t have to worry about being restricted to the control panel’s settings to manage your VPS server either. Like I said, it’s flexible. It allows you to work as you want to work.

Plus, it works on a number of configurations:

  • Linux vs. Windows
  • Apache vs. nginx
  • Ruby on Rails vs. Node.js.

Whatever you choose, settings are available to deeply customize and configure each so that the VPS hosting plan works exactly as you need it to.

Wrapping Up

It’s your hope that when you build a website for a client, it doesn’t go to waste. You design powerful website experiences so that clients can effectively leverage their web presences to drum up new business and increase conversions.

Sadly, something like a poor choice of web hosting can compromise all of that planning and hard work on your part. Unless you’re in the habit of designing websites for very small businesses or nonprofits, Plesk VPS Hosting is the logical choice. Not only is it a great solution in terms of easing your administration and management responsibilities, but it’s also an amazing tool for building your design business.

If you’re interested in using Plesk VPS hosting, I’d suggest you start by looking at HostGator. In addition to being one of the leading hosting companies around the world, there is a 45-day Money-Back Guarantee available which may help you encourage your clients to give it a try.

(ms, ra, yk, il)
Categories: Around The Web

Building Real-Time Charts With GraphQL And Postgres

Wed, 03/27/2019 - 8:00am
Building Real-Time Charts With GraphQL And Postgres Building Real-Time Charts With GraphQL And Postgres Rishichandra Wawhal 2019-03-27T13:00:08+01:00 2019-04-12T11:36:01+00:00

Charts form an integral part of any industry that deals with data. Charts are useful in the voting and polling industry, and they’re also great at helping us better understand the different behaviors and characteristics of the users and clients we work with.

Why are real-time charts so important? Well, they’re useful in cases when new data is produced continuously; for example, when using live-time series for visualizing stock prices is a great use for real-time charts. In this tutorial, I’ll explain how to build real-time charts with open-source technologies apt for exactly this particular task.

Note: This tutorial requires basic knowledge of React and GraphQL.

  1. PostgreSQL
    The very point behind using Charts is to visualize “huge” volumes data. We, therefore, need a database that efficiently handles large data and provides an intuitive API to restructure it. SQL databases allow us to make views that abstract and aggregate data for us. We will be using Postgres which is a time-tested and highly efficient database. It also has fancy open-source extensions like Timescale and PostGIS which allow us to build geolocation-based and time-series-based charts respectively. We will be using Timescale for building our time series chart.
  2. GraphQL Engine
    This post is about building real-time charts, and GraphQL comes with a well-defined spec for real-time subscriptions. Hasura GraphQL Engine is an open-source GraphQL server that takes a Postgres connection and allows you to query the Postgres data over realtime GraphQL. It also comes with an access control layer that helps you restrict your data based on custom access control rules.
  3. ChartJS
    ChartJS is a popular and well maintained open source library for building charts with JavaScript. We will use chart.js along with its ReactJS abstraction react-chartjs-2. About why React, it is because React empowers developers with an intuitive event-driven API. Also, React’s unidirectional data flow is ideal for building charts that are data-driven.

For this tutorial, you will need the following on your system:

  1. Docker CE
    Docker is a software that lets you containerize your applications. A docker image is an independent packet that contains software along with its dependencies and a minimalistic operating system. Such docker images can be technically run in any machine that has docker installed. You will need docker for this tutorial.
  2. npm: npm is the package manage for JavaScript.

We will build the following live time series chart that shows the maximum temperature of a location in intervals of 5 seconds over the past 20 minutes from the present moment.

GIF Demo of the realtime chart Setting Up The Backend Running The Services

The backend comprises of a Postgres database, its timescale extension, and Hasura GraphQL Engine. Let us get the database and our GraphQL server running by running the respective docker images. Create a file called docker-compose.yaml and paste this content into it.

Note: docker-compose is a utility to run multiple docker images declaratively.

version: '2' services: timescale: image: timescale/timescaledb:latest-pg10 restart: always environment: POSTGRES_PASSWORD: postgrespassword volumes: - db_data:/var/lib/postgresql/data graphql-engine: image: hasura/graphql-engine:v1.0.0-alpha38 ports: - "8080:8080" depends_on: - "timescale" restart: always environment: HASURA_GRAPHQL_DATABASE_URL: postgres://postgres:postgrespassword@timescale:5432/postgres HASURA_GRAPHQL_ACCESS_KEY: mylongsecretkey command: - graphql-engine - serve - --enable-console volumes: db_data:

This docker-compose.yaml contains the spec for two services:

  1. timescale
    This is our Postgres database with Timescale extension installed. It is configured to run at port 5432.
  2. graphql-engine
    This is our Hasura GraphQL Engine instance, i.e. the GraphQL server that points to the database and gives GraphQL APIs over it. It is configured to run at the port 8080, and the port 8080 is mapped to the port 8080 of the machine that this docker container runs on. This means that you can access this GraphQL server through at localhost:8080 of the machine.

Let’s run these docker containers by running the following command wherever you have placed your docker-compose.yaml.

docker-compose up -d

This command pulls the docker images from the cloud and runs them in the given order. It might take a few seconds based on your internet speed. Once it is complete, you can access your GraphQL Engine console at http://localhost:8080/console.

Hasura GraphQL Engine console (Large preview) Setting Up The Database

Next, let us create a table called temperature that stores the values of temperatures at different times. Go to the Data tab in the console and go to the SQL section. Create our temperature table by running this SQL block:

CREATE TABLE temperature ( temperature numeric not null, location text not null, recorded_at timestamptz not null default now() );

This creates a simple Postgres table in the database. But we wish to leverage the time interval partitioning of the Timescale extension. To do this, we must convert this table into timescale’s hypertable by running the SQL command:

SELECT create_hypertable('temperature', 'recorded_at');

This command creates a hypertable that is partitioned by time in the field recorded_at.

Now, since this table is created, we can directly start making GraphQL queries over it. You can try them out by clicking on the GraphiQL tab on top. Try making a mutation first:

mutation { insert_temperature ( objects: [{ temperature: 13.4 location: "London" }] ) { returning { recorded_at temperature } } }

The GraphQL mutation above inserts a row in the temperature table. Now try to make a GraphQL query to check if the data was inserted.

Then try making a query:

query { temperature { recorded_at temperature location } }

Hope it worked :)

Now, the task at our hand is to create a live time-series chart that shows the maximum temperature of a location in intervals of 5 seconds over the past 20 minutes from the present moment. Let’s create a view that gives us exactly this data.

CREATE VIEW last_20_min_temp AS ( SELECT time_bucket('5 seconds', recorded_at) AS five_sec_interval, location, MAX(temperature) AS max_temp FROM temperature WHERE recorded_at > NOW() - interval '20 minutes' GROUP BY five_sec_interval, location ORDER BY five_sec_interval ASC );

This view groups the data from the temperature table in 5-second windows with their max temperature (max_temp). The secondary grouping is done using the location field. All this data is only from the past twenty minutes from the present moment.

That’s it. Our backend is set up. Let us now build a nice real-time chart.

Frontend Hello GraphQL Subscriptions

GraphQL subscriptions are essentially “live” GraphQL queries. They operate over WebSockets and have exactly the same response structure like GraphQL queries. Go back to http://localhost:8080/console and try to make a GraphQL subscription to the view we created.

subscription { last_20_min_temp( order_by: { five_sec_interval: asc } where: { location: { _eq: "London" } } ) { five_sec_interval location max_temp } }

This subscription subscribes to the data in the view where the location is London and it is ordered in ascending order of the five_second_intervals.

Naturally, the response from the view would be an empty array because we have not inserted anything in the database in the past twenty minutes. (You might see the entry that we inserted sometime back if you reached this section within twenty minutes.)

{ "data": { "last_20_min_temp": [] } }

Keeping this subscription on, open another tab and try inserting another value in the temperatures table using the same mutation that we performed earlier. After inserting, if you go back to the tab where the subscription was on, you would see the response having updated automatically. That’s the realtime magic that GraphQL Engine provides. Let’s use this subscription to power our real-time chart.

Getting Started With Create-React-App

Let us quickly get started with a React app starter using create react app. Run the command:

npx create-react-app time-series-chart

This will create an empty starter project. cd into it and install the GraphQL and chart libraries. Also, install moment for converting timestamps to a human-readable format.

cd time-series-chart npm install --save apollo-boost apollo-link-ws subscriptions-transport-ws graphql react-apollo chart.js react-chartjs-2 moment

Finally, run the app with npm start and a basic React app would open up at http://localhost:3000.

Raw creat-react-app (Large preview) Setting Up Apollo Client For Client-Side GraphQL

Apollo client is currently the best GraphQL client that works with any GraphQL compliant server. Relay modern is good too but the server must support the relay spec to leverage all the benefits of Relay modern. We’ll use Apollo client for client-side GraphQL for this tutorial. Let us perform the setup to provide Apollo client to the app.

I am not getting into the subtleties of this setup because the following code snippets are taken directly from the docs. Head to src/index.js in the React app directory and instantiate Apollo client and add this code snippet above ReactDOM.render.

import { WebSocketLink } from 'apollo-link-ws'; import { ApolloClient } from 'apollo-client'; import { ApolloProvider } from 'react-apollo'; import { InMemoryCache } from 'apollo-cache-inmemory'; // Create a WebSocket link: const link = new WebSocketLink({ uri: 'ws://localhost:8080/v1alpha1/graphql', options: { reconnect: true } }); const cache = new InMemoryCache(); const client = new ApolloClient({ link, cache });

Finally, wrap the App inside ApolloProvider so that we can use Apollo client in the children components. Your App.js should finally look like:

import React from 'react'; import ReactDOM from 'react-dom'; import './index.css'; import App from './App'; import { WebSocketLink } from 'apollo-link-ws'; import { ApolloClient } from 'apollo-client'; import { ApolloProvider } from 'react-apollo'; import { InMemoryCache } from 'apollo-cache-inmemory'; // Create a WebSocket link: const link = new WebSocketLink({ uri: `ws://localhost:8080/v1alpha1/graphql`, options: { reconnect: true } }); const cache = new InMemoryCache(); const client = new ApolloClient({ link, cache }); ReactDOM.render( ( <ApolloProvider client={client}> <App /> </ApolloProvider> ), document.getElementById('root') );

Apollo client has been set up. We can now easily use real-time GraphQL from our App. Head to src/App.js.

Building The Chart

ChartJS provides a pretty neat API for building charts. We will be building a line chart; so a line chart expects data of the form:

{ "labels": ["label1", "label2", "label3", "label4"], "datasets": [{ "label": "Sample dataset", "data": [45, 23, 56, 55], "pointBackgroundColor": ["red", "brown", "green", "yellow"], "borderColor": "brown", "fill": false }], }

If the above dataset is used for rendering a line chart, it would look something like this:

Sample line chart (Large preview)

Let us try to build this sample chart first. Import Line from react-chartjs-2 and render it passing the above object as a data prop. The render method would look something like:

render() { const data = { "labels": ["label1", "label2", "label3", "label4"], "datasets": [{ "label": "Sample dataset", "data": [45, 23, 56, 55], "pointBackgroundColor": ["red", "brown", "green", "yellow"], "borderColor": "brown", "fill": false }], } return ( <div style={{display: 'flex', alignItems: 'center', justifyContent: 'center', margin: '20px'}} > <Line data={data} /> </div> ); }

Next, we will subscribe to the data in our view and feed it to the Line chart. But how do we perform subscriptions on the client?

Apollo’s <Subscription> components work using the render prop pattern where the children of a component are rendered with the context of the subscription data.

<Subscription subscription={gql`subscription { parent { child } }`} /> { ({data, error, loading}) => { if (error) return <Error error={error} />; if (loading) return <Loading />; return <RenderData data={data} />; } } </Subscription>

Let us use one such Subscription component to subscribe to our view and then transform the subscription data to the structure that ChartJS expects. The transforming logic looks like this:

let chartJSData = { labels: [], datasets: [{ label: "Max temperature every five seconds", data: [], pointBackgroundColor: [], borderColor: 'brown', fill: false }] }; data.last_20_min_temp.forEach((item) => { const humanReadableTime = moment(item.five_sec_interval).format('LTS'); chartJSData.labels.push(humanReadableTime); chartJSData.datasets[0].data.push(item.max_temp); chartJSData.datasets[0].pointBackgroundColor.push('brown'); })

Note: You can also use the open-source library graphq2chartjs for transforming the data from GraphQL response to a form that ChartJS expects.

After using this inside the Subscription component, our App.js looks like:

import React, { Component } from 'react'; import { Line } from 'react-chartjs-2'; import { Subscription } from 'react-apollo'; import gql from 'graphql-tag'; import moment from 'moment'; const TWENTY_MIN_TEMP_SUBSCRIPTION= gql' subscription { last_20_min_temp( order_by: { five_sec_interval: asc } where: { location: { _eq: "London" } } ) { five_sec_interval location max_temp } } ' class App extends Component { render() { return ( <div style={{display: 'flex', alignItems: 'center', justifyContent: 'center', margin: '20px'}} > <Subscription subscription={TWENTY_MIN_TEMP_SUBSCRIPTION}> { ({data, error, loading}) => { if (error) { console.error(error); return "Error"; } if (loading) { return "Loading"; } let chartJSData = { labels: [], datasets: [{ label: "Max temperature every five seconds", data: [], pointBackgroundColor: [], borderColor: 'brown', fill: false }] }; data.last_20_min_temp.forEach((item) => { const humanReadableTime = moment(item.five_sec_interval).format('LTS'); chartJSData.labels.push(humanReadableTime); chartJSData.datasets[0].data.push(item.max_temp); chartJSData.datasets[0].pointBackgroundColor.push('brown'); }) return ( <Line data={chartJSData} options={{ animation: {duration: 0}, scales: { yAxes: [{ticks: { min: 5, max: 20 }}]} }} /> ); } } </Subscription> </div> ); } } export default App;

You will have a fully working real-time chart ready at http://localhost:3000 . However, it would be empty, so let’s populate some sample data so we can actually see some magic happen.

Note: I have added some more options to the Line chart because I don’t like those fancy animations in ChartJS. A time series looks sweet when it’s simple, however, you can remove the options prop if you like.

Inserting Sample Data

Lets write a script that populates our database with dummy data. Create a separate directory (outside this app) and create a file called script.js with the following content,

const fetch = require('node-fetch'); setInterval( () => { const randomTemp = (Math.random() * 5) + 10; fetch( `http://localhost:8080/v1alpha1/graphql`, { method: 'POST', body: JSON.stringify({ query: ` mutation ($temp: numeric) { insert_temperature ( objects: [{ temperature: $temp location: "London" }] ) { returning { recorded_at temperature } } } `, variables: { temp: randomTemp } }) } ).then((resp) => resp.json().then((respObj) => console.log(JSON.stringify(respObj, null, 2)))); }, 2000 );

Now run these two commands:

npm install --save node-fetch node script.js

You can go back to http://localhost:3000 and see the chart updating.

Finishing Up

You can build most of the real-time charts using the ideas that we discussed above. The algorithm is:

  1. Deploy GraphQL Engine with Postgres;
  2. Create tables where you wish to store data;
  3. Subscribe to those tables from your React app;
  4. Render the chart.

You can find the source code here.

(dm, ra, il)
Categories: Around The Web