Jump to Navigation

Smashing Magazine

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

Onboarding Users Of Your Product: From Trial To Payment

5 hours 54 min ago
Onboarding Users Of Your Product: From Trial To Payment Onboarding Users Of Your Product: From Trial To Payment Joe Leech 2018-08-21T14:20:21+02:00 2018-08-21T13:33:03+00:00

(This is a sponsored article.) In part one of this series, we looked at the Attraction phase of the customer lifecycle. This three-part series outlines the three phases of the product lifecycle, the future for UX, and the skills and approach you’ll need to design modern digital products.

  • Part 1: Attraction
    Going out there to get users to evaluate your product.
  • Part 2: Activation
    Signing up, onboarding users, asking for payment.
  • Part 3: Retention
    Encouraging users to come back and keep using and paying for your product.
Part Two: Activation Plotting Out The Journey

When we talk about the Attraction phase, we’re talking about users discovering they have a need, discovering our product and visiting our website to see if our product meets their needs.

Within the lifecycle, we can split the larger three phases into smaller phases to help us plan our approach. In this case, we can use Philip Kotler's model (expanded to 6 steps by Bryony Thomas).

  • Awareness
    Realizing they have a need.
  • Interest
    Looking for something to help with that need.
  • Evaluation
    Looking at products that help with their need.
  • Trial
    Trying the product to see if it meets their need.
  • Adoption
    Choosing a product and using it for a while.
  • Loyalty
    Deciding to stay using the product or switch to a different one.
(Large preview)

We’re interested in the middle two parts that fall under the Acquisition phase.

In part one, we looked at the Evaluation phase. The user is now ready to sign up and get going with our product; we used the example of the money management app:

Homepage showing what our app does. (Large preview)

Let’s take that app forward into the Acquisition phase of the lifecycle.

A. Trial/Onboarding

In the Trial phase, our user is going to sign up and see if it is the product for them.

The first challenge is to onboard the user. Onboarding is a real challenge as it can be complex, involving the user entering personal information as well as getting to grips with what the product does. There is a huge potential for users to drop out and leave.

Joshua Porter sums it up:

“Onboarding should not be a separate function/consideration/afterthought. It should be an initial (and primary) focus of design.”

Joshua Porter

So with that in mind, let’s take a look at onboarding.

Onboarding: Steady Progress Showing Value

For our money management app to work well we need for our user we need to accomplish three goals:

  1. Collect some personal data from our users.
    Who they are (including email, mobile phone number, etc.).
  2. Bank account access, to auto pull in transactions.
    As we’re in the EU, open banking regulations mean that all banks have to provide API access to transaction data.
  3. Familiarize them with the product.

That’s a big ask. Let’s think about how we can soften that. We need a simple hook to get started. We use a concept in psychology called ‘incremental commitment.’ We ask for a low commitment to the product and then when the user gets something in return was ask for more.

We ask the simple question, “How much do you think you spend on coffee a month?”

A simple question to get started. (Large preview)

This can be done along with a hook to encourage people to compare their spend to others. There’s now a quick, easy win for the user.

We give something back, in this case comparing to the average. Then, we ask the next question.

Incremental commitment in action. We ask a follow-up. (Large preview)

It allows us to build trust, and for the user to get value from our product early.

Next, the big ask. We want bank account access. If we’d asked for this early, we’d see a larger dropout. But we now have built some trust, and our user is invested in the product.

(Large preview)

We then go for the big ask, granting bank access. As you can see, we are gently guiding our user through the onboarding, showing useful content at each step, trying to make it feel natural.

Asking for what could be challenging data like the mobile phone number is much easier if we offer context and say what benefit there is to the user. We could include the following on the sign-up page asking for the mobile number.

Showing how giving us your mobile number adds value. (Large preview)

We can then ask further questions, like email and for a password which will have less impact being asked later after we’ve shown value.

Interaction by interaction we’re asking a question, gathering some data and showing how the product works.

Things To Avoid During Onboarding

There are other pitfalls to designing a product onboarding flow.

  • Avoid the term registration, Registration is a meaningless concept, offer a reason for why you are asking for a pieces of information.
  • Similarly don’t ask too many questions, that might sound obvious, but the more you ask the more likely it is for users to drop out.
  • Answer these three simple questions when it comes to form fields:
    • Why are you asking the question?
    • What will you use the data for?
    • What value does the user get from giving us this data?
  • Avoid Captcha; it is a big cause of dropouts as captchas can harm conversion rates. Plus, they aren’t very friendly.
  • And, of course, if your users are located in the EU, you need to wrangle with GDPR.
B. Adoption

Onboarding doesn’t end when the user has signed up. This is a common mistake made by organizations big and small. “Great, our new registrations are up month on month. But our retention rate is really poor” is a common problem.

We need to support our users through the first few weeks and months of using our app. We need to give them a reason to come back to us.

In part one, we talked about SEO and Marketing skills and tools we can use to improve the experience.

We’ll be expanding our skill set to look at email, and how we can improve the email experience. To encourage product adoption, we need to understand and map the email user journey.

Any modern UX or product designer needs to know how to design multi-channel experiences, and after the product itself email is the most important.

Planning And Encouraging The Second Visit

For our money management app we have access to the users' bank transaction data. Rather than hoping they return to our app, we need to reach out and give them a reason to come back.

The pull: using email to get users to come back to our app

Let’s look at an email we can send them the next day. But before we do that, let’s look back at one question we asked users:

Notice that the ‘on coffee’ can be changed for other spending items. (Large preview)

The user could have changed ‘on coffee’ to be ‘at Restaurants’ or ‘at Amazon’ or another discretionary purchase option.

This is a tiny piece of personalization, and the best follow-up emails are personalized.

When designing an email the most important element is the subject line. A good subject line encourages the user to open it.

Let’s look at the most common email provider of them all, Gmail. Like we did in part one when designing Facebook ads, we’ll design in context, in this case the crowded inbox. Actually, the promotions inbox on Gmail.

There’s one email in there that stands out, yes it’s us! (Large preview)

By referencing the Frotos we identified in part one (Frotos: are the current bad state the user has and their wish for a new state. The From and the To, Froto) we should get a better open rate.

And yes, that is an emoji you see. Two in fact.

Categories: Around The Web

UX And HTML5: Let’s Help Users Fill In Your Mobile Form (Part 1)

Mon, 08/20/2018 - 7:45am
UX And HTML5: Let’s Help Users Fill In Your Mobile Form (Part 1) UX And HTML5: Let’s Help Users Fill In Your Mobile Form (Part 1) Stéphanie Walter 2018-08-20T13:45:31+02:00 2018-08-21T13:33:03+00:00

Forms are one of the most basic primary interactions users will have with your websites (and mobile apps). They link people together and let them communicate. They let them comment on articles and explain to the author how they strongly disagree with what they’ve written. They let people chat directly on a dating app to meet “the one”. Whether for forums, product orders, online communities, account creation or online payment, forms are a big part of users’ online life.

It’s 2018, and we have more mobile than desktop users around the globe. Yet, we still treat those users as second-class citizens of the web. Everybody writes and speaks about user experience all the time. So, why, why, why are so many websites and products still doing it wrong. Why is their mobile user experience damaged for half of the world? Why is it still a pain, why is it still super-hard to book a flight and register an account in a mobile form today? Users expect better!

Recommended reading: World Wide Web, Not Wealthy Western Web

This is the first part of a series of two articles. In this one, I will sum up some essential best practices to improve your mobile forms, including scannability and readability. I will guide you through label and input placement, size and optimization. We will see how to choose the right form element to reduce interaction costs. Finally, you will learn how to prevent and deal with errors on mobile forms.

In the second part, I will take a closer look at specific mobile capabilities and HTML5 form elements, and we will go beyond classic form elements to make unique and enjoyable web applications and websites.

Note: While most of the code enhancement in this article are web-related (because I don’t know Swift or Java), the usability best practices hold true for mobile applications.

Nope, we can't do any magic tricks, but we have articles, books and webinars featuring techniques we all can use to improve our work. Smashing Members get a seasoned selection of magic front-end tricks — e.g. live designing sessions and perf audits, too. Just sayin'! ;-)

Explore Smashing Wizardry → Form Design 101: Prioritizing Scannability And Readability

“A form is the name, value, pairs, in a structure for storing data on a computer barfed out as labels and input fields to human being.” This is a direct quote from Luke Wroblewski at a conference. Like him, I believe that most form usability issues come from this tendency to serve the structure of the database to users.

Strong Information Architecture

To build better forms, you first need to take a few steps away from your database’s structure. Try to understand how users want to fill in forms. This is where doing some usability testing and user research on your forms becomes handy. User mental models is a UX concept that can help you with that. Nielsen Norman Group describes it as “what the user believes about the system at hand”. Ask your tester to think aloud and tell you how they would fill the form. Which steps do they expect? What come first? What comes next? This will give you a better idea of how to structure your form in a more user-friendly way.

Visually grouping fields that belong together will also help users fill a form. In the code, use the fieldset tag to group them programmatically. It will also help screen readers understand the hierarchy.

Chunking information and grouping related pieces of information helps the human brain process this information in an easy, more readable way (Large preview)

If the form is long, don’t expose everything by default. Be smart about what you display. Use branching wisely to display only the fields that people need. In a checkout form, for example, don’t display all of the detailed fields for all of the shipment options. This will overwhelm the user. Display enough information to help them choose the right shipment option. Then, display only the details and fields related to that choice.

User attention spans get shorter with time: Ask for optional things at the end of the form. For instance, if your form is a customer-satisfaction survey, ask for demographic information at the end. Better yet, auto-fill them, if possible. Ask users only for what’s necessary.

Finally, plan ahead for localization: What will happen when your form gets translated? What will happen, say, for German? Will your design still work?

Label Placement And Input Optimization Single-Column Layout Works Best

Due to the lack of space, you don’t get endless options for placing labels and fields on mobile screens:

  • Present fields in a single-column layout. There’s no room on mobile for multiple columns. Multi-columns forms are not a great idea on desktop either anyway.
  • In portrait mode, it’s better to place the label on top of the field so that users can see what’s in the field when they type.
In portrait mode, it’s better to put the label on top of the field. (Large preview)
  • In landscape mode, the screen’s height is reduced. You might want to put labels on the left and inputs on the right. But test it to make sure it works.
In landscape mode, you want to put labels on the left and inputs on the right. (Large preview)

For more on label placement, see Baymard Institute’s “Mobile Form Usability: Place Labels Above the Field”.

Labels Should Be Clear And Visible And Work Without Context

Remember that as soon as a field gets focus, the keyboard opens and will take at least one third of the screen’s area. On small mobile screens, users will also have to scroll to fill the form. This means that they will lose part of the context while filling the form. Plan accordingly:

  • Your labels should be clear, visible text that can be read and understood without context. User should be able to complete each label and field pair as a separate task, even if they lose context.
Just “Address” without context is more complicated to process that “Shipping Address”. (Large preview)
  • Avoid jargon, abbreviations and industry-specific language whenever you can.
  • Be consistent. If you use “customer” in a label once, stick with that word. Avoid using “clients” later because it might confuse users.
  • The font size should be big enough. Test your form on real devices as soon as possible, and adjust the size accordingly.
  • All-caps text can be hard to read for some users. You might want to avoid using all-caps text on labels.
  • The label copy should be short and scannable. If a field needs clarification, don’t put it in the label. Use a field description instead.
Avoid full caps, jargon and very long labels. (Large preview) Input Size Best Practice

If possible, the size of the input element should match the size of the expected content. This will help users quickly fill in the form and understand what’s expected.

Properly sized inputs help the user scan the form and understand what is expected in the fields. (Large preview) Using Masks To Avoid Splitting Inputs On Mobile

Don’t split inputs just for the sake of formatting. It’s especially annoying on mobile, where users can’t use the keyboard to navigate between fields. It requires extra taps just to go to the next field to fill in the form. You might be thinking, “But I’ll automagically put the focus on the next field when I get the required number of characters in that field”. That could work. But you will have taken control of the UI, which becomes unpredictable for the user. Also, it would be a pain if you automagically sent them to the next field and they needed to correct something in the last field. Finally, it’s more complicated to guess what’s mandatory with split inputs. So, let’s stop playing the “But what if” game and simply not split inputs.

Don’t split the phone number into many little inputs. (Large preview)

I get it: You still want to be able to format your user’s data in small pieces to help them fill in your fields. And you are perfectly right about that. To do so, you could use masks. Instead of splitting an input, just put a mask on top of it, to visually help the user fill it. Here is a video example of what a mask would look like to help users fill in a credit-card field:

Masks help to prevent errors by guiding users to the correct format. Avoid gradually revealing them — show the format directly. Also, avoid putting fake values in the mask. Users might think it’s already filled. That’s why I’ve replaced the numbers with a little “X” in my demo. Find what works best for your type of input.

Finally, remember that some data can vary between countries, and sometimes the format changes, too (phone numbers, for example). Plan accordingly.

Efficient Fields Descriptions

Displaying efficient field descriptions can make the difference between a seamless and a painful form experience.

What Can Descriptions Be Used For?

Descriptions can help users in so many ways. Here are a few examples.

  • What Exactly Are You Asking For?

    For whatever database-related reason, some shipment companies ask for "Address 1" and “Address 2” fields. This is highly confusing for users, but you might not have a choice here. Add description fields to help users understand what they need to put in each field.

    Inline descriptions help users understand why you need this information. (Large preview)

    The same goes for acronyms and abbreviations. I know I said that you should avoid them, but sometimes you can’t. If you work on complex forms for a particular industry, for instance, they might have their own set of abbreviations. Any new user who needs to fill in the form might not be familiar (yet) with those abbreviations. Having a description available somewhere will help them.

  • Why Do You Need This Information?
    Users might be reluctant to give you personal information if they don’t understand why you need it and what you will do with it. But sometimes you still need to ask for such information for legal reasons (like date of birth for a website that sells alcohol). Using field descriptions here will help users understand why this kind of information is needed.

    On e-commerce websites, you might want to ask for the user’s phone number in case the delivery person needs to contact them. This is a legitimate reason. So, again, use descriptions to explain to e-commerce users why you need their phone number.

    Sometimes you need information for legal or practical reasons. Again, tell the user why. (Large preview)
  • “Where Do I Find the Information?”
    If your users need to find certain information somewhere else in order to fill a form, tell them where to find it. I worked on a mobile app that lets user track their house. Users needed to pair the app to the monitoring device using a serial number. It’s not very easy to find this serial number on the device; it requires some instruction. We added a little ? button next to the serial number field. The button opens a modal that shows a picture and some indication to help the user understand where to find the serial number on the monitoring device. E-commerce websites do the same with promo codes: They give indicators that tell users where to find the codes. Users can tap on the link (left) or the question mark (right) to open a popup where they can find extra information to help them fill in the field. (Large preview)
  • “How Should I Format The Information?”
    Some fields need a particular format. In this case, use descriptions to let users know the formatting rules up front. Here are a few examples:
    • Phone number: do I need to put the international dialing code (+xx) in front of the field?
    • Is there a maximum length? Twitter on mobile does a good job with that one.
    • When dealing with monetary amounts, is the format with comma (like 10,000) or a space (like 10 000)?
    • What format do you expect for dates? I’ll let you check on Wikipedia what a nightmare that is. The difference between DD MM YY and MM DD YY can cause a *lot* of trouble to users when booking online.
    Note that a lot of those formatting issues can be solved by input masks. We will come to that later in the article (or you can jump right in if you are impatient). In the old 180-character days, Twitter used to tell you exactly how many characters you had left. Also, the date format varies from one country to another, so you might want to explain what to expect. (Large preview)
How To Display Descriptions

In the examples, above, we saw a few ways to display field descriptions. Here is a summary of what to do:

  • Inline descriptions should be directly visible and displayed next to the field.
  • If you need more in-depth descriptions with heavy content, you can use tooltips or modals. Tooltips are generally triggered on hover on desktop and on tap on mobile. The same goes for the modals: Open it when the user taps the help icon or “see more” link, for instance.
Be Careful With Placeholders

I get it: it’s tempting to remove fields on mobile to gain space and use placeholders instead. We’ve all gone down that road. But please don’t. The HML5 specification is clear about this: “The placeholder attribute represents a short hint (a word or short phrase) intended to aid the user with data entry”. And here is why:

  • The placeholder disappears when the user starts typing. The user must then rely on short-term memory to remember what they are supposed to put in the field. If they can’t, they will need to empty the field to see the indication.
  • It’s hard for users to double-check fields before submitting because the fields no longer have any label indications.
  • It’s hard to recover from errors once a field has been submitted because, again, there’s no label to help the user.
Placeholders rely on short-term memory. They make forms hard to check before submission. And recovering from errors is hard, especially when error messages don’t help much. (Large preview)

Even if you use placeholders with labels, you might still have some issues. It’s hard to tell the difference between a filled field and a field with a placeholder. I’m a UX designer who writes about mobile form design and even I got tricked last week by one of those. If it happens to me, it will happen to your users — trust me on that one. Finally, most placeholders have light-gray text, so you might have some contrast issues as well.

It’s easy to mistake some of these fields for being filled in. The right screenshot is something I’ve seen online. I’ll let you guess what is filled in and what is not. (Large preview)

If you want to go deeper in this topic, there’s a great article named “Placeholder Attribute Is Not A Label, and also Joshua Winn and FeedbackGuru go into detail on why this is a bad idea. Nielsen Norman Group also wrote a piece on the topic, named “Placeholders in Form Fields Are Harmful.”

Placeholders are not mandatory in HTML5. From a usability point of view, you most certainly don’t need a placeholder in every field of your form. But with the massive adoption of Bootstrap and other frameworks, it looks like a lot of people just copy and paste components. Those components have placeholders, so I guess people feel kind of obligated to add something to the placeholder in the code? If your form’s placeholders look like “Please fill your — label — here”, you’re doing it wrong.

I’m not joking: I’ve actually seen forms with 12 fields, with each placeholder less useful than the last. (Large preview)

Labels inside fields could, nevertheless, work well for short forms in which fields are predictable. Login forms are a good candidate for this. But please don’t use the HTML5 placeholder to code this. Use a real label in the code and move it around with CSS and JavaScript.

Labels inside fields can work on really short forms, like login forms, where users don’t have a lot of information to remember. (Large preview)

Since the success of Android’s material design, a pattern has started to emerge: the floating label. This label is inside the field when the field is not filled in, so it takes a bit less vertical space on mobile. When users start interacting with the field, the label moves above the field.

This looks like an interesting way to gain some space, without running into the “placeholders in place of labels” issues cited above. Nevertheless, it does not solve the problem of users possibly mistaking a placeholder for filled-in content.

The floating label, even if not perfect, is an interesting alternative to gaining vertical space on the screen. (Large preview) Interaction Cost Reduction For Successful Forms

Reducing the interaction cost (i.e. the number of taps, swipes, etc.) of users achieving their task will help you build a seamless form experience. There are different techniques to achieve that. Let’s look at a few of them in detail.

A Magic Study On The Internet Told Me To Reduce The Number Of Fields

More fields mean fewer conversions, right? You might have encountered the “we reduced our subscription form from 11 to 4 fields, and it drove up conversions by 160%” study. It’s a classic. And if you look at their contact form, it kind of makes sense. Why would users want to fill in 11 fields just to contact the company? You can’t ask such a big commitment of people who barely know you, right?

Start by asking only for useful information. Why do you need a person’s gender to create an account for them? Why do you have two lines for the address if your subscription form is for an online service?

Ask only for the information you need. And then ask for the information in context. If you have an e-commerce website, users might be more inclined to give you their address in the shipping section of the checkout process than when they register. It will make your e-commerce registration form so much easier to fill on mobile!

Ask for the user’s address in the shipping section of the checkout, not when they register. (Large preview)

Also, don’t blindly trust every statistic and study you find on the Internet. Remember the 11-fields-to-4 study? Well another more recent study showed that by reducing fields from 9 to 6, conversions dropped by 14%. Shocking, isn’t it? Why? Well, they removed the most engaging fields. Long story short, they then went back to 9 fields, put the most important on the top, and voilà, conversions increased by 19.21%.

The bottom line is that while these studies are interesting, those websites are not your website. Don’t blindly trust the first study you find on the Internet.

So, what can you do? Test. Test. And test!

  • Do some user testing to see the time to completion of your mobile form.
  • Measure drop outs.
  • Measure problems with certain fields.
  • Measure the frustration associated with certain fields. How willing are users to give that information? How personal is that information?
Optimizing Touch Interactions Making Controls Touch-Friendly

If your fields are too small or hard to reach, users will make errors and will need extra interactions to achieve their goals. Remember Fitt’s law? You could apply it to mobile design as well: Make your labels, fields and form controls easy to tap by increasing the touch target size. For labels on the web, a little more padding can increase the touchable area. Sometimes you will also need to add some margins between elements to avoid missed taps.

Also, don’t forget to link labels with their components by pairing for and ID values. That way, if the user misses a tap on the label, the corresponding field will still get focus.

On mobile, respect mobile touch-optimized best practices, and make sure inputs are big enough to be easily tappable. (Large preview)

Steven Hoober conducted some user research on touch areas. You’ll find a summary in “Designing for Touch”. Based on what he discovered, he built a little plastic ruler tool: the mobile touch template. The tool could help you make sure your touch areas are big enough for mobile forms and more generally for mobile design.

Image from Steven Hoober’s mobile touch template. (Large preview)

To learn more about designing for touch you can read the following:

Providing Feedback

Mobile users don’t have a mouse (no kidding), so they don’t get the “click” feedback that desktop users get when hitting a button. Mobile form users need clear feedback when interacting with elements:

  • Provide a focus state for the form field that the user is interacting with.
  • Provide visual feedback when the user interacts with a button.

I’m not a big fan of material design’s ripple effect on buttons. But I must admit that the animations on Android provide clear feedback when the user interacts with a button.

Honor The Next And Previous Button Order

Finally, honor the next and previous buttons on mobile keyboards. Users can use them to quickly navigate fields. The tabindex order should match the visual order of fields and components.

iOS has small arrows on the keyboard to go from one field to another. (Large preview) Avoid Dropdowns On Mobile If Possible

Dropdowns (the HTML select element) on the web require a lot of tabs and interactions. Therefore, as Luke Wroblewski said, they should be the UI of last resort. Many other UI components work better than dropdowns in many situations.

Segment controls and radio buttons are good alternatives to dropdowns if you have between two and four options. Why hide the options under a dropdown when you can show them all directly on one screen? Note that, like radio buttons, segment controls are mutually exclusive.

Example of segment controls in the iOnic library. (Large preview)

A country list is a good candidate for a component. A dropdown of over a hundred countries is an interaction nightmare on mobile. It’s OK if you are looking for Afghanistan (at the beginning of the list) or Zimbabwe (the end of the list). If you’re looking for Luxembourg, you will end up in a game of scrolling to reach the middle of the list, going too far to the letter M, trying to come back to L, and so on.

Long dropdowns can be replaced by predictive text input fields. When the user starts typing L, the interface would propose nine countries. If they add a U — voilà! — Luxembourg it is. Four interactions instead of two, versus as many as six or seven scrolling interactions with the dropdown.

Long dropdowns are a nightmare when you’re searching for France. Predictive fields work better. (Large preview)

If you need users to pick a date, forget about splitting it into a day, month and year dropdown like people are used to doing on paper forms. Replace multiple date dropdowns with a date picker. The HTML5 input type=date works in most cases. But you might have some special needs and end up building your own date picker in JavaScript, especially if you are in the booking business (hotels, cars, flights).

A double date-picker built in JavaScript makes it easy to pick arrival and departure dates with a minimum of interaction (Large preview)

In his article “Mobile DropDowns Revisited”, Klaus Schaefers explains how using a date-picker for arrival and departure dates made interactions 60% faster.

A date-picker, using HTML5 or JavaScript, instead of dropdowns, via Mobile DropDowns Revisited. (Large preview)

Let’s stick with the booking business. Suppose the user needs to add multiple travellers to their itinerary. You can **replace the dropdown *with a* stepper** to select the number of passengers. A stepper is a control that allows the user to increase and decrease values simply by tapping on + and - buttons. That tends to be faster when fewer than six persons have to be added. It’s also more intuitive. Below is an example of a stepper used in the Android-native Airbnb app to select guests, and on the mobile-optimized website of Kayak to add passengers.

A stepper is used in the Android-native Airbnb app to select guests and on the mobile-optimized website of Kayak to add passengers. (Large preview)

A final alternative to dropdowns is the list view. The options would be listed in a specific subview, as radio buttons, for instance. This is mostly how Android settings work.

In our monitoring app, when the user clicks on “notification type 1”, it opens a list view with the options. (Large preview) Getting Smart With Auto-Completion

If you want to decrease the interaction cost of your form, be smart. Don’t ask for information that you can auto-detect or guess based on other information users have given you. Autocomplete and prefill as much as you can.

Places and Addresses

If the user searches for a place or needs to enter an address, you can offer auto-completion to help them. As they type, an API would fill in the rest of the address for them. This also reduces errors.

You could use:

In the Algolia Place demo, as the user types, it offers suggestions and can autocomplete the field.

In France and many other countries, you can guess the city based on the area code. So, if a French user enters an area code, you could automatically auto-complete or at least propose the city. My country, Luxembourg, is small (don’t make fun of me). My area code is linked to my street. So, if I enter my area code, the form should even be able to suggest my street.

Credit Cards

Another area where auto-detection is easy is credit cards. You don’t need to ask the user what type of credit card they have. You can auto-detect this based on the initial numbers they enter. There’s even a library that can do the job for you.


A demo of the payment script that detects credit card type. Using HTML5 Autocompletion (Autofill)

The HTML autocomplete attribute can prefill fields based on the user’s earlier inputs. This attribute has an on and off state. Some smart people have started working on a specification to make this more powerful and to extend the autocomplete attribute for form fields. The WHATWG also has an interesting list.

Chrome and other mobile browsers already support some of the extended values for credit cards and names. This means that users can prefill forms with their name and credit card data that they use on other websites.

Help users check out faster with Autofill (Source: Google Developers) (Large preview)

In short, when you must choose between different systems, count the number of interactions each is going to require.

Mistakes Happen: Handling Errors In Mobile Forms

The last step on our journey towards better mobile forms is handling errors and mistakes. We can try to reduce mistakes to ease the user’s cognitive load. We can also help them recover from errors, because no matter how great your form design is, mistakes happen.

Avoiding Errors While Filling The Forms

“Prevention is better than a cure,” my mother used to say. That’s also true of form design: Preventing errors will improve your mobile form’s experience.

Explicit Format Limitation

“Be conservative in what you do. Be liberal in what you accept from others.” This robustness principle can be applied to form fields as well. If possible, let the user enter data in any format.

If you think you need to limit what a user can enter in the field, start by asking yourself “why”. In the user experience field, we have a technique called “the three whys”. If the answer is “because blah blah database”, maybe it’s time to change things. For instance, why do you refuse special characters like é, à and ö in the user name field? I wrote an article explaining how rude forms are to me when I try to enter “Stéphanie” as a user name. I’m still trying to figure out a good reason for that (apart from database reasons).

If you have a good reason to require a specific format from users, state this up front. You can use HTML5 placeholders to give users a hint about what the data should look like, but again, be careful with those. You could also use all of the field description techniques explained at the beginning of this article. Finally, input masks can guide users towards the right format.

Marking Mandatory Fields (And Optional Ones)

Don’t wait for users to submit a half-completed form to tell them about required fields. If a field is mandatory, users should know about it. Marking mandatory fields with an asterix (*) and a legend has become a standard pattern for forms. The good part is that it does not take much space. The problem is that it has no semantic value, so it can cause accessibility issues if poorly coded and if you rely on people’s habits with form interaction.

You could instead explicitly mark both mandatory and optional fields with the words “required” (or “mandatory”) and “optional”. Both Baymard Institute and Luke Wroblewski agree on that. This avoids ambiguity with long forms on mobile, such as when using a scroller, proceeding with something else, then coming back and not remembering if mandatory fields were marked with an asterisk or something else.

A form with both mandatory and optional fields marked. (Large preview)

Eventually, the decision on how to mark those fields will depend on the design and length of the field and on the context. The best way to know whether you’ve made the right decision is, again, to test the form.

Sensible Defaults

Be careful about default selected options in forms. When I applied for my previous job, there was an information form. The marital status was optional. They made the first element in the dropdown, “divorced”, the default field. So, I could either not answer (because it was an optional field) and let the system believe that I was divorced, or correct this and disclose my actual marital status even if I did not want to.

Also, be careful about gender. Again, have an option for people who don’t want to disclose it; make clear why you’re asking for their gender; better yet, ask for pronouns, or don’t ask if you don’t really need to. If you are interested in this topic, I recommend “Designing Forms for Gender Diversity and Inclusion.” And if the gender is optional, again, don’t auto-check the first choice, otherwise people won’t be able to uncheck that radio button and choose not to answer.

Should I leave the default and lie, or put the right information even I don’t want to? (Large preview)

Smart defaults, on the other hand, can help users avoid mistakes when filling a form. Unless you’re in a Dr. Who episode, you’re not supposed to book a hotel in the past. Booking.com understands that. When you open the date-picker on the website, the default date is set to the current date and you can’t select a date in the past. When you select a return date, the default is the day after the departure date.

