How to Create Printer-friendly Pages with CSS

In this article, we review the art of creating printer-friendly web pages with CSS.

“Who prints web pages?” I hear you cry! Relatively few pages will ever be reproduced on paper. But consider:

  • printing travel or concert tickets
  • reproducing route directions or timetables
  • saving a PDF for offline reading
  • accessing information in an area with poor connectivity
  • using data in dangerous or dirty conditions — for example, a kitchen or factory
  • outputting draft content for pen annotations
  • printing web receipts for bookkeeping purposes
  • providing documents to those with disabilities who find it difficult to use a screen
  • printing a page for your colleague who refuses to use this newfangled t’internet nonsense.

The Web and apps can’t cover all situations, but printing pages can be a frustrating experience:

  • text can be too small, too large, or too faint
  • columns can be too narrow or overflow page margins
  • sections are cropped or disappear entirely
  • ink is wasted on unnecessary colored backgrounds and images
  • link URLs can’t be seen
  • advertisements are shown which could never be clicked!

Developers may advocate web accessibility, yet few remember to make the printed web accessible.

Converting responsive, continuous media to paged paper of any size and orientation can be challenging. However, CSS print control has been possible for many years, and a basic stylesheet can be completed within hours. The following sections describe well-supported and practical options for making your pages printer-friendly.

Print Stylesheets

Print CSS can either be:

  1. Applied in addition to screen styling. Taking your screen styles as a base, the printer styles override those defaults as necessary.
  2. Applied as separate styles. The screen and print styles are entirely separate; both start from the browser’s default styles.

The choice will depend on your site/app. Personally, I use screen styles as a print base for most websites. However, I have used separate styles for applications with radically different outputs — for example, a conference session booking system which displayed a timetable grid on-screen but a chronological schedule on paper.

A print stylesheet can be added to the HTML <head> after the standard stylesheet:

<link href="main.css" />
<link media="print" href="print.css" />

The print.css styles will be applied in addition to screen styles when the page is printed.

To separate screen and print media, main.css should target the screen only:

<link media="screen" href="main.css" />
<link media="print" href="print.css" />

Alternatively, print styles can be included within an existing CSS file using @media rules. For example:

/* main.css */
body {
  margin: 2em;
  color: #fff;
  background-color: #000;

/* override styles when printing */
@media print {

  body {
    margin: 0;
    color: #000;
    background-color: #fff;


Any number of @media print rules can be added, so this may be practical for keeping associated styles together. Screen and print rules can also be separated, but it’s a little more cumbersome:

/* main.css */

/* on-screen styles */
@media screen {

  body {
    margin: 2em;
    color: #fff;
    background-color: #000;


/* print styles */
@media print {

  body {
    margin: 0;
    color: #000;
    background-color: #fff;


Testing Printer Output

It’s not necessary to kill trees and use horrendously expensive ink every time you want to test your print layout! The following options replicate print styles on-screen.

Print Preview

The most reliable option is the print preview option in your browser. This shows how page breaks will be handled using your default paper size.

Alternatively, you may be able to save or preview the page by exporting to a PDF.

Developer Tools

The DevTools can emulate print styles, although page breaks won’t be shown.

In Chrome, open the Developer Tools and select More Tools, then Rendering from the three-dot icon menu. Change the Emulate CSS Media to print at the bottom of that panel.

In Firefox, open the Developer Toolbar (Shift + F2) and enter media emulate print. Print emulation doesn’t remain active between page refreshes, but press the up cursor key followed by enter to re-execute the command.

Hack Your Media

Presuming you’re using a <link> tag to load printer CSS, you could temporarily change the media attribute to screen:

<link href="main.css" />
<link media="screen" href="print.css" />

Again, this will not reveal page breaks. Don’t forget to restore the attribute to media="print" once you finish testing.

The post How to Create Printer-friendly Pages with CSS appeared first on SitePoint.

Source: Sitepoint

Best Practices For Mobile Form Design

Best Practices For Mobile Form Design

Best Practices For Mobile Form Design

Nick Babich


(This article is kindly sponsored by Adobe.) Forms are the linchpin of all mobile interactions; it stands between the person and what they’re looking for. Every day, we use forms for essential online activities. Recall the last time you bought a ticket, booked a hotel room or made a purchase online — most probably those interactions contained a step with filling out a form.

Forms are just a means to an end. Users should be able to complete them quickly and without confusion. In this article, you’ll learn practical techniques that will help you design an effective form.

What Makes For An Effective Form

The primary goal with every form is completion. Two factors have a major impact on completion rate:

  • Perception of complexity
    The first thing users do when they see a new form is estimate how much time is required to complete it. Users do this by scanning the form. Perception plays a crucial role in the process of estimation. The more complex a form looks, the more likely users will abandon the process.
  • Interaction cost
    Interaction cost is the sum of efforts — both cognitive and physical — that the users put into interacting with an interface in order to reach their goal. Interaction cost has a direct connection with form usability. The more effort users have to make to complete a form, the less usable the form is. A high interaction cost could be the result of data that is difficult to input, an inability to understand the meaning of some questions, or confusion about error messages.

The Components Of Forms

A typical form has the following five components:

  • Input fields
    These include text fields, password fields, checkboxes, radio buttons, sliders and any other fields designed for user input.
  • Field labels
    These tell users what the corresponding input fields mean.
  • Structure
    This includes the order of fields, the form’s appearance on the page, and the logical connections between different fields.
  • Action buttons
    The form will have at least one call to action (the button that triggers data submission).
  • Feedback
    Feedback notifies the user about the result of an operation. Feedback can be positive (for example, indicating that the form was submitted successfully) or negative (saying something like, “The number you’ve provided is incorrect”).

This article covers many aspects related to structure, input fields, labels, action buttons and validation. Most points mentioned in this article have visual do and don’t examples; all such examples were created using Adobe XD.

Input Fields

When it comes to form design, the most important thing a designer can do is to minimize the need for typing. Reducing input effort is essential. Designers can achieve this goal by focusing on form field design.

Minimize The Total Number Of Fields

Every field you ask users to fill out requires some effort. The more effort is needed to fill out a form, the less likely users will complete the form. That’s why the foundational rule of form design is shorter is better — get rid of all inessential fields.

Baymard Institute analyzed checkout forms and found that a too long or too complicated checkout process is one of the top reasons for abandonment during checkout. The study found that the average checkout contains almost 15 form fields. Most online services could reduce the number of fields displayed by default by 20 to 60%.

Top reasons for abandonment during checkout. (Image: Baymard Institute) (Large preview)

Many designers are familiar with the “less is more” rule; still, they ask additional questions in an attempt to gather more data about their users. It might be tempting to collect more data about your users during the initial signup, but resist that temptation. Think about it this way: With every additional field you add to your form, you increase the chance of losing a prospective user. Is the information you gain from a field worth losing new users? Remember that, as long as you’ve collected a user’s contact information, you can always follow up with a request for more data.

Clearly Distinguish All Optional Fields

Before optimizing optional fields, ask yourself whether you really need to include them in your form. Think about what information you really need, not what you want. Ideally, the number of optional fields in your form should be zero.

If after a brainstorming session, you still want to include a few optional questions in your form, make it clear for users that those fields are optional:

  • Mark optional fields instead of mandatory ones.
    If you ask as little as possible, then the vast majority of fields in your form will be mandatory. Therefore, mark only those fields in the minority. For instance, if five out of six fields are mandatory, then it makes sense to mark only one field as optional.
  • Use the “Optional” label to denote optional fields.
    Avoid using the asterisk (*) to mean “optional.” Not all users will associate the asterisk with optional information, and some users will be confused by the meaning (an asterisk is often used to denote mandatory fields).

Clearly distinguish all optional fields.
Clearly distinguish all optional fields. (Large preview)

Size Fields Accordingly

When possible, use field length as an affordance. The length of an input field should be in proportion to the amount of information expected in the field. The size of the field will act as a visual constraint — the user will know how much text is expected to be entered just by looking at the field. Generally, fields such as ones for area codes and house numbers should be shorter than ones for street addresses.

The size of a field is used as a visual constraint.
The size of a field is used as a visual constraint. (Large preview)

Offer Field Focus

Auto-focus the first input field in your form. Auto-focusing a field gives the user an indication and a starting point, so that they are able to quickly start filling out the form. By doing that, you reduce the interaction cost — saving the user one unnecessary tap.

Make the active input field prominent and focused. The field focus itself should be crystal clear — users should be able to understand at a glance where the focus is. It could be an accented border color or a fade-in of the box.

Amazon puts strong visual focus on the input field.
Amazon puts strong visual focus on the input field. (Large preview)

Don’t Ask Users To Repeat Their Email Address

The reason why an extra field for the email address is so popular among product developers is apparent: Every company wants to minimize the risk of hard bounces (non-deliverables caused by invalid email addresses). Unfortunately, following this approach doesn’t guarantee that you’ll get a valid address. Users often copy and paste their address from one field to another.

Avoid asking users to retype their email address.
Avoid asking users to retype their email address. (Large preview)

Provide “Show Password” Option

Duplicating the password input field is another common mistake among product designers. Designers follow this approach because they believe it will prevent users from mistyping a password. In reality, a second field for a password not only increases interaction cost, but also doesn’t guarantee that users will proceed without mistakes. Because users don’t see what they’ve entered in the field, they can make the same mistake twice (in both fields) and will face a problem when they try to log in using a password. As Jakob Nielsen summarized:

Usability suffers when users type in passwords and the only feedback they get is a row of bullets. Typically, masking passwords doesn’t even increase security, but it does cost you business due to login failures.

Instead of duplicating the password field, provide an option that allows users to view the password they have chosen to create. Have an icon or checkbox that unmasks the password when clicked. A password preview can be an opportunity for users to check their data before sending.

Show password' option
Not being able to see what you’re typing is a huge issue. Providing a ‘Show password’ option next to the password field will help to solve this problem. (Large preview)

Don’t Slice Data Fields

Do not slice fields when asking for a full name, phone number or date of birth. Sliced fields force the user to make additional taps to move to the next field. For fields that require some formatting (such as phone numbers or a date of birth), it’s also better to have a single field paired with clear formatting rules as its placeholder.

“Full name” field
Avoid splitting input fields; don’t make people jump between fields. Instead of asking for a first name and last name in two separate fields, have a single ‘Full name’ field. (Large preview)

Avoid Dropdown Menus

Luke Wroblewski famously said that dropdowns should be the UI of last resort. Dropdowns are especially bad for mobile because collapsed elements make the process of data input harder on a small screen: Placing options in a dropdown requires two taps and hides the options.

If you’re using a dropdown for selection of options, consider replacing it with radio buttons. They will make all options glanceable and also reduce the interaction cost — users can tap on the item and select at once.

(Large preview)

Use Placeholders And Masked Input

Formatting uncertainty is one of the most significant problems of form design. This problem has a direct connection with form abandonment — when users are uncertain of the format in which they should provide data, they can quickly abandon the form. There are a few things you can do to make the format clear.

Placeholder Text

The text in an input field can tell users what content is expected. Placeholder text is not required for simple fields such as “Full name”, but it can be extremely valuable for fields that require data in a specific format. For example, if you design search functionality for tracking a parcel, it would be good to provide a sample tracking number as a placeholder for the tracking-number field.

(Large preview)

It’s vital that your form should have a clear visual distinction between the placeholder text and the actual value entered by the user. In other words, placeholder text shouldn’t look like a preset value. Without clear visual distinction, users might think that the fields with placeholders already have values.

Masked Input

Field masking is a technique that helps users format inputted text. Many designers confuse field masking with placeholder text — they are not the same thing. Unlike placeholders, which are basically static text, masks automatically format the data provided by the user. In the example below, the parentheses, spaces and dashes appear on the screen automatically as a phone number is entered.

Masked input also makes it easy for users to validate information. When a phone number is displayed in chunks, it makes it easier to find and correct a typo.

Masked input for a phone number. (Image: Josh Morony)

Provide Matching Keyboard

Mobile users appreciate apps and websites that provide an appropriate keyboard for the field. This feature prevents them from doing additional actions. For example, when users need to enter a credit card number, your app should only display the dialpad. It’s essential to implement keyboard matching consistently throughout the app (all forms in your app should have this feature).

Set HTML input types to show the correct keypad. Seven input types are relevant to form design:

  • input type="text" displays the mobile device’s normal keyboard.
  • input type="email" displays the normal keyboard and ‘@’ and ‘.com’.
  • input type="tel" displays the numeric 0 to 9 keypad.
  • input type="number" displays a keyboard with numbers and symbols.
  • input type="date" displays the mobile device’s date selector.
  • input type="datetime" displays the mobile device’s date and time selector.
  • input type="month" displays the mobile device’s month and year selector.

When users tap into a field with credit card number, they should see a numerical dialpad — all numbers, no letters. (Large preview)

Use A Slider When Asking For A Specific Range

Many forms ask users to provide a range of values (for example, a price range, distance range, etc.). Instead of using two separate fields, “from” and “to”, for that purpose, use a slider to allow users to specify the range with a thumb interaction.

Sliders are good for touch interfaces because they allow users to specify a range without typing.
Sliders are good for touch interfaces because they allow users to specify a range without typing. (Large preview)

Clearly Explain Why You’re Asking For Sensitive Information

People are increasingly concerned about privacy and information security. When users see a request for information they consider as private, they might think, “Hm, why do they need this?” If your form asks users for sensitive information, make sure to explain why you need it. You can do that by adding support text below relevant fields. As a rule of thumb, the explanation text shouldn’t exceed 100 characters.

A request for a phone number in a booking form might confuse users. Explain why you are asking for it.
A request for a phone number in a booking form might confuse users. Explain why you are asking for it. (Large preview)

Be Careful With Static Defaults

Unlike smart defaults, which are calculated by the system based on the information the system has about users, static defaults are preset values in forms that are the same for all users. Avoid static defaults unless you believe a significant portion of your users (say, 95%) would select those values — particularly for required fields. Why? Because you’re likely to introduce errors — people scan forms quickly, and they won’t spend extra time parsing all of the questions; instead, they’ll simply skip the field, assuming it already has a value.

Protect User Data

Jef Raskin once said, “The system should treat all user input as sacred.” This is absolutely true for forms. It’s great when you start filling in a web form and then accidentally refresh the page but the data remains in the fields. Tools such as Garlic.js help you to persist a form’s values locally until the form is submitted. This way, users won’t lose any precious data if they accidentally close the tab or browser.

Automate Actions

If you want to make the process of data input as smooth as possible, it’s not enough to minimize the number of input fields — you should also pay attention to the user effort required for the data input. Typing has a high interaction cost — it’s error-prone and time-consuming, even with a physical keyboard. But when it comes to mobile screens, it becomes even more critical. More typing increases the user’s chance of making errors. Strive to prevent unnecessary typing, because it will improve user satisfaction and decrease error rates.

Here are a few things you can do to achieve this goal:


Most users experience autocompletion when typing a question in Google’s search box. Google provides users with a list of suggestions related to what the user has typed in the field. The same mechanism can be applied to form design. For example, a form could autocomplete an email address.

This form suggests the email host and saves users from typing a complete address. (Image: GitHub)

Autocapitalizing makes the first letter a capital automatically. This feature is excellent for fields like names and street addresses, but avoid it for password fields.


Autocorrection modifies words that appear to be misspelled. Turn this feature off for unique fields, such as names, addresses, etc.

Auto-filling of personal details

Typing an address is often the most cumbersome part of any online signup form. Make this task easier by using the browser function to fill the field based on previously entered values. According to Google’s research, auto-filling helps people fill out forms 30% faster.

Address prefill. Image: Google

Use The Mobile Device’s Native Features To Simplify Data Input

Modern mobile devices are sophisticated devices that have a ton of amazing capabilities. Designers can use a device’s native features (such as camera or geolocation) to streamline the task of inputting data.

Below are just a few tips on how to make use of sensors and device hardware.

Location Services

It’s possible to preselect the user’s country based on their geolocation data. But sometimes prefilling a full address can be problematic due to accuracy issues. Google’s Places API can help solve this problem. It uses both geolocation and address prefilling to provide accurate suggestions based on the user’s exact location.

Address lookup using Google Places API. (Image: Chromatic HQ) (Large preview)

Using location services, it’s also possible to provide smart defaults. For example, for a “Find a flight” form, it’s possible to prefill the “From” field with the nearest airport to the user based on the user’s geolocation.

Biometric Authorization

The biggest problem of using a text password today is that most people forget passwords. 82% of people can’t remember their passwords, and 5 to 10% of sessions require users to reset a password. Password recovery is a big deal in e-commerce. 75% of users wouldn’t complete a purchase if they had to attempt to recover their password while checking out.

The future of passwords is no passwords. Even today, mobile developers can take advantage of biometric technologies. Users shouldn’t need to type a password; they should be able to use biometric readers for authentication — signing in using a fingerprint or face scanning.

eBay took advantage of the biometrics functionality on smartphones. Users can use their thumbprint to login into their eBay account.
eBay took advantage of the biometrics functionality on smartphones. Users can use their thumbprint to login into their eBay account. (Large preview)

If your form asks users to provide credit card details or information from their driver’s license, it’s possible to simplify the process of data input by using the camera as a scanner. Provide an option to take a photo of the card and fill out all details automatically.

Let users scan their identity card, instead of having to fill out their credit card information manually. (Image: blinkid)

But remember that no matter how good your app fills out the fields, it’s essential to leave them available for editing. Users should be able to modify the fields whenever they want.


Voice-controlled devices, such as Apple HomePod, Google Home and Amazon Echo, are actively encroaching on the market. The number of people who prefer to use voice for common operations has grown significantly. According to ComScore, 50% of all searches will be voice searches by 2020.

How people in the US use smart speakers (according to comScore) (Large preview)

As users get more comfortable and confident using voice commands, they will become an expected feature of mobile interactions. Voice input provides a lot of advantages for mobile users — it’s especially valuable in situations when users can’t focus on a screen, for example, while driving a car.

When designing a form, you can provide voice input as an alternative method of data input.

Google Translate provides an option to enter the text for translation using voice. (Large preview)

Field Labels

Write Clear And Concise Labels

The label is the text that tells users what data is expected from them in a particular input field. Writing clear labels is one of the best ways to make a form more accessible. Labels should help the user understand what information is required at a glance.

Avoid using complete sentences to explain. A label is not help text. Write succinct and crisp labels (a word or two), so that users can quickly scan your form.

Place The Label And Input Close Together

Put each label close to the input field, because the eye will visually know they’re tied together.

A label and its field should be visually grouped, so that users can understand which label belongs to which field.
A label and its field should be visually grouped, so that users can understand which label belongs to which field. (Large preview)

Don’t Use Disappearing Placeholder Text As Labels

While inline labels look good and save valuable screen estate, these benefits are far outweighed by the significant usability drawbacks, the most critical of which is the loss of context. When users start entering text in a field, the placeholder text disappears and forces people to recall this information. While it might not be a problem for simple two-field forms, it could be a big deal for forms that have a lot of fields (say, 7 to 10). It would be tough for users to recall all field labels after inputting data. Not surprisingly, user testing continually shows that placeholders in form fields often hurt usability more than help.

Don’t use placeholder text that disappears when the user interacts with the field.
Don’t use placeholder text that disappears when the user interacts with the field. (Large preview)

There’s a simple solution to the problem of disappearing placeholders: the floating (or adaptive) label. After the user taps on the field with the label placeholder, the label doesn’t disappear, it moves up to the top of the field and makes room for the user to enter their data.

Floating labels assure the user that they’ve filled out the fields correctly. (Image: Matt D. Smith)

Top-Align Labels

Putting field labels above the fields in a form improves the way users scan the form. Using eye-tracking technology for this, Google showed that users need fewer fixations, less fixation time and fewer saccades before submitting a form.

Another important advantage of top-aligned labels is that they provide more space for labels. Long labels and localized versions will fit more easily in the layout. The latter is especially suitable for small mobile screens. You can have form fields extend the full width of the screen, making them large enough to display the user’s entire input.

(Large preview)

Sentence Case Vs. Title Case

There are two general ways to capitalize words:

  • Title case: Capitalize every word. “This Is Title Case.”
  • Sentence case: Capitalize the first word. “This is sentence case.”

Using sentence case for labels has one advantage over title case: It is slightly easier (and, thus, faster) to read. While the difference for short labels is negligible (there’s not much difference between “Full Name” and “Full name”), for longer labels, sentence case is better. Now You Know How Difficult It Is to Read Long Text in Title Case.

Avoid Using Caps For Labels

All-caps text  —  meaning text with all of the letters cap­i­tal­ized  —  is OK in contexts that don’t involve substantive reading (such as acronyms and logos), but avoid all caps otherwise. As mentioned by Miles Tinker in his work Legibility of Print, all-capital print dramatically slows the speed of scanning and reading compared to lowercase type.

All-capitalized letters
All-capitalized letters are hard to scan and read. (Large preview)


You know by now that users scan web pages, rather than read them. The same goes for filling out forms. That’s why designers should design a form that is easy to scan. Allowing for efficient, effective scanning is crucial to making the process of the filling out a form as quick as possible.

Use A Single-Column Layout

A study by CXL Institute found that single-column forms are faster to complete than multi-column forms. In that study, test participants were able to complete a single-column form an average of 15.4 seconds faster than a multi-column form.

Multiple columns disrupt a user’s vertical momentum; with multiple columns, the eyes start zigzagging. This dramatically increases the number of eye fixations and, as a result, the completion time. Moreover, multiple-column forms might raise unnecessary questions in the user, like “Where should I begin?” and “Are questions in the right column equal in importance to questions in the left one?”

In a one-column design, the eyes move in a natural direction, from top to bottom, one line at a time. This helps to set a clear path for the user. One column is excellent for mobile because the screens are longer vertically, and vertical scrolling is a natural motion for mobile users.

There are some exceptions to this rule. It’s possible to place short and logically related fields on the same row (such as for the city and area code).

If a form has horizontally adjacent fields, the user has to scan the form following a Z pattern. When the eyes start zigzagging, it slows the speed of comprehension and increases completion time. (Large preview)

(Large preview)

Create A Flow With Your Questions

The way you ask questions also matters. Questions should be asked logically from the user’s perspective, not according to the application or database’s logic, because it will help to create a sense of conversation with the user. For example, if you design a checkout form and asks for details such as full name, phone number and credit card, the first question should be for the full name. Changing the order (for example, starting with a phone number instead of a name) leads to discomfort. In real-world conversations, it would be unusual to ask for someone’s phone number before asking their name.

Defer In-Depth Questions To The End

When it comes to designing a flow for questions you want to ask, think about prioritization. Follow the rule “easy before difficult” and place in-depth or personal questions last. This eases users into the process; they will be more likely to answer complex and more intrusive questions once they’ve established a rapport. This has a scientific basis: Robert Cialdini’s principle of consistency stipulates that when someone takes a small action or step towards something, they feel more compelled to finish.

Group Related Fields Together

One of the principles of Gestalt psychology, the principle of proximity, states that related elements should be near each other. This principle can be applied to the order of questions in a form. The more related questions are, the closer they should be to each other.

Designers can group related fields into sections. If your form has more than six questions, group related questions into logical sections. Don’t forget to provide a good amount of white space between sections to distinguish them visually.

Generally, if your form has more than six questions, it’s better to group related questions into logical sections. Put things together that make sense together. (Large preview)

Make A Long Form Look Simpler

How do you design a form that asks users a lot of questions? Of course, you could put all of the questions on one screen. But this hinder your completion rate. If users don’t have enough motivation to complete a form, the form’s complexity could scare them away. The first impression plays a vital role. Generally, the longer or more complicated a form seems, the less likely users will be to start filling in the blanks.

Minimize the number of fields visible at one time. This creates the perception that the form is shorter than it really is.

There are two techniques to do this.

Progressive Disclosure

Progressive disclosure is all about giving users the right thing at the right time. The goal is to find the right stuff to put on the small screen at the right time:

  • Initially, show users only a few of the most important options.
  • Reveal parts of your form as the user interacts with it.
Using progressive disclosure to reduce cognitive load and keep the user focused on a task. (Image: Ramotion)

Chunking entails breaking a long form into steps. It’s possible to increase the completion rate by splitting a form into a few steps. Chunking can also help users process, understand and remember information. When designing multi-step forms, always inform users of their progress with a completeness meter.

Progress tracker for e-commerce form. (Image: Murat Mutlu) (Large preview)

Designers can use either a progress tracker (as shown in the example above) or a “Step # out of #” indicator both to tell how many steps there are total and to show how far along the user is at the moment. The latter approach could be great for mobile forms because step indication doesn’t take up much space.

Action Buttons

A button is an interactive element that direct users to take an action.

Make Action Buttons Descriptive

A button’s label should explain what the button does; users should be able to understand what happens after a tap just by looking at the button. Avoid generic labels such as “Submit” and “Send”, using instead labels that describe the action.

Label should help users finish the sentence, ‘I want to…’ For example, if it’s a form to create an account, the call to action could be ‘Create an account’. (Large preview)

Don’t Use Clear Or Reset Buttons

Clear or reset buttons allow users to erase their data in a form. These buttons almost never help users and often hurt them. The risk of deleting all of the information a user has entered outweighs the small benefit of having to start again. If a user fills in a form and accidentally hits the wrong button, there’s a good chance they won’t start over.

Use Different Styles For Primary And Secondary Buttons

Avoid secondary actions if possible. But if your form has two calls to action (for example, an e-commerce form that has “Apply discount” and “Submit order”) buttons, ensure a clear visual distinction between the primary and secondary actions. Visually prioritize the primary action by adding more visual weight to the button. This will prevent users from tapping on the wrong button.

Ensure a clear visual distinction between primary and secondary buttons. (Large preview)

Design Finger-Friendly Touch Targets

Tiny touch targets create a horrible user experience because they make it challenging for users to interact with interactive objects. It’s vital to design finger-friendly touch targets: bigger input fields and buttons.

The image below shows that the width of the average adult finger is about 11 mm.

People often blame themselves for having “fat fingers”. But even baby fingers are wider than most touch targets. (Image: Microsoft) (Large preview)

According to material design guidelines, touch targets should be at least 48 × 48 DP. A touch target of this size results in a physical size of about 9 mm, regardless of screen size. It might be appropriate to use larger touch targets to accommodate a wider spectrum of users.

Not only is target size important, but sufficient space between touch targets matters, too. The main reason to maintain a safe distance between touch targets is to prevent users from touching the wrong button and invoking the wrong action. The distance between buttons becomes extremely important when binary choices such as “Agree” and “Disagree” are located right next to each other. Material design guidelines recommend separating touch targets with 8 DP of space or more, which will create balanced information density and usability.

(Large preview)

Disable Buttons After Tap

Forms actions commonly require some time to be processed. For example, data calculation might be required after a submission. It’s essential not only to provide feedback when an action is in progress, but also to disable the submit button to prevent users from accidentally tapping the button again. This is especially important for e-commerce websites and apps. By disabling the button, you not only prevent duplicate submissions, which can happen by accident, but you also provide a valuable acknowledgment to users (users will know that the system has received their submission).

This form disables the button after submission. (Image: Michaël Villar)

Assistance And Support

Provide Success State

Upon successful completion of a form, it’s critical to notify users about that. It’s possible to provide this information in the context of an existing form (for example, showing a green checkmark above the refreshed form) or to direct users to a new page that communicates that their submission has been successful.

Example of success state. (Image: João Oliveira Simões)

Errors And Validation

Users will make mistakes. It’s inevitable. It’s essential to design a user interface that supports users in those moments of failures.

While the topic of errors and validation deserves its own article, it’s still worth mentioning a few things that should be done to improve the user experience of mobile forms.

Use Input Constraints for Each Field

Prevention is better than a cure. If you’re a seasoned designer, you should be familiar with the most common cases that can lead to an error state (error-prone conditions). For example, it’s usually hard to correctly fill out a form on the first attempt, or to properly sync data when the mobile device has a poor network connection. Take these cases into account to minimize the possibility of errors. In other words, it’s better to prevent users from making errors in the first place by utilizing constraints and offering suggestions.

For instance, if you design a form that allows people to search for a hotel reservation, you should prevent users from selecting check-in dates that are in the past. As shown in the example below, you can simply use a date selector that allows users only to choose today’s date or a date in the future. Such a selector would force users to pick a date range that fits.

You can significantly decrease the number of mistakes or incorrectly inputted data by putting constraints on what can be inputted in the field. The date picker in’s app displays a full monthly calendar but makes past dates unavailable for selection. (Large preview)
Don’t Make Data Validation Rules Too Strict

While there might be cases where it’s essential to use strict validation rules, in most cases, strict validation is a sign of lazy programming. Showing errors on the screen when the user provides data in a slightly different format than expected creates unnecessary friction. And this would have a negative impact on conversions.

It’s very common for a few variations of an answer to a question to be possible; for example, when a form asks users to provide information about their state, and a user responds by typing their state’s abbreviation instead of the full name (for example, CA instead of California). The form should accept both formats, and it’s the developer job to convert the data into a consistent format.

Clear Error Message

When you write error messages, focus on minimizing the frustration users feel when they face a problem in interacting with a form. Here are a few rules on writing effective error messages:

  • Never blame the user.
    The way you deliver an error message can have a tremendous impact on how users perceive it. An error message like, “You’ve entered a wrong number” puts all of the blame on the user; as a result, the user might get frustrated and abandon the app. Write copy that sounds neutral or positive. A neutral message sounds like, “That number is incorrect.”
  • Avoid vague or general error messages.
    Messages like “Something went wrong. Please, try again later” don’t say much to users. Users will wonder what exactly went wrong. Always try to explain the root cause of a problem. Make sure users know how to fix errors.
  • Make error messages human-readable.
    Error messages like “User input error: 0x100999” are cryptic and scary. Write like a human, not like a robot. Use human language, and explain what exactly the user or system did wrong, and what exactly the user should do to fix the problem.
Display Errors Inline

When it comes to displaying error messages, designers opt for one of two locations: at the top of the form or inline. The first option can make for a bad experience. Javier Bargas-Avila and Glenn Oberholzer conducted research on online form validation and discovered that displaying all error messages at the top of the form puts a high cognitive load on user memory. Users need to spend extra time matching error messages with the fields that require attention.

Avoid displaying errors at the top of the form. (Image: John Lewis) (Large preview)

It’s much better to position error messages inline. First, this placement corresponds with the user’s natural top-to-bottom reading flow. Secondly, the errors will appear in the context of the user’s input.

eBay uses inline validation.
eBay uses inline validation. (Large preview)
Use Dynamic Validation

The time at which you choose to display an error message is vital. Seeing an error message only after pressing the submit button might frustrate users. Don’t wait until users finish the form; provide feedback as data is being entered.

Use inline validation with real-time feedback. This validation instantly tells people whether the information they’ve typed is compatible with the form’s requirements. In 2009, Luke Wroblewski tested inline validation against post-submission validation and found the following results for the inline version:

  • 22% increase in success rate,
  • 22% decrease in errors made,
  • 31% increase in satisfaction rating,
  • 42% decrease in completion times,
  • 47% decrease in the number of eye fixations.

But inline validation should be implemented carefully:

  • Avoid showing inline validation on focus.
    In this case, as soon as the user taps a field, they see an error message. The error appears even when the field is completely empty. When an error message is shown on focus, it might look like the form is yelling at the user before they’ve even started filling it out.
  • Don’t validate after each character typed.
    This approach not only increases the number of unnecessary validation attempts, but it also frustrates users (because users will likely see error messages before they have completed the field). Ideally, inline validation messages should appear around 500 to 1000 milliseconds after the user has stopped typing or after they’ve moved to the next field. This rule has a few exceptions: It’s helpful to validate inline as the user is typing when creating a password (to check whether the password meets complexity requirements), when creating a user name (to check whether a name is available) and when typing a message with a character limit.
Reward early, punish late is a solid validation  approach. (Image: Mihael Konjević)


Users of all abilities should be able to access and enjoy digital products. Designers should strive to incorporate accessibility needs as much as they can when building a product. Here are a few things you can do to make your forms more accessible.

Ensure The Form Has Proper Contrast

Your users will likely interact with your form outdoors. Ensure that it is easy to use both in sun glare and in low-light environments. Check the contrast ratio of fields and labels in your form. The W3C recommends the following contrast ratios for body text:

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

Measuring color contrast can seem overwhelming. Fortunately, some tools make the process simple. One of them is Web AIM Color Contrast Checker, which helps designers to measure contrast levels.

Do Not Rely On Color Alone To Communicate Status

Color blindness (or color vision deficiency) affects approximately 1 in 12 men (8%) and 1 in 200 women in the world. While there are many types of color blindness, the most common two are protanomaly, or reduced sensitivity to red light, and deuteranomaly, or reduced sensitivity to green light. When displaying validation errors or success messages, don’t rely on color alone to communicate the status (i.e. by making input fields green or red). As the W3C guidelines state, color shouldn’t be used as the only visual means of conveying information, indicating an action, prompting a response or distinguishing a visual element. Designers should use color to highlight or complement what is already visible. Support colorblind people by providing additional visual cues that help them understand the user interface.

Use icons and supportive text to show which fields are invalid. This will help colorblind people fix the problems.
Use icons and supportive text to show which fields are invalid. This will help colorblind people fix the problems. (Large preview)

Allow Users To Control Font Size

Allow users to increase font size to improve readability. Mobile devices and browsers include features to enable users to adjust the font size system-wide. Also, make sure that your form has allotted enough space for large font sizes.

WhatsApp provides an option to change the font size in the app’s settings
WhatsApp provides an option to change the font size in the app’s settings. (Large preview)

Test Your Design Decisions

All points mentioned above can be considered as industry best practices. But just because something is called a “best practice” doesn’t mean it is always the optimal solution for your form. Apps and websites largely depend on the context in which they are used. Thus, it’s always essential to test your design decisions; make sure that the process of filling out a form is smooth, that the flow is not disrupted and that users can solve any problems they face along the way. Conduct usability testing sessions on a regular basis, collect all valuable data about user interactions, and learn from it.


Users can be hesitant to fill out forms. So, our goal as designers is to make the process of filling out a form as easy as possible. When designing a form, strive to create fast and frictionless interactions. Sometimes a minor change — such as properly writing an error message — can significantly increase the form’s usability.

his 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.

Smashing Editorial
(al, yk, il)

Source: Smashing Magazine

Case Study: Builds Single Customer View with MongoDB

This article was originally published on MongoDB. Thank you for supporting the partners who make SitePoint possible.

Transforms customer experience, fights fraud, and meets the demands of the GDPR with MongoDB Atlas and Apache Kafka running on AWS.

In a world where standards and speed in online retail are getting ever higher, one retailer, has consistently been able to differentiate itself around its core focus: customer experience.

At the beginning of 2017 it was clear there was a big opportunity to use customer data more effectively, to drive:

  1. Continued improvement to the customer experience
  2. Faster identification of fraud
  3. Compliance with the EU’s new GDPR personal privacy regulations

AO responded by starting a new team, giving them the mandate to build a 360-degree single view platform of all its customer data.

To ensure they could move quickly and keep the team focused on business goals, the team chose to use the MongoDB Atlas database service in the cloud. We spoke with Jon Vines, Software Development Team Lead at, about the experience of building the single customer view application, his development philosophy, and the impact it’s having at AO.

Can you start by telling us about is one of the UK’s leading online electrical retailers. At AO, what really drives us and makes us special is how obsessed we are with the customer’s experience. We make sure that our employees are empowered to make the call on what’s best for each and every customer, that means no scripts or rules in the contact centre, we just do what we think is right. Our guide has always been to ask whether our mum would be proud of the decisions we make every day and whether we feel we would have treated our own Nan in the same way.

That philosophy extends right through to the core technology decisions we make. For instance, the third of our three core business model pillars is infrastructure. We know it’s incredibly important to have systems that are scalable and extendable while making sure we get all the benefit of operational gearing and pace from our investments and long-term growth.

With quality infrastructure as such a key part of AO’s strategy, what was your team trying to achieve?

We were tasked with pulling together the many sources of customer information within AO, to build a single, holistic view of each of our customers. Our data is spread across many different departments, each using their own technology.

The ultimate goal is to deliver one source of truth for all customer data – to drive a host of new and enhanced applications and business processes. This enables our staff, with the appropriate permissions, to access all the useful data we have at the company, from one single place, and all from one easy-to-consume operational data layer.

Can you tell us a little bit about what apps will consume the single view?

There are three core apps we are serving today:

  • Call center: For us, it is all about the customer and relentlessly striving to make our customers happy. Evaluating our contact centre systems showed us that we could enhance our customer journey by exposing more data points that were not currently available to our agents. This allows us to provide a better level of customer experience.
  • Fraud: Anything in the fraud grey area gets passed to our fraud team for the personal touch. As our company grows, we’re constantly looking for ways to be more efficient and effective. This is where the single view comes in. The high-throughput, low-latency capabilities and the aggregation of multiple disparate data sources makes it the perfect vehicle to provide additional decision support and anomaly detection for our fraud team.
  • GDPR: We need to be able to tell customers what personal data we store about them. Our marketing teams need to be able to see customer’s preferences in relation to communications with us. The single view makes all of this much easier.

This is just the start. There are many more projects that are under development.

So how did you get started with the single view project?

The team was formed in May 2017, and our first task was to identify source data and define the domain we were operating in. We have a lot of historical data assets that need to be blended with real-time data. This meant working with multiple instances of Microsoft SQL Server, and various data repositories and message queues hosted on Amazon Web Services (AWS), including SQS. We had to figure out a way to extract that data cleanly, without impacting source systems.

We spent several months cataloging our data assets, before turning to prototyping and technology selection. We started development in October 2017 and went into production just three months later in January 2018. The key to this development velocity was the underlying technology we selected to power the single view platform.

What are you using to move data from your source systems?

As a business we were already running in AWS, so we first looked at Kinesis, but decided on using Apache Kafka and Confluent Open Source. We can use Kafka’s Connect API to extract data via the Change Data Capture streams on existing data sources, with Kafka streaming and transforming the source data into our single view data model. This allows us to extract data without creating dependencies on other teams who we would otherwise have to rely upon to publish this data, or give us access to their source systems.

Once the data is in Kafka, it opens up a multitude of potential downstream applications. The single customer view is just the first of these. We can also use the oplog in MongoDB to extract data into Kafka, which allows us to decouple our microservices architecture in a very natural way.

How about the database layer?

It was clear that legacy relational databases would never give the schema flexibility we needed, so we explored more modern database options.

The post Case Study: Builds Single Customer View with MongoDB appeared first on SitePoint.

Source: Sitepoint

20 Tips for Optimizing CSS Performance

In this article, we look at 20 ways to optimize your CSS so that it’s faster-loading, easier to work with and more efficient.

According to the latest HTTP Archive reports, the web remains a bloated mess with the mythical median website requiring 1,700Kb of data split over 80 HTTP requests and taking 17 seconds to fully load on a mobile device.

The Complete Guide to Reducing Page Weight provides a range of suggestions. In this article, we’ll concentrate on CSS. Admittedly, CSS is rarely the worst culprit and a typical site uses 40KB spread over five stylesheets. That said, there are still optimizations you can make, and ways to change how we use CSS that will boost site performance.

1. Learn to Use Analysis Tools

You can’t address performance problems unless you know where the faults lie. Browser DevTools are the best place to start: launch from the menu or hit F12, Ctrl + Shift + I or Cmd + Alt + I for Safari on macOS.

All browsers offer similar facilities, and the tools will open slowly on badly-performing pages! However, the most useful tabs include the following …

The Network tab displays a waterfall graph of assets as they download. For best results, disable the cache and consider throttling to a lower network speed. Look for files that are slow to download or block others. The browser normally blocks browser rendering while CSS and JavaScript files download and parse.

The Performance tab analyses browser processes. Start recording, run an activity such as a page reload, then stop recording to view the results. Look for:

  1. Excessive layout/reflow actions where the browser has been forced to recalculate the position and size of page elements.
  2. Expensive paint actions where pixels are changed.
  3. Compositing actions where the painted parts of the page are put together for displaying on-screen. This is normally the least processor-intensive action.

Chrome-based browsers provide an Audits tab which runs Google’s Lighthouse tool. It’s often used by Progressive Web App developers, but also makes CSS performance suggestions.

Online Options

Alternatively, use online analysis tools that are not influenced by the speed and capabilities of your device and network. Most can test from alternative locations around the world:

2. Make Big Wins First

CSS is unlikely to be the direct cause of performance issues. However, it may load heavy-hitting assets which can be optimized within minutes. Examples:

  • Activate HTTP/2 and GZIP compression on your server
  • Use a content delivery network (CDN) to increase the number of simultaneous HTTP connections and replicate files to other locations around the world
  • Remove unused files.

Images are normally the biggest cause of page bulk, yet many sites fail to optimize effectively:

  1. Resize bitmap images. An entry-level smartphone will take multi-megapixel images that can’t be displayed in full on the largest HD screen. Few sites will require images of more than 1,600 pixels in width.
  2. Ensure you use an appropriate file format. Typically, JPG is best for photographs, SVG for vector images, and PNG for everything else. You can experiment to find the optimum type.
  3. Use image tools to reduce file sizes by striping metadata and increasing compression factors.

That said, be aware that xKb of image data is not equivalent to xKb of CSS code. Binary images download in parallel and require little processing to place on a page. CSS blocks rendering and must be parsed into an object model before the browser can continue.

3. Replace Images with CSS Effects

It’s rarely necessary to use background images for borders, shadows, rounded edges, gradients and some geometric shapes. Defining an “image” using CSS code uses considerably less bandwidth and is easier to modify or animate later.

4. Remove Unnecessary Fonts

Services such as Google Fonts make it easy to add custom fonts to any page. Unfortunately, a line or two of code can retrieve hundreds of kilobytes of font data. Recommendations:

  1. Only use the fonts you need.
  2. Only load the weights and styles you require — for example, roman, 400 weight, no italics.
  3. Where possible, limit the character sets. Google fonts allows you to pick certain characters by adding a &text= value to the font URL — such as for displaying “SitePoint” in Open Sans.
  4. Consider variable fonts, which define multiple weights and styles by interpolation so files are smaller. Support is currently limited to Chrome, Edge, and some editions of Safari but should grow rapidly. See How to Use Variable Fonts.
  5. Consider OS fonts. Your 500Kb web font may be on-brand, but would anyone notice if you switched to the commonly available Helvetica or Arial? Many sites use custom web fonts, so standard OS fonts are considerably less common than they were!

5. Avoid @import

The @import at-rule allows any CSS file to be included within another. For example:

/* main.css */
@import url("base.css");
@import url("layout.css");
@import url("carousel.css");

This appears a reasonable way to load smaller components and fonts. It’s not. @import rules can be nested so the browser must load and parse each file in series.

Multiple <link> tags within the HTML will load CSS files in parallel, which is considerably more efficient — especially when using HTTP/2:

<link rel="stylesheet" href="base.css">
<link rel="stylesheet" href="layout.css">
<link rel="stylesheet" href="carousel.css">

That said, there may be more preferable options …

The post 20 Tips for Optimizing CSS Performance appeared first on SitePoint.

Source: Sitepoint

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

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

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

Stéphanie Walter


In this second part, I want to focus more on mobile-specific capabilities. HTML5, for instance, has brought us a lot of really cool features to help users fill in mobile forms and format their data. We will see in detail how HTML5 attributes can help you with that. Then, we will go beyond “classic” form elements and see how to use mobile capabilities such as the camera, geolocation and fingerprint scanners to really take your mobile form experience to the next level on websites and in native applications.

Helping The User Format Content With HTML5

In the first part of this series, we saw some general advice on how to display fields. Now it’s time to go a bit deeper and look at how a few well-crafted lines of HTML5 code can improve your mobile forms.

HTML5 Mobile-Optimized Goodness

HTML5 opens a whole world of possibilities for optimizing forms for mobile and touch devices. A lot of interesting new input types can trigger different keyboards to help users. We can also do some interesting things with capturing media directly in the browser.

Entering Numerical Data

input type= number

The HTML5 <input type=number> attribute restricts an input field to numbers. It has a built-in validation system that rejects anything that is not a number.

In some desktop browsers, this input is presented with little arrows on the right that the user can click to increment the number. On mobile, it opens a keyboard with numbers, which decreases typos and form-validation errors. The input’s look and feel depend on the operating system.

On the left, Android’s keyboard, and on the right, the iOS keyboard with numbers.
On the left, Android’s keyboard, and on the right, the iOS keyboard with numbers. (Large preview)

The input should allow for decimals and negative numbers (but few keyboards respect that). As explained in the W3C’s specifications, “a simple way of determining whether to use type=number is to consider whether it would make sense for the input control to have a spinbox interface (e.g. with ‘up’ and ‘down’ arrows)”. This means that the input is not supposed to be used for credit cards or area codes.

The pattern And inputmode Attributes

To add some restrictions to your number inputs, you could use the pattern attribute to specify a regular expression against which you want to control values.

This is what it looks like:

<input type="number" id="quantity" name="quantity" pattern="[0-9]*" inputmode="numeric" />

You can use this pattern to bring up the big-button numeric keyboard on the iPhone (but not the iPad). This keyboard does not have the minus sign or comma, so users lose the ability to use negative numbers and decimals. Also, they can’t switch back to another keyboard here, so be careful when using this.

Also, note that patterns can be applied to any other type of inputs.

Using only this pattern won’t work on most Android phones. You’ll still need a combination of input type=number and the attribute to make this work.

Android and iOS demo with input type=number, pattern and inputmode.
Android and iOS demo with input type=number, pattern and inputmode. (Large preview)


If you only want to trigger the mobile numeric keyboard but don’t want to deal with the type=number and pattern mess, you could use a text input and apply the inputmode=numeric attribute. It would look like this:

<input type="text" id="quantity" name="quantity" inputmode="numeric" />

Unfortunately (at the time of writing), only Chrome 67 mobile supports this, but it should be arriving in Chrome desktop 66 without a flag.

To learn more about how to enter numbers in a form, read “I Wanted to Type a Number”.

input type=tel

If you want users to enter a phone number, you can use the input type=tel. As you can see in the screenshot below, it triggers the same digits on iOS’ keyboard as the pattern attribute described above. Due to the complexity of phone numbers across the world, there is no automatic validation with this input type.

input type=tel on Android and iOS
input type=tel on Android and iOS (Large preview)
Entering Dates

Even if they are technically numerical data, dates deserve their own section. There are a few HTML5 input types for entering dates. The most used is input type=date. It will trigger a date-picker in supported browsers. The appearance of the date-picker depends on the browser and OS. To learn more on how browsers render input type="date", I recommend you read “Making input type=date complicated.”

A date-picker based on input type=date on Android and iOS
A date-picker based on input type=date on Android and iOS (Large preview)

There’s also type=week to pick a week, type=time to enter a time (up to the hour and minute), and type=datetime-local to pick a date and a time (using the user’s local time). So many choices!

Example of date-picker with more options on Android
Example of date-picker with more options on Android (week, date and time, etc.) (Large preview)

input type=date works well for booking interfaces, for example. You might have some needs that require you to build your own date-picker, though (as we’ve already seen in the section on sensible defaults). But input type=date is always a nice option if you need a date-picker and don’t want to bring a whole JavaScript library into the website for the job.

Yet, sometimes not using type=date for dates is better. Let’s take the example of a birth date. If I was born in 1960 (I’m not — this is just an example), it would take me many taps to pick my birth date if I was starting from 2018. On Android, I discovered recently that if I press on the year in the picker, I get a sort of dropdown wheel with all of the years. A bit better, but it still requires a fair amount of scrolling.

A user told me on Twitter:

“I’m born in 1977 and can confirm the annoyance. The more time it takes to scroll, the older you feel :-(“

So, maybe birth dates are not the best candidate for date-pickers.

With Android’s date-picker, even though you can press and hold the year to get a year-picker, picking a birth date is still tedious.
With Android’s date-picker, even though you can press and hold the year to get a year-picker, picking a birth date is still tedious. (Large preview)

Mobile phones hide some other keyboard and input-optimization goodness that enhance the user’s experience when filling in a form. The devil is in the details, as they say.

Using the input type=url field will bring up an optimized keyboard on mobile, with / (the slash key) directly accessible. Depending on the OS, you can also give quick access to commons top-level domains, like the .fr in the screenshot below. If you long-press this button, shortcuts to other top-level domains will appear. This also comes with automatic browser validation that checks that the URL’s format is valid.

input type=url keyboard on Android and iOS
input type=url keyboard on Android and iOS (Large preview)

The input type=emailfield brings up an email-optimized keyboard giving quick access to the @ symbol. This input requires the presence of @ somewhere in the field in order to be valid. That’s the only verification it does.

input type=email keyboard on Android and iOS
input type=email keyboard on Android and iOS (Large preview)

The input type=search field brings up a search-optimized keyboard. The user can directly launch the search from a button on the keyboard. There’s also a little cross to clear the field and type a new query.

input type=search keyboard on Android and iOS
input type=search keyboard on Android and iOS (Large preview)
Range And Color

The last two input types we looked at are not particularly optimized for mobile, but by using them, we can avoid having to load heavy custom JavaScript libraries, which is a good idea for mobile users.

input type=range provides a visual UI slider to input a number. The UI for this control is browser-dependent.

input type=color provides an easy way for the user to enter a color value. In many browser implementations, this comes with a color-picker.

input type=range and input type=color on Android and iOS
input type=range and input type=color on Android and iOS (Large preview)
HTML Media Capture: Taking And Uploading Pictures And Recording Sound

I remember the time of the iPhone 3, when Apple would not even allow a simple input type=file to be used on a website, for security reasons. Those times are long gone. With the HTML media capture API, it’s now possible to access different sensors of a device. We can capture photos and videos, and we can even record voice directly in the browser.

The accept attribute lets you specify what kind of media to accept in the input: audio, image, video. The user can give the browser direct access to their camera, for example.

The code looks like this:

<input type="file" id="take-picture" accept="image/*">

The accept attribute is set to image. The browser asks whether I want to access the camera directly or the files on the device.
The accept attribute is set to image. The browser asks whether I want to access the camera directly or the files on the device. (Large preview)

The capture attribute lets you specify the preferred mode of capture. If you add the capture attribute on top of the accept attribute, you can make the browser open the camera or voice recorder directly.

<input type="file" accept="image/*" capture> // opens the camera>
<input type="file" accept="video/*" capture> // opens the camera in video mode
<input type="file" accept="audio/*" capture> // opens the voice recorder

The mobile browser directly opens the capture mechanism: on the left, the camera, on the right, the video recorder.
The mobile browser directly opens the capture mechanism: on the left, the camera, on the right, the video recorder. (Large preview)

For more details on how to use media directly in the browser, read the section “Accessing and Handling Images, Video and Audio Directly in the Browser” in my article on the secret powers of mobile browsers.

HTML5 Autos: Autocorrect, Autocomplete, Autofill, Autocapitalize And Autofocus

HTML5 comes with a slew of automatic attributes. To enhance the mobile experience, you will want to be smart about what can be automated and what can’t. Here are some general rules of thumb:

  • Disable autocorrect on things for which the dictionary is weak: email addresses, numbers, names, addresses, cities, regions, area codes, credit card numbers.
  • Disable autocapitalize for email fields and other fields where appropriate (for example, website URLs). Note that type=email does the job for you in recents version of iOS and Android, but disable it anyway for older versions or if type=email is not supported.
  • You can set the autocapitalize attribute to words to automatically uppercase the first letter of each word the user types. This can be useful for names, places and the like, but, again, be careful with it, and test it.

Use input type=email for email addresses. If you don’t, at least deactivate auto-capitalization. No email address starts with a capital letter.
Use input type=email for email addresses. If you don’t, at least deactivate auto-capitalization. No email address starts with a capital letter. (Large preview)
  • For input type=tel, set autocomplete="tel".
  • You could use autofocus to give the focus to a control element when the user loads the page. But just because the user opens the “contact” page, it does not mean they are ready to jump right to the first field of your form. So, again, use it wisely.

In this example, we could use autofocus to take the user directly to the first field once they’ve clicked on the button.
In this example, we could use autofocus to take the user directly to the first field once they’ve clicked on the button. (Large preview)

If you want more autocomplete options, a whole list is on the WhatWG Wiki. Just make sure you use the right ones. Implement, test, and test again.

HTML5 Form Validation

I won’t get into the technical details here, but you should know that HTML5 has a built-in form-validation API for many fields. It’s nice if you don’t want to use a JavaScript library to display inline validation messages. Here are the main things you need to know as a UX designer about HTML5 form validation:

HTML native form validation in an Android browser
HTML native form validation in an Android browser (Large preview)

In “Native Form Validation, Part 1,” Peter-Paul Koch goes into detail on why HTML and CSS form validation doesn’t really make forms better at this time.

Offline Support To Save User Data

A lot of things can go wrong, especially on mobile. Mistakes happen. A user could mistap the back button in the browser and lose all of their data.

If the user comes back to the page, it would be nice to display their data again. The same goes for if the browser crashes or the user closes the tab. You can store the user’s data in local or session storage to ensure nothing gets lost if something goes wrong. Geoffrey Crofte has written a JavaScript library to help you with that.

If the connection is lost as the user is submitting the form, they might also lose the data. To avoid this, you could use a combination of the** HTML5 offline API** and the Service Workers API to:

  • store the data in the cache,
  • try to automatically send it again when the connection comes back.

To learn how to code this, check out the article on “Offline-Friendly Forms”.

Mobile Device Capabilities Can Take the Experience To The Next Level

In part 1, we stuck to the basic common HTML form elements and attributes for enhancing mobile forms. But mobile devices capabilities now go far beyond displaying HTML, CSS and JavaScript web pages. Those little devices come equipped with a lot of sensors. And we will be able to use many of those in native apps and on the web to make our users’ lives so much easier.

Detecting The User’s Location

In the previous section, I wrote about pre-filling information for places and addresses. That’s a good start. We can go one step further. Instead of asking users to type a location, we can detect it. Meet the geolocation API for the web. There are also native iOS, Android and Windows Phone geolocation APIs.

Citymapper is a website and an app that helps users plan their travels. When the user goes into the first field, they see the “Use current location” option. If they select it, they are asked to allow the browser to access their geolocation data. This is the geolocation API. The browser then autocompletes the location it found and, the user can proceed to the destination field. The native app works pretty much the same way.

Citymapper proposes the user’s current location as the starting point for the journey.

Be Smart When Asking For The User’s Permission

You might have noticed in the previous video that I had to agree to give access to my position to the Citymapper website. In the browser, the user handles permissions website by website, API by API.

You also need to be careful how you ask for permission. The user might refuse access to the geolocation, notification or other API if you ask too soon. They also might refuse if they don’t understand why you need the permission. You get one chance; use it wisely. After that, it will be almost impossible to recover. I’m an Android power user, and even I have to search around for the options in my browser when I want to reset the permissions I’ve given to a website. Imagine the trouble your users will have.

Here is some general advice on asking for permissions on the web:

  • Don’t be the creepy geolocation or notification stalker: Don’t ask for permission as soon as the user arrives on your website. They might not know about you or your service yet.
  • Let the user discover your website and service. Then, ask for permission in context. If you want to access their location, ask them only when you need it (Citymapper is a good example).
  • Explain why you need permission and what you will do with it.

Citymapper asks for access to the user’s location only when it needs it. Clearing permissions after the user refuses it can get really complicated because the user will need to search through their settings for that website.
Citymapper asks for access to the user’s location only when it needs it. Clearing permissions after the user refuses it can get really complicated because the user will need to search through their settings for that website. (Large preview)

If you want to go further, Luke Wroblewski (yes, him again) has created a nice video to help you with the permission-asking process.

A Better Checkout Experience

A big area of improvement for forms is the whole checkout payment experience. Here again, sensors on the device can make this an almost painless experience. The only pain will be the amount of money the user spends.

iOS Credit Card Scanner

In the previous section, I wrote about autodetection of credit cards and autocompletion features based on the user’s previous input. This still means that the user has to type their credit card data at least once.

Apple has taken this to the next level with its credit card scanner. Since iOS 8 in Safari, users can use their camera to scan and autocomplete their credit card information. To perform this magic, you will need to add the autocomplete cc-number attribute and some name to identify this as a credit card field. Apple doesn’t have much official information on it, but some people did some testing and put the results on StackOverflow.

Safari also has autofill options that users can use to add their credit card, allowing them reuse it on multiple websites.

The credit card scanning option appears when Safari detects a field that matches the credit card format. If the user already has a card registered on the phone, they can use the autofill option.
The credit card scanning option appears when Safari detects a field that matches the credit card format. If the user already has a card registered on the phone, they can use the autofill option. (Large preview)
Take Checkout One Step Further With Google Pay API

Google launched something similar: the Google Pay API. When implemented on a website, the API eliminates the need to manually enter payment information. It goes one step further: It can store billing and shipping addresses as well.

The user gets a dialog in Chrome that displays the various payment information they’ve stored. They can choose which one to use and can pay directly through the dialog.

The Google Pay API pop-up triggered on an e-commerce website
The Google Pay API pop-up triggered on an e-commerce website (Source) (Large preview)

A standardized version of the Payment Request API is currently a W3C candidate recommendation. If this gets implemented in browsers, it would allow users to check out with a single button, which would request the API. Every step thereafter would be handled by native browser dialogs.

Making Authentication Easier

Mobile phones are, in most cases, personal devices that people don’t usually share with others. This opens up some interesting opportunities for authentication.

I use a password manager. I don’t know 99% of my passwords. They are all randomly generated. In order to log into a new Slack workspace, I must:

  1. open my password manager,
  2. enter my master password,
  3. search for the workspace,
  4. copy and paste the password into the Slack app.

It’s a tedious process, but Slack was smart enough to provide a better option.

Many users have they mail synchronized on their phone. Slack understood that. When you add a new Slack workspace in the app, you can either log in using the password or ask for the “magic link” option. If you opt for the latter, Slack sends a magic link to your mailbox. Open the mail, click on the big green button, and — ta-da! — you’re logged in.

Behind the scenes, this magic link contains an authentication token. The Slack app catches this and authenticates you without requiring the password.

When using the magic link option, Slack sends you an email with a link that lets you connect to your slack without having to enter your password.
When using the magic link option, Slack sends you an email with a link that lets you connect to your slack without having to enter your password. (Large preview)
Fingerprint For Smart Identification

I do almost all of my banking on my mobile device. And when it comes to logging into my bank accounts, there’s a world of difference between my French Societe General bank app and the German N26 app.

With Société Générale, I have a login string and a passphrase. I can ask the app to remember the login string, which is 10 random digits. I’m not able to remember that one; I use a password manager for it. I must still remember and enter the six-digit passphrase on a custom-built keypad. Of course, the numbers’ positions change every time I log in. Security — yeah, I know. Also, I must change this passphrase every three months. The last time I was forced to change the passphrase, I did what most people do: choose almost the same passphrase, because I don’t want to have to remember yet another six-digit number. And of course, I was damn sure I would remember it, so I did not enter it in my password manager. Rookie mistake. Two weeks later, I tried to log in. Of course, I forgot it. I made three failed attempts, and then my account was blocked. Fortunately, I only use this account for savings. In the app, you can ask for a new passcode. It took almost one week for the bank to send me a new six-digit passphrase by paper mail to my home address in Luxembourg. Yeah.

N26, on the other hand, uses my email address as the login string. I can remember that without a password manager. When I want to log in, I put my finger on the start button of my Xperia phone, and that’s it. In the background, my phone scans my fingerprint and authenticates me. If that does not work, I can fall back to a password.

Same device, two apps, two totally different experiences.

Dropbox has another example of fingerprint authentication.
Dropbox has another example of fingerprint authentication. (Large preview)

More and more apps on both Android and iOS now offer user the possibility to authenticate with a fingerprint. No more passwords — it’s an interesting and elegant solution.

Of course, people have expressed some security concerns about this. For the National Institute of Standards and Technology (NIST), biometrics is not considered secure enough. It advises combining biometrics with a second factor of authentication.

Fingerprint sensors can also be tricked — yes, like in spy movies. Did you hear about the plane that was forced to land because a woman learned of her husband’s infidelity after using his thumb to unlock his phone while he was sleeping?

Facial Recognition And Face ID

In 2018, Apple launched the iPhone X with the brand new face ID. Users can unlock their iPhone X using their face. Of course, some other Android phones and Windows tablets and computers had proposed this feature earlier. But when Apple launches something, it tends to become “a thing”. For the moment, this technology is mostly used as authentication to unlock phones and computer.

There are some pretty big challenges with facial-recognition technology. First, some algorithms can be fooled by a picture of the person, which is easily hackable. Another bigger concern is diversity. Facial-recognition algorithms tend to have difficulty recognizing people of color. For instance, a black researcher had to wear a white mask to test her own project. The researcher is Joy Buolamwini, and she gave a TED talk about the issue.

Some facial-recognition software is also used by some customs services to speed up border processing. It is used in New Zealand and will be used in Canada.

Most of us have seen enough science fiction to see the potential problems and consequences of systems that use facial recognition at scale. This kind of technology used outside of the private space of unlocking phones can get controversial and scary.

Google: One-Tap Sign-Up

If a user has a Google account, they can benefit from Google’s one-tap sign-up. When visiting a website and prompted to create an account in an inline dialog, the user doesn’t need to enter a password. Google provides a secure token-based password-less account, linked to the user’s Google account. When the user returns, they are automatically signed in. If they store their passwords in the Smart Lock, they get automatically signed in on other devices as well.

Google’s one-tap sign-up dialog
Google’s one-tap sign-up dialog (Source) (Large preview)

Note: This is an interesting password-less solution. Of course, by using it, users are linked to Google, which not everyone will feel comfortable with.


You can do a lot of really cool things when you start using mobile capabilities to help users fill in forms. We need a mobile-first mindset when building forms; otherwise, we’ll get stuck on the desktop capabilities we are familiar with.

Again, be careful with the device’s capabilities: always have a fallback solution in case a sensor fails or the user refuses access. Avoid making those capabilities the only options for those functions (unless you are building a map app that relies on geolocation).

This is the end of a series of two really long articles in which I’ve given you some general UX and usability advice and best practices. In the end, what matter are your form and your users. Some things described here might not even work specifically for your users — who knows? So, whatever you do, don’t take my (or Luke’s) word for it. Test it, with real users, on real devices. Measure it. And test again. Do some user research and usability testing. User experience is not only about best practices and magic recipes that you copy and paste. You need to adapt the recipe to make it work for you.

So, in short: Test it. Test it on real devices. Test it with real users.

Smashing Editorial
(lf, ra, al, il)

Source: Smashing Magazine

Three ways to grow your traffic and capture audience

Introduction According to a number of studies published over the last 12 months, only 25% of all websites get more than 5,000 unique visitors per month, which (unfortunately!) means that 75% of the internet aren’t reaching anywhere near their traffic (and therefore their monetisation) potential. For context, at SitePoint we tend to try to measure […]

The post Three ways to grow your traffic and capture audience appeared first on SitePoint.

Source: Sitepoint

Three winning strategies for setting up Google Adsense

Adsense is, without question, the best, most comprehensive and most accessible advertising service for small business on the web. That said, there are a few things that you need to keep in mind when implementing and running Adsense as your advertising platform of choice. Testing is everything! New to advertising on your blog or small […]

The post Three winning strategies for setting up Google Adsense appeared first on SitePoint.

Source: Sitepoint

Build a Health Tracking App with React, GraphQL, and User Authentication

This article was originally published on the Okta developer blog. Thank you for supporting the partners who make SitePoint possible.

I think you’ll like the story I’m about to tell you. I’m going to show you how to build a GraphQL API with Vesper framework, TypeORM, and MySQL. These are Node frameworks, and I’ll use TypeScript for the language. For the client, I’ll use React, reactstrap, and Apollo Client to talk to the API. Once you have this environment working, and you add secure user authentication, I believe you’ll love the experience!

Why focus on secure authentication? Well, aside from the fact that I work for Okta, I think we can all agree that pretty much every application depends upon a secure identity management system. For most developers who are building React apps, there’s a decision to be made between rolling your own authentication/authorization or plugging in a service like Okta. Before I dive into building a React app, I want to tell you a bit about Okta, and why I think it’s an excellent solution for all JavaScript developers.

What Is Okta?

In short, we make identity management a lot easier, more secure, and more scalable than what you’re used to. Okta is a cloud service that allows developers to create, edit, and securely store user accounts and user account data, and connect them with one or multiple applications. Our API enables you to:

Are you sold? Register for a forever-free developer account, and when you’re done, come on back so we can learn more about building secure apps in React!

Why a Health Tracking App?

In late September through mid-October 2014, I’d done a 21-Day Sugar Detox during which I stopped eating sugar, started exercising regularly, and stopped drinking alcohol. I’d had high blood pressure for over ten years and was on blood pressure medication at the time. During the first week of the detox, I ran out of blood pressure medication. Since a new prescription required a doctor visit, I decided I’d wait until after the detox to get it. After three weeks, not only did I lose 15 pounds, but my blood pressure was at normal levels!

Before I started the detox, I came up with a 21-point system to see how healthy I was each week. Its rules were simple: you can earn up to three points per day for the following reasons:

  1. If you eat healthy, you get a point. Otherwise, zero.
  2. If you exercise, you get a point.
  3. If you don’t drink alcohol, you get a point.

I was surprised to find I got eight points the first week I used this system. During the detox, I got 16 points the first week, 20 the second, and 21 the third. Before the detox, I thought eating healthy meant eating anything except fast food. After the detox, I realized that eating healthy for me meant eating no sugar. I’m also a big lover of craft beer, so I modified the alcohol rule to allow two healthier alcohol drinks (like a greyhound or red wine) per day.

My goal is to earn 15 points per week. I find that if I get more, I’ll likely lose weight and have good blood pressure. If I get fewer than 15, I risk getting sick. I’ve been tracking my health like this since September 2014. I’ve lost weight, and my blood pressure has returned to and maintained normal levels. I haven’t had good blood pressure since my early 20s, so this has been a life-changer for me.

I built 21-Points Health to track my health. I figured it’d be fun to recreate a small slice of that app, just tracking daily points.

Building an API with TypeORM, GraphQL, and Vesper

TypeORM is a nifty ORM (object-relational mapper) framework that can run in most JavaScript platforms, including Node, a browser, Cordova, React Native, and Electron. It’s heavily influenced by Hibernate, Doctrine, and Entity Framework. Install TypeORM globally to begin creating your API.

npm i -g typeorm@0.2.7

Create a directory to hold the React client and GraphQL API.

mkdir health-tracker
cd health-tracker

Create a new project with MySQL using the following command:

typeorm init --name graphql-api --database mysql

Edit graphql-api/ormconfig.json to customize the username, password, and database.

    "username": "health",
    "password": "pointstest",
    "database": "healthpoints",

TIP: To see the queries being executed against MySQL, change the “logging” value in this file to be “all”. Many other logging options are available too.

Install MySQL

Install MySQL if you don’t already have it installed. On Ubuntu, you can use sudo apt-get install mysql-server. On macOS, you can use Homebrew and brew install mysql. For Windows, you can use the MySQL Installer.

Once you’ve got MySQL installed and configured with a root password, login and create a healthpoints database.

mysql -u root -p
create database healthpoints;
use healthpoints;
grant all privileges on *.* to 'health'@'localhost' identified by 'points';

Navigate to your graphql-api project in a terminal window, install the project’s dependencies, then start it to ensure you can connect to MySQL.

cd graphql-api
npm i
npm start

You should see the following output:

Inserting a new user into the database...
Saved a new user with id: 1
Loading users from the database...
Loaded users:  [ User { id: 1, firstName: 'Timber', lastName: 'Saw', age: 25 } ]
Here you can setup and run express/koa/any other framework.

Install Vesper to Integrate TypeORM and GraphQL

Vesper is a Node framework that integrates TypeORM and GraphQL. To install it, use good ol’ npm.

npm i vesper@0.1.9

Now it’s time to create some GraphQL models (that define what your data looks like) and some controllers (that explain how to interact with your data).

Create graphql-api/src/schema/model/Points.graphql:

type Points {
  id: Int
  date: Date
  exercise: Int
  diet: Int
  alcohol: Int
  notes: String
  user: User

Create graphql-api/src/schema/model/User.graphql:

type User {
  id: String
  firstName: String
  lastName: String
  points: [Points]

Next, create a graphql-api/src/schema/controller/PointsController.graphql with queries and mutations:

type Query {
  points: [Points]
  pointsGet(id: Int): Points
  users: [User]

type Mutation {
  pointsSave(id: Int, date: Date, exercise: Int, diet: Int, alcohol: Int, notes: String): Points
  pointsDelete(id: Int): Boolean

Now that your data has GraphQL metadata create entities that will be managed by TypeORM. Change src/entity/User.ts to have the following code that allows points to be associated with a user.

import { Column, Entity, OneToMany, PrimaryColumn } from 'typeorm';
import { Points } from './Points';

export class User {

  id: string;

  firstName: string;

  lastName: string;

  @OneToMany(() => Points, points => points.user)
  points: Points[];

In the same src/entity directory, create a Points.ts class with the following code.

import { Entity, PrimaryGeneratedColumn, Column, ManyToOne } from 'typeorm';
import { User } from './User';

export class Points {

  id: number;

  @Column({ type: 'timestamp', default: () => 'CURRENT_TIMESTAMP'})
  date: Date;

  exercise: number;

  diet: number;

  alcohol: number;

  notes: string;

  @ManyToOne(() => User, user => user.points, { cascade: ["insert"] })
  user: User|null;

Note the cascade: ["insert"] option on the @ManyToOne annotation above. This option will automatically insert a user if it’s present on the entity. Create src/controller/PointsController.ts to handle converting the data from your GraphQL queries and mutations.

import { Controller, Mutation, Query } from 'vesper';
import { EntityManager } from 'typeorm';
import { Points } from '../entity/Points';

export class PointsController {

  constructor(private entityManager: EntityManager) {

  // serves "points: [Points]" requests
  points() {
    return this.entityManager.find(Points);

  // serves "pointsGet(id: Int): Points" requests
  pointsGet({id}) {
    return this.entityManager.findOne(Points, id);

  // serves "pointsSave(id: Int, date: Date, exercise: Int, diet: Int, alcohol: Int, notes: String): Points" requests
  pointsSave(args) {
    const points = this.entityManager.create(Points, args);
    return, points);

  // serves "pointsDelete(id: Int): Boolean" requests
  async pointsDelete({id}) {
    await this.entityManager.remove(Points, {id: id});
    return true;

Change src/index.ts to use Vesper’s bootstrap() to configure everything.

import { bootstrap } from 'vesper';
import { PointsController } from './controller/PointsController';
import { Points } from './entity/Points';
import { User } from './entity/User';

  port: 4000,
  controllers: [
  entities: [
  schemas: [
    __dirname + '/schema/**/*.graphql'
  cors: true
}).then(() => {
  console.log('Your app is up and running on http://localhost:4000. ' +
    'You can use playground in development mode on http://localhost:4000/playground');
}).catch(error => {
  console.error(error.stack ? error.stack : error);

This code tells Vesper to register controllers, entities, GraphQL schemas, to run on port 4000, and to enable CORS (cross-origin resource sharing).

Start your API using npm start and navigate to http://localhost:4000/playground. In the left pane, enter the following mutation and press the play button. You might try typing the code below so you can experience the code completion that GraphQL provides you.

mutation {
  pointsSave(exercise:1, diet:1, alcohol:1, notes:"Hello World") {

Your result should look similar to mine.

GraphQL Playground

You can click the “SCHEMA” tab on the right to see the available queries and mutations. Pretty slick, eh?!

You can use the following points query to verify that data is in your database.

query {
  points {id date exercise diet notes}

Fix Dates

You might notice that the date returned from pointsSave and the points query is in a format the might be difficult for a JavaScript client to understand. You can fix that, install graphql-iso-date.

npm i graphql-iso-date@3.5.0

Then, add an import in src/index.ts and configure custom resolvers for the various date types. This example only uses Date, but it’s helpful to know the other options.

import { GraphQLDate, GraphQLDateTime, GraphQLTime } from 'graphql-iso-date';

  customResolvers: {
    Date: GraphQLDate,
    Time: GraphQLTime,
    DateTime: GraphQLDateTime

Now running the points query will return a more client-friendly result.

  "data": {
    "points": [
        "id": 1,
        "date": "2018-06-04",
        "exercise": 1,
        "diet": 1,
        "notes": "Hello World"

You’ve written an API with GraphQL and TypeScript in about 20 minutes. How cool is that?! There’s still work to do though. In the next sections, you’ll create a React client for this API and add authentication with OIDC. Adding authentication will give you the ability to get the user’s information and associate a user with their points.

Get Started with React

One of the quickest ways to get started with React is to use Create React App. Install the latest release using the command below.

npm i -g create-react-app@1.1.4

Navigate to the directory where you created your GraphQL API and create a React client.

cd health-tracker
create-react-app react-client

Install the dependencies you’ll need to talk to integrate Apollo Client with React, as well as Bootstrap and reactstrap.

npm i apollo-boost@0.1.7 react-apollo@2.1.4 graphql-tag@2.9.2 graphql@0.13.2

Configure Apollo Client for Your API

Open react-client/src/App.js and import ApolloClient from apollo-boost and add the endpoint to your GraphQL API.

import ApolloClient from 'apollo-boost';

const client = new ApolloClient({
  uri: "http://localhost:4000/graphql"

That’s it! With only three lines of code, your app is ready to start fetching data. You can prove it by importing the gql function from graphql-tag. This will parse your query string and turn it into a query document.

import gql from 'graphql-tag';

class App extends Component {

  componentDidMount() {
      query: gql`
          points {
            id date exercise diet alcohol notes
    .then(result => console.log(result));

Make sure to open your browser’s developer tools so you can see the data after making this change. You could modify the console.log() to use this.setState({points:}), but then you’d have to initialize the default state in the constructor. But there’s an easier way: you can use ApolloProvider and Query components from react-apollo!

Below is a modified version of react-client/src/App.js that uses these components.

import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';
import ApolloClient from 'apollo-boost';
import gql from 'graphql-tag';
import { ApolloProvider, Query } from 'react-apollo';
const client = new ApolloClient({
  uri: "http://localhost:4000/graphql"

class App extends Component {

  render() {
    return (
      <ApolloProvider client={client}>
        <div className="App">
          <header className="App-header">
            <img src={logo} className="App-logo" alt="logo" />
            <h1 className="App-title">Welcome to React</h1>
          <p className="App-intro">
            To get started, edit <code>src/App.js</code> and save to reload.
          <Query query={gql`
              points {id date exercise diet alcohol notes}
            {({loading, error, data}) => {
              if (loading) return <p>Loading...</p>;
              if (error) return <p>Error: {error}</p>;
              return => {
                return <div key={}>
                  <p>Date: {}</p>
                  <p>Points: {p.exercise + + p.alcohol}</p>
                  <p>Notes: {p.notes}</p>

export default App;

You’ve built a GraphQL API and a React UI that talks to it – excellent work! However, there’s still more to do. In the next sections, I’ll show you how to add authentication to React, verify JWTs with Vesper, and add CRUD functionality to the UI. CRUD functionality already exists in the API thanks to the mutations you wrote earlier.

Add Authentication for React with OpenID Connect

You’ll need to configure React to use Okta for authentication. You’ll need to create an OIDC app in Okta for that.

Log in to your Okta Developer account (or sign up if you don’t have an account) and navigate to Applications > Add Application. Click Single-Page App, click Next, and give the app a name you’ll remember. Change all instances of localhost:8080 to localhost:3000 and click Done. Your settings should be similar to the screenshot below.

OIDC App Settings

Okta’s React SDK allows you to integrate OIDC into a React application. To install, run the following commands:

npm i @okta/okta-react@1.0.2 react-router-dom@4.2.2

Okta’s React SDK depends on react-router, hence the reason for installing react-router-dom. Configuring routing in client/src/App.tsx is a common practice, so replace its code with the JavaScript below that sets up authentication with Okta.

import React, { Component } from 'react';
import { BrowserRouter as Router, Route } from 'react-router-dom';
import { ImplicitCallback, SecureRoute, Security } from '@okta/okta-react';
import Home from './Home';
import Login from './Login';
import Points from './Points';

function onAuthRequired({history}) {

class App extends Component {
  render() {
    return (
        <Security issuer='https://{yourOktaDomain}/oauth2/default'
                  redirect_uri={window.location.origin + '/implicit/callback'}
          <Route path='/' exact={true} component={Home}/>
          <SecureRoute path='/points' component={Points}/>
          <Route path='/login' render={() => <Login baseUrl='https://{yourOktaDomain}'/>}/>
          <Route path='/implicit/callback' component={ImplicitCallback}/>

export default App;

Make sure to replace {yourOktaDomain} and {clientId} in the code above. You can find both values in the Okta Developer Console.

The code in App.js references two components that don’t exist yet: Home, Login, and Points. Create src/Home.js with the following code. This component renders the default route, provides a Login button, and links to your points and logout after you’ve logged in.

import React, { Component } from 'react';
import { withAuth } from '@okta/okta-react';
import { Button, Container } from 'reactstrap';
import AppNavbar from './AppNavbar';
import { Link } from 'react-router-dom';

export default withAuth(class Home extends Component {
  constructor(props) {
    this.state = {authenticated: null, userinfo: null, isOpen: false};
    this.checkAuthentication = this.checkAuthentication.bind(this);
    this.login = this.login.bind(this);
    this.logout = this.logout.bind(this);

  async checkAuthentication() {
    const authenticated = await this.props.auth.isAuthenticated();
    if (authenticated !== this.state.authenticated) {
      if (authenticated && !this.state.userinfo) {
        const userinfo = await this.props.auth.getUser();
        this.setState({authenticated, userinfo});
      } else {

  async componentDidMount() {

  async componentDidUpdate() {

  async login() {

  async logout() {
    this.setState({authenticated: null, userinfo: null});

  render() {
    if (this.state.authenticated === null) return null;
    const button = this.state.authenticated ?
          <Button color="link"><Link to="/points">Manage Points</Link></Button><br/>
          <Button color="link" onClick={this.logout}>Logout</Button>
      <Button color="primary" onClick={this.login}>Login</Button>;

    const message = this.state.userinfo ?
      <p>Hello, {this.state.userinfo.given_name}!</p> :
      <p>Please log in to manage your points.</p>;

    return (
        <Container fluid>

This component uses <Container/> and <Button/> from reactstrap. Install reactstrap, so everything compiles. It depends on Bootstrap, so include it too.

npm i reactstrap@6.1.0 bootstrap@4.1.1

Add Bootstrap’s CSS file as an import in src/index.js.

The post Build a Health Tracking App with React, GraphQL, and User Authentication appeared first on SitePoint.

Source: Sitepoint

The Benefits of Using CSS Grid for Web Form Layout

Form layout and design is a fundamental yet frustrating part of web design and development. Ask anyone who’s ever tried to style a <select> box or align a label consistently in all browsers.

In 2016 I wrote “Make Forms Fun with Flexbox”, which identified how several form difficulties could be solved with Flexbox. A key benefit was HTML source order consistency, with the <label> always following its associated field tag in a container:

  <input id="name" name="name" type="text" />
  <label for="name">name</label>

  <select id="experience" name="experience"><!-- options --></select>
  <label for="experience">experience</label>

  <input id="html" name="html" type="checkbox" />
  <label for="html">HTML</label>

Flexbox could then be used to:

  • reposition the label if necessary — that is, move it to the left of the field on text inputs, select boxes, and textareas
  • vertically align the label and field.

It also became possible to style labels based on the state of their field using adjacent sibling selectors — for example, applying bold to a label when its associated checkbox is checked:

input:checked + label {
  font-weight: bold;

Flawed Flexboxed Forms

Unfortunately, there are a number of problems using Flexbox to lay out a form. Flexbox creates a one-dimensional layout where each item follows another and wraps to a new line when necessary. Field/label pairs must be placed in container elements with display: flex; applied to guarantee each appears on a new row.

It was also necessary to define a fixed label width, such as 10em. If a long label required more room, its text would either overflow or resize the element and push the field out of alignment with others.

Finally, forms are normally laid out in a grid. Shouldn’t we be using CSS Grid now that it’s fully supported in all mainstream browsers? Absolutely!

Development Approach

Most CSS Grid articles demonstrate the concepts and may provide graceful degradation fallbacks for older browsers. That approach is ideal when the layout is mostly decorative — for example, positioning page content, headers, footers and menus. It rarely matters when oldBrowserX shows linear blocks in an unusual order because the page content remains usable.

Form layout is more critical: a misaligned label could lead the user to enter information in the wrong box. For this reason, this tutorial takes a progressive enhancement approach:

  1. An initial floated layout will work in all browsers including IE8+ (which doesn’t support Flexbox either). It will not be perfect, but floats never were!
  2. Enhance the layout using CSS Grid in all modern browsers.

The examples below contain very few CSS classes, and styling is applied directly to HTML elements. That’s not the BEM way, but it is intentional to keep the code clean and understandable without distractions.

You could consider using similar code as the base for all forms on your site.


A typical HTML form can be kept clean, since there’s no need for containing (<div>) elements around field/label pairs:

<form action="get">
    <legend>Your web development skillset</legend>

    <div class="formgrid">

      <input id="name" name="name" type="text" />
      <label for="name">name</label>

      <select id="experience" name="experience">
        <option value="1">1 year or less</option>
        <option value="2">2 years</option>
        <option value="3">3 - 4 years</option>
        <option value="5">5 years or more</option>
      <label for="experience">experience</label>

      <input id="html" name="html" type="checkbox" />
      <label for="html">HTML</label>

      <input id="css" name="css" type="checkbox" />
      <label for="css">CSS</label>

      <input id="javascript" name="javascript" type="checkbox" />
      <label for="javascript">JavaScript</label>

      <textarea id="skills" name="skills" rows="5" cols="20"></textarea>
      <label for="skills">other skills</label>

      <button type="submit">SUBMIT</button>



The only additional element is <div class="formgrid">. Browsers can’t apply display: grid or display: flex to fieldset elements. That may eventually be fixed, but an outer container is currently required.

The post The Benefits of Using CSS Grid for Web Form Layout appeared first on SitePoint.

Source: Sitepoint

Mobile Gaming: Build a Security Token Service with Object Storage Service

This article was originally published on Alibaba Cloud. Thank you for supporting the partners who make SitePoint possible.

Think you got a better tip for making the best use of Alibaba Cloud services? Tell us about it and go in for your chance to win a Macbook Pro (plus other cool stuff). Find out more here.

In mobile gaming, many applications require developers to segregate player resources. This includes a range of things, from saving files to processing user profile information. Using traditional methods, developers can manage this segregation, but must consider many other problems such as security, scalability, and APIs.

As cloud technologies evolve, the need for higher-level usability and features is increasing. With Object Storage Service (OSS), customers can store and manage their objects easily and efficiently. OSS provides real-time image processing service online. Some customers may want additional features such as allowing users to have limited access to a service like OSS, but with the convenience of secure, centralized management.

Security Token Service provides short-term access permission management for Alibaba Cloud accounts or RAM users. Through STS, you can issue federated users, who are managed in your local account system, with an access credential that customizes the expiration duration and access permission. Federated users can use the STS temporary access credential to directly call the Alibaba Cloud service API or to log on to the Alibaba Cloud Management Console to access authenticated resources.

In this scenario, we test the functionality of STS by using OSS.


It requires the ability to adjust Resource Access Management (RAM) settings and Roles. For more information, see Roles.

The sample code is written in Python. While it is not required, a basic understanding of computer programming is an advantage. The sample code provided in this tutorial can serve as a template which can be modified to meet your specific needs. Many people are currently using the raw API so as to manage an environment, or an application. While an SDK is available in many languages, the raw API provides more flexibility.


In this diagram, a RAM user wants to upload images to a separate folder in an OSS bucket.

The upload process is as follows:

  1. The user assumes a RAM role for Read and Write OSS Access for a specific folder in Alibaba Cloud by calling AssumeRole.
  2. STS returns a set of temporary security credentials.
  3. The user applies the temporary security credentials to access OSS. The user can then make a read or write call on the object.

We take OSS as an example here. However, STS can be used to grant temporary access to a wide range of Alibaba Cloud services. In this tutorial, we use fine-grained STS permission to limit access to a specific OSS bucket.


Three files in the sample code are as follows:

    • This is the code for assuming the role and to retrieve essential information such as accessKeyId, accessKeySecret, and securityToken.

The available functions are as follows:

  • Generate signatures to guarantee request authenticity
  • Get HTTPS requests

The example code for file “” is as follows:

The post Mobile Gaming: Build a Security Token Service with Object Storage Service appeared first on SitePoint.

Source: Sitepoint