Booking.com’s smart defaults help users avoid mistakes. You can’t search in the past or before your arrival date. (Large preview) Less Painful Password Experience

I’ve written about password-less authentication, but you can’t always use those techniques. Users will eventually have to create a password and enter it in a mobile form. And most of the time, that experience sucks. Here are a few ideas on how to make it better and help users avoid mistakes.

  • When Creating An Account
    I won’t get into the details of what kind of passwords you should require and how many characters they should be composed of — plenty of articles on that topic are on the web — just make up your mind about your password criteria. When users create an account, be proactive, not reactive. For the love of Cthulhu, don’t let people guess. Tell users your password criteria up front.

    A lot of websites now show you a gauge for password strength telling you in real time what is missing. This is an interesting and excellent pattern. KLM uses it in its sign-in form: KLM sign-in form example (Large preview) But there are still some big problems with this design.
  1. They don’t tell users their password criteria up front. Users who want to generate a password (using a password manager, for instance) must first guess that they need to first interact with the field in other to see the password criteria.
  2. They limit the password’s length to 12 characters, but they never tell users how many characters are left. Sure, let’s add "counting the dots" to the cognitive load of building a password with so many criteria. After 12 characters, you can keep on typing on the keyboard, and nothing will happen.
  3. What happens if, like me, you reached the 12-character limit but haven’t met all of the criteria? Well, you would just have to delete the entire password and start over again.
  4. Finally, you must enter the password twice. How is a user supposed to remember and retype the password that they just created based on those criteria while counting the dots?
  5. Back to 1, generating a password with a password manager.

If KLM wanted to make this form better, it could provide a mask/unmask option for the password. Doing so, it would not need to ask for the same password twice. Users could visually check that the password they typed is the one they want.


TransferWise doesn’t solve my first problem in the list, but at least I can unmask while typing.
  • When Logging In
    In a login form, a mask/unmask password option would tremendously improve the user experience.
    A button to show and hide the password in a form.

    Amazon has an interesting history of iterating on passwords in its login form. It used to have a version in which you could not see the password. The next iteration allowed users to reveal it. Then, the password was revealed by default, and you could hide it. This is what is looked like in 2015:

    Showing Passwords on Log-In Screens, Luke Wroblewski, 2015 (Large preview)

    Amazon tested the last version, and 60% people got suspicious. So, they replaced the “hide password” unchecked checkbox with a “show password” checked box. This would show the password in smaller characters, under the field, while the user typed. This is what it looks like at the time of writing this article:

    Amazon’s show and hide password functionality (Large preview)

    As you can see, there’s always room for improvement.

Inline Validation

If you are familiar with usability principles, you might know the Gestalt law of proximity. On mobile, avoid the summary of errors at the top of the page, with no contextual information, after the user has tapped the submit button.

Instead, error messages should be located close to the errors themselves.

An example of inline validation (Large preview) Real-Time Validation

You also don’t need to wait until users hit the submit button. You can validate fields and display feedback while the user is filling them in.

A few tips:

  • As mentioned earlier, password fields would benefit from real-time validation and feedback on each keystroke.
  • You might also want to validate user names in real time when accounts are being created, to make sure they’re available. Twitter does a good job of that.
  • Don’t validate every keystroke. Wait until the user has finished typing. (Use JavaScript blur for web forms, or just wait a few seconds to detect inactivity.)

Note: *Mihael Konjević has written a nice article on “Inline Validation in Forms: Designing the Experience.” He explains the concept of “reward early, punish late.”*

“If the user is entering the data in the field that was in a valid state, perform the validation after the data entry.” “If the user is entering the data in the field that was in an invalid state, perform the validation during the data entry.”
Example from Keechma based on the article. Color Matters

I’m not saying that color matters just because of my current ginger, pink and purple hair color. Color really matters in form design.

There are some conventions on the web that you don’t want to break. Non-colorblind users know that red is for errors, yellow is for warnings, and green is almost always for confirmation or success. It’s best to stick with these three colors. Red can make people anxious, though. The user might think they’ve made a really serious mistake. Using orange or yellow for error messages could cause less panic. The problem with yellow and orange is that it’s hard to find colorblind-friendly hues of them.

Colors have different connotations across countries and cultures. Be careful with them. (Large preview)

Speaking of colorblindness: Color should not be the only way to convey an error message. This is an accessibility criterion.

In the example below on the left, the field with an error is in orange, and the field that has been corrected has turned green. I used a colorblind testing tool to take the screenshot in the middle: You can’t distinguish between the default gray border and the green one anymore. Adding some icons in the last screenshot ensures that the error messages are conveyed to colorblind people.

Color should not be the only way to convey error messages. The colorblind simulation in the middle shows that the green border cannot be seen by a colorblind person. (Large preview) Recovering From Errors: Writing User-Friendly Error Messages

At this point, we’ve done everything we can to help users fill our forms and avoid errors. But sometimes, despite our best effort, mistakes happen. It’s time to figure out how to help users recover from those mistakes.

First, remember: Don’t hijack control of the system. If a problem isn’t critical, the user should be able to continue interacting with as much of the rest of the interface as possible. Avoid those JavaScript alert error message and modals that blocks users whenever possible. Also, if your form needs some permission, request it in the flow of use. If permission is not granted, do not consider this an error because it is not. Be careful about the copy you use here.

You’re Not A Robot, And Neither Are Your Users

Robots are cool, I know. But you’re not a robot, and neither are your users. Yet so many error messages are still so poorly written. Here are a few tips when it comes to human-friendly error messages:

  • Never show a raw error message, like “An error of type 2393 has occurred. Server could not complete the operation.” Instead, explain what happened in human language and why it happened.
  • Never show a dead-end error message, like “An error has occurred.” Instead suggest ways to recover from the error. Write actionable copy.
  • Never show a vague error message, like “A server with the specified hostname could not be found”, with a “Try again” button. Instead, make error messages informative and consistent. Please don’t sound like a robot.
  • Don’t assume that people know the context of a message. Your users are not tech-savvy geeks. Instead, explain to them in plain language, without technical jargon, how to recover from this error.
Examples of non-human-friendly error messages. Eek! (Large preview) Beware The Language You Use In Messages

Whatever you write, avoid making people feel stupid about a mistake. If possible, leave out negative words; they tend to scare people and make them even more anxious. Use a courteous, positive, affirming tone instead.

Don’t blame users for mistakes; blame the system instead. The system won’t hold a grudge, I promise. Shift the user’s attention to how the system could not process the action, and explain to them how to find a solution.

A little trick is to read your own message out loud. It will help you hear whether it works or is too harsh or too casual, etc.

You could also get creative with error messages and incorporate imagery and humour to make them less threatening. This will really depend on your brand’s identity and tone, though.

To help you write better error message, I suggest you read the following:

Time To Submit The Form

The user has filled in the form, there are no more errors, and everything looks good. Finally, it’s time to submit the form!

The first rule is, don’t mask the submit button. Seriously! I wonder what twisted mind came up with this idea, but I’ve seen it in some forms. The submit button would be displayed only once all required fields were filled in without any errors. It’s disturbing for the user to wonder whether something is wrong or the form’s button has not loaded or the website is broken and so on.

If you don’t want users to be able to hit the submit button if there’s missing mandatory fields or there are validation errors, use the disabled HTML attribute on the submit input. You will need to re-enable the button using JavaScript once the form is valid and ready for submission.

Do not hide the submit button. Instead, deactivate it until users have filled in the required information. (Large preview)

If you have a primary and secondary call to action, use color, size and styling to show the hierarchy.

Example of primary and secondary actions (Large preview)

If are wondering whether the confirmation button should come before or after the cancellation button, so am I (and a lot of other people). If you are building a native app, stick to the OS guidelines. It’s become particularly fun since Android changed the button positions in its fourth version. On the web, it’s more complicated because there are no real guidelines. Regardless of the OS, here are some general guidelines for mobile-optimized submit buttons:

  • Give the call to action descriptive, actionable verbs.
  • Provide visual feedback when the user taps it.
  • If you have two buttons, make the primary action stand out.
  • Unless you’re working on a very specific back-office enterprise form (in which case, you’ll have a lot of challenges optimizing for mobile), avoid a reset button. Users might confuse it with the submit button and will lose all of their data by accident.
Conclusion

In this first part, I’ve discussed a lot of little techniques to take your form to the next level and help users fill it in. Some of these general guidelines and mobile best practices might not work 100% of the time — that’s the catch with best practices. So, always test your forms on real users and real devices, and adapt the guidelines to your users’ specific needs and experience.

Also, do some regression and automated functional testing — again, on real devices. Chrome’s mobile emulator won’t be enough to test touch-optimized forms. I say this because I had launched an e-commerce website with a search form that didn’t work on mobile. We only did automated testing using an emulator. Here is what happened. The search form was hidden under a search icon. You could tap on the button, which opened a box with the search field. It worked by emulating a mouse hover as a touch event. We tested tapping on the button, and it opened the box. Nobody tried to launch a search. So, nobody (not even the client) saw that the search field disappeared as soon as users tried to interact with it. What happened? When the input element got focus, the button lost the hover state, so it closed the box with the field. Automated testing was not able to catch this because the input was not losing focus. So, we launched an e-commerce website without search functionality on mobile. Not a super experience.

In the second part of this series, we will see more advanced mobile-specific techniques. We will see how to use cool HTML5 features to format fields and how to use mobile capabilities to take the mobile user experience to the next level.

(lf, ra, al, il)
Categories: Around The Web

Designing For Micro-Moments

Fri, 08/17/2018 - 7:50am
Designing For Micro-Moments Designing For Micro-Moments Suzanna Scacca 2018-08-17T13:50:09+02:00 2018-08-21T13:33:03+00:00

A couple of years ago, Google announced a new mobile-first initiative it wanted web designers and marketers to pick up on. This was our introduction to micro-moments.

These are not to be confused with micro-interactions, which are miniscule engagements websites have with visitors when they "touch" key points of the interface. A mouse changes its appearance when a user hovers over a clickable element. A display error appears after a field is incorrectly populated. A checkbox briefly enlarges and changes color after it’s been ticked off. These are micro-interactions.

A micro-moment, however, originates with your visitor. In Myriam Jessier’s "Things Designers Should Know About SEO In 2018", she sums up Google’s four micro-moments:

  1. “I want to know.”
  2. “I want to go.”
  3. “I want to do.”
  4. “I want to buy.”

Basically, these are four key moments in every consumer’s life when they decide to pick up their mobile device for a specific purpose. As such, it’s your job to know how to specifically design for these micro-moments.

Recommended reading: What You Need To Know To Increase Mobile Checkout Conversions

How You Should Be Designing For Micro-Moments

When a visitor arrives at a mobile website (or app), they’ve come with a clear motivation:

  1. “I want to know.”
  2. “I want to go.”
  3. “I want to do.”
  4. “I want to buy.”

Seems pretty simple, right? However, as Google launched this initiative a couple of years ago, its had time to quietly observe users in these micro-moments as well as the websites that have most aptly responded to them. As you will soon see, consumers have incredibly high expectations for what the mobile web can do for them. Basically, they want you to be a mind reader and anticipate their every need (and even their location) without them having to say a word.

Is your pattern library up to date today? Alla Kholmatova has just finished a fully fledged book on Design Systems and how to get them right. With common traps, gotchas and the lessons she learned. Hardcover, eBook. Just sayin'.

Table of Contents →

Is that intimidating? It shouldn’t be. You already have all the information you’d ever need to answer that question.

Here is how you should be designing your mobile website to respond to and draw in consumers as they experience these micro-moments:

1. Start With The Data

Google Analytics will help you decipher where they’re spending the most time productively on your website.

An example of Google Analytics’ visitor behavior breakdowns. (Source: Google Analytics) (Large preview)

Google Search Console will tell you which keywords are most effective in driving high-quality leads to the site.

An example listing of keywords and associated clicks and impressions for a website. (Source: Google Search Console) (Large preview)

Once you know where exactly visitors see the greatest value in your product, you can then turn to third-party tools like Answer the Public to give you some insights into what relevant questions your users may be asking about you.

An example of how Answer the Public provides micro-moment answers. (Source: Answer the Public) (Large preview)

Ultimately, this data needs to tell you all about your customers’ journey before they ever reach you. What exactly was the question that triggered them to pick up their smartphone and do that search? If you can identify those micro-moments, you can start using various design elements to respond to these questions.

2. Respond With Immediacy

According to Google:

People are searching at the exact moment they need something and are looking for places that can meet their immediate need. In other words, when making these on-the-spot decisions, they are more loyal to their need than to any particular place.

Although we’ve heard a lot about customer loyalty to brands in the past, it’s interesting to get Google’s take on this matter.

While consumers may indeed still remain loyal to brands that take very good care of them and produce a high-quality product nearly 100% of the time, this opportunity to steal attention from those customers in one of their micro-moments is real. Do that enough times and your brand and website could realistically win that customer over so long as you are there every time they go searching to fill that need.

One of the ways you can do this is by providing users with instant solutions. Is your business open now? Can you mail out that new product same-day? Will there be an open table at your restaurant tonight? Answer that immediately and you could find conversions increase dramatically.

Take the Delaware State Fair website, for example.

The top of the Delaware State Fair home page gives users easy access to everything they want to know and do. (Source: Delaware State Fair) (Large preview)

Look at the top of the homepage. There are the dates of the fair, which probably answer one of the most commonly searched questions. There is a link to the concert lineup as well as calendar, which answers anything people would want to know about special events they might want to go to. And then there’s a button to buy tickets right away. It’s all right there.

Office Depot is a company that also explicitly addresses immediate needs:

The Office Depot mobile site uses a variety of time-driven design elements to satisfy visitors’ needs. (Source: Office Depot) (Large preview)

As you can see in the example above, Office Depot uses a number of design tactics and elements to play into this need for immediacy.

  • There is a search bar at the very top. Consumers don’t have to even bother with navigation or scrolling through pages if they don’t want to/have the time to.
  • You’ll also see that the closest store’s hours are posted and boldly tell me how quickly I can have any products available in store.
  • Finally, you have the promotional categories for upcoming needs for parents that are about to send kids back to school.

Another website is Universal Studios Orlando; it does a great job sparing mobile users the trouble of sifting through irrelevant information and instead gets them to exactly what they need:

Universal Studios includes immediate options for research and booking on the home page and navigation. (Source: Universal Studios) (Large preview)

Aside from a single banner at the top of the home page, the Universal Studios website design gives visitors exactly what they want right away. The navigation includes only the most pertinent links to information and booking as does this succinct section on the home page. There’s really no time to waste when the options are so clear.

And here is one final example of a website that deals in immediacy, albeit with a more subtle design technique: Nordstrom:

Nordstrom appeals to immediacy with this one subtle trick. (Source: Nordstrom) (Large preview)

As you can see, this is a pretty typical e-commerce product page. However, there’s one key difference: Nordstrom is subtly calling attention to its Anniversary Sale and the main reason why there is a significant price drop for this purchase. Rather than use an obtrusive pop-up to announce the sale and pester users to shop, it’s made the price change directly on the page and drawn attention to it with the highlighted text.

3. Respond With Relevant Content

According to Google:

Not only have mobile searches for ‘best’ grown over 80% in the past two years, but searches for ‘best’ have shown higher growth among ‘low-consideration’ products than ‘high-consideration’ products. In other words, we’re all becoming research-obsessed, even about the small stuff.

We understand that the opinions of family, friends, and colleagues matter greatly in the minds of consumers. But as more and more of them to turn the web to make their purchases, it means being open to trusting other opinions online as well — ones that may be more conveniently expressed from a company’s website, from an influencer’s blog, or from social media.

Wherever those words of wisdom happen to come from, it’s important to take Google’s research to heart. With so many consumers now obsessed with this idea of having the best of everything and being able to get it in a pinch, your website needs to be the answer to that question.

But that’s the tricky part. According to Google, it’s not as simple as being a dog food manufacturer and configuring your site to be the answer to:

“Best Dog Food”

Consumers experience these micro-moments at a granular level. Sure, there may be some who think, “What is the best dog food?” But isn’t it more likely that question would be more specific in nature? For instance:

  • Best puppy food?
  • Best grain-free dog food?
  • Best vegan dog food?

Let's take a look at Google, for example. Here’s a variety of searches for a singular “best of” concept:

Example of the variety in “Best” searches in Google. (Source: Google) (Large preview)

As you can see, it goes beyond the basic questions. Through your design and your content, you must be ready to answer the most relevant questions your users have about your product or service.

With content, you’ll be able to answer many of the “I want to know” questions that are related to the brand with things like:

  • Informational pages regarding services and products.
  • Whitepapers, ebooks, case studies, reports, and other long-form content that provide heavily researched answers on related matters.
  • Blog posts, vlogs, podcasts, and other shorter content that can dabble more in appealing to the emotions of consumers.
  • Tutorials and guides that directly answer questions that consumers are asking.

As far as the design piece is concerned, it’s your responsibility to highlight these pages, so visitors don’t have to dig through various parts or layers of the site (like the footer or secondary navigation) to find their answers.

Google told them it was here, so it’s your job to get them right to it.

The navigation will play a big part in this, as evidenced by Globus Journeys:

Globus Journeys provides answers to micro-moments in the navigation. (Source: Globus Journeys) (Large preview)

As you can see in this example, Globus Journeys answers many of those micro-moments right within the navigation: tips on touring (Touring 101), tips on travel best practices (Travel Tips), deals available for travel (Deals & Offers), etc.

Another way to use navigational design to inform visitors on what they’ll learn/know from this experience can take place on the blog. Salesforce has an interesting example of this:

Salesforce includes a navigation menu for the blog. (Source: Salesforce) (Large preview)

There is the standard navigation for the Salesforce website, and then there is the navigation that’s specific to the Salesforce blog. This gives you — as the designer and planner of the site’s layout — a chance to better and more clearly organize content found within it. So, when visitors show up and want to know tips specific to one of those categories, it doesn’t require random searches or (even worse) endless scrolling through a full blog feed.

Another way you can more quickly and thoroughly inform visitors on topics of interest to them is by using strategically placed sections within blog posts.

While you likely won’t have anything to do with the writing of a website’s blog content, you will have control over its layout and formatting. The first thing you can do to expedite the knowledge acquisition process is by using callouts to detail and link to the various sections covered on the page as Be Brain Fit does:

Be Brain Fit calls out a linkable index of topics from the blog post. (Source: Be Brain Fit) (Large preview)

Of course, the post itself is easy to scan, so readers could guide themselves to the most relevant parts. However, by placing this towards the top of the piece, you’re enabling them to get right to the information they seek.

I’m also going to suggest that pop-ups would be helpful in this matter.

I know, I know. Mobile pop-ups can be annoying, but not when they’re used properly as Fit Small Business has done here.

Fit Small Business not only provides all the information needed, but also offers an alternative solution to what they seek. (Source: Fit Small Business) (Large preview)

I encountered this blog post after doing a search for the best way to create a Facebook page. This was one of the links on the first SERP. I was actually quite pleased with the post as a whole. It broke it up into easy-to-follow steps, attractive and informative visuals, and got me the answer I needed.

However, I was especially pleased to see the bottom banner pop-up after I finished getting through the post. Not only has Fit Small Business attempted to reach its audience by providing helpful content, but it’s also providing an alternative solution to anyone who got here and realized, “Eh, I really don’t want to bother with this on my own."

4. Respond With Geotargeting

According to Google:

Looking for something nearby — a coffee shop, noodle restaurant, shoe store — is one of the most common searches we do. In fact, nearly one-third of all mobile searches are related to location.

Here’s the thing though: users aren’t using “near me” qualifiers as much anymore.

Google demonstrates how location qualifiers are decreasing in use. (Source: Google) (Large preview)

According to Google, this is because many consumers now assume that search engines, websites, and mobile apps are tracking this sort of information already. They expect that if they search for something like “dog food,” Google will automatically serve them the most relevant results — and that includes taking into account location proximity.

In Google’s research, it found that about two-thirds of mobile consumers are more likely to buy something from a website or app if information is geographically personalized. There are a plethora of ways to communicate this local-friendliness to visitors — through the copy, through various design elements, and even photos.

Google is a pioneer in this space and so I want to give it a special shout-out in this section for what it does with search results:

Google’s auto-populated search results aren’t just for Google. (Source: Google) (Large preview)

The biggest thing to take away from here is the fact that Google provides its users with auto-populated search recommendations. These are based on the users’ geography, behavior, history, as well as what Google knows about the query itself. As you can see here, it expands on Baltimore to provide more specific results based on the area of the city in which the user wants to drink.

With AI-assisted search functionality, any website can offer this same level of smart search for its users.

Of course, you first need to get access to visitors’ geographic data before you can provide them with these kinds of smart and geographically relevant results. One way to do this is to require them to sign in and fill out a profile with these details. Another way, however, is by serving them with this geotargeting request as Best Buy has done:

Best Buy requests for access to users’ geographic location. (Source: Best Buy) (Large preview)

Once you have access to a visitors’ current location, however, you can start providing them with information that helps them with the “I want to go”, “I want to do”, and the “I want to buy” micro-moments that caused them to reach for the phone in the first place.

Here is what the Best Buy website shows me after I granted it permission:

Best Buy uses its visitors’ location to provide helpful in-store visit details. (Source: Best Buy) (Large preview)

The top of the page now displays the nearest location to me as well as opening hours. As I peruse the rest of the site, I will receive relevant information regarding in-store product availability, buy-online-pick-up-in-store options, and so on. This is a really great option for businesses with a sales website and brick-and-mortar location that want to merge the two experiences.

You could also benefit from using this on websites that offer services, appointments, and reservations. Here is an example of what The Palm Restaurant does with my information:

The Palm Restaurant streamlines the reservation process with geotargeting. (Source: The Palm Restaurant) (Large preview)

To start, it uses my information to let me know right away if there even is a location close to me. Philadelphia isn’t too far, but it’s still nice to have the address fully displayed so I can make up my mind about whether I want to dine there. And, if I do, I can choose the “Reservations” button above it.

What’s especially nice about this is that the reservation form is pre-populated:

The Palm pre-populates its reservation form based on user information. (Source: The Palm Restaurant) (Large preview)

As you can see, it’s used a mixture of my geographic location along with the most popular reservation types (i.e. two people at 7 p.m.) to pre-populate the form. This saves me, as the user, time in filling it out and making my reservation.

5. Respond With Convenience

According to Google:

Every day, people are becoming more reliant on their smartphones to help make last-minute purchases or spur-of-the-moment decisions. In fact, smartphone users are 50% more likely to expect to purchase something immediately while using their smartphone compared to a year ago.

Recently, I wrote a post about what you need to know to increase mobile checkout conversions. The underlying message was that mobile consumers have certain expectations that need to be met if you intend on converting them there (as opposed to switching back to desktop).

  • Convenience in getting the information they want is one of them.
  • Speed in getting to and through checkout is another.
  • Handling their contact and payment information securely is the final piece.

Clearly, web designers are doing something right as over half of smartphone users reach for their phone to buy something and subsequently do. But it can’t stop with the 10 tips offered in that article. You need to be able to predict what they’re going to purchase and what exactly they want to do when you catch them in those exact micro-moments.

Let’s use UPack as one example.

UPack includes a price quote form at the very top of the website. (Source: UPack) (Large preview)

At the very top of every page is a short price quote form that asks only the most pertinent details they need in order to provide a quote to interested customers. By anticipating that’s what they’re looking to do when they visit a moving company’s website, UPack likely experiences very high conversion rates.

However, if someone should arrive at this form and wonder, “Should I even bother with a quote from UPack?”, they’ve provided an answer to that on the next step down on the home page:

UPack uses an explainer graphic to sell the value of its service right away. (Source: UPack) (Large preview)

This explainer graphic is simple. It includes four points and shows how exactly someone uses the UPack service to move their home from one destination to another. When someone arrives there with the intention of getting help with their move, UPack has already made it all the more simple in just one scroll and two panels of the home page.

Then, you have a company like HostGator that doesn’t waste any time at all:

HostGator’s home page includes smart design callouts that sum up its services. (Source: HostGator) (Large preview)

If someone shows up on a web hosting company’s website — especially one that is well known as they are — of course they know what they want to do. Now, they could hop into the navigation and dig deeper into the various hosting plans (which some may do). However, HostGator is probably hoping to appeal to two specific audiences with these “Buy Now!” callouts on the home page:

  • The web developer who knows exactly which plan he or she needs, and doesn’t need a full page to explain the benefits to him.
  • The small business owner who doesn’t know a thing about web hosting, but trusts HostGator’s good name and just wants to get their web hosting purchases ASAP.

This is a really good choice of design techniques if you know that a good portion of your audience will be immediately ready to buy upon entering the site. If they don’t have to click through to another site, don’t make them do it.

And, of course, CTAs, in general, are an important element to use when designing for micro-moments. When they’re designed well — colorful, large, well-labeled — you’re essentially giving your users a shortcut to conversion.

BarkBox uses a number of these right on its home page:

BarkBox has a number of CTA shortcuts available on its website. (Source: BarkBox) (Large preview)

Since the brand is particularly well-known among dog owners, this is a good move. While there are some people who enjoy scrolling through the site to see the funny dog pictures and find out more about what’s in this month’s BarkBox, if they’ve arrived here on mobile, they shouldn’t have to wait to subscribe. BarkBox provides those shortcuts in a number of locations, ensuring there’s no friction between its customers and their goals.

Wrapping Up

It’s pretty amazing to watch the web change so quickly as consumers become more trusting of their mobile devices. Now, nearly two years after Google first began recommending that we design with micro-moments in mind, it appears that these suggestions have really paid off.

Designing for micro-moments gives us the opportunity to more effectively reach consumers in their moment of need. This, consequently, means reaching consumers who are in a more purchase-intent mindset as opposed to ones casually browsing the web. If you can use your data and design to actively reach consumers in their micro-moments, you can effectively increase your mobile site’s conversion rate in the years to come.

(lf, ra, yk, il)
Categories: Around The Web

Monthly Web Development Update 8/2018: The Cost Of JavaScript, Ethics In Open Source, And QUIC

Fri, 08/17/2018 - 5:57am
Monthly Web Development Update 8/2018: The Cost Of JavaScript, Ethics In Open Source, And QUIC Monthly Web Development Update 8/2018: The Cost Of JavaScript, Ethics In Open Source, And QUIC Anselm Hannemann 2018-08-17T11:57:10+02:00 2018-08-21T13:33:03+00:00

Building technology and software has become a very responsible job. People trust the products we create, and they can have a significant impact on their lives, too. Considering this, we not only need to think about inclusive solutions, but also stand up and advocate for ethics, reliability, and security. It’s a position that gives us power.

Eric Meyer published an article elaborating the problems which an HTTPS-only web is bringing along. In it, he reveals that developing countries suffer a lot from this development as they often have bad internet connections and, due to the encryption, they now experience more website errors than before. Ben Werdmüller jumped in and published the article “Stop building for San Francisco” in which he points out one of the biggest problems we have as developers: We use privileged hardware and infrastructure. We build experiences using the latest iPhones, Macbooks with Gigabit or fast 4G connections but never consider that most people we’re building for use devices and infrastructures that are far from being that well-equipped. Making the web more secure is a great idea, beyond question, but we should also keep in mind the consequences that the latest tech and our design decisions might have for others.

News

With so much happening on the web, what should we really pay attention to? At SmashingConf New York 2018

Categories: Around The Web

Scroll Bouncing On Your Websites

Wed, 08/15/2018 - 8:00am
Scroll Bouncing On Your Websites Scroll Bouncing On Your Websites William Lim 2018-08-15T14:00:49+02:00 2018-08-21T13:33:03+00:00

Scroll bouncing (also sometimes referred to as scroll ‘rubber-banding’, or ‘elastic scrolling’) is often used to refer to the effect you see when you scroll to the very top of a page or HTML element, or to the bottom of a page or element, on a device using a touchscreen or a trackpad, and empty space can be seen for a moment before the element or page springs back and aligns itself back to its top/bottom (when you release your touch/fingers). You can see a similar effect happen in CSS scroll-snapping between elements.

However, this article focuses on scroll bouncing when you scroll to the very top or very bottom of a web page. In other words, when the scrollport has reached its scroll boundary.

Collecting Data, The Powerful Way

Did you know that CSS can be used for collecting statistics? Indeed, there's even a CSS-only approach for tracking UI interactions using Google Analytics. Read article →

A good understanding of scroll bouncing is very useful as it will help you to decide how you build your websites and how you want the page to scroll.

Scroll bouncing is undesirable if you don’t want to see fixed elements on a page move. Some examples include: when you want a header or footer to be fixed in a certain position, or if you want any other element such as a menu to be fixed, or if you want the page to scroll-snap at certain positions on scroll and you do not want any additional scrolling to occur at the very top or bottom of the page which will confuse visitors to your website. This article will propose some solutions to the problems faced when dealing with scroll bouncing at the very top or bottom of a web page.

Getting the process just right ain't an easy task. That's why we've set up 'this-is-how-I-work'-sessions — with smart cookies sharing what works really well for them. A part of the Smashing Membership, of course.

Explore features → My First Encounter With The Effect

I first noticed this effect when I was updating a website that I built a long time ago. You can view the website here. The footer at the bottom of the page was supposed to be fixed in its position at the bottom of the page and not move at all. At the same time, you were supposed to be able to scroll up and down through the main contents of the page. Ideally, it would work like this:

Scroll bouncing in Firefox on macOS. (Large preview)

It currently works this way in Firefox or on any browser on a device without a touchscreen or trackpad. However, at that time, I was using Chrome on a MacBook. I was scrolling to the bottom of the page using a trackpad when I discovered that my website was not working correctly. You can see what happened here:

Scroll bouncing in Chrome on macOS. (Large preview)

Oh no! This was not what was supposed to happen! I had set the footer's position to be at the bottom of the page by setting its CSS position property to have a value of fixed. This is also a good time to revisit what position: fixed; is. According to the CSS 2.1 Specification, when a “box” (in this case, the dark blue footer) is fixed, it is “fixed with respect to the viewport and does not move when scrolled.” What this means is that the footer was not supposed to move when you scroll up and down the page. This was what worried me when I saw what was happening on Chrome.

To make this article more complete, I’ll show you how the page scrolls on both Mobile Edge, Mobile Safari and Desktop Safari below. This is different to what happens in scrolling on Firefox and Chrome. I hope this gives you a better understanding of how the exact same code currently works in different ways. It is currently a challenge to develop scrolling that works in the same way across different web browsers.

Scroll bouncing in Safari on macOS. A similar effect can be seen for Edge and Safari on iOS. (Large preview) Searching For A Solution

One of my first thoughts was that there would be an easy and a quick way to fix this issue on all browsers. What this means is that I thought that I could find a solution that would take a few lines of CSS code and that no JavaScript would be involved. Therefore, one of the first things I did, was to try to achieve this. The browsers I used for testing included Chrome, Firefox and Safari on macOS and Windows 10, and Edge and Safari on iOS. The versions of these browsers were the latest at the time of writing this article (2018).

HTML And CSS Only Solutions Absolute And Relative Positioning

One of the first things I tried, was to use absolute and relative positioning to position the footer because I was used to building footers like this. The idea would be to set my web page to 100% height so that the footer is always at the bottom of the page with a fixed height, whilst the content takes up 100% minus the height of the footer and you can scroll through that. Alternatively, you can set a padding-bottom instead of using calc and set the body-container height to 100% so that the contents of the application do not overlap with the footer. The CSS code looked something like this:

html { width: 100%; height: 100%; overflow: hidden; position: relative; } body { width: 100%; margin: 0; font-family: sans-serif; height: 100%; overflow: hidden; } .body-container { height: calc(100% - 100px); overflow: auto; } .color-picker-main-container { width: 100%; font-size: 22px; padding-bottom: 10px; } footer { position: absolute; bottom: 0; height: 100px; width: 100%; }

This solution works in almost the same way as the original solution (which was just position: fixed;). One advantage of this solution compared to that is that the scroll is not for the entire page, but for just the contents of the page without the footer. The biggest problem with this method is that on Mobile Safari, both the footer and the contents of the application move at the same time. This makes this approach very problematic when scrolling quickly:

Absolute and Relative Positioning.

Another effect that I did not want was difficult to notice at first, and I only realized that it was happening after trying out more solutions. This was that it was slightly slower to scroll through the contents of my application. Because we are setting our scroll container’s height to 100% of itself, this hinders flick/momentum-based scrolling on iOS. If that 100% height is shorter (for example, when a 100% height of 2000px becomes a 100% height of 900px), the momentum-based scrolling gets worse. Flick/momentum-based scrolling happens when you flick on the surface of a touchscreen with your fingers and the page scrolls by itself. In my case, I wanted momentum-based scrolling to occur so that users could scroll quickly, so I stayed away from solutions that set a height of 100%.

Other Attempts

One of the solutions suggested on the web, and that I tried to use on my code, is shown below as an example.

html { width: 100%; position: fixed; overflow: hidden; } body { width: 100%; margin: 0; font-family: sans-serif; position: fixed; overflow: hidden; } .body-container { width: 100vw; height: calc(100vh - 100px); overflow-y: auto; -webkit-overflow-scrolling: touch; } .color-picker-main-container { width: 100%; font-size: 22px; padding-bottom: 10px; } footer { position: fixed; bottom: 0; height: 100px; width: 100%; }

This code works on Chrome and Firefox on macOS the same way as the previous solution. An advantage of this method is that scroll is not restricted to 100% height, so momentum-based scrolling works properly. On Safari, however, the footer disappears:

Missing Footer on macOS Safari. (Large preview)

On iOS Safari, the footer becomes shorter, and there is an extra transparent (or white) gap at the bottom. Also, the ability to scroll through the page is lost after you scroll to the very bottom. You can see the white gap below the footer here:

Shorter Footer on iOS Safari.

One interesting line of code you might see a lot is: -webkit-overflow-scrolling: touch;. The idea behind this is that it allows momentum-based scrolling for a given element. This property is described as “non-standard” and as “not on a standard track” in MDN documentation. It shows up as an “Invalid property value” under inspection in Firefox and Chrome, and it doesn’t appear as a property on Desktop Safari. I didn’t use this CSS property in the end.

To show another example of a solution you may encounter and a different outcome I found, I also tried the code below:

html { position: fixed; height: 100%; overflow: hidden; } body { font-family: sans-serif; margin: 0; width: 100vw; height: 100vh; overflow-y: auto; overflow-x: hidden; -webkit-overflow-scrolling: touch; } .color-picker-main-container { width: 100%; font-size: 22px; padding-bottom: 110px; } footer { position: fixed; }

This actually works well across the different desktop browsers, momentum-based scrolling still works, and the footer is fixed at the bottom and does not move on desktop web browsers. Perhaps the most problematic part of this solution (and what makes it unique) is that, on iOS Safari the footer always shakes and distorts very slightly and you can see the content below it whenever you scroll.

Solutions With JavaScript

After trying out some initial solutions using just HTML and CSS, I gave some JavaScript solutions a try. I would like to add that this is something that I do not recommend you to do and would be better to avoid doing. From my experience, there are usually more elegant and concise solutions using just HTML and CSS. However, I had already spent a lot of time trying out the other solutions, I thought that it wouldn’t hurt to quickly see if there were some alternative solutions that used JavaScript.

Touch Events

One approach of solving the issue of scroll bouncing is by preventing the touchmove or touchstart events on the window or document. The idea behind this is that the touch events on the overall window are prevented, whilst the touch events on the content you want to scroll through are allowed. An example of code like this is shown below:

// Prevents window from moving on touch on older browsers. window.addEventListener('touchmove', function (event) { event.preventDefault() }, false) // Allows content to move on touch. document.querySelector('.body-container').addEventListener('touchmove', function (event) { event.stopPropagation() }, false)

I tried many variations of this code to try to get the scroll to work properly. Preventing touchmove on the window made no difference. Using document made no difference. I also tried to use both touchstart and touchmove to control the scrolling, but these two methods also made no difference. I learned that you can no longer call event.preventDefault() this way for performance reasons. You have to set the passive option to false in the event listener:

// Prevents window from moving on touch on newer browsers. window.addEventListener('touchmove', function (event) { event.preventDefault() }, {passive: false}) Libraries

You may come across a library called “iNoBounce” that was built to “stop your iOS webapp from bouncing around when scrolling.” One thing to note when using this library right now to solve the problem I’ve described in this article is that it needs you to use -webkit-overflow-scrolling. Another thing to note is that the more concise solution I ended up with (which is described later) does a similar thing as it on iOS. You can test this yourself by looking at the examples in its GitHub Repository, and comparing that to the solution I ended up with.

Overscroll Behavior

After trying out all of these solutions, I found out about the CSS property overscroll-behavior. The overscroll-behavior CSS property was implemented in Chrome 63 on December 2017, and in Firefox 59 on March 2018. This property, as described in MDN documentation, “allows you to control the browser's scroll overflow behavior — what happens when the boundary of a scrolling area is reached.” This was the solution that I ended up using.

All I had to do was set overscroll-behavior to none in the body of my website and I could leave the footer’s position as fixed. Even though momentum-based scrolling applied to the whole page, rather than the contents without the footer, this solution was good enough for me and fulfilled all of my requirements at that point in time, and my footer no longer bounced unexpectedly on Chrome. It is perhaps useful to note that Edge has this property flagged as under development now. overscroll-behavior can be seen as an enhancement if browsers do not support it yet.

Conclusion

If you don’t want your fixed headers or footers to bounce around on your web pages, you can now use the overscroll-behavior CSS property.

Despite the fact that this solution works differently in different browsers (bouncing of the page content still happens on Safari and Edge, whereas on Firefox and Chrome it doesn’t), it will keep the header or footer fixed when you scroll to the very top or bottom of a website. It is a concise solution and on all the browsers tested, momentum-based scrolling still works, so you can scroll through a lot of page content very quickly. If you are building a fixed header or footer on your web page, you can begin to use this solution.

(rb, ra, yk, il)
Categories: Around The Web

The Complete Anatomy Of The Gutenberg WordPress Editor

Tue, 08/14/2018 - 8:00am
The Complete Anatomy Of The Gutenberg WordPress Editor The Complete Anatomy Of The Gutenberg WordPress Editor Manish Dudharejia 2018-08-14T14:00:22+02:00 2018-08-21T13:33:03+00:00

It seems that Gutenberg has been a term of controversy in the world of WordPress lately. Hailed as the most significant change to WordPress 5.0 this year, the Gutenberg editor has received a mixed response from web developers and regular folk alike. All of this chaos is making it difficult to see Gutenberg for what it really is. So, I’ll try to put some of the confusion to rest once and for all.

In this article, I will cover the following:

  1. What is Gutenberg?
  2. More Than Just An Editor
  3. What Does Gutenberg Change In WordPress?
  4. Installing Gutenberg
  5. Exploring Gutenberg At Length
  6. Pros And Cons
  7. Understanding Compatibility Issues
  8. Gutenberg Is The Future
  9. Latest News And Further Resources
1. What Is Gutenberg?

Named after Johannes Gutenberg, who invented the mechanical printing press, Gutenberg was introduced to the world by Matt Mullenweg at WordCamp Europe in 2017. In essence, Gutenberg is a new WordPress editor, with dozens of cutting-edge features. It simplifies website creation and editing for the average non-technical user.

It has earned several accolades, from “WordPress’s new publishing experience” to “the future of website creation”. Some skeptics think it is the nail in the coffin for WordPress. All this babble aside, Gutenberg is going to be way more than just an editor for WordPress (which I will discuss next).

It allows website creators to build a website using blocks, which are small drag-and-drop units. Thus, it replaces the current inconsistent and distracting customization process. It also enables HTML tags such as section and figure, outputting solid HTML. At the time of writing, Gutenberg is still a plugin. However, the community is planning to merge it with WordPress 5.0 this year.

Getting workflow just right ain’t an easy task. So are proper estimates. Or alignment among different departments. That’s why we’ve set up “this-is-how-I-work”-sessions — with smart cookies sharing what works well for them. A part of the Smashing Membership, of course.

Explore features → 2. More Than Just An Editor

Gutenberg is more than just an editor because it allows you to handle website content in customizable chunks or blocks. You don’t need to be fluent in HTML or write shortcodes. You can control a website’s entire layout (both back end and front end) from a single console.

This new editor attempts to combine the best features from both page-builder plugins such as Divi and Visual Composer, as well as do-it-yourself platforms such as Medium, Wix and Squarespace. So, just like those page-builder plugins, you can handle multi-column layouts through a single interface.

Does this spell the end of plugins such as Divi and Beaver Builder? That’s a topic for another post, but the short answer is no. Gutenberg is unlikely to replace those plugins completely. You can continue to use them even once Gutenberg becomes the default editor.

3. What Does Gutenberg Change In WordPress?

The sole purpose of the Gutenberg editor is to provide an alternative to the current open text editor, not to mention the difficult-to-remember shortcodes, with an agile and visual user interface (UI). So, unlike the current WordPress editor, you don’t have to:

  • import images, multimedia and approved files from the media library or add HTML shortcodes;
  • copy and paste links for embeds;
  • write shortcodes for specialized assets of different plugins;
  • create featured images to be added at the top of a post or page;
  • add excerpts for subheads;
  • add widgets for content on the side of a page.

In short, Gutenberg doesn’t change how WordPress functions. It does, however, change the way website owners (or creators) interact with it. Instead of a whole lot of shortcodes and meta boxes, you will be using simple blocks.

What Are Blocks?

Consider a block as the most basic (therefore, smallest) unit of the new editor. They will be the building blocks of WordPress 5.0. In other words, everything—including content, images, quotes, galleries, cover images, audio, video, headings, embeds, custom codes, paragraphs, separators and buttons—will turn into distinct blocks. Because you can drag and drop each block, identifying these items and placing them on the page becomes a lot easier.

4. Installing Gutenberg

You can download the latest version of Gutenberg directly from the WordPress repository. You can also search for it under “Add New” plugins in your WordPress dashboard. I would recommend installing it in your staging environment. However, you’ll need the latest version of WordPress (version 4.8 or later) to install the Gutenberg editor.

  1. Sign into your WordPress admin dashboard.
  2. Go to the Plugins menu on the left side of the dashboard.
  3. Click “Plugins” to open the “Add New” menu.
  4. Type “Gutenberg” in the search box, located in the top-left corner.
  5. You will see the Gutenberg plugin in the results.
  6. Click the “Install Now” button.
  7. Click the “Activate” button to initiate the plugin.
Gutenberg Installation Steps (Large preview) 5. Exploring Gutenberg At Length

Once installed and activated, Gutenberg will show an icon in the left menu bar. When you launch it for the first time, you will see a new sample post, titled “Gutenberg Demo.” You can practice on the demo post before creating your own.

Gutenberg Sample Post (Large preview) A. Add New

Go to “Posts” in the left menu bar of your WordPress dashboard. The new post will launch in Gutenberg first. You can later edit it in both the classic editor and Gutenberg.

Adding a new post in Gutenberg (Large preview) B. Edit

Go to the “Posts” menu, and hover the mouse over a saved post to see the option to choose between the two editors. Although the classic editor option is available for the time being, it will most likely be removed with the launch of WordPress 5.0.

Editing a post in Gutenberg (Large preview) C. Switch Between Editors

You can also switch between the two editors when editing a post. Click on the dropdown menu in the upper-right corner to toggle between the visual editor mode and the text editor (i.e. code). Alternatively, you can also use the shortcut Ctrl + Shift + Alt + M to switch between editors.

Text editor:

The text editor in Gutenberg (Large preview)

Visual editor:

The visual editor in Gutenberg (Large preview) D. Copy All Content

This feature allows you to copy all content in the HTML version with just one click. You can open this feature in both editors by clicking on the dropdown menu in the upper-right corner of the dashboard.

“ The ‘Copy All Content’ tool in Gutenberg (Large preview) E. Content Structures

This feature allows you to count the number of words in an entire post. You can also see the number of headings, paragraphs and blocks with just a click. Click the information icon (i) in the upper-left area.

Content information in Gutenberg (Large preview) F. Redo and Undo

You can find these options next to the information icon (i). They allow you to undo or redo the last command.

Undo/Redo Command (Large preview) G. Page and Document Settings

This allows you to change various page and document settings. You can find it in the right menu bar. You can make the following adjustments:

  • Make a post public or private.
  • Change the publishing date.
  • Select a post’s format.
  • Add or edit categories and tags.
  • Upload featured images.
  • Write an excerpt.
  • Enable and disable comments, pingbacks and trackbacks.
Page/Document Settings (Large preview) H. Stick to Front Page

This feature will come handy if you’re running a blog. When you turn this on in the document settings, that particular post will always appear on the front page of your blog. And just turn it off to remove it from the front page.

Making your post stick to the front page (Large preview) I. Using Blocks

As mentioned, blocks are the fundamental unit of the new Gutenberg editor. To use Gutenberg efficiently, you need to understand how to use these blocks. I will cover the main blocks one by one. Click the plus (+) button next to the redo/undo option to open the blocks menu.

Common Blocks

Common blocks allow you to add the elements required to create a rich UI.

  • Paragraph
    The paragraph block comes with a few excellent features, such as custom font sizes, drop caps, background colors and text colors, among others. You are also able to add more CSS classes here.
Gutenberg Text Editor Options (Large preview)
  • Image
    This element comes with a new feature that allows you to toggle between gallery and image layouts. You also get more control over images because you can set particular size dimensions, percentage size ratios, and an alternative text description for each image.
Image Settings in Gutenberg (Large preview)
  • Other elements include:
    • quotes,
    • galleries,
    • cover images,
    • headings,
    • lists,
    • audio,
    • files,
    • subheadings,
    • video.
Formatting

As the name suggests, these blocks comprise all of the formatting tools.

  • Table
    Adding a table using custom HTML code was a tedious job. With the table block, however, the task is a lot easier. You are able to add and remove rows and columns of a table without coding.
Table Block in Gutenberg (Large preview)
  • Custom HTML
    You can use a custom HTML code in Gutenberg. And the nice part is that you can insert your code and see a preview in the block itself.
Custom HTML in Gutenberg (Large preview)
  • Other elements include:
    • code,
    • classic,
    • preformatted,
    • pull quote,
    • verse.
Layout

Use your imagination to create a stunning layout using this block. Each element in this block comes with excellent features.

  • Button
    You can add buttons such as “Subscribe now” and “Buy now” using this block. It has different options, including alignment and font styles. You can also set the background color and shape of the button.
Button Layout in Gutenberg (Large preview)
  • Columns (beta)
    Creating columns in the code-based editor is time-consuming and laborious. This block allows you to add text columns. You are able to add one to six columns in a single row.
Column Layout in Gutenberg (Large preview)
  • Other elements include:
    • read more,
    • page break,
    • separator,
    • spacer.
Widgets

These blocks allow you to add an archive, categories, the latest posts and the latest comments with just a click anywhere on the page. You are also able to adjust these elements without any coding.

  • Latest Post
    With this block element, you can show posts in a grid view or list view, organize them in categories, and order them alphabetically or according to publication date. You can also choose to display the publication date.
Latest Posts Setting in Gutenberg (Large preview) Embeds

You can easily access any embeds using these blocks. Whether you want to add a YouTube or Twitter link, it’s super-easy and quick. All you need to do is paste the URL in the given blank space, and Gutenberg will embed the code for you. Here is an example of inserting a YouTube link:

Embed Youtube Link in Gutenberg (Large preview) Reusable Blocks

Reusable blocks give developers improved usability. You can convert any block into a reusable block so that you can use it in a different location. You can edit the same and save it as a new reusable block again.

You can also see a preview of a reusable block. All reusable blocks are available under the “Shared Block” options. Most importantly, you can turn one back into a regular block anytime.

Reusable Blocks in Gutenberg (Large preview) Most Used

Under this option, you will see the most used blocks, for quick access. Alternatively, you can use the search box to find a block by name.

J. Edit Block

To edit any block, open the dropdown menu by clicking in the upper-right corner of the block. You will see different options, including to edit as HTML, duplicate and add to the reusable blocks.

Edit Block in Gutenberg (Large preview) K. Insert Blocks

Using this feature, you can insert a new block anytime. When you bring your mouse over a block, you will see a plus icon (+). Click it to insert a new block.

Inserting a block in Gutenberg (Large preview) L. Slash Autocomplete

The Slash Autocomplete feature is available in Gutenberg 1.1.0 and later versions. Chances are you are already familiar with the similar feature in Slack. It was added to reduce the amount of pointing and clicking required to create new blocks.

When you open a new block, just press / (slash key) on your keyboard to select any of the autocomplete options. It works in the default paragraph block only, but it might become a part of other types of blocks in the future.

Slash Autocomplete in Gutenberg (Large preview) M. Move Blocks

Gutenberg enables you to move each block up and down. You can use the arrows (on the left side of each block) to move them vertically.

Moving a block in Gutenberg (Large preview) 6. Gutenberg Pros And Cons Pros
  • No technical skill is required to make a custom layout for a blog post or website. It works like Medium, so people looking for that kind of style and user-friendly editing experience will love it.
  • It allows you to create a consistent and advanced design without relying much on TinyMCE.
  • Furthermore, blocks are an excellent concept. They allow non-developers to intuitively craft complex layouts. If you are new to WordPress or have no knowledge of it whatsoever, you are still going to love it.
  • The Gutenberg editor itself works well on mobile (it’s responsive). Unlike its predecessor, it allows you to make quick edits on the go. In fact, mobile-savvy developers can manage to do more than just a few quick edits.
  • The increased screen space is proving to be a less distracting user experience for many developers.
  • Hardcore developers can still create customized reusable blocks using HTML5. So, it seems like a win-win for both geeks and non-technical users.
Cons
  • For the time being, there is no Markdown support in the beta version of the WordPress editor.
  • It still doesn’t support responsive columns. You will need to do some custom coding to make this feature responsive. So, using this feature on mobile isn’t an option right now.
  • The design layout options are inadequate at the moment.
  • Compatibility issues could be a significant concern for some WordPress users.
  • You get only partial support for meta boxes. For now, it only supports Yoast SEO. So, using most custom plugins in Gutenberg is not possible. However, developers are working hard to extend meta box support.
  • Backward compatibility is going to be a primary concern for most developers. It will destroy current plugins and themes, especially ones that require integration with TinyMCE.
7. Understanding Compatibility Issues

Despite its simplicity and agility, Gutenberg might not be everyone’s cup of tea. Most WordPress developers might find it difficult to work with, especially in the beginning. They will need to retrain their reflexes to get used to the new UX.

  • Owing to the backward-compatibility issue, you will need to update many plugins and themes to ensure they are fully compatible with the new editor.
  • For the time being, blocks are more focused on content. As a result, Gutenberg lacks precision and control over the layout of custom websites.
  • Shortcodes are replaced by shortcode blocks. However, you will still be able to add shortcodes from the widget block.
  • Meta boxes will be available under a new name and a new UI. Conflicting meta boxes are likely to lead to the classic editor, instead of Gutenberg, with an alert. While this system might prove helpful, some meta boxes will not be supported in Gutenberg.
  • Custom post types are supported and remain backward-compatible in Gutenberg.
  • You won’t be able to turn off Gutenberg once it is integrated in WordPress core. However, you can disable it using the official plugin anytime.
8. Gutenberg Is The Future

Contrary to popular opinion, Gutenberg is not a replacement for the current text editor. It is a new way to build websites. I like to think of it as Facebook for WordPress.

You don’t need to be a computer geek to publish things on Facebook or any other social media platform. Gutenberg is just a way to bring this simplicity and flexibility to WordPress, so that people don’t need to code in order to create and publish websites. That’s why I think it is going to be the future, not only for WordPress, but for the web in general.

Granted, Gutenberg has a long way to go. People (including me) have had issues with its implementation, but soon we will have Gutenberg-ready themes, plugins and tools surfacing everywhere. Nevertheless, you have to start somewhere. So, you might as well be a part of this change from the beginning.

9. Latest News And Further Resources

If you are interested in riding the Gutenberg train from the beginning, here are a few links to find the latest buzz. Keep in mind that none of these websites are officially endorsed by WordPress.

For official updates and news, you can try the following:

Wrapping Up

Whether you like it or not, Gutenberg is coming to WordPress 5.0. Do try to be a part of the ongoing discussion about it on the web. It will certainly help. In fact, while you’re at it, try to speed up the development process with your skills. Meanwhile, let me know if this post has shed some light on the topic. Drop your queries and suggestions in the comments section. I would love to keep the conversation going.

(ra, il)
Categories: Around The Web

Everything You Need To Know About Alignment In Flexbox

Mon, 08/13/2018 - 8:00am
Everything You Need To Know About Alignment In Flexbox Everything You Need To Know About Alignment In Flexbox Rachel Andrew 2018-08-13T14:00:57+02:00 2018-08-21T13:33:03+00:00

In the first article of this series, I explained what happens when you declare display: flex on an element. This time we will take a look at the alignment properties, and how these work with Flexbox. If you have ever been confused about when to align and when to justify, I hope this article will make things clearer!

History Of Flexbox Alignment

For the entire history of CSS Layout, being able to properly align things on both axes seemed like it might truly be the hardest problem in web design. So the ability to properly align items and groups of items was for many of us the most exciting thing about Flexbox when it first started to show up in browsers. Alignment became as simple as two lines of CSS:

See the Pen Smashing Flexbox Series 2: center an item by Rachel Andrew (@rachelandrew) on CodePen.

The alignment properties that you might think of as the flexbox alignment properties are now fully defined in the Box Alignment Specification. This specification details how alignment works across the various layout contexts. This means that we can use the same alignment properties in CSS Grid as we use in Flexbox — and in future in other layout contexts, too. Therefore, any new alignment capability for flexbox will be detailed in the Box Alignment specification and not in a future level of Flexbox.

Nope, we can't do any magic tricks, but we have articles, books and webinars featuring techniques we all can use to improve our work. Smashing Members get a seasoned selection of magic front-end tricks — e.g. live designing sessions and perf audits, too. Just sayin'! ;-)

Explore Smashing Wizardry → The Properties

Many people tell me that they struggle to remember whether to use properties which start with align- or those which start with justify- in flexbox. The thing to remember is that:

  • justify- performs main axis alignment. Alignment in the same direction as your flex-direction
  • align- performs cross-axis alignment. Alignment across the direction defined by flex-direction.

Thinking in terms of main axis and cross axis, rather than horizontal and vertical really helps here. It doesn’t matter which way the axis is physically.

Main Axis Alignment With justify-content

We will start with the main axis alignment. On the main axis, we align using the justify-content property. This property deals with all of our flex items as a group, and controls how space is distributed between them.

The initial value of justify-content is flex-start. This is why, when you declare display: flex all your flex items line up against the start of the flex line. If you have a flex-direction of row and are in a left to right language such as English, then the items will start on the left.

The items line up to the start (Large preview)

Note that the justify-content property can only do something if there is spare space to distribute. Therefore if you have a set of flex items which take up all of the space on the main axis, using justify-content will not change anything.

There is no space to distribute (Large preview)

If we give justify-content a value of flex-end then all of the items will move to the end of the line. The spare space is now placed at the beginning.

The items line up at the end (Large preview)

We can do other things with that space. We could ask for it to be distributed between our flex items, by using justify-content: space-between. In this case, the first and last item will be flush with the ends of the container and all of the space shared equally between the items.

The spare space is shared out between the items (Large preview)

We can ask that the space to be distributed around our flex items, using justify-content: space-around. In this case, the available space is shared out and placed on each side of the item.

The items have space either side of them (Large preview)

A newer value of justify-content can be found in the Box Alignment specification; it doesn’t appear in the Flexbox spec. This value is space-evenly. In this case, the items will be evenly distributed in the container, and the extra space will be shared out between and either side of the items.

The items are spaced evenly (Large preview)

You can play with all of the values in the demo:

See the Pen Smashing Flexbox Series 2: justify-content with flex-direction: row by Rachel Andrew (@rachelandrew) on CodePen.

These values work in the same way if your flex-direction is column. You may not have extra space to distribute in a column however unless you add a height or block-size to the flex container as in this next demo.

See the Pen Smashing Flexbox Series 2: justify-content with flex-direction: column by Rachel Andrew (@rachelandrew) on CodePen.

Cross Axis Alignment with align-content

If you have added flex-wrap: wrap to your flex container, and have multiple flex lines then you can use align-content to align your flex lines on the cross axis. However, this will require that you have additional space on the cross axis. In the below demo, my cross axis is running in the block direction as a column, and I have set the height of the flex container to 60vh. As this is more than is needed to display my flex items I have spare space vertically in the container.

I can then use align-content with any of the values:

See the Pen Smashing Flexbox Series 2: align-content with flex-direction: row by Rachel Andrew (@rachelandrew) on CodePen.

If my flex-direction were column then align-content would work as in the following example.

See the Pen Smashing Flexbox Series 2: align-content with flex-direction: column by Rachel Andrew (@rachelandrew) on CodePen.

As with justify-content, we are working with the lines as a group and distributing the spare space.

The place-content Shorthand

In the Box Alignment, we find the shorthand place-content; using this property means you can set justify-content and align-content at once. The first value is for align-content, the second for justify-content. If you only set one value then both values are set to that value, therefore:

.container { place-content: space-between stretch; }

Is the same as:

.container { align-content: space-between; justify-content: stretch; }

If we used:

.container { place-content: space-between; }

This would be the same as:

.container { align-content: space-between; justify-content: space-between; } Cross Axis Alignment With align-items

We now know that we can align our set of flex items or our flex lines as a group. However, there is another way we might wish to align our items and that is to align items in relationship to each other on the cross axis. Your flex container has a height. That height might be defined by the height of the tallest item as in this image.

The container height is defined by the third item (Large preview)

It might instead be defined by adding a height to the flex container:

The height is defined by a size on the flex container (Large preview)

The reason that flex items appear to stretch to the size of the tallest item is that the initial value of align-items is stretch. The items stretch on the cross axis to become the size of the flex container in that direction.

Note that where align-items is concerned, if you have a multi-line flex container, each line acts like a new flex container. The tallest item in that line would define the size of all items in that line.

In addition to the initial value of stretch, you can give align-items a value of flex-start, in which case they align to the start of the container and no longer stretch to the height.

The items aligned to the start of the cross axis (Large preview)

The value flex-end moves them to the end of the container on the cross axis.

The items aligned to the end of the cross axis (Large preview)

If you use a value of center the items all centre against each other:

Centering the items on the cross axis (Large preview)

We can also do baseline alignment. This ensures that the baselines of text line up, as opposed to aligning the boxes around the content.

Aligning the baselines (Large preview)

You can try these values out in the demo:

See the Pen Smashing Flexbox Series 2: align-items by Rachel Andrew (@rachelandrew) on CodePen.

Individual Alignment With align-self

The align-items property means that you can set the alignment of all of the items at once. What this really does is set all of the align-self values on the individual flex items as a group. You can also use the align-self property on any individual flex item to align it inside the flex line and against the other flex items.

In the following example, I have used align-items on the container to set the alignment for the group to center, but also used align-self on the first and last items to change their alignment value.

See the Pen Smashing Flexbox Series 2: align-self by Rachel Andrew (@rachelandrew) on CodePen.

Why Is There No justify-self?

A common question is why it is not possible to align one item or a group of the items on the main axis. Why is there no -self property for main axis alignment in Flexbox? If you think about justify-content and align-content as being about space distribution, the reason for their being no self-alignment becomes more obvious. We are dealing with the flex items as a group, and distributing available space in some way — either at the start or end of the group or between the items.

If might be also helpful to think about how justify-content and align-content work in CSS Grid Layout. In Grid, these properties are used to distribute spare space in the grid container between grid tracks. Once again, we take the tracks as a group, and these properties give us a way to distribute any extra space between them. As we are acting on a group in both Grid and Flexbox, we can’t target an item on its own and do something different with it. However, there is a way to achieve the kind of layout that you are asking for when you ask for a self property on the main axis, and that is to use auto margins.

Using Auto Margins On The Main Axis

If you have ever centered a block in CSS (such as the wrapper for your main page content by setting a margin left and right of auto), then you already have some experience of how auto margins behave. A margin set to auto will try to become as big as it can in the direction it has been set in. In the case of using margins to center a block, we set the left and right both to auto; they each try and take up as much space as possible and so push our block into the center.

Auto margins work very nicely in Flexbox to align single items or groups of items on the main axis. In the next example, I am achieving a common design pattern. I have a navigation bar using Flexbox, the items are displayed as a row and are using the initial value of justify-content: start. I would like the final item to be displayed separated from the others at the end of the flex line — assuming there is enough space on the line to do so.

I target that item and give it a margin-left of auto. This then means that the margin tries to get as much space as possible to the left of the item, which means the item gets pushed all the way over to the right.

See the Pen Smashing Flexbox Series 2: alignment with auto margins by Rachel Andrew (@rachelandrew) on CodePen.

If you use auto margins on the main axis then justify-content will cease to have any effect, as the auto margins will have taken up all of the space that would otherwise be assigned using justify-content.

Fallback Alignment

Each alignment method details a fallback alignment, this is what will happen if the alignment you have requested can’t be achieved. For example, if you only have one item in a flex container and ask for justify-content: space-between, what should happen? The answer is that the fallback alignment of flex-start is used and your single item will align to the start of the flex container. In the case of justify-content: space-around, a fallback alignment of center is used.

In the current specification you can’t change what the fallback alignment is, so if you would prefer that the fallback for space-between was center rather than flex-start, there isn’t a way to do that. There is a note in the spec which says that future levels may enable this.

Safe And Unsafe Alignment

A more recent addition to the Box Alignment specification is the concept of safe and unsafe alignment using the safe and unsafe keywords.

With the following code, the final item is too wide for the container and with unsafe alignment and the flex container on the left-hand side of the page, the item becomes cut off as the overflow is outside the page boundary.

.container { display: flex; flex-direction: column; width: 100px; align-items: unsafe center; } .item:last-child { width: 200px; } Unsafe alignment will give you the alignment you asked for but may cause data loss (Large preview)

A safe alignment would prevent the data loss occurring, by relocating the overflow to the other side.

.container { display: flex; flex-direction: column; width: 100px; align-items: safe center; } .item:last-child { width: 200px; } Safe alignment tries to prevent data loss (Large preview)

These keywords have limited browser support right now, however, they demonstrate the additional control being brought to Flexbox via the Box Alignment specification.

See the Pen Smashing Flexbox Series 2: safe or unsafe alignment by Rachel Andrew (@rachelandrew) on CodePen.

In Summary

The alignment properties started as a list in Flexbox, but are now in their own specification and apply to other layout contexts. A few key facts will help you to remember how to use them in Flexbox:

  • justify- the main axis and align- the cross axis;
  • To use align-content and justify-content you need spare space to play with;
  • The align-content and justify-content properties deal with the items as a group, sharing out space. Therefore, you can’t target an individual item and so there is no -self alignment for these properties;
  • If you do want to align one item, or split a group on the main axis, use auto margins to do so;
  • The align-items property sets all of the align-self values as a group. Use align-self on the flex child to set the value for an individual item.
(il)
Categories: Around The Web

Web Performance For Third Party Scripts: SmashingConf Videos

Wed, 08/08/2018 - 7:30am
Web Performance For Third Party Scripts: SmashingConf Videos Web Performance For Third Party Scripts: SmashingConf Videos The Smashing Editorial 2018-08-08T13:30:35+02:00 2018-08-21T13:33:03+00:00

We are continuing our exploration of video from Smashing Conferences this year with two videos that explore the impact of third party scripts. These scripts can add functionality, and give us valuable information, but what do they cost?

These two talks will help you to assess the third party scripts you might be considering adding to a site, and to be able to advise your clients or team members when the request comes in to add yet another script to a global include file!

Name That Script!

Recorded at the SmashingConf in San Francisco earlier this year, Trent Walton asks how can we objectively measure the value of third party scripts for advertising, A/B testing, or analytics? We need to consider their impact on web performance, user experience, as well as understand if they really help our business goals.

A/B Testing, Ads and Other Third Party Tags

At the SmashingConf in London, Andy Davies approached the same subject from a technical angle, showing us the impact that “just a snippet of JavaScript” can have.

Enjoyed watching these talks? There are many more SmashingConf videos on Vimeo. We’re also getting ready for the upcoming SmashingConf in New York — see you there? ;-)

With so much happening on the web, what should we really pay attention to? At SmashingConf New York 2018

Categories: Around The Web

Attracting Users To Evaluate Your Product

Sun, 08/05/2018 - 6:30pm
Attracting Users To Evaluate Your Product Attracting Users To Evaluate Your Product Joe Leech 2018-08-05T23:30:38+01:00 2018-08-21T13:33:03+00:00

(This is a sponsored article.) The entire ecosystem in which we are designing and researching the user experience is shifting and changing constantly. Traditional UX skills need to be expanded to meet the reality of the modern digital ecosystem. Understanding the user is essential to the job, but you also need to understand the wider user context. How do they discover they have a need? How do they find and evaluate a product to meet that need?

This three-part series outlines the three phases of the product life cycle, the future of UX, and the skills and approach you’ll need to design modern digital products.

  • Part 1: Attraction
    Going out there to get users to evaluate your product.
  • Part 2: Activation
    Signing up, onboarding users, asking for payment.
  • Part 3: Retention
    Encouraging users to come back and keep using and paying for your product.

Due to their technical skills, creativity and deep understanding of user needs, UXers are in a perfect position to apply marketing, SEO and growth-hacking tools and processes to their work.

For focused UX efforts, it’s all about knowing user outcomes at each stage of their journey.

1. Attraction Large preview Getting Started

The days of changing the text on one button and having a dramatic effect on the user experience are behind us. Luckily, we have the processes and skills in our UX toolbox to meet this changing world.

More often than not, there are many small usability and experience issues throughout a user journey that cumulatively create a poor experience.

Mapping out the full user life cycle will help us discover and fix these problems. It’s often the case that a problem at the very beginning of the user journey only surfaces when a user drops out further along in the product life cycle.

We need data to help us understand how UX professional can improve performance. We’ll need user research data, business metrics, data to frame decisions made when improving UX, and metrics to help us understand the business values.

Marketing metrics tracked by team employing growth hacking. (Source). (Large preview) Plotting Out the Journey

When we talk about the attraction phase, we’re talking about users discovering they have a need, discovering our product and visiting our website to see if our product meets their needs.

Within the life cycle, we can split the larger three phases into smaller phases to help us plan our approach. In this case, we can use Philip Kotler's model (expanded to six steps by Bryony Thomas):

  1. Awareness: realizing they have a need;
  2. Interest: looking for something to help with that need;
  3. Evaluation: looking at products that help with their need;
  4. Trial: trying the product to see if it meets their need;
  5. Adoption: choosing a product and using it for a while;
  6. Loyalty: deciding to continue using the product or switching to a different one.

We’re interested in the first three parts, which fall under the attraction phase.

Large preview

We’ll look into trial, adoption and loyalty in future parts of this series.

We’ll use the customer life cycle to align user needs and expectations — what they want and when they need it — to business metrics. We’ll also look at a tool and UX process to use at each step on the journey.

As we move through the process we’ll use the example of a money management app that helps people understand what they are spending and save money.

1. Awareness: They Understand That They Have A Need The first battle isn’t fought on the ground but in the mind of the customer.
It isn’t fought with your built out solution but instead with an offer.

The Science of How Customers Buy Anything

This is most challenging phase because there is very little that is concrete in terms of user need.

Users can’t articulate what they want, but by looking at how they complete a task or the context of their life, we can identify the problems they face, how they address (or don’t!) the problems now, and potential product features to address the problems.

The goal here is to identify unmet, hidden user needs. This is something Amazon, for example, is very good at.

The secret to Amazon’s success? Be the first to uncover hidden needs. Jeff Bezos, founder of amazon.com. (Large preview) How To Identify A Need And A Solution Using Fro-Tos

A good technique to use here is to plot the current problem as articulated by the user and then the result of that problem being solved.

Al Ramadan, in his book Play Bigger, named this overarching science category design.

Category design takes people on a journey. We refer to it as creating a from/to. Actually, we use a shorthand term: frotos. Remember, a great new category is one that solves a problem people didn’t know they had, or solves an obvious problem no one thought could be solved.

You have to help them move from the way they used to think, to a new frame of reference. This is what it means to condition the market. You have to first define and market the problem — and only then can you help people understand that you can solve the problem better than anyone else.

The “from” is the problem the user is facing. The “to” is the solution your product offers. The solution described here are the words the user uses to solve the problem.

If we take the example of our money management tool, in user research, we would identify the from as:

I don’t have much money left at the end of the month. Why?

The user then identifies the to as:

I need to something to help me analyze what I spend.

Put the two together and you have frotos: a definition of the problem and an articulation of the solution.

There is a slidedeck that has a good overview of Play Bigger and its techniques.

Bonus: You can also use the jobs-to-be-done timeline as a great tool to map the intent phase.

User research helps us uncover the hidden needs and identify the frotos.

User Research To Uncover Frotos And Other Useful Details

Traditionally, user research has been focused on the experience of the product. We need to expand user research to include all parts of the user acquisition phase.

It’s not easy to research with users who aren’t yet interacting with you. We can turn to the same tools that we are using to raise awareness to also find users to research with.

Recruit and conduct research with users who might respond to your product’s messaging by using Facebook ads or Google demographic targeting. You can then use a tool like Ethn.io to ask them a few questions to aid with recruitment.

The value in researching users who are in the user acquisition phase is that they don’t bring any preconceptions of your product. In fact, when you are reaching out to users for them to give you feedback, don’t talk much about who you are researching for.

Ethnographic and contextual research is the most useful tool here. Going out and observing users in their homes and offices is a great technique. Watching a user go through a typical task will help you identify their needs. You can’t simply ask users what their unmet needs are because they won’t know. The only true way to get to unmet need is to observe behavior.

With our money management app, we might observe that some potential users under 30 years of age don’t have much money left at the end of the month to save or are curious about how much they spend on coffee.

The user research can also uncover any common identifiable traits (and patterns of behavior) that your users show, such as age-related (for example, they are under 30) or interests they share (love of coffee). We can use these traits to target them in our messaging.

The goal from the user research is to uncover unmet needs and identify the frotos: the from state and the to state.

An example of a froto might be:

FROM
I love coffee, but it can get expensive. I wonder how much I spend a month on coffee?

TO
I need to know how much I spend on expensive luxuries like coffee, so that I can reduce my spend.

We can also use the jobs-to-be-done interview framework to help identify unmet needs.

Journey Maps To Understand The Details

Taking the frotos and other learnings, you can add more detail to the journey by mapping out the steps and behaviors at a granular level.

Niall O’Connor has a great overview of how to build a journey and experience map.

Below is a high-level journey map for our money management app, showing needs mapped against each phase of the life cycle.

In the awareness phase, we can see how the need is quite abstract, but we can clearly see a need for our product. Our money management app can help people understand their current spending. (Large preview) Personas To Target

Personas are a divisive issue in the UX world. For the purpose of targeting users in the intent stage, we need to know demographic traits and interests.

We can then use tools such as Facebook ads to target the users who will respond to our frotos.

Facebook ad targeting: We can see how easy it is to find the users we are looking for based on their interests and age group. (Large preview)

In Facebook ads, we can target a specific age group who are coffee lovers. We can use this to target users who might be in the market for our product because they might spend a lot on coffee. Let’s roll up our sleeves and start designing the interactive elements to support this behavior.

Prototyping Attraction

Prototyping and wireframing have traditionally been limited to designing just the product. A modern UXer needs to take prototyping into the wider context and design interactions from the very beginning of the user journey. Rapid prototyping interactions at each step of the product life cycle to gather user feedback and validate ideas can save a lot of time, money and effort later.

For our money management app, we’ll design a Facebook ad to target potential users. We know what copy to include in the ad from our frotos.

An example showing how easy it is to create a Facebook ad prototype interaction. (Large preview)

When we get our target users and run user testing on the prototype, we’re testing the entire user experience — from awareness onwards — receiving high-quality UX insights from all parts of the user journey.

The attraction phase is really important for the user experience because it’s where expectations are set. As shown below, we need to use the tools and UX activities at our disposal to design the interactions with our user as we would design the interactions within the product.

An overview of tools and activities to use to improve the UX during the attraction phase. (Large preview) 2. Interest

The interest phase is characterized by the user looking for a product to help with the frotos we identified during the awareness phase.

Here, we’ll be working with our SEO colleagues, which means we UXers need to know the tools and processes that SEO practitioners use to help design the search and discovery journey.

Back To The Experience Map To Review The Interest Phase

We used user research to identify the frotos and the questions and information at each step of the journey.

Large preview

If we take the interest phase, we can see that the user has come to the conclusion they need something to:

  • Analyze what I spend, and
  • Manage my money.

We can take these interest statements and look to search and keyword-planning tools to refine the language used.

Using Google’s Keyword Planner:

Google’s Keyword Planner shows the suggested terms to target. (Large preview)

We are offered the following:

After selecting a keyword, we are shown alternatives we might not have considered. (Large preview)

Google’s documentation has some more useful help with the search terms report.

We can see from the related search terms what other words our target audience might type in when looking for our product. These words will help us design and improve the search user experience.

You can also use the free Google keyword research tool from SERPS.com to help define the terms used by your users to describe the problem. The higher the volume, the more likely a person is to search for that term.

A list of related search terms based on our initial query. Also shown is the relative popularity of each term. (Large preview)

We can use these search terms to refine the language we use when building the next part of our prototype.

Design The Ad In Your Prototype Tool

We can use Google’s Keyword Planner to design the interest phase of our prototype. You can update the text and the design will change in real time. This is the best approach because Google is constantly changing the format of paid and organic search listings, and any design templates will be quickly out of date.

Creating the ad in Google’s tool shows a live preview of how it will look. (Large preview)

You can also live prototype the ad in using Google’s tools on desktop and mobile.

You can preview the ad on desktop and mobile. (Large preview)

Our prototype now contains details for the first two subphases of the attraction part of the user life cycle.

Now that we have generated interest in the product, we need to start looking at how our user will evaluate our product to see if it is something they would want to invest time in.

3. Evaluation

The evaluation phase is all about the first visit to our website and that all-important first impression.

We need to look at where users are landing from, be it Facebook ads, Google search results or indeed other routes to our product, such as YouTube, Instagram or Pinterest.

Google Analytics can tell us the most common landing pages and where people come from. A report named “Network Referrals” can help.

We can see here that Facebook is major source of inbound traffic. (Large preview)

SiteTuners’ custom Google Analytics report identifies landing pages with a high bounce rate. We can interpret these as pages users are interested in, but users can’t find what they need or the messaging might not resonate with them. This report is fantastic for UXers to find pages that are causing problems and need to be improved.

Google Analytics shows pages with high-traffic and high-bounce rates (i.e. problematic pages). (Large preview)

Quick Sprout’s tool is great for evaluating landing pages to give you some clues as to why the page we identified from the custom report is failing.

Prototype The Landing Page

User research has helped us define what our users need at each step, and we’ve mapped out those needs. If it’s an existing product, then we know which landing pages are causing us problems.

The journey map can help us determine the type of copy to include on the landing page — what the user is expecting to see, what questions they need answering and what concerns they may have.

The three parts of the attraction phase and user questions and information needs. (Large preview)

We can then directly translate the user needs into the design for the landing page.

A quick mockup of the landing page meeting the user questions and information needs. (Large preview)

Understanding and mapping the problems users have, the solutions they need, as well as the questions they have when evaluating will make designing this page a straightforward task. If we have an existing but underperforming landing page, we’ll know what content the user is expecting and can evaluate and recommend what needs to change.

Previously, when prototyping we may have used lorem ipsum text. Now, we don’t need to because we have the copy we need. We can design the calls to action to reflect the problems our users are facing, increasing the likelihood of them using our product. No more need for lorem ipsum!

This landing page is just the start. In the next UX life cycle article, we’ll look at further enhancements.

Here’s more great guidance on How To Design An Effective Mobile Landing Page.

User Research The Journey, Including The Landing Page

We can now use the prototype to user test the whole attraction journey, from initial awareness to evaluation. Another Smashing Magazine article has some great suggestions to help with your user research.

Just Scratching The Surface

We’ve looked at how UXers can learn from other disciplines, such as marketing and SEO, to better understand, research, design and improve the attraction phase of the product life cycle.

If you’d like to learn more, I suggest these great books:

In the next part of the series, we’ll look at the next phase, activation: helping users to sign up, onboard and pay for your product.

This article is part of the UX design series sponsored by Adobe. Adobe XD tool is made for a fast and fluid UX design process, as it lets you go from idea to prototype faster. Design, prototype and share — all in one app. You can check out more inspiring projects created with Adobe XD on Behance, and also sign up for the Adobe experience design newsletter to stay updated and informed on the latest trends and insights for UX/UI design.

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

We Are Just Getting Started: 1,000 Smashing Members

Fri, 08/03/2018 - 7:50am
We Are Just Getting Started: 1,000 Smashing Members We Are Just Getting Started: 1,000 Smashing Members Vitaly Friedman 2018-08-03T13:50:31+02:00 2018-08-21T13:33:03+00:00

We’ve all been there: bringing a new product to the market is a tough nut to crack. It requires patience, commitment, and a bit of healthy stubbornness. That's the exact attitude we started off with when we launched our shiny new Smashing Membership last October — a friendly and respectful community that keeps this website alive, along with books, webinars, discounts, networking, and a seasoned selection of fancy cats.

Thanks to the generous support of Smashing Members, we're incredibly honored to have crossed the 1,000 members mark today. This is a very important day for us, and frankly, it's quite flattering to see 1,000 people actively supporting our little site and sharing our goals. In fact, with Membership, sometimes it feels like walking around a small town in which everyone knows each other and their friends, and so we know many members by name, and we've also met some of them at Smashing Conferences. It's a wonderful family that shares similar values and wants to get better at their work. But it's also a family that wants to bring along a shift in the industry.

The People Behind The Scenes

When looking at obscure avatars and nicknames appearing in remote corners of the web, it's easy to forget that there are actually real people behind them. That's why it was important for us that the Membership experience is focused around real names and real faces of the community members — both on the new Smashing Magazine website and in our Membership Slack channel. It's the people who shape the community and make it feel like home, and so Membership should become a humane product, with approachable and friendly authors, contributors and attendees.

We reached out to a few members to ask them why out of all the wonderful resources on the web, they chose to support the red, cat-friendly, and quirky Smashing Magazine, and what they found useful or remarkably painful during their Membership so far.

Allen Brady

Allen is based in Knoxville, TN. He is passionate about building great experiences on the web for companies and their audiences. Currently he is learning to make the web more accessible with great HTML, CSS and inclusive design.

“I wanted to support Smashing Magazine as soon as they launched their membership program because not only have they been an excellent resource over the years with all the fantastic articles, books and conferences, but also because they’re so great at amplifying the voices in this industry, which is really important. I know that with my membership I’m getting a diverse range of perspectives that’s really helped shape me into a better developer.

The best part about this membership is the community. There’s a fantastic Slack group where you can talk about your projects, ask for help or just chat about whatever. The webinars have also been great. My favorite part is that we get to chat with the hosts and each other during the live recording. Involving the community in everything they can seems to be a theme with Smashing Magazine. It sets them apart from other resources out there and I love it.”


Verena Vertonghen

Verena's journey in the development world started 6 years ago. She studied Multimedia Technology with a specialisation in Web&UX in Antwerp.

“Now I'm a front-end developer who also picks up some design challenges from time to time. I love creating all sorts of things and going on walks with my dogs. Because Smashing Magazine has been an invaluable learning resource for me throughout my studies and my career. I decided on membership to support the continuation of all the great work that Smashing Magazine already offers. But also because you get even more goodies when you do.

Some of the things I really like about it are the eBooks, previews to articles, webinars and the Slack channel that gives me the opportunity to connect with people that have a similar profile. The user experience is overall really great, and SmashingMag cat mascot gives a very playful and personal vibe!”
Emily Serven

Emily is a recent college graduate and new member of the workforce. In her spare time, she like practicing photography, listening to foreign music, and occasionally playing Overwatch.

“I remember checking SmashingMag regularly as far back as middle school and have always loved the quality and steady quantity of content. I know I can trust the quality of writing on Smashing (especially considering there’s so much content and noise from other places to sift through nowadays)!

I’m also a cat person, for sure. I’ve found the available resources to be really useful (eBook library and book discounts), and I can’t wait for the printed magazine to come out. That’s the other thing about Smashing; even though the medium in which I express my work as a web dev is primarily digital, Smashing still recognizes the value of well-produced and attractive physical media. I love getting the physical books for that reason.

Oh, another thing. I used to freelance more back in middle school until I got my full-time position recently. When I found Smashing for the first time, I really loved how it really ‘got’ me and my job. There was coding, but also design (Photoshop, UX, etc.) and freelance articles specifically. It all felt very well balanced. I think that helped me develop my dev skills and the other auxiliary talents in a way that led to my holistic view of dev nowadays, too.


Arthur Leonov

Arthur is a product designer that also codes front-end. He is a firm believer that merging design and technology can solve even the most difficult problems.

“I’m a designer that codes front-end. What a combo, right? I also believe that merging design and technology can solve even the most difficult problems in this world. The Smashing community keeps me inspired and informed day in and day out.

I catch up on SmashingMag every morning because it is one of the few online magazines in this industry who puts a lot of emphasis on good quality, relevant, and practical content.”

It might sound like an overstatement, but these people have already made a difference. They’ve helped us initiate projects that we wouldn't be able to support otherwise. Now, don't get me wrong: with dwindling ad revenues facing us, of course our aim was to earn enough with the help of the Membership to keep the magazine independent and self-funded. But that’s just one side of the story. Our aim was also to support design education and new voices in the industry; reward great people doing great work; foster open, diverse, inclusive and accessible initiatives. Last but not least, we wanted to help community events and projects, and the people behind them.

Did we achieve any of these goals with the money we've earned? I'm glad you asked.

So How Much Money Did We Earn? Total: $33,128

Initially, we were hoping to provide a larger financial support for new design/tech education initiatives and open-source projects, but with limited resources we had to be more realistic and pragmatic. We reached 1,013 Smashing Members in 257 days, with 30 supporters, 562 members, and 421 smashers. That makes a current total of $6,689 gross per month for August 2018.

Since the launch of the Membership, Smashing Members contributed a total of $33,128 net over the course of 10 months (including current month):

Month Net revenue Total $33,128 November 2017 $1,104 December 2017 $1,530 January 2018 $2,130 February 2018 $2,181 March 2018 $2,748 April 2018 $4,015 May 2018 $4,440 June 2018 $4,750 July 2018 $4,990 August 2018 $5,240

It goes without saying that these kind contributions massively helped us cover monthly costs, from maintenance to honorarium for authors, in particular:

  • Honorarium for authors contributing articles and chapters for Smashing Magazine, our eBooks and printed books,
  • Honorarium for reviewers, editors, proofreaders, illustrator Ricardo Gimenes and front-end developer Ilya Pukhalski,
  • Honorarium for all webinar speakers,
  • All design education initiatives and community support is enabled by Smashing Membership,
  • All money was reinvested in the Magazine and Membership projects.

From day one, we kept things fully transparent; we've been sharing monthly reports on how much money we've earned and how we spent it. So here's what happened since the launch of Membership last year.

Smashing TV: 24 Live Sessions

Each month, we are proud to host 2 curated webinars for Smashing Members. We've teamed up with active members of the community to run 1:1 interactive sessions with Smashing Members. Overall, we ran 24 Smashing TV webinars on front-end, UX, ethics, performance, accessibility and design workflow. With Marcy Sutton, Val Head, Dan Rose, Ada Rose Cannon, Martin Splitt, Michael Riethmueller, Sara Soueidan, dina Amin, Rachel Andrew and Dan Mall, among others.

The goal of every session is to be highly practical and provide actionable insights and learnings — be it in front-end or in user experience. Everyone can also suggest topics for upcoming webinars in the Membership Slack channel, and we'll invite speakers to cover the topic. Of course, live recordings of these sessions are available as well, and are later released publicly for free for everybody.

Smashing TV: “Smashing Big Bang Redesign” with Vitaly Friedman Design/Tech Courses And Trainings

These days there is always something to do, learn, or wrap your head around these days, and because all of us tend to get lost in small details, video tutorials and courses can be quite helpful. There are of course huge video course platforms which are wonderful, but there are also many fantastic one-man-show-teachers out there in the community who produce courses and tutorials for everybody to learn from.

That's why we've teamed up with some of these teachers to provide community discounts for training and video courses. For example, for a "Debugging" course run by Remy Sharp, or "DevTools Web Performance Course" by Umar Hansa, or "CSS Layouts Course" by Rachel Andrew or "React/ES6" courses by Wes Bos — with many more courses coming up over the next months.

Supporting Community Initiatives

It's not easy to maintain and grow a community, and we are proud to help community initiatives around the world to connect like-minded designers and developers.

Here are the projects we've supported so far:

If you are running a meet-up or a community in your city, we'd be happy to support you as well. Just drop us a line and tell us a bit about your community, and we'll make it happen!

Smashing Book 6: New Frontiers In Web Design

It took us a while, but we are almost there. The brand new Smashing Book 6 is coming out early September, with contributions by Laura Elizabeth, Marcy Sutton, Rachel Andrew, Mike Riethmuller, Harry Roberts, Lyza Gardner, Yoav Weiss, Adrian Zumbrunnen, Greg Nudelman, Ada Rose Cannon, and yours truly.

It explores common pain points and solutions from real-world projects: be it accessibility in times of single-page apps, performance loading patterns, making design systems work in real-life, AR/VR, responsive art-direction, building an advanced service worker and designing for next-gen interfaces. A book packed with practical advice for designers and developers alike, designed and illustrated by Chiara Aliotta.

Smashing Book 6 is coming. Shipping of the book will start late September, but you can already start reading the first chapters if you order your copy today. (Large preview)

The book is being finished as we speak, but we've been slowly releasing chapters, so Members can actually start reading the book already before its official release. All new books and eBooks — as well as upcoming Smashing Print magazine (currently in the works) — is made available for Members free of charge. But that goes without saying, doesn't it?

Smashing Diversity Program

There is a huge amount of discrimination out there, and not everybody is getting a fair chance even though they deserve one. That's why we've launched a Smashing Diversity program, providing conference and workshop tickets for students, non-profits, and people who might not be able to afford a conference ticket or attend a workshop. We also make sure that our conference volunteers can attend the sessions they'd love to see.

Beyond that, please ping us if there is a way we can help you become a better speaker. To support and encourage new voices in the industry, I'll be heading to Paris for Mozilla's Tech Speaker program to provide mentorship, training, and opportunities to up-and-coming speakers from all over the world.

Support New Wave Of Digital Education

Tiego Pedras and Sara Ramos run the New Digital School, a new design education initiative in Porto, Portugal. In fact, they spoke about their project at SmashingConf Freiburg last year. Their goal is to provide students with better front-end and design education to be ready for real-life world.

Each group of students had their own project to work on at The New Digital School. (Image source: Tiago Pedras) (Large preview) Students presented their projects and shared their results with the group. (Image source: Tiago Pedras) (Large preview)

For two years in a row now, I was honored to be able to explore the current state of front-end, interface design, and responsive art-direction with students from all over the world. In February this year, I headed to Porto to spend a week with students from India, Malaysia, Portugal, France and USA for an entire week. Each group of students was working on their own project, ranging from interactive VR storytelling to (hello, Miguel and Sarthak!) to Olympics leaderboards (and hello to you, Prashant and Marissa!).

It might not sound like a big deal, but it was so rewarding to see the sparkle in the eyes of the students as they were working on their projects. Being able to provide an experience that hopefully many students will remember was a huge privilege and a remarkable moment in the entire experience. And it was all possible thanks to the contributions of our Smashing Members. I couldn't be more proud of this effort.

Berlin Design Campus

Late June is usually quite slow, with most projects slowly fading into sleep mode. Well, it was quite the opposite for us. For June, we teamed up with Prjctr Design School (Kyiv, Ukraine) to run Berlin Design Campus — a week-long trip to Berlin to explore digital design agencies and studios with students from Ukraine. It was our first initiative to improve design education by setting up a project of our own.

We visited the offices of Mozilla (thanks, Emanuela and Amin!), SinnerSchrader (thanks, Martin!), EdenSpiekermann (thanks, Daniel!), Hort (thanks, Eike!), Fjord (thanks, Simon and Jake!), Contentful (thanks, Ben!), Matteo Cevucci (previously EdenSpiekermann, Thoughtworks) with hands-on workshops in those companies throughout the week.

We couldn't be more proud to team up with Prjctr Design School from Kiev, Ukraine who are trying change the education landscape in Kiev, Ukraine, and London. Visuals were designed by the Prjctr team as well. (Image source) (Large preview)

We visited both design agencies and larger consultancy firms, spoke with local freelancers, artists and entrepreneurs. We've set up informal evening meetings in which students could ask questions, and we organized visits to offices so students could see how other professionals work. It was a fascinating week with practical insights you would never get otherwise; a look behind the scenes in actual real-life projects with early prototypes that failed and hands-on exercises to work on.

During Berlin Design Campus, we visited a number of offices in Berlin. One of them was Mozilla's office, with a hands-on workshop by Amin al Hazwani. (Image source) (Large preview)

You never get to visit or see how designers in those respected companies work, and what their processes look like. So happy and honored to be a part of this little initiative, and looking forward to more adventures in the future. Again, made possible through contributions of wonderful Smashing Members.

New SmashingConf Experience

With a few more resources available to us, we were able to focus on exploring new formats for Smashing Conferences. Being inspired by our Italian friends from the NoSlidesConf, we tested a brand new format in Toronto earlier this year: interactive live sessions in which speakers were not allowed to use slides (be it Powerpoint, Keynote or Reveal.js). Instead, we encouraged speakers to show how they work, how they design and build, what their setup looks like, and give audience insights into how they think as they make progress in their work.

One of those unforgettable moments. When Gemma O’Brien brought her entire studio to SmashingConf Toronto, a conference where speakers weren’t allowed to use slides. We’ll be rolling out this format at all Smashing events in 2019. (Image credit: Marc Thiele) (Large preview)

Instead of speaking in front of a podium, we set up a coffee shop-alike setting with speakers sitting at the desk and literally walking the audience through their thought process. It was a quite special event. Some speakers felt challenged and excited about the new format, and attendees appreciated the fact that every session was unique and pushed the speakers outside their comfort zones. That's why we'll be rolling out this format for SmashingConf 2019, along with lightning talks, design nights, and a book exchange board. It goes without saying: all Smashing Members are getting a heavy discount on all Smashing Conferences.

Giving Back To The Community

Of course, Smashing Magazine has always been free, but with Rachel Andrew joining us on board last year, we now have a strong and keen Editor-in-Chief focusing on getting the best articles out there every single day. Since then, we've published 87 articles — all thoroughly reviewed and edited by the Smashing Editorial team. We refocus back on the heart of it all — yours truly Smashing Magazine.

We are committed to make the content we get out there accessible to as many people as possible. That goes for our eBooks as well. That's why we also publicly released "Inclusive Design Patterns" eBook by Heydon Pickering (PDF, ePUB, Amazon Kindle), a wonderful book on inclusive design patterns — for free. Why? Because accessibility matters.

We Are Just Getting Started

1,000 is a first major milestone for us. Not many people know it, but the entire Smashing team is actually quite small, with just 13 of us floating from one project to another. Frankly, we might be a bit slow at times, but we are trying our best to bring along a positive change to our industry.

We need less craziness and narrow-mindedness around us, and we need more respect, care, and constructive help. That's the goal we are aiming to provide with the Smashing Membership, with our next projects, and with your help. There might be something in it for you, too. We are in it for a long game. We are, after all, just getting started.

Huge thank you to Cosima Mielke for helping with preparations of this article, and Scott Whitehead for his kind support and work on the Smashing Membership. You are truly smashing!

(cm, sw, il)

With so much happening on the web, what should we really pay attention to? At SmashingConf New York 2018

Categories: Around The Web

What Happens When You Create A Flexbox Flex Container?

Thu, 08/02/2018 - 8:00am
What Happens When You Create A Flexbox Flex Container? What Happens When You Create A Flexbox Flex Container? Rachel Andrew 2018-08-02T14:00:35+02:00 2018-08-21T13:33:03+00:00

In a short series of articles, I’m going to spend some time in detailed unpacking of Flexbox — in the same way I have done in the past with grid. We’ll have a look at the things Flexbox was designed for, what it really does well, and why we might not choose it as a layout method. In this article, we will take a detailed look at what actually happens when you add display: flex to your stylesheet.

A Flex Container, Please!

In order to use Flexbox, you need an element that will be the flex container. In your CSS, you use display: flex:

See the Pen Smashing Flexbox Series 1: display: flex; by Rachel Andrew (@rachelandrew) on CodePen.

Let us spend a little while thinking about what display: flex really means. In the Display Module Level 3, each value of display is described as actually being a combination of two things: an inner display model, and an outer display model. When we add display: flex, we are really defining display: block flex. The outer display type of our flex container is block; it acts like a block level element in normal flow. The inner display type is flex, so items directly inside our container will participate in flex layout.

This is something you might never have really thought about but probably understand anyway. The flex container acts like any other block on your page. If you have a paragraph followed by a flex container, both of these things behave as we have become accustomed to block elements behaving.

Nope, we can't do any magic tricks, but we have articles, books and webinars featuring techniques we all can use to improve our work. Smashing Members get a seasoned selection of magic front-end tricks — e.g. live designing sessions and perf audits, too. Just sayin'! ;-)

Explore Smashing Wizardry →

We can also define our container with a value of inline-flex which is like using display: inline flex, i.e. a flex container that acts like an inline level element, with children that participate in flex layout. The children of our inline flex container behave in the same way that children of our block flex container behave; the difference is how the container itself behaves in the overall layout.

See the Pen Smashing Flexbox Series 1: display: inline-flex; by Rachel Andrew (@rachelandrew) on CodePen.

This concept of elements having an outer display type, which defines how they behave as a box on the page (plus an inner display type) dictating how their children behave is quite useful. You can apply this thinking to any box in CSS. How does this element act? How do the children of this element act? The answers relate to their outer and inner display models.

Rows Or Columns?

Once we have defined our flex container, some initial values come into play. Without our adding any extra properties, the flex items display as a row. This happens because the initial value of the flex-direction property is row. If you don’t set it, you get a row.

The flex-direction property is how we set the direction of the main axis. Other values for flex-direction are:

  • column
  • row-reverse
  • column-reverse

With our items in a row, the items are placed with the first item at the start edge of the inline dimension and display in the order that they appear in the source. In the specification, this edge is described as main-start:

main-start is at the start of the inline dimension (Large preview)

If we use the value column, the items begin to lay out from the start edge of the block dimension and therefore form a column.

main-start is the start of the block dimension (Large preview)

When we use row-reverse, the location of main-start and main-end are switched; therefore, the items lay themselves out one after the other ending up in reverse order.

main-start is at the end of the inline dimension (Large preview)

The value column-reverse does the same thing. It’s important to remember that these values don’t “switch the order of items” although this is what we see happening, they change the place where the flow of items starts: by switching where main-start is. So our items do display in reverse order, but that is because they start laying out at the other end of the container.

It is also important to remember that when this happens, the effect is purely visual. We are asking the items to display themselves starting at the end edge; they are still flowing in the same order and this is the order that your screen reader uses and also the order they can be tabbed through. You should never use row-reverse when what you really want to do is change the order of the items. Make that change in your document source.

The Two Axes Of Flexbox

We have already exposed an important feature of flexbox: the ability to switch the main axis from row to column. This axis switching is why I think that often it is easier to understand things like alignment in Grid Layout first. With Grid, working in two dimensions, you can align on both axes in pretty much the same way. Flexbox is a little trickier because different things happen depending on whether you are working with the main axis, or the cross axis.

We have already encountered the main axis, i.e. the axis that you define as the value of flex-direction. The cross axis is the other dimension. If you have set flex-direction: row, your main axis is along the row, and your cross axis is down the columns. With flex-direction: column, the main axis is down the column and your cross axis along the rows. It is here where we need to explore another important feature of Flexbox, and that is the fact that it is not tied to the physical dimensions of the screen. We don’t talk about a row running from left to right, or a column from top to bottom, because that is not always the case.

Writing Modes

When I described row and column above, I mentioned the block and inline dimensions. This article is written in English, which is a horizontal writing mode. This means that when you ask Flexbox to give you a row, you get a horizontal display of your flex items. In this case, main-start is on the left — the place in which sentences start in English.

If I were working in a right-to-left language such as Arabic, then the start edge would be on the right:

See the Pen Smashing Flexbox Series 1: row with rtl text by Rachel Andrew (@rachelandrew) on CodePen.

The initial values of flexbox mean that if all I do is create a flex container, my items would start on the right and be displayed moving towards the left. The start edge in the inline direction is the place where sentences start in the writing mode you are using.

If you happen to be in a vertical writing mode and ask for a row, your row will run vertically, because that is the way in which rows of text run in a vertical language. You can try this by adding the writing-mode property to your flex container and setting it to the value vertical-lr. Now, when you set flex-direction to row, you get a vertical column of items.

See the Pen Smashing Flexbox Series 1: row with a vertical writing mode by Rachel Andrew (@rachelandrew) on CodePen.

So a row can run horizontally, with a main-start of the left or the right, and also run vertically with main-start at the top. It’s still a flex-direction of row even if our horizontal text accustomed minds find it hard to think of a row running vertically!

To cause the items to lay themselves out in the block dimension, we set the value of flex-direction to column or column-reverse. In English (or in Arabic), we then see the items displaying one on top of the other down the page, starting at the top of the container.

In a Vertical Writing Mode, the Block dimension runs across the page, as this is the direction blocks are laid out in those writing modes. If you ask for a column in vertical-lr, your blocks will run left to right vertically:

See the Pen Smashing Flexbox Series 1: column in vertical-lr writing mode by Rachel Andrew (@rachelandrew) on CodePen.

However, no matter in which direction the blocks are displayed, if you are working with a column then you are working in the block dimension.

Understanding the fact that a row or a column can run in different physical directions is helpful in understanding some of the terminology being used for Grid and Flexbox. We don’t refer to ‘left and right’ or ‘top and bottom’ in Flexbox and Grid because we don’t make any assumption as to the writing mode of our document. All of CSS is becoming more writing mode aware; if you are interested in some other properties and values being implemented to make the rest of CSS behave in this same way, read my article on Logical Properties and Values.

As a summary, remember that:

  • flex-direction: row

    • main axis = inline dimension
    • main-start will be where sentences begin in that writing mode
    • cross axis = block dimension
  • flex-direction: column

    • main axis = block dimension
    • main-start will be where blocks start to lay out in that writing mode
    • cross axis = inline dimension
Initial Alignment

Some other things happen when we apply display: flex. Some initial alignment happens. In a future article in this series, we will take a good look at alignment; however, in our exploration of display: flex, we should look at the initial values that are applied.

Note: It is worth noting that while these alignment properties started life in the Flexbox specification, the Box Alignment specification will ultimately supersede those defined in the Flexbox specification, as explained in the Flexbox specification.

Main-Axis Alignment

The initial value of justify-content is set to flex-start. It is as if our CSS was:

.container { display: flex; justify-content: flex-start; }

This is the reason that our flex items line up at the start edge of the flex container. It’s also the reason why when we set row-reverse they switch to the end edge because that edge then becomes the start of the main axis.

When you see an alignment property which begins with justify-, then it applies to the main axis in Flexbox. So justify-content performs main-axis alignment and aligns our items to the start.

The other possible values for justify-content are:

  • flex-end
  • center
  • space-around
  • space-between
  • space-evenly (added in Box Alignment)

These values deal with the distribution of available space in the flex container. This is why the items are moved around, or spaced out. If you add justify-content: space-between, then any available space is shared out between the items. However, this can only happen if there is free space to start with. If you had a tightly packed flex container (with no extra space after all the items had been laid out), then justify-content would do nothing at all.

You can see this if you switch your flex-direction to column. Without a height on the flex container there is no free space, so setting justify-content: space-between won’t achieve anything. If you add a height and make it so that the container is taller than is required to display the items, then the property has an effect:

See the Pen Smashing Flexbox Series 1: column with a height by Rachel Andrew (@rachelandrew) on CodePen.

Cross-Axis Alignment

Items are also aligned on the cross axis with a single line flex container; the alignment that we are performing is to align the boxes against each other in the line. In the next example, one of our boxes has more content in than all the others. Something is telling the other boxes to stretch to the same height. That something is the align-items property, which has an initial value of stretch:

See the Pen Smashing Guide to Layout: clearfix by Rachel Andrew (@rachelandrew) on CodePen.

When you see an alignment property which begins with align- and you are in flexbox, then you are dealing with cross-axis alignment, and align-items aligns the items within the flex line. The other possible values are:

  • flex-start
  • flex-end
  • center
  • baseline

If you do not want the boxes to all stretch to the height of the tallest, then setting align-items: flex-start will cause them all to align to the start edge of the cross axis.

See the Pen Smashing Flexbox Series 1: align-items: flex-start by Rachel Andrew (@rachelandrew) on CodePen.

Initial Values For The Flex Items

Finally, the flex items themselves also have initial values, they are set to:

  • flex-grow: 0
  • flex-shrink: 1
  • flex-basis: auto

This means that our items will not grow by default to fill the available space on the main axis. If flex-grow were set to a positive value, this would cause the items to grow and take up any available space.

The items can shrink, however, as flex-shrink is set to the positive value of 1. This means that if we have a very narrow flex container, then the items will get as small as they can before any overflow happens. This is sensible behavior; in general, we want things to stay inside their boxes and not overflow if there is space to display them.

In order to get the best possible layout by default, flex-basis is set to auto. We will have a proper look at what that means in a future article in this series, however, most of the time you can think of auto as “big enough to fit the content”. What you will see happen, when you have flex items that fill the container, and one of those items has a larger amount of content than the others, the larger item will be given more space.

See the Pen Smashing Flexbox Series 1: initial values of flex items by Rachel Andrew (@rachelandrew) on CodePen.

This is Flexbox’s flexibility in action. With a flex-basis of auto and no sizing applied to the items, the flex items have a base size of the max-content size. This would be the size they would be if they stretched out and did no wrapping whatsoever. Then, space is taken away from each item in proportion, detailed in the following note in the flexbox specification.

“Note: The flex shrink factor is multiplied by the flex base size when distributing negative space. This distributes negative space in proportion to how much the item is able to shrink, so that e.g. a small item won’t shrink to zero before a larger item has been noticeably reduced.”

The larger item has less space taken away and so we get the final layout. You can compare the two screenshots below, both taken using the example above. However, in the first screenshot, the third box has a smaller amount of content, and therefore our columns have a more equal distribution of space.

The items flex to give the larger item more room (Large preview)

Flexbox here is helping us to end up with a reasonable end result given no other input from the person writing the CSS. Rather than reduce the space evenly and end up with a very tall item with a couple words on each line, it assigns that item more space to lay itself out. Within this kind of behavior is the key to the real use cases for Flexbox. Flexbox is at its best when used to lay sets of things out — along one axis — in a flexible and content aware way. I’m touching on a little of the detail here, but we will take a proper look at these algorithms later in this series.

Summary

In this article, I’ve taken the initial values of Flexbox, in order to explain what actually happens when you say display: flex. It’s a surprising amount once you begin to unpack it, and contained within these few properties are many of the key features of flex layouts.

Flex layouts are flexible: they try to make good choices by default about your content — squishing and stretching to get the best readability. Flex layouts are writing mode aware: the directions of row and column relate to the writing mode being used. Flex layouts allow alignment of the items as a group on the main axis, by choosing how space is distributed. They allow alignment of items within their flex line, moving the items on the cross axis in relationship to each other. Importantly, flex layouts understand how big your content is, and try to make good basic decisions in order to display it. In future articles, we will explore these areas in more depth, and consider further exactly when and why we might choose to use Flexbox.

(il)
Categories: Around The Web

User Experience Psychology And Performance: SmashingConf Videos

Wed, 08/01/2018 - 7:30am
User Experience Psychology And Performance: SmashingConf Videos User Experience Psychology And Performance: SmashingConf Videos The Smashing Editorial 2018-08-01T13:30:35+02:00 2018-08-21T13:33:03+00:00

Today, we’d like to shine a light on two videos from our archives as we explore two very different approaches to User Experience (UX). The first explores how we relate our websites to the needs and situations of our visitors, trying to meet them where they are emotionally. The second is a detailed technical exploration into how we measure and track the data around performance as it relates to user experience.

The second video may seem unrelated to the first video; however, while the collecting and analyzing of data might seem very impersonal, the improvements we can make based on the information makes a real difference to the experience of the people we build our sites to serve.

Designing Powerful User Experiences With Psychology

Recorded at the SmashingConf in San Francisco earlier this year, Joe Leech explains how psychology impacts user experience. Joe explains the frustrations people using our products face, and the things happening in their everyday lives and environment that can make interacting with our websites and applications difficult. He goes on to help us understand how we can design in a way to help these visitors rather than frustrate them.

How’s The UX On The Web, Really?

Once you have created a great user experience, how do you know that it is really working well? Especially in terms of site performance, we can track how people are using our sites and examine that data to see what is really happening.

At the SmashingConf in London, Ilya Grigorik was the Mystery Speaker and spoke about the ways to assess performance in real terms, and benchmark your application against other destinations on the web.

Enjoyed listening to these talks? There are many more SmashingConf videos on Vimeo. We’re also getting ready for the upcoming SmashingConf in New York — see you there? ;-)

With so much happening on the web, what should we really pay attention to? At SmashingConf New York 2018

Categories: Around The Web

Sunshine All Day Every Day (August 2018 Wallpapers Edition)

Tue, 07/31/2018 - 7:11am
Sunshine All Day Every Day (August 2018 Wallpapers Edition) Sunshine All Day Every Day (August 2018 Wallpapers Edition) Cosima Mielke 2018-07-31T13:11:56+02:00 2018-08-21T13:33:03+00:00

Everybody loves a beautiful wallpaper to freshen up their desktops. So to cater for new and unique artworks on a regular basis, we embarked on our monthly wallpapers adventure nine years ago, and since then, countless artists and designers from all over the world have accepted the challenge and submitted their designs to it. It wasn’t any different this time around, of course.

This post features wallpapers created for August 2018. Each of them comes in versions with and without a calendar and can be downloaded for free. A big thank-you to everyone who participated!

Finally, as a little bonus, we also collected some “oldies but goodies” from previous August editions in this collection. Please note, that they only come in a non-calendar version. Which one will make it to your desktop this month?

Please note that:

  • All images can be clicked on and lead to the preview of the wallpaper,
  • 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.
Submit your wallpaper

We are always looking for creative designers and artists to be featured in our wallpapers posts. So if you have an idea for a wallpaper, please don’t hesitate to submit your design. We’d love to see what you’ll come up with. Join in! →

Meet Smashing Book 6 with everything from design systems and accessible single-page apps to CSS Custom Properties, Grid, Service Workers, performance, AR/VR and responsive art direction. New frontiers in front-end and UX with Marcy Sutton, Harry Roberts, Laura Elizabeth and many others.

Table of Contents → Purple Haze

“Meet Lucy: she lives in California, loves summer and sunbathing at the beach. This is our Jimi Hendrix Experience tribute. Have a lovely summer!” — Designed by PopArt Web Design from Serbia.

Coffee Break Time

Designed by Ricardo Gimenes from Sweden.

A Midsummer Night’s Dream

“Inspired by William Shakespeare.” — Designed by Sofie Lee from South Korea.

This August, Be The Best!

“Here is the August monthly calendar to remind you of your as well as your team’s success in the previous months. Congratulations, you guys deserved all the success that came your way. Hope you continue this success this month and in the coming months.” — Designed by Webandcrafts from India.

No Drama LLama

“Llamas are showing up everywhere around us, so why not on our desktops too?” — Designed by Melissa Bogemans from Belgium.

The Colors Of Life

“The countenance of the clown is a reflection of our own feelings and emotions of life in the most colorful way portrayed with a deeper and stronger expression whether it is a happy clown or a sad clown. The actions of the clown signify your uninhibited nature — the faces of life in its crudest form — larger, louder, and in an undiluted way.” — Designed by Acowebs from India.

Hello August

“August brings me to summer, and summer brings me to fruit. In the hot weather there is nothing better than a fresh piece of fruit.” — Designed by Bram Wieringa from Belgium.

Exploring Thoughts

“Thoughts, planning, daydreams are simply what minds do. It’s following the human impulse to explore the unexplored, question what doesn’t ring true, dig beneath the surface of what you think you know to formulate your own reality, and embrace the inherent ‘now’ of life. The main character here has been created blending texture and composition. Thoughts will never have an end.” — Designed by Sweans from London.

Chilling At The Beach

“In August it’s Relaxation Day on the 15th so that’s why I decided to make a wallpaper in which I showcase my perspective of relaxing. It’s a wallpaper where you’re just chilling at the beach with a nice cocktail and just looking at the sea and looking how the waves move. That is what I find relaxing! I might even dip my feet in the water and go for a swim if I’m feeling adventurous!” — Designed by Senne Mommens from Belgium.

Let Peace Reign

“The freedom and independence sprouts from unbiased and educated individuals that build the nation for peace, prosperity and happiness to reign in the country for healthy growth.” — Designed by Admission Zone from India.

On The Ricefields Of Batad

“Somebody once told me that I should make the most out of vacation. So there I was, carefully walking on a stone ridge in the ricefields of Batad. This place is hidden high up in the mountains. Also August is harvesting season.” — Designed by Miguel Lammens from Belgium.

Fantasy

Designed by Ilse van den Boogaart from The Netherlands.

Oldies But Goodies

The past nine years have brought forth lots of inspiring wallpapers, and, well, it’d be a pity to let them gather dust somewhere down in the archives. That’s why we once again dug out some goodies from past August editions that are bound to make a great fit on your desktop still today. Please note that these wallpapers, thus, don’t come with a calendar.

Happiness Happens In August

“Many people find August one of the happiest months of the year because of holidays. You can spend days sunbathing, swimming, birdwatching, listening to their joyful chirping, and indulging in sheer summer bliss. August 8th is also known as the Happiness Happens Day, so make it worthwhile.” — Designed by PopArt Studio from Serbia.

Psst, It’s Camping Time...

“August is one of my favorite months, when the nights are long and deep and crackling fire makes you think of many things at once and nothing at all at the same time. It’s about these heat and cold which allow you to touch the eternity for a few moments.” — Designed by Igor Izhik from Canada.

Bee Happy!

“August means that fall is just around the corner, so I designed this wallpaper to remind everyone to ‘bee happy’ even though summer is almost over. Sweeter things are ahead!” — Designed by Emily Haines from the United States.

Hello Again

“In Melbourne it is the last month of quite a cool winter so we are looking forward to some warmer days to come.” — Designed by Tazi from Australia.

A Bloom Of Jellyfish

“I love going to aquariums – the colours, patterns and array of blue hues attract the nature lover in me while still appeasing my design eye. One of the highlights is always the jellyfish tanks. They usually have some kind of light show in them, which makes the jellyfish fade from an intense magenta to a deep purple – and it literally tickles me pink. On a recent trip to uShaka Marine World, we discovered that the collective noun for jellyfish is a bloom and, well, it was love-at-first-collective-noun all over again. I’ve used some intense colours to warm up your desktop and hopefully transport you into the depths of your own aquarium.” — Designed by Wonderland Collective from South Africa.

Let Us Save The Tigers

“Let us take a pledge to save these endangered species and create a world that is safe for them to live and perish just like all creatures.” — Designed by Acodez IT Solutions from India.

Shades

“It’s sunny outside (at least in the Northern Hemisphere!), so don’t forget your shades!” — Designed by James Mitchell from the United Kingdom.

Ahoy

Designed by Webshift 2.0 from South Africa.

About Everything

“I know what you’ll do this August. :) Because August is about holiday. It’s about exploring, hiking, biking, swimming, partying, feeling and laughing. August is about making awesome memories and enjoying the summer. August is about everything. An amazing August to all of you!” — Designed by Ioana Bitin from Bucharest, Romania.

Shrimp Party

“A nice summer shrimp party!” — Designed by Pedro Rolo from Portugal.

The Ocean Is Waiting

“In August, make sure you swim a lot. Be cautious though.” — Designed by Igor Izhik from Canada.

Oh La La… Paris Night

“I like the Paris night! All is very bright!” — Designed by Verónica Valenzuela from Spain.

World Alpinism Day

“International Day of Alpinism and Climbing.” Designed by cheloveche.ru from Russia.

Estonian Summer Sun

“This is a moment from Southern Estonia that shows amazing summer nights.” Designed by Erkki Pung / Sviiter from Estonia.

Aunt Toula At The Beach

“A memory from my childhood summer vacations.” — Designed by Poppie Papanastasiou from Greece.

Flowing Creativity

Designed by Creacill, Carole Meyer from Luxembourg.

Searching for Higgs Boson

Designed by Vlad Gerasimov from Russia.

Unforgettable Summer Night

Designed by BootstrapDash from India.

Join In Next Month!

Thank you to all designers for their participation. Join in next month!

Categories: Around The Web

What Do You Need To Know When Converting A Flash Game Into HTML5?

Mon, 07/30/2018 - 8:00am
What Do You Need To Know When Converting A Flash Game Into HTML5? What Do You Need To Know When Converting A Flash Game Into HTML5? Tomasz Grajewski 2018-07-30T14:00:26+02:00 2018-08-21T13:33:03+00:00

With the rise of HTML5 usage, many companies start redoing their most popular titles to get rid of outdated Flash and match their products to the latest industry standards. This change is especially visible in the Gambling/Casino & Entertainment industries and has been happening for several years now, so a decent selection of titles has already been converted.

Unfortunately, when browsing the Internet, you can quite often stumble upon examples of a seemingly hasty job, which results in the lover quality of the final product. That's why it's a good idea for game developers to dedicate some of their time for getting familiar with the subject of Flash to HTML5 conversion and learning which mistakes to avoid before getting down to work.

Among the reasons for choosing JavaScript instead of Flash, apart from the obvious technical issues, is also the fact that changing your game design from SWF to JavaScript can yield a better user experience, which in turn give it a modern look. But how to do it? Do you need a dedicated JavaScript game converter to get rid of this outdated technology? Well, Flash to HTML5 conversion can be a piece of cake — here's how to take care of it.

Recommended reading: Principles Of HTML5 Game Design

How To Improve HTML5 Game Experience

Converting a game to another platform is an excellent opportunity to improve it, fix its issues, and increase the audience. Below are few things that can be easily done and are worth considering:

  • Supporting mobile devices
    Converting from Flash to JavaScript allows reaching a broader audience (users of mobile devices); support for touchscreen controls usually needs to be implemented into the game, too. Luckily, both Android and iOS devices now also support WebGL, so 30 or 60 FPS rendering usually can be easily achieved. In many cases, 60 FPS won't cause any problems, which will only improve with time, as mobile devices become more and more performant.

  • Improving performance
    When it comes to comparing ActionScript and JavaScript, the latter is faster than the first one. Other than that, converting a game is a good occasion to revisit algorithms used in game code. With JavaScript game development you can optimize them or completely strip unused code that’s left by original developers.
  • Fixing bugs and making improvements to the gameplay
    Having new developers looking into game’s source code can help to fix known bugs or discover new and very rare ones. This would make playing the game less irritating for the players, which would make them spend more time on your site and encourage to try your other games.
  • Adding web analytics
    In addition to tracking the traffic, web analytics can also be used to gather knowledge on how players behave in a game and where they get stuck during gameplay.
  • Adding localization
    This would increase the audience and is important for kids from other countries playing your game. Or maybe your game is not in English and you want to support that language?

Nope, we can't do any magic tricks, but we have articles, books and webinars featuring techniques we all can use to improve our work. Smashing Members get a seasoned selection of magic front-end tricks — e.g. live designing sessions and perf audits, too. Just sayin'! ;-)

Explore Smashing Wizardry → Why Skipping HTML And CSS For In-Game UI Will Improve Game Performance

When it comes to JavaScript game development, it may be tempting to leverage HTML and CSS for in-game buttons, widgets, and other GUI elements. My advice is to be careful here. It’s counterintuitive, but actually leveraging DOM elements is less performant on complex games and this gains more significance on mobile. If you want to achieve constant 60 FPS on all platforms, then resigning from HTML and CSS may be required.

Non-interactive GUI elements, such as health bars, ammo bars, or score counters can be easily implemented in Phaser by using regular images (the Phaser.Image class), leveraging the .crop property for trimming and the Phaser.Text class for simple text labels.

Such interactive elements as buttons and checkboxes can be implemented by using the built-in Phaser.Button class. Other, more complex elements can be composed of different simple types, like groups, images, buttons and text labels.

Note: Each time you instantiate a Phaser.Text or PIXI.Text object, a new texture is created to render text onto. This additional texture breaks vertex batching, so be careful not to have too many of them.

How To Ensure That Custom Fonts Have Loaded

If you want to render text with a custom vector font (e.g. TTF or OTF), then you need to ensure that the font has already been loaded by the browser before rendering any text. Phaser v2 doesn’t provide a solution for this purpose, but another library can be used: Web Font Loader.

Assuming that you have a font file and include the Web Font Loader in your page, then below is a simple example of how to load a font:

Make a simple CSS file that will be loaded by Web Font Loader (you don’t need to include it in your HTML):

@font-face { // This name you will use in JS font-family: 'Gunplay'; // URL to the font file, can be relative or absolute src: url('../fonts/gunplay.ttf') format('truetype'); font-weight: 400; }

Now define a global variable named WebFontConfig. Something as simple as this will usually suffice:

var WebFontConfig = { 'classes': false, 'timeout': 0, 'active': function() { // The font has successfully loaded... }, 'custom': { 'families': ['Gunplay'], // URL to the previously mentioned CSS 'urls': ['styles/fonts.css'] } };

It the end, remember to put your code in the ‘active’ callback shown above. And that’s it!

How To Make It Easier For Users To Save The Game

To persistently store local data in ActionScript you would use the SharedObject class. In JavaScript, the simple replacement is localStorage API, which allows storing strings for later retrieval, surviving page reloads.

Saving data is very simple:

var progress = 15; localStorage.setItem('myGame.progress', progress);

Note that in the above example the progress variable, which is a number, will be converted to a string.

Loading is simple too, but remember that retrieved values will be strings or null if they don’t exists.

var progress = parseInt(localStorage.getItem('myGame.progress')) || 0;

Here we’re ensuring that the return value is a number. If it doesn’t exist, then 0 will be assigned to the progress variable.

You can also store and retrieve more complex structures, for example, JSON:

var stats = {'goals': 13, 'wins': 7, 'losses': 3, 'draws': 1}; localStorage.setItem('myGame.stats', JSON.stringify(stats)); … var stats = JSON.parse(localStorage.getItem('myGame.stats')) || {};

There are some cases when the localStorage object won’t be available. For example, when using the file:// protocol or when a page is loaded in a private window. You can use the try and catch statement to ensure your code will both continue working and use default values, what is shown in the example below:

try { var progress = localStorage.getItem('myGame.progress'); } catch (exception) { // localStorage not available, use default values }

Another thing to remember is that the stored data is saved per domain, not per URL. So if there is a risk that many games are hosted on a single domain, then it’s better to use a prefix (namespace) when saving. In the example above 'myGame.' is such a prefix and you usually want to replace it with the name of the game.

Note: If your game is embedded in an iframe, then localStorage won’t persist on iOS. In this case, you would need to store data in the parent iframe instead.

How To Leverage Replacing Default Fragment Shader

When Phaser and PixiJS render your sprites, they use a simple internal fragment shader. It doesn’t have many features because it’s tailored for a speed. However, you can replace that shader for your purposes. For example, you can leverage it to inspect overdraw or support more features for rendering.

Below is an example of how to supply your own default fragment shader to Phaser v2:

function preload() { this.load.shader('filename.frag', 'shaders/filename.frag'); } function create() { var renderer = this.renderer; var batch = renderer.spriteBatch; batch.defaultShader = new PIXI.AbstractFilter(this.cache.getShader('filename.frag')); batch.setContext(renderer.gl); }

Note: It’s important to remember that the default shader is used for ALL sprites as well as when rendering to a texture. Also, keep in mind that using complex shaders for all in-game sprites will greatly reduce rendering performance.

How To Change Tinting Method With A Default Shader

Custom default shader can be used to replace default tinting method in Phaser and PixiJS.

Tinting in Phaser and PixiJS works by multiplying texture pixels by a given color. Multiplication always darkens colors, which obviously is not a problem; it's simply different from the Flash tinting. For one of our games, we needed to implement tinting similar to Flash and decided that a custom default shader could be used. Below is an example of such fragment shader:

// Specific tint variant, similar to the Flash tinting that adds // to the color and does not multiply. A negative of a color // must be supplied for this shader to work properly, i.e. set // sprite.tint to 0 to turn whole sprite to white. precision lowp float; varying vec2 vTextureCoord; varying vec4 vColor; uniform sampler2D uSampler; void main(void) { vec4 f = texture2D(uSampler, vTextureCoord); float a = clamp(vColor.a, 0.00001, 1.0); gl_FragColor.rgb = f.rgb * vColor.a + clamp(1.0 - vColor.rgb/a, 0.0, 1.0) * vColor.a * f.a; gl_FragColor.a = f.a * vColor.a; }

This shader lightens pixels by adding a base color to the tint one. For this to work, you need to supply negative of the color you want. Therefore, in order to get white, you need to set:

sprite.tint = 0x000000; // This colors the sprite to white Sprite.tint = 0x00ffff; // This gives red

The result in our game looks like this (notice how tanks flash white when hit):

Custom default shader (tanks flashing white). How To Inspect Overdraw To Detect Fill Rate Issues

Replacing default shader can also be leveraged to help with debugging. Below I've explained how overdraw can be detected with such a shader.

Overdrawing happens when many or all pixels on the screen are rendered multiple times. For example, many objects taking the same place and being rendered one over another. How many pixels a GPU can render per second is described as fill rate. Modern desktop GPUs have excessive fill rate for usual 2D purposes, but mobile ones are a lot slower.

There is a simple method of finding out how many times each pixel on the screen is written by replacing the default global fragment shader in PixiJS and Phaser with this one:

void main(void) { gl_FragColor.rgb += 1.0 / 7.0; }

This shader lightens pixels that are being processed. The number 7.0 indicates how many writes are needed to turn pixel white; you can tune this number to your liking. In other words, lighter pixels on screen were written several times, and white pixels were written at least 7 times.

This shader also helps to find both “invisible” objects that for some reason are still rendered and sprites that have excessive transparent areas around that need to be stripped (GPU still needs to process transparent pixels in your textures).

Overdraw shader in action. (Large preview)

The picture on the left shows how a player sees the game, while the one on the right displays the effect of applying the overdraw shader to the same scene.

Why Physics Engines Are Your Friends

A physics engine is a middleware that's responsible for simulating physics bodies (usually rigid body dynamics) and their collisions. Physics engines simulate 2D or 3D spaces, but not both. A typical physics engine will provide:

  • object movement by setting velocities, accelerations, joints, and motors;
  • detecting collisions between various shape types;
  • calculating collision responses, i.e. how two objects should react when they collide.

At Merixstudio, we’re big fans of the Box2D physics engine and used it on a few occasions. There is a Phaser plugin that works well for this purpose. Box2D is also used in the Unity game engine and GameMaker Studio 2.

While a physics engine will speed-up your development, there is a price you'll have to pay: reduced runtime performance. Detecting collisions and calculating responses is a CPU-intensive task. You may be limited to several dozen dynamic objects in a scene on mobile phones or face degraded performance, as well as reduced frame rate deep below 60 FPS.

Phaser's physics debug overlay. (Large preview)

The left part of the image is a scene from a game, while the right side shows the same scene with Phaser physics debug overlay displayed on top.

How To Export Sounds From A .fla File

If you have a Flash game sound effects inside of a .fla file, then exporting them from GUI is not possible (at least not in Adobe Animate CC 2017) due to the lack of menu option serving this purpose. But there is another solution — a dedicated script that does just that:

function normalizeFilename(name) { // Converts a camelCase name to snake_case name return name.replace(/([A-Z])/g, '_$1').replace(/^_/, '').toLowerCase(); } function displayPath(path) { // Makes the file path more readable return unescape(path).replace('file:///', '').replace('|', ':'); } fl.outputPanel.clear(); if (fl.getDocumentDOM().library.getSelectedItems().length > 0) // Get only selected items var library = fl.getDocumentDOM().library.getSelectedItems(); else // Get all items var library = fl.getDocumentDOM().library.items; // Ask user for the export destination directory var root = fl.browseForFolderURL('Select a folder.'); var errors = 0; for (var i = 0; i < library.length; i++) { var item = library[i]; if (item.itemType !== 'sound') continue; var path = root + '/'; if (item.originalCompressionType === 'RAW') path += normalizeFilename(item.name.split('.')[0]) + '.wav'; else path += normalizeFilename(item.name); var success = item.exportToFile(path); if (!success) errors += 1; fl.trace(displayPath(path) + ': ' + (success ? 'OK' : 'Error')); } fl.trace(errors + ' error(s)');

How to use the script to export sound files:

  1. Save the code above as a .jsfl file on your computer;
  2. Open a .fla file with Adobe Animate;
  3. Select ‘Commands’ → ‘Run Command’ from the top menu and select the script in the dialogue that opens;
  4. Now another dialogue file pops up for selecting export destination directory.

And done! You should now have WAV files in the specified directory. What’s left to do is convert them to, for example, MP3’s, OGG, or AAC.

How To Use MP3s In Flash To HTML5 Convertions

The good old MP3 format is back, as some patents have expired and now every browser can decode and play MP3’s. This makes development a bit easier since finally there's no need to prepare two separate audio formats. Previously you needed, for instance, OGG and AAC files, while now MP3 will suffice.

Nonetheless, there are two important things you need to remember about MP3:

  • MP3’s need to decode after loading, what can be time-consuming, especially on mobile devices. If you see a pause after all your assets have loaded, then it probably means that MP3’s being decoded;
  • gaplessly playing looped MP3’s is a little problematic. The solution is to use mp3loop, about which you can read in the article posted by Compu Phase.
So, Why Should You Convert Flash To JavaScript?

As you can see, Flash to JavaScript conversion is not impossible if you know what to do. With knowledge and skill, you can stop struggling with Flash and enjoy the smooth, entertaining games created in JavaScript. Don't try to fix Flash — get rid of it before everyone is forced to do so!

Want To Learn More?

In this article, I was focused mainly on Phaser v2. However, a newer version of Phaser is now available, and I strongly encourage you to check it out, as it introduced a plethora of fresh, cool features, such as multiple cameras, scenes, tilemaps, or Matter.js physics engine.

If you are brave enough and want to create truly remarkable things in browsers, then WebGL is the right thing to learn from the ground up. It’s a lower level of abstraction than various game-building frameworks or tools but allows to achieve greater performance and quality even if you work on 2D games or demos. Among many websites which you may find useful when learning the basics of WebGL would be WebGL Fundamentals (uses interactive demos). In addition to that, to find out more about WebGL feature adoption rates, check WebGL Stats.

Always remember that there's no such thing as too much knowledge — especially when it comes to game development!

(rb, ra, yk, il)
Categories: Around The Web

Logging Activity With The Web Beacon API

Fri, 07/27/2018 - 7:40am
Logging Activity With The Web Beacon API Logging Activity With The Web Beacon API Drew McLellan 2018-07-27T13:40:14+02:00 2018-08-21T13:33:03+00:00

The Beacon API is a JavaScript-based Web API for sending small amounts of data from the browser to the web server without waiting for a response. In this article, we’ll look at what that can be useful for, what makes it different from familiar techniques like XMLHTTPRequest (‘Ajax’), and how you can get started using it.

If you know why you want to use Beacon already, feel free to jump directly to the Getting Started section.

What Is The Beacon API For?

The Beacon API is used for sending small amounts of data to a server without waiting for a response. That last part is critical and is the key to why Beacon is so useful — our code never even gets to see a response, even if the server sends one. Beacons are specifically for sending data and then forgetting about it. We don’t expect a response and we don’t get a response.

Think of it like a postcard sent home when on vacation. You put a small amount of data on it (a bit of “Wish you were here” and “The weather’s been lovely”), put it in the mailbox, and you don’t expect a response. No one sends a return postcard saying “Yes, I do wish I was there actually, thank you very much!”

For modern websites and applications, there’s a number of use cases that fall very neatly into this pattern of send-and-forget.

Getting the process just right ain't an easy task. That's why we've set up 'this-is-how-I-work'-sessions — with smart cookies sharing what works really well for them. A part of the Smashing Membership, of course.

Explore features → Tracking Stats And Analytics Data

The first use case that comes to mind for most people is analytics. Big solutions like Google Analytics might give a good overview of things like page visits, but what if we wanted something more customized? We could write some JavaScript to track what’s happening in a page (maybe how a user interacts with a component, how far they’ve scrolled to, or which articles have been displayed before they follow a CTA) but we then need to send that data to the server when the user leaves the page. Beacon is perfect for this, as we’re just logging the data and don’t need a response.

There’s no reason we couldn’t also cover the sort of mundane tasks often handled by Google Analytics, reporting on the user themselves and the capability of their device and browser. If the user has a logged in session, you could even tie those stats back to a known individual. Whatever data you gather, you can send it back to the server with Beacon.

Debugging And Logging

Another useful application for this behavior is logging information from your JavaScript code. Imagine you have a complex interactive component on your page that works perfectly for all your tests, but occasionally fails in production. You know it’s failing, but you can’t see the error in order to begin debugging it. If you can detect a failure in the code itself, you could then gather up diagnostics and use Beacon to send it all back for logging.

In fact, any logging task can usefully be performed using Beacon, be that creating save-points in a game, collecting information on feature use, or recording results from a multivariate test. If it’s something that happens in the browser that you want the server to know about, then Beacon is likely a contender.

Can’t We Already Do This?

I know what you’re thinking. None of this is new, is it? We’ve been able to communicate from the browser to the server using XMLHTTPRequest for more than a decade. More recently we also have the Fetch API which does much the same thing with a more modern promise-based interface. Given that, why do we need the Beacon API at all?

The key here is that because we don’t get a response, the browser can queue up the request and send it without blocking execution of any other code. As far as the browser is concerned, it doesn’t matter if our code is still running or not, or where the script execution has got to, as there’s nothing to return it can just background the sending of the HTTP request until it’s convenient to send it.

That might mean waiting until CPU load is lower, or until the network is free, or even just sending it right away if it can. The important thing is that the browser queues the beacon and returns control immediately. It does not hold things up while the beacon sends.

To understand why this is a big deal, we need to look at how and when these sorts of requests are issued from our code. Take our example of an analytics logging script. Our code may be timing how long the users spend on a page, so it becomes critical that the data is sent back to the server at the last possible moment. When the user goes to leave a page, we want to stop timing and send the data back home.

Typically, you’d use either the unload or beforeunload event to execute the logging. These are fired when the user does something like following a link on the page to navigate away. The trouble here is that code running on one of the unload events can block execution and delay the unloading of the page. If unloading of the page is delayed, then the loading next page is also delayed, and so the experience feels really sluggish.

Keep in mind how slow HTTP requests can be. If you’re thinking about performance, typically one of the main factors you try to cut down on is extra HTTP requests because going out to the network and getting a response can be super slow. The very last thing you want to do is put that slowness between the activation of a link and the start of the request for the next page.

Beacon gets around this by queuing the request without blocking, returning control immediately back to your script. The browser then takes care of sending that request in the background without blocking. This makes everything much faster, which makes users happier and lets us all keep our jobs.

Getting Started

So we understand what Beacon is, and why we might use it, so let’s get started with some code. The basics couldn’t be simpler:

let result = navigator.sendBeacon(url, data);

The result is boolean, true if the browser accepted and queued the request, and false if there was a problem in doing so.

Using navigator.sendBeacon()

navigator.sendBeacon takes two parameters. The first is the URL to make the request to. The request is performed as an HTTP POST, sending any data provided in the second parameter.

The data parameter can be in one of several formats, all if which are taken directly from the Fetch API. This can be a Blob, a BufferSource, FormData or URLSearchParams — basically any of the body types used when making a request with Fetch.

I like using FormData for basic key-value data as it’s uncomplicated and easy to read back.

// URL to send the data to let url = '/api/my-endpoint'; // Create a new FormData and add a key/value pair let data = new FormData(); data.append('hello', 'world'); let result = navigator.sendBeacon(url, data); if (result) { console.log('Successfully queued!'); } else { console.log('Failure.'); } Browser Support

Support in browsers for Beacon is very good, with the only notable exceptions being Internet Explorer (works in Edge) and Opera Mini. For most uses, that should be fine, but it’s worth testing for support before trying to use navigator.sendBeacon.

That’s easy to do:

if (navigator.sendBeacon) { // Beacon code } else { // No Beacon. Maybe fall back to XHR? }

If Beacon isn’t available and your request is important, you could fall back to a blocking method such as XHR. Depending on your audience and purpose, you might equally choose to not bother.

An Example: Logging Time On A Page

To see this in practice, let’s create a basic system to time how long a user stays on a page. When the page loads we’ll note the time, and when the user leaves the page we’ll send the start time and current time to the server.

As we only care about time spent (not the actual time of day) we can use performance.now() to get a basic timestamp as the page loads:

let startTime = performance.now();

If we wrap up our logging into a function, we can call it when the page unloads.

let logVisit = function() { // Test that we have support if (!navigator.sendBeacon) return true; // URL to send the data to, e.g. let url = '/api/log-visit'; // Data to send let data = new FormData(); data.append('start', startTime); data.append('end', performance.now()); data.append('url', document.URL); // Let's go! navigator.sendBeacon(url, data); };

Finally, we need to call this function when the user leaves the page. My first instinct was to use the unload event, but Safari on a Mac seems to block the request with a security warning, so beforeunload works just fine for us here.

window.addEventListener('beforeunload', logVisit);

When the page unloads (or, just before it does) our logVisit() function will be called and provided the browser supports the Beacon API our beacon will be sent.

(Note that if there is no Beacon support, we return true and pretend it all worked great. Returning false would cancel the event and stop the page unloading. That would be unfortunate.)

Considerations When Tracking

As so many of the potential uses for Beacon revolve around tracking of activity, I think it would be remiss not to mention the social and legal responsibilities we have as developers when logging and tracking activity that could be tied back to users.

GDPR

We may think of the recent European GDPR laws as they related to email, but of course, the legislation relates to storing any type of personal data. If you know who your users are and can identify their sessions, then you should check what activity you are logging and how it relates to your stated policies.

Often we don’t need to track as much data as our instincts as developers tell us we should. It can be better to deliberately not store information that would identify a user, and then you reduce your likelihood of getting things wrong.

DNT: Do Not Track

In addition to legal requirements, most browsers have a setting to enable the user to express a desire not to be tracked. Do Not Track sends an HTTP header with the request that looks like this:

DNT: 1

If you’re logging data that can track a specific user and the user sends a positive DNT header, then it would be best to follow the user’s wishes and anonymize that data or not track it at all.

In PHP, for example, you can very easily test for this header like so:

if (!empty($_SERVER['HTTP_DNT'])) { // User does not wish to be tracked ... } In Conclusion

The Beacon API is a really useful way to send data from a page back to the server, particularly in a logging context. Browser support is very broad, and it enables you to seamlessly log data without negatively impacting the user’s browsing experience and the performance of your site. The non-blocking nature of the requests means that the performance is much faster than alternatives such as XHR and Fetch.

If you’d like to read more about the Beacon API, the following sites are worth a look.

(ra, il)
Categories: Around The Web

WordPress Notifications Made Easy

Thu, 07/26/2018 - 8:20am
WordPress Notifications Made Easy WordPress Notifications Made Easy Jakub Mikita 2018-07-26T14:20:27+02:00 2018-08-21T06:48:29+00:00

WordPress doesn’t offer any kind of notification system. All you can use is the wp_mail() function, but all of the settings have to be hardcoded, or else you have to create a separate settings screen to allow the user tweak the options. It takes many hours to write a system that is reliable, configurable and easy to use. But not anymore. I’ll show you how to create your own notification system within minutes with the free Notification plugin. By notification, I mean any kind of notification. Most of the time, it will be email, but with the plugin we’ll be using, you can also send webhooks and other kinds of notifications.

While creating a project for one of my clients, I encountered this problem I’ve described. The requirement was to have multiple custom email alerts with configurable content. Instead of hardcoding each and every alert, I decided to build a system. I wanted it to be very flexible, and the aim was to be able to code new scenarios as quickly as possible.

The code I wrote was the start of a great development journey. It turned out that the system I created was flexible enough that it could work as a separate package. This is how the Notification plugin was born.

Suppose you want to send an email about a user profile being updated by one of your website’s members. WordPress doesn’t provide that functionality, but with the Notification plugin, you can create such an email in minutes. Or suppose you want to synchronize your WooCommerce products with third-party software by sending a webhook to a separate URL every time a new product is published. That’s easy to do with the plugin, too.

Lessons Learned While Developing WordPress Plugins

Good plugin development and support lead to more downloads. More downloads mean more money and a better reputation. Learn how you can develop good-quality products with seven golden rules. Read more →

In this article, you’ll learn how to integrate the plugin in your own application and how to create an advanced WordPress notification system more quickly and easily than ever.

In this article, we’ll cover:

  1. how to install the plugin,
  2. the idea behind the plugin and its architecture,
  3. creating a custom scenario for notifications,
  4. creating the action (step 1 of the process),
  5. creating the trigger (step 2 of the process),
  6. creating the custom notification type,
  7. how to enable white-label mode and bundle the plugin in your package.

Getting the process just right ain't an easy task. That's why we've set up 'this-is-how-I-work'-sessions — with smart cookies sharing what works really well for them. A part of the Smashing Membership, of course.

Explore features → Installing The Plugin

To create your own scenarios, you are going to need the Notification plugin. Just install it from the WordPress.org repository in your WordPress dashboard, or download it from the GitHub repository.

Large preview

Later in the article, you’ll learn how to hide this plugin from your clients and make it work as an integrated part of your plugin or theme.

The Idea Of The Plugin

Before going into your code editor, you’ll need to know what the plugin’s architecture looks like. The plugin contains many various components, but its core is really a few abstract classes.

The main components are:

  • The notification
    This could be an email, webhook, push notification or SMS.
  • The trigger
    This is what sends the notification. It’s effectively the WordPress action.
  • The merge tag
    This is a small portion of the dynamic content, like {post_title}.

To give you a better idea of how it all plays together, you can watch this short video:

The core of the Notification plugin is really just an API. All of the default triggers, like Post published and User registered are things built on top of that API.

Because the plugin was created for developers, adding your own triggers is very easy. All that’s required is a WordPress action, which is just a single line of code and a class declaration.

Custom Scenario

Let’s devise a simple scenario. We’ll add a text area and button to the bottom of each post, allowing bugs in the article to be reported. Then, we’ll trigger the notification upon submission of the form.

This scenario was covered in another article, “Submitting Forms Without Reloading the Page: AJAX Implementation in WordPress”.

For simplicity, let’s make it a static form, but there’s no problem putting the action in an AJAX handler, instead of in the wp_mail() function.

Let’s create the form.

The Form add_filter( 'the_content', 'report_a_bug_form' ); function report_a_bug_form( $content ) { // Display the form only on posts. if ( ! is_single() ) { return $content; } // Add the form to the bottom of the content. $content .= '<form action="' . admin_url( 'admin-post.php' ) . '" method="POST"> <input type="hidden" name="post_id" value="' . get_ID() . '"> <input type="hidden" name="action" value="report_a_bug"> <textarea name="message" placeholder="' . __( 'Describe what\'s wrong...', 'reportabug' ) . '"></textarea> <button>' . __( 'Report a bug', 'reportabug' ) . '</button> </div>'; return $content; }

Please note that many components are missing, like WordPress nonces, error-handling and display of the action’s result, but these are not the subject of this article. To better understand how to handle these actions, please read the article mentioned above.

Preparing The Action

To trigger the notification, we are going to need just a single action. This doesn’t have to be a custom action like the one below. You can use any of the actions already registered in WordPress core or another plugin.

The Form Handler And Action add_action( 'admin_post_report_a_bug', 'report_a_bug_handler' ); add_action( 'admin_post_nopriv_report_a_bug', 'report_a_bug_handler' ); function report_a_bug_handler() { do_action( 'report_a_bug', $_POST['post_id'], $_POST['message'] ); // Redirect back to the article. wp_safe_redirect( get_permalink( $_POST['post_id'] ) ); exit; }

You can read more on how to use the admin-post.php file in the WordPress Codex.

This is all we need to create a custom, configurable notification. Let’s create the trigger.

Registering The Custom Trigger

The trigger is just a simple class that extends the abstract trigger. The abstract class does all of the work for you. It puts the trigger in the list, and it handles the notifications and merge tags.

Let’s start with the trigger declaration.

Minimal Trigger Definition class ReportBug extends \BracketSpace\Notification\Abstracts\Trigger { public function __construct() { // Add slug and the title. parent::__construct( 'reportabug', __( 'Bug report sent', 'reportabug' ) ); // Hook to the action. $this->add_action( 'report_a_bug', 10, 2 ); } public function merge_tags() {} }

All you need to do is call the parent constructor and pass the trigger slug and nice name.

Then, we can hook into our custom action. The add_action method is very similar to the add_action() function; so, the second parameter is the priority, and the last one is the number of arguments. Only the callback parameter is missing because the abstract class does that for us.

Having the class, we can register it as our new trigger.

register_trigger( new ReportBug() );

This is now a fully working trigger. You can select it from the list when composing a new notification.

(Large preview)

Although the trigger is working and we can already send the notification we want, it’s not very useful. We don’t have any way to show the recipient which post has a bug and what the message is.

This would be the time, then, to register some merge tags and set up the trigger context with the action parameters we have: the post ID and the message.

To do this, we can add another method to the trigger class. This is the action callback, where we can catch the action arguments.

Handling Action Arguments public function action( $post_ID, $message ) { // If the message is empty, don't send any notifications. if ( empty( $message ) ) { return false; } // Set the trigger properties. $this->post = get_post( $post_ID ); $this->message = $message; }

Note the return false; statement. If you return false from this method, the trigger will be stopped, and no notification will be sent. In our case, we don’t want a notification to be submitted with an empty message. In the real world, you’d want to validate that before the form is sent.

Then, we just set the trigger class’ properties, the complete post object and the message. Now, we can use them to add some merge tags to our trigger. We can just fill the content of the merge_tags method we declared earlier.

Defining Merge Tags public function merge_tags() { $this->add_merge_tag( new \BracketSpace\Notification\Defaults\MergeTag\UrlTag( array( 'slug' => 'post_url', 'name' => __( 'Post URL', 'reportabug' ), 'resolver' => function( $trigger ) { return get_permalink( $trigger->post->ID ); }, ) ) ); $this->add_merge_tag( new \BracketSpace\Notification\Defaults\MergeTag\StringTag( array( 'slug' => 'post_title', 'name' => __( 'Post title', 'reportabug' ), 'resolver' => function( $trigger ) { return $trigger->post->post_title; }, ) ) ); $this->add_merge_tag( new \BracketSpace\Notification\Defaults\MergeTag\HtmlTag( array( 'slug' => 'message', 'name' => __( 'Message', 'reportabug' ), 'resolver' => function( $trigger ) { return nl2br( $trigger->message ); }, ) ) ); $this->add_merge_tag( new \BracketSpace\Notification\Defaults\MergeTag\EmailTag( array( 'slug' => 'post_author_email', 'name' => __( 'Post author email', 'reportabug' ), 'resolver' => function( $trigger ) { $author = get_userdata( $trigger->post->post_author ); return $author->user_email; }, ) ) ); }

This will add four merge tags, all ready to use while a notification is being composed.

The merge tag is an instance of a special class. You can see that there are many types of these tags, and we are using them depending on the value that is returned from the resolver. You can see all merge tags in the GitHub repository.

All merge tags are added via the add_merge_tag method, and they require the config array with three keys:

  • slug
    The static value that will be used in the notification (i.e. {post_url}).
  • name
    The translated label for the merge tag.
  • resolver
    The function that replaces the merge tag with the actual value.

The resolver doesn’t have to be the closure, as in our case, but using it is convenient. You can pass a function name as a string or an array if this is a method in another class.

In the resolver function, only one argument is available: the trigger class instance. Thus, we can access the properties we just set in the action method and return the value we need.

And that’s all! The merge tags are not available to use with our trigger, and we can set up as many notifications of the bug report as we want.

(Large preview) Creating The Custom Notification Type

The Notification plugin offers not only custom triggers, but also custom notification types. The plugin ships with two types, email and webhook, but it has a simple API to register your own notifications.

It works very similarly to the custom trigger: You also need a class and a call to one simple function to register it.

I’m showing only an example; the implementation will vary according to the system you wish to integrate. You might need to include a third-party library and call its API or operate in WordPress’ file system, but the guide below will set you up with the basic process.

Let’s start with a class declaration:

class CustomNotification extends \BracketSpace\Notification\Abstracts\Notification { public function __construct() { // Add slug and the title. parent::__construct( 'custom_notification', __( 'Custom Notification', 'textdomain' ) ); } public function form_fields() {} public function send( \BracketSpace\Notification\Interfaces\Triggerable $trigger ) {} }

In the constructor, you must call the parent’s class constructor and pass the slug and nice name of the notification.

The form_fields method is used to create a configuration form for notifications. (For example, the email notification would have a subject, body, etc.)

The send method is called by the trigger, and it’s where you can call the third-party API that you wish to integrate with.

Next, you have to register it with the register_notification function.

register_trigger( new CustomNotification() ); The Notification Form

There might be a case in which you have a notification with no configuration fields. That’s fine, but most likely you’ll want to give the WordPress administrator a way to configure the notification content with the merge tags.

That’s why we’ll register two fields, the title and the message, in the form_fields method. It looks like this:

public function form_fields() { $this->add_form_field( new \BracketSpace\Notification\Defaults\Field\InputField( array( 'label' => __( 'Title', 'textdomain' ), 'name' => 'title', 'resolvable' => true, 'description' => __( 'You can use merge tags', 'textdomain' ), ) ) ); $this->add_form_field( new \BracketSpace\Notification\Defaults\Field\TextareaField( array( 'label' => __( 'Message', 'textdomain' ), 'name' => 'message', 'resolvable' => true, 'description' => __( 'You can use merge tags', 'textdomain' ), ) ) ); }

As you can see, each field is an object and is registered with the add_form_field method. For the list of all available field types, please visit the GitHub repository.

Each field has the translatable label, the unique name and a set of other properties. You can define whether the field should be resolved with the merge tags with the resolvable key. This means that when someone uses the {post_title} merge tag in this field, it will be changed with the post’s actual title. You can also provide the description field for a better user experience.

At this point, your custom notification type can be used in the plugin’s interface with any available trigger type.

(Large preview) Sending The Custom Notification

In order to make it really work, we have to use the send method in our notification class declaration. This is the place where you can write an API call or use WordPress’ file system or any WordPress API, and do whatever you like with the notification data.

This is how you can access it:

public function send( \BracketSpace\Notification\Interfaces\Triggerable $trigger ) { $title = $this->data['title']; $message = $this->data['message']; // @todo Write the integration here. }

At this point, all of the fields are resolved with the merge tags, which means the variables are ready to be shipped.

That gives you endless possibilities to integrate WordPress with any service, whether it’s your local SMS provider, another WordPress installation or any external API you wish to communicate with.

White Labeling And Bundling The Plugin

It’s not ideal to create a dependency of a plugin that can be easily deactivated and uninstalled. If you are building a system that really requires the Notification plugin to be always available, you can bundle the plugin in your own code.

If you’ve used the Advanced Custom Fields plugin before, then you are probably familiar with the bundling procedure. Just copy the plugin’s files to your plugin or theme, and invoke the plugin manually.

The Notification plugin works very similarly, but invoking the plugin is much simpler than with Advanced Custom Fields.

Just copy the plugin’s files, and require one file to make it work.

require_once( 'path/to/plugin/notification/load.php' );

The plugin will figure out its location and the URLs.

But bundling the plugin might not be enough. Perhaps you need to completely hide that you are using this third-party solution. This is why the Notification plugin comes with a white-label mode, which you can activate at any time.

It also is enabled as a single call to a function:

notification_whitelabel( array( // Admin page hook under which the Notifications will be displayed. 'page_hook' => 'edit.php?post_type=page', // If display extensions page. 'extensions' => false, // If display settings page. 'settings' => false, // Limit settings access to user IDs. // This works only if settings are enabled. 'settings_access' => array( 123, 456 ), ) );

By default, calling this function will hide all of the default triggers.

Using both techniques, white labeling and bundling, will completely hide any references to the plugin’s origin, and the solution will behave as a fully integrated part of your system.

Conclusion

The Notification plugin is an all-in-one solution for any custom WordPress notification system. It’s extremely easy to configure, and it works out of the box. All of the triggers that are registered will work with any notification type, and if you have any advanced requirements, you can save some time by using an existing extension.

If you’d like to learn more details and advanced techniques, go to the documentation website.

I’m always open to new ideas, so if you have any, you can reach out to me here in the comments, via the GitHub issues or on Twitter.

Download the plugin from the repository, and give it a try!

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

How To Improve Test Coverage For Your Android App Using Mockito And Espresso

Wed, 07/25/2018 - 8:00am
How To Improve Test Coverage For Your Android App Using Mockito And Espresso How To Improve Test Coverage For Your Android App Using Mockito And Espresso Vivek Maskara 2018-07-25T14:00:04+02:00 2018-08-20T09:38:12+00:00

In app development, a variety of use cases and interactions come up as one iterates the code. The app might need to fetch data from a server, interact with the device’s sensors, access local storage or render complex user interfaces.

The important thing to consider while writing tests is the units of responsibility that emerge as you design the new feature. The unit test should cover all possible interactions with the unit, including standard interactions and exceptional scenarios.

In this article, we will cover the fundamentals of testing and frameworks such as Mockito and Espresso, which developers can use to write unit tests. I will also briefly discuss how to write testable code. I’ll also explain how to get started with local and instrumented tests in Android.

Recommended reading: How To Set Up An Automated Testing System Using Android Phones (A Case Study)

Fundamentals Of Testing

A typical unit test contains three phases.

  1. First, the unit test initializes a small piece of an application it wants to test.
  2. Then, it applies some stimulus to the system under test, usually by calling a method on it.
  3. Finally, it observes the resulting behavior.

If the observed behavior is consistent with the expectations, the unit test passes; otherwise, it fails, indicating that there is a problem somewhere in the system under test. These three unit test phases are also known as arrange, act and assert, or simply AAA. The app should ideally include three categories of tests: small, medium and large.

  • Small tests comprise unit tests that mock every major component and run quickly in isolation.
  • Medium tests are integration tests that integrate several components and run on emulators or real devices.
  • Large tests are integration and UI tests that run by completing a UI workflow and ensure that the key end-user tasks work as expected.

Note: An instrumentation test is a type of integration test. These are tests that run on an Android device or emulator. These tests have access to instrumentation information, such as the context of the app under test. Use this approach to run unit tests that have Android dependencies that mock objects cannot easily satisfy.

Nope, we can't do any magic tricks, but we have articles, books and webinars featuring techniques we all can use to improve our work. Smashing Members get a seasoned selection of magic front-end tricks — e.g. live designing sessions and perf audits, too. Just sayin'! ;-)

Explore Smashing Wizardry →

Writing small tests allows you to address failures quickly, but it’s difficult to gain confidence that a passing test will allow your app to work. It’s important to have tests from all categories in the app, although the proportion of each category can vary from app to app. A good unit test should be easy to write, readable, reliable and fast.

Here’s a brief introduction to Mockito and Espresso, which make testing Android apps easier.

Mockito

There are various mocking frameworks, but the most popular of them all is Mockito:

Mockito is a mocking framework that tastes really good. It lets you write beautiful tests with a clean & simple API. Mockito doesn’t give you hangover because the tests are very readable and they produce clean verification errors.

Its fluent API separates pre-test preparation from post-test validation. Should the test fail, Mockito makes it clear to see where our expectations differ from reality! The library has everything you need to write complete tests.

Espresso

Espresso helps you write concise, beautiful and reliable Android UI tests.

The code snippet below shows an example of an Espresso test. We will take up the same example later in this tutorial when we talk in detail about instrumentation tests.

@Test public void setUserName() { onView(withId(R.id.name_field)).perform(typeText("Vivek Maskara")); onView(withId(R.id.set_user_name)).perform(click()); onView(withText("Hello Vivek Maskara!")).check(matches(isDisplayed())); }

Espresso tests state expectations, interactions and assertions clearly, without the distraction of boilerplate content, custom infrastructure or messy implementation details getting in the way. Whenever your test invokes onView(), Espresso waits to perform the corresponding UI action or assertion until the synchronization conditions are met, meaning:

  • the message queue is empty,
  • no instances of AsyncTask are currently executing a task,
  • the idling resources are idle.

These checks ensure that the test results are reliable.

Writing Testable Code

Unit testing Android apps is difficult and sometimes impossible. A good design, and only a good design, can make unit testing easier. Here are some of the concepts that are important for writing testable code.

Avoid Mixing Object Graph Construction With Application Logic

In a test, you want to instantiate the class under test and apply some stimulus to the class and assert that the expected behavior was observed. Make sure that the class under test doesn’t instantiate other objects and that those objects do not instantiate more objects and so on. In order to have a testable code base, your application should have two kinds of classes:

  • The factories, which are full of the “new” operators and which are responsible for building the object graph of your application;
  • The application logic classes, which are devoid of the “new” operator and which are responsible for doing the work.
Constructors Should Not Do Any Work

The most common operation you will do in tests is the instantiation of object graphs. So, make it easy on yourself, and make the constructors do no work other than assigning all of the dependencies into the fields. Doing work in the constructor not only will affect the direct tests of the class, but will also affect related tests that try to instantiate your class indirectly.

Avoid Static Methods Wherever Possible

The key to testing is the presence of places where you can divert the normal execution flow. Seams are needed so that you can isolate the unit of test. If you build an application with nothing but static methods, you will have a procedural application. How much a static method will hurt from a testing point of view depends on where it is in your application call graph. A leaf method such as Math.abs() is not a problem because the execution call graph ends there. But if you pick a method in a core of your application logic, then everything behind the method will become hard to test, because there is no way to insert test doubles

Avoid Mixing Of Concerns

A class should be responsible for dealing with just one entity. Inside a class, a method should be responsible for doing just one thing. For example, BusinessService should be responsible just for talking to a Business and not BusinessReceipts. Moreover, a method in BusinessService could be getBusinessProfile, but a method such as createAndGetBusinessProfile would not be ideal for testing. SOLID design principles must be followed for good design:

  • S: single-responsibility principle;
  • O: open-closed principle;
  • L: Liskov substitution principle;
  • I: interface segregation principle;
  • D: dependency inversion principle.

In the next few sections, we will be using examples from a really simple application that I built for this tutorial. The app has an EditText that takes a user name as input and displays the name in a TextView upon the click of a button. Feel free to take the complete source code for the project from GitHub. Here’s a screenshot of the app:

Large preview Writing Local Unit Tests

Unit tests can be run locally on your development machine without a device or an emulator. This testing approach is efficient because it avoids the overhead of having to load the target app and unit test code onto a physical device or emulator every time your test is run. In addition to Mockito, you will also need to configure the testing dependencies for your project to use the standard APIs provided by the JUnit 4 framework.

Setting Up The Development Environment

Start by adding a dependency on JUnit4 in your project. The dependency is of the type testImplementation, which means that the dependencies are only required to compile the test source of the project.

testImplementation 'junit:junit:4.12'

We will also need the Mockito library to make interaction with Android dependencies easier.

testImplementation "org.mockito:mockito-core:$MOCKITO_VERSION"

Make sure to sync the project after adding the dependency. Android Studio should have created the folder structure for unit tests by default. If not, make sure the following directory structure exists:

<Project Dir>/app/src/test/java/com/maskaravivek/testingExamples Creating Your First Unit Test

Suppose you want to test the displayUserName function in the UserService. For the sake of simplicity, the function simply formats the input and returns it back. In a real-world application, it could make a network call to fetch the user profile and return the user’s name.

@Singleton class UserService @Inject constructor(private var context: Context) { fun displayUserName(name: String): String { val userNameFormat = context.getString(R.string.display_user_name) return String.format(Locale.ENGLISH, userNameFormat, name) } }

We will start by creating a UserServiceTest class in our test directory. The UserService class uses Context, which needs to be mocked for the purpose of testing. Mockito provides a @Mock notation for mocking objects, which can be used as follows:

@Mock internal var context: Context? = null

Similarly, you’ll need to mock all dependencies required to construct the instance of the UserService class. Before your test, you’ll need to initialize these mocks and inject them into the UserService class.

  • @InjectMock creates an instance of the class and injects the mocks that are marked with the annotations @Mock into it.
  • MockitoAnnotations.initMocks(this); initializes those fields annotated with Mockito annotations.

Here’s how it can be done:

class UserServiceTest { @Mock internal var context: Context? = null @InjectMocks internal var userService: UserService? = null @Before fun setup() { MockitoAnnotations.initMocks(this) } }

Now you are done setting up your test class. Let’s add a test to this class that verifies the functionality of the displayUserName function. Here’s what the test looks like:

@Test fun displayUserName() { doReturn("Hello %s!").`when`(context)!!.getString(any(Int::class.java)) val displayUserName = userService!!.displayUserName("Test") assertEquals(displayUserName, "Hello Test!") }

The test uses a doReturn().when() statement to provide a response when a context.getString() is invoked. For any input integer, it will return the same result, "Hello %s!". We could have been more specific by making it return this response only for a particular string resource ID, but for the sake of simplicity, we are returning the same response to any input. Finally, here’s what the test class looks like:

class UserServiceTest { @Mock internal var context: Context? = null @InjectMocks internal var userService: UserService? = null @Before fun setup() { MockitoAnnotations.initMocks(this) } @Test fun displayUserName() { doReturn("Hello %s!").`when`(context)!!.getString(any(Int::class.java)) val displayUserName = userService!!.displayUserName("Test") assertEquals(displayUserName, "Hello Test!") } } Running Your Unit Tests

In order to run the unit tests, you need to make sure that Gradle is synchronized. In order to run a test, click on the green play icon in the IDE.

making sure that Gradle is synchronized

When the unit tests are run, successfully or otherwise, you should see this in the “Run” menu at the bottom of the screen:

Large preview

You are done with your first unit test!

Writing Instrumentation Tests

Instrumentation tests are most suited for checking values of UI components when an activity is run. For instance, in the example above, we want to make sure that the TextView shows the correct user name after the Button is clicked. They run on physical devices and emulators and can take advantage of the Android framework APIs and supporting APIs, such as the Android Testing Support Library. We’ll use Espresso to take actions on the main thread, such as button clicks and text changes.

Setting Up The Development Environment

Add a dependency on Espresso:

androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1'

Instrumentation tests are created in an androidTest folder.

<Project Dir>/app/src/androidTest/java/com/maskaravivek/testingExamples

If you want to test a simple activity, create your test class in the same package as your activity.

Creating Your First Instrumentation Test

Let’s start by creating a simple activity that takes a name as input and, on the click of a button, displays the user name. The code for the activity above is quite simple:

class MainActivity : AppCompatActivity() { var button: Button? = null var userNameField: EditText? = null var displayUserName: TextView? = null override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) AndroidInjection.inject(this) setContentView(R.layout.activity_main) initViews() } private fun initViews() { button = this.findViewById(R.id.set_user_name) userNameField = this.findViewById(R.id.name_field) displayUserName = this.findViewById(R.id.display_user_name) this.button!!.setOnClickListener({ displayUserName!!.text = "Hello ${userNameField!!.text}!" }) } }

To create a test for the MainActivity, we will start by creating a MainActivityTest class under the androidTest directory. Add the AndroidJUnit4 annotation to the class to indicate that the tests in this class will use the default Android test runner class.

@RunWith(AndroidJUnit4::class) class MainActivityTest {}

Next, add an ActivityTestRule to the class. This rule provides functional testing of a single activity. For the duration of the test, you will be able to manipulate your activity directly using the reference obtained from getActivity().

@Rule @JvmField var activityActivityTestRule = ActivityTestRule(MainActivity::class.java)

Now that you are done setting up the test class, let’s add a test that verifies that the user name is displayed by clicking the “Set User Name” button.

@Test fun setUserName() { onView(withId(R.id.name_field)).perform(typeText("Vivek Maskara")) onView(withId(R.id.set_user_name)).perform(click()) onView(withText("Hello Vivek Maskara!")).check(matches(isDisplayed())) }

The test above is quite simple to follow. It first simulates some text being typed in the EditText, performs the click action on the button, and then checks whether the correct text is displayed in the TextView.

The final test class looks like this:

@RunWith(AndroidJUnit4::class) class MainActivityTest { @Rule @JvmField var activityActivityTestRule = ActivityTestRule(MainActivity::class.java) @Test fun setUserName() { onView(withId(R.id.name_field)).perform(typeText("Vivek Maskara")) onView(withId(R.id.set_user_name)).perform(click()) onView(withText("Hello Vivek Maskara!")).check(matches(isDisplayed())) } } Running Your Instrumentation Tests

Just like for unit tests, click on the green play button in the IDE to run the test.

Large preview

Upon a click of the play button, the test version of the app will be installed on the emulator or device, and the test will run automatically on it.

Large preview Intrumentation Testing Using Dagger, Mockito, And Espresso

Espresso is one of the most popular UI testing frameworks, with good documentation and community support. Mockito ensures that objects perform the actions that are expected of them. Mockito also works well with dependency-injection libraries such as Dagger. Mocking the dependencies allows us to test a scenario in isolation. Until now, our MainActivity hasn’t used any dependency injection, and, as a result, we were able to write our UI test very easily. To make things a bit more interesting, let’s inject UserService in the MainActivity and use it to get the text to be displayed.

class MainActivity : AppCompatActivity() { var button: Button? = null var userNameField: EditText? = null var displayUserName: TextView? = null @Inject lateinit var userService: UserService override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) AndroidInjection.inject(this) setContentView(R.layout.activity_main) initViews() } private fun initViews() { button = this.findViewById(R.id.set_user_name) userNameField = this.findViewById(R.id.name_field) displayUserName = this.findViewById(R.id.display_user_name) this.button!!.setOnClickListener({ displayUserName!!.text = userService.displayUserName(userNameField!!.text.toString()) }) } }

With Dagger in the picture, we will have to set up a few things before we write instrumentation tests. Imagine that the displayUserName function internally uses some API to fetch the details of the user. There should not be a situation in which a test does not pass due to a server fault. To avoid such a situation, we can use the dependency-injection framework Dagger and, for networking, Retrofit.

Setting Up Dagger In The Application

We will quickly set up the basic modules and components required for Dagger. If you are not familiar with Dagger, check out Google’s documentation on it. We will start adding dependencies for using Dagger in the build.gradle file.

implementation "com.google.dagger:dagger-android:$DAGGER_VERSION" implementation "com.google.dagger:dagger-android-support:$DAGGER_VERSION" implementation "com.google.dagger:dagger:$DAGGER_VERSION" kapt "com.google.dagger:dagger-compiler:$DAGGER_VERSION" kapt "com.google.dagger:dagger-android-processor:$DAGGER_VERSION"

Create a component in the Application class, and add the necessary modules that will be used in our project. We need to inject dependencies in the MainActivity of our app. We will add a @Module for injecting in the activity.

@Module abstract class ActivityBuilder { @ContributesAndroidInjector internal abstract fun bindMainActivity(): MainActivity }

The AppModule class will provide the various dependencies required by the application. For our example, it will just provide an instance of Context and UserService.

@Module open class AppModule(val application: Application) { @Provides @Singleton internal open fun provideContext(): Context { return application } @Provides @Singleton internal open fun provideUserService(context: Context): UserService { return UserService(context) } }

The AppComponent class lets you build the object graph for the application.

@Singleton @Component(modules = [(AndroidSupportInjectionModule::class), (AppModule::class), (ActivityBuilder::class)]) interface AppComponent { @Component.Builder interface Builder { fun appModule(appModule: AppModule): Builder fun build(): AppComponent } fun inject(application: ExamplesApplication) }

Create a method that returns the already built component, and then inject this component into onCreate().

open class ExamplesApplication : Application(), HasActivityInjector { @Inject lateinit var dispatchingActivityInjector: DispatchingAndroidInjector<Activity> override fun onCreate() { super.onCreate() initAppComponent().inject(this) } open fun initAppComponent(): AppComponent { return DaggerAppComponent .builder() .appModule(AppModule(this)) .build() } override fun activityInjector(): DispatchingAndroidInjector<Activity>? { return dispatchingActivityInjector } } Setting Up Dagger In The Test Application

In order to mock responses from the server, we need to create a new Application class that extends the class above.

class TestExamplesApplication : ExamplesApplication() { override fun initAppComponent(): AppComponent { return DaggerAppComponent.builder() .appModule(MockApplicationModule(this)) .build() } @Module private inner class MockApplicationModule internal constructor(application: Application) : AppModule(application) { override fun provideUserService(context: Context): UserService { val mock = Mockito.mock(UserService::class.java) `when`(mock!!.displayUserName("Test")).thenReturn("Hello Test!") return mock } } }

As you can see in the example above, we’ve used Mockito to mock UserService and assume the results. We still need a new runner that will point to the new application class with the overwritten data.

class MockTestRunner : AndroidJUnitRunner() { override fun onCreate(arguments: Bundle) { StrictMode.setThreadPolicy(StrictMode.ThreadPolicy.Builder().permitAll().build()) super.onCreate(arguments) } @Throws(InstantiationException::class, IllegalAccessException::class, ClassNotFoundException::class) override fun newApplication(cl: ClassLoader, className: String, context: Context): Application { return super.newApplication(cl, TestExamplesApplication::class.java.name, context) } }

Next, you need to update the build.gradle file to use the MockTestRunner.

android { ... defaultConfig { ... testInstrumentationRunner ".MockTestRunner" } } Running The Test

All tests with the new TestExamplesApplication and MockTestRunner should be added at androidTest package. This implementation makes the tests fully independent from the server and gives us the ability to manipulate responses. With the setup above in place, our test class won’t change at all. When the test is run, the app will use TestExamplesApplication instead of ExamplesApplication, and, thus, a mocked instance of UserService will be used.

@RunWith(AndroidJUnit4::class) class MainActivityTest { @Rule @JvmField var activityActivityTestRule = ActivityTestRule(MainActivity::class.java) @Test fun setUserName() { onView(withId(R.id.name_field)).perform(typeText("Test")) onView(withId(R.id.set_user_name)).perform(click()) onView(withText("Hello Test!")).check(matches(isDisplayed())) } }

The test will run successfully when you click on the green play button in the IDE.

Large preview

That’s it! You have successfully set up Dagger and run tests using Espresso and Mockito.

Conclusion

We’ve highlighted that the most important aspect of improving code coverage is to write testable code. Frameworks such as Espresso and Mockito provide easy-to-use APIs that make writing tests for various scenarios easier. Tests should be run in isolation, and mocking the dependencies gives us an opportunity to ensure that objects perform the actions that are expected of them.

A variety of Android testing tools are available, and, as the ecosystem matures, the process of setting up a testable environment and writing tests will become easier.

Writing unit tests requires some discipline, concentration and extra effort. By creating and running unit tests against your code, you can easily verify that the logic of individual units is correct. Running unit tests after every build helps you to quickly catch and fix software regressions introduced by code changes to your app. Google’s testing blog discusses the advantages of unit testing. The complete source code for the examples used in this article is available on GitHub. Feel free to take a look at it.

(da, lf, ra, al, il)
Categories: Around The Web

Introducing “The WebP Manual”

Tue, 07/24/2018 - 6:00am
Introducing “The WebP Manual” Introducing “The WebP Manual” Markus Seyfferth 2018-07-24T12:00:00+02:00 2018-08-17T10:16:34+00:00

What’s WebP in the first place? Can we actually use it today? And if yes, how exactly? The role of media in performance, specifically images, is of huge concern. Images are powerful. Engaging visuals evoke visceral feelings. They can provide key information and context to articles, or merely add humorous asides. They do anything for us that plain text just can’t by itself.

But when there’s too much imagery, it can be frustrating for users on slow connections, or run afoul of data plan allowances. In the latter scenario, that can cost users real money. This sort of inadvertent trespass can carry real consequences.

In this eBook, you’ll learn all about WebP: what it’s capable of, how it performs, how to convert images to the format in a variety of ways, and most importantly, how to use it. Of course — the eBook is — and always will be, free for all Smashing Members.

84 pages. Written by Jeremy Wagner. Cover Design by Ricardo Gimenes. Available in PDF, Kindle, and ePub formats.

  • eBook
  • Free for Members
$14.90Get the eBook

PDF, ePUB, Kindle.

$0.00 $14.90 Free for Members →

...along with 12 webinars and 56 other eBooks.

What’s In The eBook

This guide will encourage you to experiment and see what’s possible with WebP:

  • WebP Basics
    WebP images usually use less disk space when compared to other formats at reasonably comparable visual similarity. Depending on your site’s audience and the browsers they use, this is an opportunity to deliver less data-intensive user experiences for a significant segment of your audience.

  • Performance
    We’ll cover how both lossy and lossless WebP compare to JPEGs and PNGs exported by a number of image encoders.

  • Converting Images To WebP (Excerpt)
    This can be done in a myriad of ways, from something as simple as exporting from your preferred design program, by using Cloudinary and similar services, and even in Node.js-based build systems. Here, we’ll cover all avenues.

  • Using WebP Images
    Because WebP isn’t supported in all browsers just yet, you’ll need to learn how to use it that sites and applications gracefully fall back to established formats when WebP support is lacking. Here, we’ll discuss the many ways you can use WebP responsibly, starting by detecting browser support in the Accept request header.

About The Author

Jeremy Wagner is a performance-obsessed front-end developer, author and speaker living and working in the frozen wastes of Saint Paul, Minnesota. He is also the author of Web Performance in Action, a web developer’s companion guide for creating fast websites. You can find him on Twitter @malchata, or read his blog of ramblings.

Here’s Why This eBook Is For You

The WebP Manual will get you ready for the new image format that is capable to significantly less data-intensive user experiences for a majority of your audience:

  • Learn how lossy and lossless WebP compare to JPEGs and PNGs exported by a number of image encoders.
  • Learn which services and plugins you can use to export or convert images to WebP with your preferred design tool or command line tool.
  • Learn how to can use WebP in production, and how to implement proper fallbacks for browsers that don’t support WebP just yet.
  • Learn how to use the full potential of the WebP format. It will substantially improve loading performance for many of your users, customers, and clients, and it will become one of your favorite tools for making websites as lean as possible.

The eBook is free for Smashing Members (you can cancel anytime, of course).

  • eBook
  • Free for Members
$14.90Get the eBook

PDF, ePUB, Kindle.

$0.00 $14.90 Free for Members →

...along with 12 webinars and 56 other eBooks.

Categories: Around The Web

Converting Images To WebP

Tue, 07/24/2018 - 5:00am
Converting Images To WebP Converting Images To WebP Jeremy Wagner 2018-07-24T11:00:30+02:00 2018-08-17T06:23:49+00:00

To use WebP, you’ll first need to convert your existing images to the format. This can be done in a myriad of ways, from something as simple as exporting from your preferred design program, to cloud services, to the official cwebp encoder, and even in Node.js-based build systems. Here, we’ll cover all avenues.

Sketch

Sketch is able to export any resource in a design document to WebP natively. To export an image to WebP, select a resource on the canvas, open the Export panel on the right hand side, and choose “WEBP” in the format dropdown.

The resource export panel in Sketch, with the WebP format chosen in the format dropdown. (Large preview)

After you make your selection, click the Export Bitmap… button. The resulting dialog will predictably ask where you want the image to be exported to. Within that dialog, a slider will appear at the bottom that prompts you to specify the quality of the WebP image from 0 to 100, implying the output is lossy WebP.

The quality slider in the export dialog when exporting a resource to WebP. (Large preview)

If you’re using design software to export to WebP, Sketch is probably one of the easier programs to use. Although, there are other programs capable of doing this, such as Photoshop.

Photoshop

Exporting images to WebP in Photoshop is possible, but is not as convenient as in Sketch. You’ll need to rely on a plug-in to get the job done. The good news, however, is that the Photoshop plug-in does give you a bit more flexibility than Sketch does. To obtain the Photoshop plug-in for exporting WebP images, visit the Telegraphics site and grab the version for your system. Once installed, start Photoshop and open an image. Once opened, you can export an image to WebP through the Save As… dialog. At the bottom of the dialog where you choose a format, you’ll notice two options: WebP, and WebP Lossless.

What happens from here depends on what you choose in the dropdown. If you choose WebP Lossless, the file will be exported, and that will be that. If you choose WebP, however, you’ll be presented with a dialog with several configuration options:

The Photoshop plug-in’s lossy WebP export dialog. (Large preview)

In most cases, you’ll merely adjust the encoding quality, but feel free to experiment with the filtering, denoising, and sharpness options to obtain the desired result. Unfortunately, this plug-in lacks the ability to show a preview of the image before you save it. If you’re accustomed to using the Save for Web tool, this is kind of a bummer, as you’ll have to go at it blind.

Of course, if you’re not a fan of tinkering around in imaging software, the easiest possible option for using WebP might just be to rely on an image optimization CDN. Cloudinary is one such service.

Cloudinary

Using WebP is not a frictionless experience, and the easiest way to use it is to never have to convert to the format on your own in the first place. Some online services can do this work for you, and Cloudinary is one of them.

You only need to upload images to the service. From there, Cloudinary will optimize your images for you. These optimizations are highly customizable, and one such optimization is to automatically serve whatever image format is optimal for your users. If you use Cloudinary to serve your site’s images and your visitors are using WebP-capable browsers, Cloudinary takes on the hassle of serving WebP images for you, provided you choose the proper URL parameters. When you upload an image, Cloudinary’s control panel will provide a URL to your image that looks something like this:

https://res.cloudinary.com/drp9iwjqz/image/upload/v1508291830/jeremywagner.me/using-webp-images/tacos-2x.jpg

Using any number of URL parameters, you can change how Cloudinary serves images to you, including serving WebP images automatically to clients that can best handle them. The parameter that controls this behavior is _fauto, which tells Cloudinary to automatically pick the best format for the client issuing the request. Parameters are added after the /upload/ portion in the URL like so:

https://res.cloudinary.com/drp9iwjqz/image/upload/f_auto/v1508291830/jeremywagner.me/using-webp-images/tacos-2x.jpg

Though Cloudinary preserves the extension, you can tell what the content type of the image is by looking at the image’s Content-Type response header. If you’re using a browser that supports WebP, that header will have a value of image/webp. Of course, Cloudinary is capable of more than simply serving the best format for a given browser. You can combine multiple parameters by separating them with commas. For example, here’s how you could tell Cloudinary to automatically pick the best format and the best quality setting (represented by q_auto):

https://res.cloudinary.com/drp9iwjqz/image/upload/f_auto,q_auto/v1508291830/jeremywagner.me/using-webp-images/tacos-2x.jpg

To learn more about what Cloudinary is capable of, check out their documentation.

While Cloudinary is a convenient tool that does the work of image optimization for you, you may yet feel compelled to encode your own images. And there are plenty of good reasons to do so! Beyond using imaging software, you can accomplish this with perhaps the most flexibility by using the Google’s official WebP command line encoder.

The Official cwebp Command Line Encoder

The official tool for encoding images to the WebP format is Google’s own command line utility. While a command line program may not be as easy to use as a graphical interface, it offers much more flexibility in controlling the output. Most graphical front-ends that export to WebP abstract away features that don’t neatly fit into a dialog, and thus aren’t the best tools for achieving the best result for your site. Before you can use the command line encoder, however, you’ll need to install it.

Installing

Your installation method will depend on your operating system. The easiest way to install the WebP encoder will be through your operating system’s package manager. macOS users can install the encoder and related tools using the Homebrew package manager:

brew install webp

Windows users can install the encoder using Chocolatey:

choco install webp

Users of Red Hat and Red Hat-derived Linux distros such as CentOS or Fedora can use yum to install the encoder:

yum install libwebp-tools

Other platforms may use different package managers (such as apt-get for Debian Linux), but the mere presence of a package manager doesn’t mean it will provide a way to install the encoder. If your operating system package manager somehow fails you, the WebP encoder is available via Node.js’s own package manager (npm):

If none of these options work for you, you can always download the source and compile your own binaries. It’s a bit onerous, but the option is there.

With the encoder installed, let’s take a look at some quick examples of how you can use it.

Simple Command Line Examples

The WebP encoder can be invoked with the cwebp command. For starters, let’s examine what is arguably the most common use case of converting an image to lossy WebP:

cwebp -q 75 source.png -o output.webp

This command takes a PNG and outputs it to lossy WebP by way of the -o parameter. By default, the encoder outputs lossy WebP images, and the quality of the output can be set from 0 to 100 via the -q parameter. The default lossy quality setting is 75.

You may remember reading earlier that WebP is capable of full alpha transparency, even for lossy images. You can control the quality of this transparency in the same fashion via the -alpha_q parameter:

cwebp -q 75 -alpha_q 10 source.png -o output.web

-alpha_q applies lossy compression to the transparency in an image. The default for -alpha_q is 100, which is lossless. You can further reduce output size by lowering this value, which will apply lossy compression to the transparency, but lowering it too much can significantly degrade the quality of transparent regions in the image.

A lossy transparent WebP with best transparency quality (left), and a lossy transparent WebP with low transparency quality (right). Note the loss of fine details at the cloud’s edges. (Large preview)

If you’re conservative in adjusting -alpha_q, you can reduce the size of transparent images even further, but be sure to examine the output to ensure it’s acceptable to you. If you’re automating conversion of images (through a shell script, for example), you might want to shy away from setting this parameter at all. It’s also worth noting that -alpha_q has no effect when encoding lossless WebP images.

We’ve discussed encoding lossy WebP images with cwebp, but what if you want to export to lossless WebP? Just use the -lossless option:

cwebp -lossless source.png -o output.webp

Depending on image content, you may not realize as much of a reduction in output file size when compared to lossy WebP. You can control the aggressiveness of the compression via the -z parameter, though:

cwebp -lossless -z 9 source.png -o output.webp

The -z parameter accepts a value between 0 (no compression) and 9 (most compression). Higher compression yields lower file sizes, but requires more time to encode images. You can also set the -m parameter to influence output size, which specifies a compression method from 0 to 6:

cwebp -lossless -m 6 -z 9 source.png -o output.webp

You can also use the -q parameter to tell cwebp how aggressively to compress the image, which can be slightly confusing because -q means something entirely different for lossless WebP than it does for lossy images For lossless WebP, -q 100 applies the most compression, whereas -q 0 applies the least. You can use -q in tandem with the -m and -z parameters to achieve very high compression, like so:

cwebp -lossless -m 6 -z 9 -q 100 source.png -o output.webp

This level of compression takes by far the longest, but it can go quite a ways further in reducing your lossless image payloads. Experiment to find what works best for you. You might shave off more kilobytes than you thought possible!

Of course, these are just some quick examples of what’s possible. cwebp is an amazingly flexible encoder. To get the full list of available options, type cwebp -longhelp and poke around.

There’s a good chance you’ll need to convert a whole bunch of images at once. Next, I’ll show you a couple ways you can convert multiple files with short commands for Unix-like systems on bash.

Bulk Conversion in Bash

If you’re using Bash on a Unix-like operating system such as macOS or Ubuntu, and you have a directory of images you need to convert to WebP, the find command does an excellent job. As the name would imply, find finds objects in the file system. The syntax for finding files by a specific extension is very straightforward:

find ./ -type f -name '*.png'

In case you’re not familiar with how find works, let’s step through this example command.

  1. The first argument is the file system path to search, which in this case, is the current directory.
  2. The second argument specifies the type of file system object. You can find directories with -type d. We’re finding files in this case, however, which means we’re going with -type f.
  3. Lastly, the -name argument is the pattern by which to find files. In this instance, we’re finding all files ending in .png. When we run this command in a directory tree containing PNG files, the output might look something like this:
./sources/5-1024w.png ./sources/14-768w.png ./sources/old/15-768w.png

This might not seem very useful by itself, but here’s where the magic happens: you can take the files found by find and redirect them as input to any other program you want via the -exec parameter. Here’s how you could use -exec with cwebp to encode all PNGs in a subtree to lossy WebP images at a quality setting of 75:

find ./ -type f -name '*.png' -exec sh -c 'cwebp -q 75 $1 -o "${1%.png}.webp"' _ {} \;

This may look a bit convoluted, but let’s step through what’s going on so we can better understand it together:

  1. The initial part of the command finds all files ending with a .png extension in the current directory (and subdirectories), just as we described earlier.
  2. Files found are sent to the -exec parameter, which invokes an instance of the sh shell. The -c parameter accepts a command to run.
  3. The command invoked is the cwebp encoder. The -q argument is the quality setting.
  4. The $1 placeholder represents the file found by find as an argument passed into sh. The -o "${1%.png}.webp" portion is the output file name. The pattern expressed replaces the .png extension with a .webp extension.
  5. The final part passes the reference to the file found by find (represented by {}) to sh, and the entire command is terminated by \;.

While this is admittedly a bit unwieldy, it’s quite useful when you need to convert a number of images to WebP quickly. When invoking cwebp in this fashion, feel free to adjust parameters as necessary to achieve the desired results. Just be aware this example command dumps the converted images into the same folder as the source images, so adjust as needed to control the location of the output.

The only drawback of this approach is it may take a long time to finish if you’re processing a large number of files, since images are processed one after the other rather than concurrently. If you need to speed up processing a bit, you might consider parallelizing image processing, which we’ll talk about next.

Concurrent Bulk Conversion in Bash

Here’s a potential scenario. You have hundreds, perhaps thousands of images you need to convert to WebP. While cwebp is reasonably fast, it can still take a very long time if you’re not processing images concurrently. Serialized processing doesn’t make the best use of your CPU’s potential like concurrent processing does. To get around this, you can augment the earlier command used for serialized batch conversion with xargs like so:

find ./ -type f -name '*.png' | xargs -P 8 -I {} sh -c 'cwebp -q 75 $1 -o "${1%.png}.webp"' _ {} \;

This isn’t much different than the command from earlier, except with some key differences:

  1. The -exec parameter is notably absent. Instead, the output from find is piped directly to xargs, which handles processing in lieu of -exec.
  2. The xargs command immediately follows the | character with three specific parts. The first is the -P parameter, which specifies the maximum amount of concurrent processes (8 in this example). The second is the -I parameter, which is the input xargs acts on (the value of which is the file found by find, represented by the {} placeholder). The final argument is the command xargs will execute, which is exactly the same as in the serialized bulk conversion command from before.

If you want to increase the amount of concurrent processes, simply change the value you pass to the -P parameter. Unlike other asynchronous approaches, xargs allows you to throttle concurrency to a specified maximum so you don’t render your system unresponsive. While this approach may only shave off a few seconds for small batches of images, it shines when operating on very large ones. For example, when converting a batch of roughly 10,000 JPEGs to WebP, a serialized approach using only find took 21 minutes and 26 seconds, whereas a concurrent approach using both find and xargs took 9 minutes and 8 seconds. This is approximately a 57% decrease in processing time, and with a relatively conservative concurrency of 8 processes at a time. If you can afford to bump up concurrency, you may realize further reductions in processing time.

Of course, these commands aren’t limited to merely converting images to WebP. Whatever shell commands you can think of that will work with find and/or xargs will be just as serviceable. Experiment and see what you can pull off.

If converting images to WebP this way isn’t to your liking, maybe you’d prefer to accomplish the task in JavaScript. Next, we’ll talk about how to convert your images to WebP using Node.js, as well as within the various build systems available in the Node.js ecosystem.

Convert Images to WebP with Node.js

Node.js’s only use isn’t just a JavaScript application stack. Even in environments where JavaScript isn’t used in an application back-end, Node.js still proves useful as a build tool. The tool used for exporting images to WebP in Node.js or any Node.js-based build system is imagemin. Imagemin is a tool that converts and optimizes images of all formats, but it can be extended to support WebP conversion via imagemin-webp. Whether you’re writing scripts to run with Node.js, or using one of many Node.js-based build systems (gulp, et al.), imagemin is the ticket. Let’s get started by demonstrating how you can convert images to WebP in a simple Node.js script.

Using a Node.js Script

Perhaps you’re not the type to reach for an opinionated build system first, and prefer to use Node.js scripts instead. That’s reasonable enough, and if you know how to write JavaScript, the learning curve isn’t very steep, since you don’t need to learn the syntax of a build system. To get started on converting images to WebP in Node.js, install the imagemin and imagemin-webp modules in your project root directory:

npm install imagemin imagemin-webp

This command installs two modules: the first is imagemin itself, and the second is the imagemin-webp plug-in that extends imagemin so it can convert images to WebP. With these two modules installed locally in our project, we can then write a small script that will process JPEG images in a directory and convert them to WebP:

const imagemin = require("imagemin"); const webp = require("imagemin-webp"); imagemin(["sources/*.png"], "images", { use: [ webp({ quality: 75 }) ] }).then(function() { console.log("Images converted!"); });

This short script imports the imagemin and imagemin-webp modules into the current script as two constants (imagemin and webp, respectively). We then run imagemin’s main method, which takes three arguments:

  1. The location of the source images. In this case, we’re converting all files ending in .png in the sources directory, which is assumed to be located in the same directory as the script itself.
  2. The destination directory, which in this case is images. This directory is created if it doesn’t already exist.
  3. An options object for the imagemin program. In this case, we’re specifying the use option, which allows us to pass plug-ins into imagemin. The only plug-in we’re using here is an instance of imagemin-webp (represented by the webp constant). The plug-in itself also accepts a configuration object, which we have used to specify that we want all PNGs converted to lossy WebP (implied, as lossy encoding is the default) with a quality setting of 75.

Imagemin will convert images for us, and when it’s finished, it will return a Promise. In that Promise, we output to the console that all of the images have been converted. If we save this script as webp.js, we can run it with the node command like so:

node webp.js

Assuming everything is successful, a message will appear in the console:

Images converted!

When all is done, WebP images should now exist in the images directory, relative to the location of where you saved webp.js. If you want to tweak the output, you can do so through a variety of options. For example, if you wanted to to generate lossless WebP images, you would instead use the lossless option like so:

webp({ lossless: true })

Just be aware that as stated earlier, the quality setting for lossless mode adjusts the compression. The compression is still lossless, but higher settings will generate smaller files.

Pro tip: the options you can pass to this plug-in are the same, no matter where you invoke the imagemin-webp plug-in, be it in a Node.js script, or the build system of your choice. Speaking of build systems, let’s next cover how you might convert images using gulp.

Using gulp

As far as build systems go, gulp is pretty common. Thanks to a huge ecosystem of plug-ins, gulp can do almost anything you’d need it to, including converting images to WebP! If you have gulp installed and configured for your project, you only need to install a few extra node modules at the command line:

npm install gulp-imagemin imagemin-webp gulp-ext-replace

gulp-imagemin is a plug-in that allows imagemin to interface with gulp. As in the previous example using a plain Node.js script, imagemin-webp is the plug-in that allows imagemin to export images to the WebP format. The final plug-in, gulp-ext-replace, just allows us to change the extension of files output by gulp. By default, gulp outputs files with the same extension as their input source. gulp-ext-replace helps us to overcome this so we can write WebP images to the disk with the proper .webp extension.

Once you have these plug-ins installed, you’d just need to write a quick gulp task that reads source images from the disk and outputs them to WebP format. That task might look something like this:

const gulp = require("gulp"); const imagemin = require("gulp-imagemin"); const webp = require("imagemin-webp"); const extReplace = require("gulp-ext-replace"); gulp.task("exportWebP", function() { let src = "src/images/**/*.png"; // Where your PNGs are coming from. let dest = "dist/images"; // Where your WebPs are going. return gulp.src(src) .pipe(imagemin([ webp({ quality: 75 }) ])) .pipe(extReplace(".webp")) .pipe(gulp.dest(dest)); });

There’s a lot going on here, so let’s break it down:

  1. Like any Node.js-driven program, the first part of the script imports the modules necessary for the script to work.
  2. Using the gulp.task method, we create a task named exportWebP, which starts with two variables: src points to the image files we want to process (PNG files in this example). dest points to the directory where the resulting WebP images will be written to.
  3. The gulp.src method reads the PNG images from the location specified by the src variable.
  4. Images are ferried to imagemin by the gulp.pipe method. The sole argument passed to imagemin is an array of imagemin plug-ins, which in this case is the sole imagemin-webp plug-in. As is the case with using imagemin in any environment, the arguments passed to the imagemin-webp plug-in (or any imagemin plug-in) will follow the same format.
  5. Before we write the converted WebP images to the disk, we want to ensure the resulting files are written with a .webp extension by using the gulp-ext-replace plug-in.
  6. Using gulp’s dest method, we write all the converted images to the location specified earlier by the dist variable.

When everything’s in place, we can invoke gulp on the command line to convert images in the src/images directory like so:

gulp exportWebP

Once the command finishes, your destination directory will contain WebP images you converted from whatever gulp finds in the source directory. That simple!

If you prefer Grunt over gulp, you’re in luck. Next, we’ll show an example of how you can use Grunt to convert images to WebP.

Using Grunt

Much like gulp, Grunt is a task runner, albeit with a different syntax. It can be used for many of the same things gulp is used for, including optimization and conversion of images to different formats via imagemin. Unsurprisingly, it too can convert images to WebP by way of imagemin’s imagemin-webp plug-in. If you have a project currently using Grunt that you would like to modify to generate WebP images, it’s a relatively trivial task. In the directory containing Gruntfile.js, simply install these two modules like so:

npm install grunt-contrib-imagemin imagemin-webp

This command installs the imagemin plug-in for Grunt (provided by grunt-contrib-imagemin), as well as the familiar imagemin-webp plug-in used to convert images to WebP. Once the installation finishes, you’ll need to set up a Grunt task in Gruntfile.js like so:

const grunt = require("grunt"); const webp = require("imagemin-webp"); grunt.initConfig({ imagemin: { dist: { options: { use: [webp({ quality: 75 })] }, files: [{ expand: true, cwd: "src/images/", src: ["**/*.png"], dest: "dist/images", ext: ".webp" }] } } }); grunt.loadNpmTasks("grunt-contrib-imagemin");

Once again, let’s step through this code and find out what’s going on:

  1. Initially, we require the necessary grunt and imagemin-webp modules that we’ll need for the imagemin Grunt task.
  2. In the imagemin task, we create a dist target, which is what we’ll run from the command line. This target contains an options object for Grunt’s imagemin plug-in that allows us to specify configuration options. In this case, we supply an instance of the imagemin-webp plug-in and pass the usual options to it.
  3. The files object is the guts of the operation. cwd specifies which directory we want to work within. src specifies the files within cwd that we want to convert to WebP. dest specifies the directory we want to output the converted images to. Finally, ext specifies that we want the converted images to be saved with a .webp extension.
  4. The last line of code loads the grunt-contrib-imagemin plug-in so we can use it in the Gruntfile.

Once you have this in place, you can convert images to WebP like so:

grunt imagemin:dist

Once this command finishes, images ending in .png in the directory specified in files.cwd will be converted to WebP, and output to the directory specified in files.dest.

Grunt is not quite as intuitive as gulp is, and is falling out of use somewhat. However, it’s still a serviceable choice for a build system, and you may yet encounter it in some situations.

To round out our documentation of how to convert images to WebP within the the Node.js ecosystem, let’s discuss how you might accomplish that same task in webpack.

Using Webpack

If you’re developing modern JavaScript applications, chances are high that webpack is in your midst. In contrast to gulp and Grunt, which style themselves as task runners, webpack is a module bundler that analyzes your code starting from one or more entry points and generates optimized output. While much of what webpack does is accomplished through loaders, it does have a large ecosystem of plug-ins, too. imagemin is represented in that space by imagemin-webpack-plugin.

How webpack works and how to write a config for it are complex subjects, especially if you’re used to using task runners like gulp. I’m going to assume you have at least some familiarity with webpack basics, and just show you how to add imagemin to an existing webpack config to convert images to WebP. Like gulp and Grunt before, you’ll need to use npm to install a few necessary Node.js modules:

npm install imagemin-webpack-plugin imagemin-webp copy-webpack-plugin

Similar to how gulp has its own imagemin plug-in, webpack has one as well, in the form of imagemin-webpack-plugin. And as is the case with all imagemin-related use cases, the imagemin-webp plug-in provides the WebP conversion functionality. The copy-webpack-plugin module is used in this case to help us copy images from a source folder, and tell imagemin to process those images for us. Webpack can be rigged up with loaders (e.g., file-loader) to pipe the files it encounters in its dependency graph to imagemin intelligently, but it may be more expedient to specify a source directory on the disk and let imagemin churn through everything it finds and spit out images to the destination directory. Such code might look something like this:

ImageminWebpackPlugin = require("imagemin-webpack-plugin").default; ImageminWebP = require("imagemin-webp"); CopyWebpackPlugin = require("copy-webpack-plugin"); module.exports = { // Omitted required entry, output, and loader configs for brevity... plugins: [ new CopyWebpackPlugin([{ from: "./src/images/*.png", to: "./images/[name].webp" }]), new ImageminWebpackPlugin({ plugins: [ ImageminWebP({ quality: 75 }) ] }) ] };

As we have with other code examples, let’s step through everything and get a handle on what’s happening:

  1. As noted, the required entry, output, and loader configurations have been omitted for brevity and relevance, as we’re assuming you have some familiarity with webpack.
  2. The plugins config is merely an array of plug-ins we want to use. The first plug-in in the array is an instance of copy-webpack-plugin. To start, we specify in from the files we want to copy from the source directory. In this example, we include all files ending in .png from a specific source directory.
  3. Next, we tell copy-webpack-plugin where we want the optimized images to go in the to option. It’s important to note in this option that we’re using a placeholder of [name] to tell copy-webpack-plugin that we want the name of the output file to be the same as its corresponding source. However, because we’re outputting WebP files, we don’t want to preserve the source file’s extension, so we’re hardcoding the output file’s extension to .webp. It’s also important to remember that files will be written to a location relative to whatever is set in output.path earlier in your webpack config.
  4. The next plug-in in the sequence is an instance of imagemin-webpack-plugin, which should look familiar to other imagemin use cases. Here, we’re simply passing an instance of the imagemin-webp plug-in to the imagemin instance.

Using this configuration, all images ending in .png found in ./src/images will be converted to WebP and output to the images directory relative to your configuration’s output.path directory.

While there are multiple approaches to converting images to WebP within webpack, this aims to be the most straightforward. Compared to other build systems, webpack is an incredibly rich (and at times complex) tool. This example is not meant to be the authoritative approach to generating WebP images within webpack, but rather to show that it’s possible.

Did You Like This Excerpt? Here’s Why This eBook May Be, Just May Be, For You

Categories: Around The Web

Text Editing Tips And Tricks Roundup

Mon, 07/23/2018 - 7:30am
Text Editing Tips And Tricks Roundup Text Editing Tips And Tricks Roundup Rachel Andrew 2018-07-23T13:30:35+02:00 2018-08-15T07:12:01+00:00

We asked the Smashing Community for their favorite text editing tricks, shortcuts, and features that save them time. Here’s a roundup of what we’ve found quite useful along with a couple of other suggestions you may find handy.

Favourite Keyboard Shortcuts

Many of you have favorite keyboard shortcuts. Some of these will be editor or operating system specific, although in many cases you’ll be able to find a similar shortcut with the tools you are using. I’ve rounded up a few from the community below.

Ste Grainer shared a tip about the movement and selection shortcuts:

The basic movement/selection shortcuts that many don’t know about:

Hold Cmd + Arrow Key to move to the beginning/end of a line or top/bottom of a document.

Hold Opt + Arrow Key to move word to word horizontally and block to block vertically.

Shift to select while doing those.

From Jo Frank:

Select all occurences of current selection (Ctrl + SHIFT + L in VSCode) and duplicate line/selection which I set up as Ctrl + D.

Loris Gillet shared a few favorite shortcuts for hopping around or deleting text:

⌥ + forward/back arrows allows to jump to the next word instead of the next letter
⌥ + up/down arrows allows to jump to the beginning/end of the paragraph
⌥ + Backspace deletes the whole word instead of letters by letters.

Many of the suggested tips came from web developers — tips for the editors they used most frequently. We also received suggestions for Android Studio from Maher Nabeel:

In Android Studio:
  • Ctrl + D — Duplicate line
  • Ctrl + Y — Delete line
  • Ctrl + W — Select block
  • Ctrl + O — Override methods
  • Ctrl + ALT + L — Reformat code

Getting workflow just right ain’t an easy task. So are proper estimates. Or alignment among different departments. That’s why we’ve set up “this-is-how-I-work”-sessions — with smart cookies sharing what works well for them. A part of the Smashing Membership, of course.

Explore features → Editor Shortcut Cheatsheets

As we can see from the tips already posted, learning the keyboard shortcuts for your editor saves a lot of time. It is always worth taking a look at what is available for your editor, as learning a few of these shortcuts can save a lot of typing over the course of a day writing code.

On Twitter, Tobin Saunders recommended the Atom Editor Cheat Sheet which is a detailed list of shortcuts for Atom. I also took a look at what was available for other frequently used editors.

Visual Studio Code

The VS Code website has a number of downloadable cheatsheets in PDF format, if you find it useful to keep a cheatsheet printed out on your desk.

Joel Reis noted that if you are switching to VS Code from Sublime Text, Atom, Vim or Visual Studio, then you can download the keymap extensions. This means that you can maintain the keyboard shortcuts from your previous editor. This tip was also noted on Smashing Magazine earlier this year when Burke Holland shared with us some of the things that you might be surprised to find that VS Code can do, in his article “Visual Studio Code Can Do That?

Sublime Text

A good selection of Sublime Text 3 shortcuts for Windows, Mac, and Linux can be found here.

We also have an article here on Smashing Magazine in which Jai Panda shares some of his favorite Sublime Text Tips and Tricks.

Customizing Your Environment

Our keyboards and default computer settings are designed more for typing text than typing code. Some commenters have made changes to their defaults in order to make it faster to type the things they most often need to type.

Alex Semenikhine made this suggestion:

I minimize the number of times I have to hold Shift and press a button. If I make brackets (( )) far more often than I use 9 and 0, I customize the keyboard to reflect that, my 9 is ( and Shift + 9 is 9, etc.

Paul van den Tool sets his ‘Key Repeat’ and ‘Delay Until Repeat’ to their highest setting in order that his cursor just “flies across the screen when using the arrows.”

Jarón Barends told us how he, “created Alt + ; as a shortcut to insert a semicolon at the end of a current line.”

Using Emmet

A number of people mentioned the text expansion system of Emmet. If you hand-code a lot of HTML and CSS then Emmet can save you a great deal of typing time. When writing HTML, Emmet abbreviations will be familiar to anyone who understands CSS. For example, if you want to create an unordered list inside a div element, you could use the following:

div>ul>li

Which would then turn into:

<div> <ul> <li></li> </ul> </div>

The abbreviation is exactly the selector that would select the li in CSS. A div with a ul as a direct child, and a li as a direct child of the ul. Take a look at the Emmet Cheat Sheet for more examples.

Emmet is built into VS Code and is available as a plugin for many other editors.

Use A Clipboard Manager

Erik Verbeek suggests using a clipboard manager so that you can grab copied code from the history. He suggests using ClipMenu for OS X, which sadly seems to be discontinued.

Similar tools include:

Many editors also include a clipboard history for copy and paste actions within the editor. On Twitter, @codevoodoo noted that Webstorm had such a feature. There is a Clipboard History extension for VS Code and a package for Atom; Sublime Text has this built in, as this tutorial on the Sublime Text Clipboard History explains.

A Collection Of Recommended Tools

There were a few specific tools recommended in the comments, so here is a roundup of useful tools you may not have heard of.

Vim

People who like Vim, really really like Vim. It certainly comes with a learning curve, however, if you are very keen on optimizing your keyboard editing then the time invested is likely to be worth it. As Jess Telford points out, you can do things like type 13k to move the cursor 13 lines up.

Take a look at the Vim Cheat Sheet for a list of commands. You can use Vim emulation in many other editors. The key mapping mentioned earlier for VS Code include mappings for Vim, and there is a plugin available for Atom as well.

Prettier

Prettier is an open-source opinionated code formatting tool. Using Prettier ensures that all code is formatted to a consistent style. This is incredibly helpful when working in a team as it means that a consistent style is enforced, without anyone really needing to think about it.

There are downloads available for several editors, in order that you can use Prettier within whichever environment you chose.

AutoHotkey

I had not heard of the tool AutoHotkey until this suggestion from @Hobbesenero. AutoHotkey is an automation scripting language for Windows. Using the scripting language you can create shortcuts for common tasks, for example, to insert a template.

Converting Text Formats With Pandoc

One of my favorite tools is Pandoc. I use Pandoc when I need to convert one text format to another. One of the really useful things Pandoc can do is turn HTML or Markdown into EPUB format. I frequently do this in order to turn a set of notes into a file I can read using iBooks on my iPad. I do this in order to have an easily accessible set of notes for my workshops or to turn lengthy documentation into an easy to read offline format to read on an airplane.

Pandoc can convert from and to many different file formats. In addition to creating quick EPUB files, I also use it to convert copy from Word documents to Markdown or other useful formats. This can be very useful if you get some messy copy from a client that needs to be converted to enter into a CMS.

TextExpander And Typinator

TextExpander is available for MacOS and Windows and is a tool that helps you create snippets which can be inserted using keyboard shortcuts or common abbreviations. TextExpander was recommended by Anders Norén. If you prefer a solution that isn’t a subscription service then you might like to give Typinator a try.

These text expansion tools can be useful outside of writing code. If you often find yourself typing the same information in answer to emails or support requests, creating a shortcut to insert that text can quickly pay dividends in terms of time saved.

Textwasher

Recommended on Facebook by Dennis Germundal, Textwasher is a very simple tool for cleaning any formatting from text.

Add Your Suggestions In The Comments

There are a vast number of ways to enhance productivity in the tools we use every day, and it is also incredibly easy to completely overlook them. I hope that among these suggestions there will be something for you to try out. Or perhaps this will be a prompt for you to dig a little deeper into the documentation for your editors and other tools. I have certainly been inspired to do so.

If you missed the tweet and have some great tips to share, then add them to the comments. We’d love to hear them!

(il)
Categories: Around The Web