emGee Software Solutions Custom Database Applications

Share this

Web Design

8 SEO Mistakes That Could Ruin Your Campaign in 2018

Webitect - Tue, 05/29/2018 - 08:46

Search engine optimization or SEO is a great digital marketing instrument when used properly. Over 60% of viewers now come to websites after searching for the information they need on search engines. Not optimizing your site for SEO is a mistake since you will miss out on a lot of potential customers and a steady stream of viewers. Of course, search engines are now much smarter. Sites are ranked based on more metrics, including user experience and mobile-friendliness. Unfortunately, many sites (and site owners) do not adapt to the changes made by search engines. They end up making mistakes and

The post 8 SEO Mistakes That Could Ruin Your Campaign in 2018 appeared first on Clayton Johnson SEO.

Categories: Web Design

How Do You Know Your Website Is A Success?

Smashing Magazine - Tue, 05/29/2018 - 07:30
How Do You Know Your Website Is A Success? How Do You Know Your Website Is A Success? Nick Babich 2018-05-29T16:30:32+02:00 2018-06-14T13:28:26+00:00

(This article is kindly sponsored by Adobe.) We live in a world where just about every business has an online presence. Let’s say you want to reach out to a business — what would be the first thing you would do? Well, you would probably look up their website to search for answers to your questions or simply any contact details you can find. With no doubt, the first impression of any website is now more important than ever.

There are more than 1.8 billion websites on the Internet right now, and the number is growing. The increase of the competition brings a great interest in examining the factors of success of a website. While no one will argue that it’s essential to have a successful website, it’s still not easy to understand what exactly success means and how to actually measure it.

Define What Site Success Means To You Set A Global Goal

Finding the answers to questions such as “What are our goals?” and “What do we want to achieve with this website?” should be the first thing to do when starting a new project. Skipping a stage of defining global goals and moving directly to the design stage is a pretty common mistake among many product teams. Without knowing exactly what you want to achieve, your chances of making a positive impact with your website will be poor.

Every website needs a well-defined product strategy. A strategy sets the tone for all of the activities, and it gives a context that helps in making design decisions. When you have a solid understanding of what you expect to get out of your site, it helps you to work towards that goal.

Product strategy is a combination of achievable goals and visions that work together to align the team around desirable outcomes for both the business and your users. (Image credit: Melissa Perri) (Large preview)

Here are a few tips that help you set a goal:

  • Tie the purpose to business goals.
    The website’s purpose should serve to support the company’s mission and make the business more effective in achieving that mission.
  • Make it specific.
    Instead of saying something like “I want to have a strong online presence,” consider this instead: “Our website should be a place where users submit requests for our services. Our goal is to have 50% of our orders submitted online, not over the phone.”
  • Conduct competitor research.
    List sites of your competitors which you find successful, and try to pinpoint why they are successful.
Strive To Create User-Focused Experience

Because visitors ultimately determine the success of a website, they should be in the spotlight during site’s development. As Dieter Rams says:

“You cannot understand good design if you do not understand people; design is made for people.”

Thus, start with gathering this understanding:

  • Portrait your ideal users.
    Try to understand what content they might need/want, their browsing habits (how they prefer to interact with a website) and the level of their technical competence. This knowledge will help you appeal to them better.
  • Think about the goal of your visitors.
    Put yourself in the shoes of your visitor. What do you want them to get done? Place an order? Reach you for a quote? Become a member? Drive the design from the user’s goals and tasks.* *Ideally, each page you design should have a goal for your users.
  • Create user journey map.
    If you have an existing site, you can figure out typical ways people use it by creating user journey maps.
User journey map. (Image credit: Temkin Group) 8 Essential Characteristics Of Website Design That Influence Its Success

In this section, we aren’t going to discuss design implementation details (e.g. where a logo should be placed). We’ll be focusing on the main principles and approaches for effective web design. These principles will be reviewed from the angle of the first impression. It’s essential to focus on great user experience during the first-time visit. Generally, the better the first impression, the better the chance that users will stay for longer. But if the first impression is negative, it might make users want to avoid interacting with your product for years.

And how do we leave a good first impression? Good design. First impressions are 94% design related. While it’s impossible to define one-fits-all design decisions that will guarantee a successful site, it is still possible to focus on factors that are able to create a great first impression: the quality of content, usability, and visual aesthetics.

1. High-Quality Content

The copy used on your website is just as important as the website’s design; it’s the reason why people visit your website. More than 95 percent of information on the web is in the form of written language. Even if your site is beautifully designed, it’s no more than an empty frame without good content. A good website has both great design and great content.

“Content precedes design. Design in the absence of content is not design, it's decoration.”

Jeffrey Zeldman Match Users’ Expectations

Provide information your users expect to see. For example, if you design a website for a chain of restaurants, most visitors will expect to find the restaurants’ menus as well as maps that show where each restaurant is located.

Content That Builds Trust

Trust is what creates a persuasive power; trust makes the user believe in your products or services. That’s why it so important to build a sense of trust on your website. For example, if you design a website that will offer services, you should include content that will bolster a visitor’s confidence in those offerings. A simple way to accomplish this is to provide social proofs — put some testimonials on your site.

One great example is Basecamp. The company lists feedback from its clients together with a data statistic that reinforces the power of the social proof.

Basecamp pairs testimonials with research findings to create an ultimate persuasive effect. Focus On Microcopy

Microcopy is the tiny words we use in user interfaces. These might be field or button labels, or description for forms and other UI objects. Right microcopy can influence business profits. But in order to write good microcopy, it’s essential to understand user’s intentions and emotions.

During the Google I/O 2017, Maggie Stanphill explained the possible business value of writing good microcopy. After the Google team changed ‘Book a room’ to ‘Check availability’ in the Hotel search on Google, the engagement rate increased by 17%. This happened because the first version of microcopy (‘Book a room’) was too committal for that stage of the user journey. Users didn’t want to book a room; they wanted to explore all available options (date range as well as prices).

Good microcopy is human-oriented. In this example, ‘Check availability’ meets the user where they are in their mindset. Text Is Optimized For Scanning

It’s necessary to adjust content to users’ browsing habits. It’s a well-known fact that users don’t read online, they scan. When a new visitor approaches a web page, the first thing s/he does is tries to do is to scan the page and divide the content into digestible pieces of information. By scanning through key parts of the page, they are trying to determine if the content is relevant to their needs.

Here are a few tips on how to format your content to make it easy to scan:

  • Avoid long blocks of text without images.
    With a huge probability, such content will be skipped. Use headings, paragraphs, or bullet points to break up a text.
  • Optimize layouts for natural scanning patterns.
    Eye tracking studies have identified that people scan pages in an “F” pattern. We read the first few lines, but then they start skipping down the page, caching only parts of the message. For this reason, it’s important to keep your text frontloaded — put the most important concepts first, so our eyes catch those important words as we track down.
Users don’t read, they scan. This heatmap shows where people’s focal points land. Effectively designed websites work with a reader’s natural behavior. (Image credit: Useit)

Quick design tip: You can measure your readability score using a tool called Webpagefx.

Avoid Distraction

The human eye can instantly recognize moving objects. Moving objects such as animated banners or video advertising can capture users’ attention. An abundance of such content can lead to annoying and distracting experience. Thus, put an emphasis on a site with minimal distractions.

Heatmaps from eye-tracking studies: The areas where users looked the most are colored red; the yellow areas indicate fewer views. Green boxes are used to highlight the advertisements. (Image credit: NNGroup) Contact Information

Make it easy for people to reach you. This requirement sounds pretty obvious; still, it’s quite a typical situation for first-time visitors to have to hunt for contact information. Don’t let that happen. Make a phone number, email, address and a contact form easily accessible.

Quick design tip: When designing your site, don’t make email or phone number a part of an image. Phone number/email should be in plain text so that users can copy this information.

Relevant Images And Videos In High Quality

Studies have proven that people are majorly visual learners. Most people are able to understand and grasp concepts far better when they are delivered in visual way.

Remember the old saying, “A picture is worth a thousand words”? It’s relevant to web design. A simple way to increase visual appeal is to provide high-quality imagery or video content.

One great example is Tesla which doesn’t tell the benefits of its car but rather shows a quick video that makes it clear what it feels like to drive a Tesla:

Tesla uses a principle ‘show, don't tell’ when demonstrating the benefits of using cars. 2. Simple Interactions

According to Hubspot survey, 76% of respondents mentioned ease of use as the most important characteristic of a website. That’s why the “Keep It Simple” principle (KIS) should play a primary role in the process of web design.

Cut Out The Noise

Cluttering a user interface overloads your user with too much information — every added button, image, and line of text makes the screen more complicated. Cutting out the clutter on a website will make the primary message more easily understood by visitors. Include only the elements that are most important for communication, and use enough whitespace. It will help to reduce the cognitive load for the visitors and will make it easier to perceive the information presented on the screen.

Quick design tip: Put more visual weight on important elements. Make important elements such as call-to-action buttons or login forms focal points so visitors see them right away. You can emphasize elements using different sizes or colors.

Lyft makes the most important information on a page (the call-to-action button) stand out. Strong Visual Hierarchy

The better visual hierarchy your create, the easier your content will be perceived by users (Simon’s law). A grid layout allows you to organize information in a way that makes it easier for visitors to read and comprehend information presented on the page. Using grids makes it much easier to create a layout that feels balanced.

Use a grid layout when designing web experiences. Using grids in Adobe XD. Good Navigation

Good navigation is one of the most important aspects of website usability. Even the most beautifully designed website will be useless if users aren’t able to find their way around.

When developing navigation for your website, think about what pages are most likely to be important to visitors, and how they will move from one page to another. Follow users’ expectations — create a predictable navigation structure and place it where users expect to see it.

Quick design tip: Reduce the total number of actions required for users to reach the destination. Try to follow the Three-click rule which means creating a structure that will enable users to find the information they are looking for within three clicks.

Recognizable Design Patterns

Design patterns are designer’s best friends. When designing your site, it’s worth remembering that users spend most of their time on other sites. Every time the user has to learn how something new works, it creates friction. By using recognizable conventions, you can reduce the learning curve. Recognizable UI patterns eventually help users to parse complicated tasks easily. Thus, when you follow users’ expectations and create a familiar experience (e.g. place UI elements in places where users expect to find them), site visitors can use their previous knowledge and act through intuition. This helps reduce the learning curve and the need to figure out how things work.

3. Fast Loading Time

As technology enables faster experiences, users’ willingness to wait has decreased. Slow loading time is one of the main reasons visitors leave websites. A typical user will only wait for a few seconds for your page to load. If nothing happens during this time, they will consider the site to be too slow, and will most likely navigate away to a competitor’s site.

Slow loading not only creates a lousy impression on users, but it also affects site’s search engine ranking, as slow-loading pages are reduced in rank in Google’s Search engine.

Test Your Website

There are tools available that allow you to test website performance. One of them is Google’s Test My Site which gives you an actionable report on how to speed up and improve your site. WebPage Test is another helpful tool which allows you to run a free website speed test from multiple locations around the globe, using real browsers (Internet Explorer and Chrome) at real consumer connection speeds.

The slower your website is, the higher your bounce rate will be. (Image credit: Luke W.) Find What Is Causing The Slow Loading Time, And Fix The Problem

If slow loading is a typical situation for your website, try to find out what causes the problem and solve it. Typically, page load times are affected by:

  • Visual elements (images and animations).
    HD images and smooth animation can only create good UX when they don’t affect loading time. Consider reading the article Image Optimization for tips on image optimization.
  • Custom fonts.
    Like any other asset, it takes some time to download a custom font (and it takes more time if the font is located on a 3rd party service).
  • Business logic.
    Whether or not a solution you’ve developed is optimized for fast loading time. There are a lot of things developers can do to minimize the loading time. For example, it’s possible to use file compression and decompression to improve the performance of а website.
  • Technical infrastructure.
    An infrastructure is a place where you host your websites. It includes both hardware and software components as well as internet bandwidth.
Create A Perception Of Speed

If you can’t improve the actual performance of your website, you can try to create a perception of speed — how fast something feels is often more important than how fast it actually is. Employing a technique of skeleton screens can help you with that. A skeleton layout is a version of your page that displays while content is being loaded. Skeletons give the impression of speed — that something is happening more quickly than it really is and improve perceived load time.

This real estate website reuses some of the data from search results page (the image of the building and basic description) while the detailed information is loading. This creates a sense of immediate response even when some time required to load the data. (Image credit: Owen Campbell-Moore) (Large preview)

Check out this Codepen example of skeleton effect in pure CSS. It uses a pulsation effect to give users a feeling that website is alive and content is loading:

See the Pen Skeleton Screen with CSS by Razvan Caliman (@oslego) on CodePen.

4. Feeling A Sense Of Control

A sense of control remains one of the basic usability heuristics for user interface design. Effective interfaces instill a sense of control in their users.

Good Error Handling

To err is human. Errors occur when people engage with user interfaces. Sometimes, they happen because users make mistakes. Sometimes, they happen because a website fails. Whatever the cause, these errors and how they are handled, have a significant impact on the user experience. Bad error handling paired with useless error messages can fill users with frustration and can lead them to abandon your website. When errors occur, it’s essential to create effective error messages.

Make your website sound human even. Each error message your website display should be clear, clean, and useful.

Designers can use a tactic called design for failure in which you try to anticipate the places users might face problems and plan for such cases. Whereas implementing the ideal user journey is the end goal, the complexities of an individual user’s experience are rarely so cut and dried. Recognizing potential pain points and preparing for it using tools like failure mapping for error recovery helps to ensure that you’re putting forth the best experience you can for the majority of your users.

No Aggressive Pushers

We all know that feeling. You visit a new website, the content on the page seems to be interesting. You begin to read it and just when you are halfway through the text, you are suddenly interrupted by a huge overlay asking you to either subscribe to a newsletter or take advantage of an offer. In most cases, your immediate reaction will be either to close the overlay or to close the entire page, the overlay along with it.

Aggressive pushers such as pop-ups with promotional content will put most people on the defensive. According to the NN Group, pop-ups are the most hated web experience ever.

Aggressive pushers create bad user experience. (Image credit: Vitaly Dulenko) (Large preview) Don’t Autoplay Video With Sound

When users arrive on a page, they don’t expect that it will play any sound. Most users don’t use headphones and will be stressed because they’ll need to figure out how to turn the sound off. In most cases, users will leave the website as soon as it plays. Thus, if you use autoplay video content on your site, set audio to off by default, with the option to turn it on.

5. Good Visual Appearance

Does an attractive design lead to more conversion? While there’s no direct connection between attractive design and conversion, visual appearance might increase chances for conversion. As Steven Bradley says:

“Human beings have an attractiveness bias; we perceive beautiful things as being better, regardless of whether they actually are better. All else being equal, we prefer beautiful things, and we believe beautiful things function better. As in nature, function can follow form.” Capitalize On Trends

Just like with any other area of design, web design is constantly changing. Design trends come and go, and its necessary to be sure that your design doesn’t look dated. Familiarize yourself with latest trends and try to keep your design up to date by tuning your design.

Awwwards and Behance are great places which will help you be familiar with the latest trends.

Avoid Generic Stock Photos

Many corporate websites are notorious for using generic stock photos to build a sense of trust. Such photos rarely hold useful information. Usability tests show that generic photos and other decorative graphic elements don’t add any value to the design and more often impair rather than improve the user experience. Eye-tracking studies show that users usually overlook stock images.

An example of a stock photo 6. Design Is Accessible To All Groups Of Users

You can’t call your design successful if your audience has trouble using it. There’s a direct connection between bad UX and inaccessibility. One typical example of design decisions that often create terrible UX for the sake of beauty is using light grey text on light backgrounds. The example below was taken from one of the most popular powerful platforms for creating websites. Even a person with normal vision will struggle to read a text on this page, and there’s a huge possibility that a visually impaired person wouldn’t be able to read it at all.

Insufficient color contrast paired with small font size create readability issues.

The website you design should be accessible to all groups of users including blind, disabled or the elderly. Be sure to check WCAG documents and WUHCAG’s checklist.

7. Memorable Design

Taking into account the fact that almost all business have an online presence today — no matter what product or service you offer online — there are many other websites offering exactly what you do (perhaps even with the same benefits). It’s essential to set your website apart from the competition by crafting really memorable design.

Barbara Fredrickson and Daniel Kahneman proposed a psychological heuristic called the “peak-end rule” which dictates the way our brain works with information. The peak-end rule states that people judge an experience based mainly on how they felt at its peak (i.e., its most intense point) and at its end, rather than based on the total sum or average of every moment of the experience. The effect occurs regardless of whether the experience is pleasant or unpleasant. In other words, when we remember experiences, we tend to recall not entire experience but only key events that happened. That’s why it’s essential to create a spark that will stay in a user’s memory for a long time.

Color

Color hugely influences on what people remember, and how vividly they remember it. Selective use of color can trigger the memory and be that one added element that ensures your brand stays memorable and recognizable.

For example, when we think about Spotify, we usually think about vibrant colors. The service uses color as a brand and experience differentiator:

Spotify plays with colors to create a memorable experience. Illustrations

Illustrations are a versatile tool useful in creating a unique design. From small icons to large hand-drawn hero sketches, illustrations bring a sense of fine craftsmanship in digital experience.

A straightforward way of using illustrations in web design is to tailor them to your messaging.

Illustrations can be a great supplement of the text copy. (Image credit: Evernote)

Using brand mascots in web design is another great example when illustrations can create a memorable experience. Mascots become the elements of identity and inter-connector between the user and the product.

By pairing illustrations with jokes, Smashing Magazine has developed a distinct design style that makes them memorable for anyone who aware of the brand. Brand Consistency

Consistency is arguably the key rule to a successful brand. Inconsistency brings a huge problem — users won’t picture a specific thing when they think about a brand, and, as a result, it can quickly become forgettable. That’s why the website’s design should be consistent with your brand. Make sure that basic brand attributes such as brand colors, fonts, logos, and slogans are used consistently on the website.

Quick design tip: An excellent way to boost your ability to maintain a consistent brand design is through a style guide. Prepare it once and use it for each product you design.

McDonald's website design is consistent with its brand. Humor

Make your experiences fun, so people remember them. One good example is Mailchimp, a service used to schedule and deploy email campaigns. The company fulfills a fairly technical niche, but by using humor it transforms this dry task into an inviting experience. Mailchimp uses a mascot called Freddie von Chimpenheimer. Freddie often cracks jokes, and humor is an effective way to connect with people. This positive attitude will often lead to people sharing and even advocating for the product with their friends.

Freddie, the cartoon mascot of MailChimp, is a great emotional carrier for humor. Mailchimp adds small and delightful surprises throughout the user journey and makes sending emails a lot more fun. (Large preview) 8. Design Is Optimized For Mobile

Just a decade ago, designing for the web meant designing for a desktop, now it means designing for mobile and desktop. Mobile phones and tablets are driving an increasing amount of web traffic, and the numbers are only going to grow. In 2018, more than 50 percent of all website traffic worldwide was generated through mobile phones.

Prioritize Content And Features

Optimizing web design for mobile is a lot more than just making your design responsive. It’s about content and feature prioritization. Taking medium limitations into account, the goal is to show only what your users need in this medium.

Focus on refining the experience around your core objectives. Know what the core purpose of your app is — analyze which features of your app are used the most and put the most effort into making that experience intuitive.

Measure Success

After we’ve defined what makes a site successful, it’s time to understand how to measure the success. Measuring a site’s success requires an in-depth look at the analytics and data. As the first step in the process of measuring usage data, it’s essential to define right metrics. Metrics will make it clear whether your design decision is working or not. There are two groups of metrics — marketing metrics and UX metrics. Both groups of metrics are essential to a site’s success.

Marketing Metrics Acquisition

Acquisition includes information about site’s visitors — how many people visit your site and how do they find it. Acquisition metrics include:

  • Number of gross visits.
    This is the most basic acquisition metric that you can track. It gives you a good baseline on how your site is doing, but it won’t tell you much without other metrics. For example, an increasing number of visitors does not necessarily mean success, because those visitors might not be relevant to your business goals.
  • Channels.
    As well as knowing your top-level traffic numbers (number of gross visits), you should also know where your traffic is coming from. If you use Google Analytics, it organizes acquired website traffic into a few broad categories such as Direct, Organic Search, Referral, Social. These groupings allow you to immediately segment your traffic source and identify specific patterns of behavior for each source.
  • Points of entrance.
    An entrance shows you what page people started their session on. You might think this would be the home page, when in fact that’s rarely the case, especially with referral and social traffic. If you go to the Behavior section of Google Analytics, you’ll be able to see your best-performing pages regarding traffic volume. Knowing what pages bring the most traffic is hugely important because it gives you reliable information on what content attracts people.
Engagement

Engagement measures the amount of time visitors stay on your website, as well as how many pages they visit. Engagement metrics help UX teams understand how much attention visitors give to a website.

Engagement metrics include:

  • Time spent on your site.
    Time visitors spend on site is often equated with engagement. Generally, the more time users spend on the site, the more valuable it’s for them. However, there might be an exception to this rule. For example, users might spend more time on a site because it’s hard to complete a specific task (e.g., find the information they need).
  • Total number of pages visited during user session.
    Generally, the more pages people visited, the better. However, it can also be an indicator of dissatisfaction – if people have to visit dozens of pages to find what they’re looking for, that often leads to unhappiness.
  • Bounce rate.
    The bounce rate (reported as a %) enables you to track how many people visit only one page before leaving your site. Naturally, you want this percentage to be as low as possible. There are some factors which could contribute to a high bounce rate. Generally, a high percentage could point to the lack of relevant content or usability issues. But of course, this rule has exceptions. For example, a visitor may have come to your site just to find contact information about your company. Once they had your phone number or address, there was no need to visit another page.

Quick tips:

  • Create a list of top 10 pages visitors are most engaged with. The pages that users are spending most time may help you determine if your goals are in-line with the goals of users.
  • Track exit pages. It’s essential not only to track how a user gets to your site but also how they leave it. This metric is different than a bounce rate in that it tracks visitors who visited multiple pages (bounce rate is a single page metric). If a particular page has a high exit rate, it might be an indication of a problem.
Retention

There are two types of website visitors: first-time visitors and returning visitors. Retention is the percentage of return visitors — people who continue visiting your website within a specific time frame. When a team measures retention, it becomes much easier to distinguish new users from returning users, and, as a result, see how quickly user base is growing or stabilizing.

Retention can be distilled from the percentage of new sessions. By comparing the percentage of new sessions vs. returning visitors, you can determine if your website is attracting new visitors and whether it offers enough value so people return to it.

Conversion

The majority of websites have a goal of getting visitors to convert (take action), whether it is to purchase an item or sign up for a newsletter. That’s why conversion is the metric that everyone cares about the most. Aim to maximize the number of people who convert (e.g., buy something after they come to your site). Obviously, the higher the conversion rate, the better your website is doing.

A conversion rate can tell you a lot about the quality of your traffic. For example, having a low conversion rate while having a lot of unique visits can be an indication that you are attracting the wrong traffic.

Here are a few tips for measuring conversion:

  • It’s always better to select easy-to-measure activities. For example, it might be something as simple as contact form submissions. Contact form submissions can be a great indicator of your site’s success — if users prompt an inquiry this is a great indication that your site has engaged them.
  • For larger sites, it’s good to have many different conversion goals on one site. For example, an eCommerce store might have three conversion goals — a product purchase, a subscriber to an email list, a social share.
Pirate Metrics (AARRR Framework)

As you can see, there are a lot of metrics that can be used. But how do you figure out which metrics to implement and track?

In the attempt to simplify the task of selecting right metrics, Dave McClure created a framework called AARRR. This framework uses a customer lifecycle as a foundation (the idea that visitors go from being a first-time visitor to a returning visitor), and tracks users through a conversion funnel over time. The life cycle consists of 5 steps:

  1. Acquisition
    Users come to the site from various channels.
  2. Activation
    Users enjoy their first visit (happy user experience).
  3. Retention
    Users come back and visit the site multiple times
  4. Referral
    Users like the product enough to refer it to others.
  5. Revenue
    Users conduct some type of monetization behavior.

Pirate metrics can help you determine where you should focus on optimizing your marketing funnel.

User Experience Metrics

While marketing metrics define the success of a product based on the conversion, user experience metrics focus on the quality of interaction with a product. Focusing on business goals does not necessarily lead to a better user experience. UX metrics can complement marketing metrics by concentrating on the critical aspects of user experience.

The Quality Of User Experience (HEART Framework)

When it comes to measuring user experience, it’s always hard to define specific metrics. Of course, there are high-level UX metrics that correlate with the success of user experiences such as usability, engagement, and conversion. But it might be hard to define metrics that will be relevant to a particular product. In the attempt to simplify this task, the Google team created a framework called HEART. This framework is intended to help designers focus on the product they create, and the user experience it provides. HEART uses some metrics that we already mentioned in the marketing section, but from a different angle.

  • Happiness
    Measures of user attitudes: satisfaction, perceived ease of use, net-promoter score. This metric can be collected via survey.
  • Engagement
    Level of user involvement. Engagement is typically measured as depth of interaction over some time period. For example, the number of visits per user per month.
  • Adoption
    Gaining new users of a product or feature. For example, the number of users who tried new product features in the last week.
  • Retention
    The rate at which existing users are returning. For example, for a web service this might be the number of active users remaining present over time. For e-commerce website, this might be the number of repeat purchases.
  • Task Success
    This category is most applicable to areas of your product that are task-focused. It includes behavior metrics such as efficiency (e.g. time to complete a task), effectiveness (e.g. percent of tasks completed), and error rate. For example, for e-commerce website this might be the number of search result success.

The HEART framework is very flexible — it can be applied to a specific feature or a whole product. It’s important to mention that you don’t need to collect metrics in all of HEART categories — you should choose only the most important for your particular project. It’s possible to choose metrics by following a process of Goals-Signals-Metrics.

The Goals-Signals-Metrics Process

The Goals-Signals-Metrics process helps you to identify meaningful metrics you’ll actually use.

Google HEART framework and Goals-Signals-Metrics process

The process of selecting metrics you can implement and track starts with goals. To define a goal, you need to focus on knowing what determines success. This is where the HEART categories will be particularly useful. For example, if you create a news site you might set a goal in the engagement category; the aim would be to have users enjoy the articles they read, and to keep them browsing to discover more articles from different categories.

Here are two tips that will help you define better goal:

  • *Don’t define your goals in terms of your existing metrics. *It’s a common pitfall when a team defines goals based on information it has. As a result, a goal might sound as something like ‘We need to increase traffic to our site.’ Yes, everyone wants to have more visitors, but does more visitors will move you towards your goal? Not necessary.
  • Work with team and stakeholders to identify the goals. You may not realize that different members of your team have different ideas about the goals of your project. Identifying goals early on in design process provides an opportunity to build consensus about where you are headed. Make sure that everyone on the team understands the proposed solution in sufficient detail.

After identifying your goals, you need to think about what user actions will result in progress toward these goals. These actions are your signals. There are usually a large number of potentially useful signals for a particular goal. Once you have identified some potential signals, you may need to do research or analysis to choose the ones that are most relevant. If we circle back to our example with a news site, an engagement signal for it might be the number of articles users read on the site.

Here are a few tips:

  • Consider how easy or difficult is to track each signal. It’s preferable to focus on signals that can be monitored automatically (e.g. your product can log the relevant information so you can use it for further analysis).
  • Try to choose signals that are sensitive to changes in your design. This way you will be able to analyze the data you have to understand whether the design changes benefit your users or not.
  • Don’t ignore negative signals. Identifying signals for possible missteps (e.g. number of errors during particular interaction) can help you reveal pain points in your product.

Once you’ve chosen signals, you can refine them into metrics you’ll track over time. In our news site engagement example, we might implement “how long users spend reading news” as “the average number of minutes spent reading news per user per day.”

  • Prioritize your metrics.
    Focus on tracking the metrics related to your top goals.
  • Don’t add metrics for sake of adding metrics.
    Avoid the temptation to add “interesting stats” to the list of metrics. Always ask yourself whether you will actually use these numbers to help you make a decision.
  • The metrics you track should be tied back to design decisions.
    When you see a change, you should be absolutely clear on what has caused that change.
What Can Influence Success Follow TETO Principle

How to make sure that website meets user’s expectations? You can’t just assume that it does — you need to test your design to see how users engage with it. Testing can reveal much more than how usable a site is — it can also demonstrate the users’ emotional response to the design. That’s why TETO-principle (test early, test often) should be applied to every web design project.

  • Don’t expect to build a perfect product right from the first attempt.
    Product design is an ongoing journey for both you and your users. That means that you design something, test it, rework it and then test it again.
  • Use comparative testing to find the best solution for your users.
    If you have multiple solutions to a particular problem and not sure what solution works best for your product, you can use A/B testing to validate it. Compare what users do in one scenario vs. another, and see which design is the most effective.
  • Collect qualitative feedback.
    All measurable data that we’ve talked about in previous sections can tell you a lot of answers on “*how many*” questions. But this data won’t tell you why people interact in a way they do. Facing readability issues, hesitation when filling out a payment form, using search because site’s navigation is really hard to deal with — all of these types of details are critical to understanding the user experience. They might be a reason why people abandon a process and leave the site. It’s possible to find answers to why questions by observing and interviewing your users.
User interview (Illustration by Igor Kopelnitsky) Data-Informed, Not Data-Driven Design

When product teams collect data, they usually follow either data-driven or data-informed design process. The latter is more preferable. Design shouldn’t be driven by data, it should be informed by data.

Don’t Be Obsessed Over Numbers

A lot of metrics get reported simply because they are flowing in from analytics tool. While it’s tempting to report a lot of different things and hope that this will make your report more valuable, in reality, this usually leads to more complex reports that are hard to read.

Don’t Fall Into The Trap Of Complete Redesign

All too often design teams try to introduce a complete rework for a solution which they believe will result in more successful web experience. Jared Spool calls major product redesign a Flip-the-Switch strategy — “the most ineffective way to get major changes into a design.” In the article, “ The Quiet Death of the Major Re-Launch,” he shares a story on the eBay redesign — and it’s a great reminder of why users don’t like dramatic changes. A complete redesign that brings new visual and interaction design might be too much change and have an adverse effect.

If you have an existing website, instead of investing in a large scale redesign focus on subtle evolution, make small and incremental changes that can (over time) improve conversions without visitors even noticing that changes have been made.

Conclusion

So, how do you know that your website is a success? As a product creator, you must first define what success means to you. For that, it’s always important to have a big picture in mind of what it is that you want to achieve.

The next step would be to focus on metrics. Metrics will show you how a site changes over time. They will help you fill in the blanks between what has happened and why.

Recommended Reading

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

(ra, il)
Categories: Web Design

Getting Started With Redux: Learn by Example

Tuts+ Code - Web Development - Mon, 05/28/2018 - 09:00

Redux helps you manage state by setting the state up at a global level. In the previous tutorial, we had a good look at the Redux architecture and the integral components of Redux such as actions, action creators, the store, and reducers. 

In this second post of the series, we are going to bolster our understanding of Redux and build on top of what we already know. We will start by creating a realistic Redux application—a contact list—that's more complex than a basic counter. This will help you strengthen your understanding of the single store and multiple reducers concept which I introduced in the previous tutorial. Then later we'll talk about binding your Redux state with a React application and the best practices that you should consider while creating a project from scratch. 

However, it's okay if you haven't read the first post—you should still be able to follow along as long as you know the Redux basics. The code for the tutorial is available in the repo, and you can use that as a starting point. 

Creating a Contact List Using Redux

We're going to build a basic contact list with the following features:

  • display all contacts
  • search for contacts
  • fetch all contacts from the server
  • add a new contact
  • push the new contact data into the server

Here's what our application is going to look like:

Final product — Contact list View


Final Product — Add contact view

Covering everything in one stretch is hard. So in this post we're going to focus on just the Redux part of adding a new contact and displaying the newly added contact. From a Redux perspective, we'll be initializing the state, creating the store, adding reducers and actions, etc. 

In the next tutorial, we'll learn how to connect React and Redux and dispatch Redux actions from a React front-end. In the final part, we'll shift our focus towards making API calls using Redux. This includes fetching the contacts from the server and making a server request while adding new contacts. Apart from that, we'll also create a search bar feature that lets you search all the existing contacts. 

Create a Sketch of the State Tree

You can download the react-redux demo application from my GitHub repository. Clone the repo and use the v1 branch as a starting point. The v1 branch is very similar to the create-react-app template. The only difference is that I've added a few empty directories to organise Redux. Here's the directory structure.

. ├── package.json ├── public ├── README.md ├── src │ ├── actions │ ├── App.js │ ├── components │ ├── containers │ ├── index.js │ ├── reducers │ └── store └── yarn.lock

Alternatively, you can create a new project from scratch. Either way, you will need to have installed a basic react boilerplate and redux before you can get started. 

It's a good idea to have a rough sketch of the state tree first. In my opinion, this will save you lots of time in the long run. Here's a rough sketch of the possible state tree. 

const initialState = { contacts: { contactList: [], newContact: { name: '', surname: '', email: '', address: '', phone: '' }, ui: { //All the UI related state here. eg: hide/show modals, //toggle checkbox etc. } } }  

Our store needs to have two properties—contacts and ui. The contacts property takes care of all contacts-related state, whereas the ui handles UI-specific state. There is no hard rule in Redux that prevents you from placing the ui object as a sub-state of contacts. Feel free to organize your state in a way that feels meaningful to your application. 

The contacts property has two properties nested inside it—contactlist and newContact. The contactlist is an array of contacts, whereas newContact temporarily stores contact details while the contact form is being filled. I am going to use this as a starting point for building our awesome contact list app. 

How to Organize Redux

Redux doesn't have an opinion about how you structure your application. There are a few popular patterns out there, and in this tutorial, I will briefly talk about some of them. But you should pick one pattern and stick with it until you fully understand how all the pieces are connected together.

The most common pattern that you'll find is the Rails-style file and folder structure. You'll have several top-level directories like the ones below:

  • components: A place to store the dumb React components. These components do not care whether you're using Redux or not.
  • containers: A directory for the smart React components that dispatch actions to the Redux store. The binding between redux and react will be taking place here. 
  • actions: The action creators will go inside this directory. 
  • reducers: Each reducer gets an individual file, and you'll be placing all the reducer logic in this directory.
  • store: The logic for initializing the state and configuring the store will go here. 

The image below demonstrates how our application might look if we follow this pattern:

The Rails style should work for small and mid-sized applications. However, when your app grows, you can consider moving towards the domain-style approach or other popular alternatives that are closely related to domain-style. Here, each feature will have a directory of its own, and everything related to that feature (domain) will be inside it. The image below compares the two approaches, Rails-style on the left and domain-style on the right. 

For now, go ahead and create directories for components, containers, store, reducers, and action. Let's start with the store. 

Single Store, Multiple Reducers

Let's create a prototype for the store and the reducer first. From our previous example, this is how our store would look: 

const store = createStore( reducer, { contacts: { contactlist: [], newContact: { } }, ui: { isContactFormHidden: true } }) const reducer = (state, action) => { switch(action.type) { case "HANDLE_INPUT_CHANGE": break; case "ADD_NEW_CONTACT": break; case "TOGGLE_CONTACT_FORM": break; } return state; }

The switch statement has three cases that correspond to three actions that we will be creating. Here is a brief explanation of what the actions are meant for. 

  • HANDLE_INPUT_CHANGE: This action gets triggered when the user inputs new values into the contact form.
  • ADD_NEW_CONTACT: This action gets dispatched when the user submits the form.
  • TOGGLE_CONTACT_FORM: This is a UI action that takes care of showing/hiding the contact form. 

Although this naive approach works, as the application grows, using this technique will have a few shortcomings.

  1. We're using a single reducer. Although a single reducer sounds okay for now, imagine having all your business logic under one very large reducer.  
  2. The code above doesn't follow the Redux structure that we've discussed in the previous section.

To fix the single reducer issue, Redux has a method called combineReducers that lets you create multiple reducers and then combine them into a single reducing function. The combineReducers function enhances readability. So I am going to split the reducer into two—a contactsReducer and a uiReducer. 

In the example above, createStore accepts an optional second argument which is the initial state. However, if we are going to split the reducers, we can move the whole initialState to a new file location, say reducers/initialState.js. We will then import a subset of initialState into each reducer file. 

Splitting the Reducer 

Let's restructure our code to fix both the issues. First, create a new file called store/createStore.js and add the following code:

import {createStore} from 'redux'; import rootReducer from '../reducers/'; /*Create a function called configureStore */ export default function configureStore() { return createStore(rootReducer); }

Next, create a root reducer in reducers/index.js as follows:

import { combineReducers } from 'redux' import contactsReducer from './contactsReducer'; import uiReducer from './uiReducer'; const rootReducer =combineReducers({ contacts: contactsReducer, ui: uiReducer, }) export default rootReducer;

Finally, we need to create the code for the contactsReducer and uiReducer.

reducers/contactsReducer.jsimport initialState from './initialState'; export default function contactReducer(state = initialState.contacts, action) { switch(action.type) { /* Add contacts to the state array */ case "ADD_CONTACT": { return { ...state, contactList: [...state.contactList, state.newContact] } } /* Handle input for the contact form. The payload (input changes) gets merged with the newContact object */ case "HANDLE_INPUT_CHANGE": { return { ...state, newContact: { ...state.newContact, ...action.payload } } } default: return state; } }reducers/uiReducer.jsimport initialState from './initialState'; export default function uiReducer(state = initialState.ui, action) { switch(action.type) { /* Show/hide the form */ case "TOGGLE_CONTACT_FORM": { return { ...state, isContactFormHidden: !state.isContactFormHidden } } default: return state; } }

When you're creating reducers, always keep the following in mind: a reducer needs to have a default value for its state, and it always needs to return something. If the reducer fails to follow this specification, you will get errors.

Since we've covered a lot of code, let's have a look at the changes that we've made with our approach:

  1. The combineReducers call has been introduced to tie together the split reducers.
  2. The state of the ui object will be handled by uiReducer and the state of the contacts by the contactsReducer. 
  3. To keep the reducers pure, spread operators have been used. The three dot syntax is part of the spread operator. If you're not comfortable with the spread syntax, you should consider using a library like Immutability.js.
  4. The initial value is no longer specified as an optional argument to createStore. Instead, we've created a separate file for it called initialState.js. We're importing initialState and then setting the default state by doing state = initialState.ui. 
State Initialization

Here's the code for the reducers/initialState.js file.

const initialState = { contacts: { contactList: [], newContact: { name: '', surname: '', email: '', address: '', phone: '' }, }, ui: { isContactFormHidden: true } } export default initialState;Actions and Action Creators

Let's add a couple of actions and action creators for adding handling form changes, adding a new contact, and toggling the UI state. If you recall, action creators are just functions that return an action. Add the following code in actions/index.js.

export const addContact =() => { return { type: "ADD_CONTACT", } } export const handleInputChange = (name, value) => { return { type: "HANDLE_INPUT_CHANGE", payload: { [name]: value} } } export const toggleContactForm = () => { return { type: "TOGGLE_CONTACT_FORM", } }

Each action needs to return a type property. The type is like a key that determines which reducer gets invoked and how the state gets updated in response to that action. The payload is optional, and you can actually call it anything you want. 

In our case, we've created three actions.

The TOGGLE_CONTACT_FORM doesn't need a payload because every time the action is triggered, the value of ui.isContactFormHidden gets toggled. Boolean-valued actions do not require a payload. 

The HANDLE_INPUT_CHANGE action is triggered when the form value changes. So, for instance, imagine that the user is filling the email field. The action then receives "email" and "bob@example.com" as inputs, and the payload handed over to the reducer is an object that looks like this:

{ email: "bob@example.com" }

The reducer uses this information to update the relevant properties of the newContact state. 

Dispatching Actions and Subscribing to the Store

The next logical step is to dispatch the actions. Once the actions are dispatched, the state changes in response to that. To dispatch actions and to get the updated state tree, Redux offers certain store actions. They are:

  • dispatch(action): Dispatches an action that could potentially trigger a state change. 
  • getState(): Returns the current state tree of your application.
  • subscriber(listener): A change listener that gets called every time an action is dispatched and some part of the state tree is changed. 

Head to the index.js file and import the configureStore function and the three actions that we created earlier:

import React from 'react'; import {render}from 'react-dom'; import App from './App'; /* Import Redux store and the actions */ import configureStore from './store/configureStore'; import {toggleContactForm, handleInputChange} from './actions';

Next, create a store object and add a listener that logs the state tree every time an action is dispatched:

const store = configureStore(); //Note that subscribe() returns a function for unregistering the listener const unsubscribe = store.subscribe(() => console.log(store.getState()) )

Finally, dispatch some actions:

/* returns isContactFormHidden returns false */ store.dispatch(toggleContactForm()); /* returns isContactFormHidden returns false */ store.dispatch(toggleContactForm()); /* updates the state of contacts.newContact object */ store.dispatch(handleInputChange('email', 'manjunath@example.com')) unsubscribe;

If everything is working right, you should see this in the developer console.

That's it! In the developer console, you can see the Redux store being logged, so you can see how it changes after each action.

Summary

We've created a bare-bones Redux application for our awesome contact list application. We learned about reducers, splitting reducers to make our app structure cleaner, and writing actions for mutating the store. 

Towards the end of the post, we subscribed to the store using the store.subscribe() method. Technically, this isn't the best way to get things done if you're going to use React with Redux. There are more optimized ways to connect the react front-end with Redux. We'll cover those in the next tutorial.  

Categories: Web Design

Introduction to API Calls With React and Axios

Tuts+ Code - Web Development - Mon, 05/28/2018 - 05:37

This tutorial will teach you how to use Axios to fetch data and then how to manipulate it and eventually display it on your page with filtering functionality. You will learn how to use the map, filter and includes methods along the way. On top of that, you will be creating a Higher-Order Component (HOC) to handle the loading state of the fetched data from the API endpoint.

Let's start with a clean React app. I assume you use create-react-app, and the filenames will be in accordance with its outputs.

We only need to install the Axios module for this tutorial.

Go to your project directory through the terminal window and then type in npm install axios -save in order to install Axios for your project locally.

Fetching the Data

We will be using the Random User Generator API to fetch random user information to use in our application.

Let's add the Axios module to our application by importing it into our App.js file.

import axios from 'axios'

The Random User Generator API offers a bunch of options for creating various types of data. You can check the documentation for further information, but for this tutorial, we will keep it simple.

We want to fetch ten different users, and we only need the name, surname, and a unique ID, which is required for React when creating lists of elements. Also, to make the call a bit more specific, let's include the nationality option as an example.

Below is the API that we will make a call for.

Note that I didn't use the id option provided in the API due to the fact that it sometimes returns null for some users. So, just to make sure that there will be a unique value for each user, I included the registered option in the API.

https://randomuser.me/api/?results=10&inc=name,registered&nat=fr

You can copy and paste it into your browser and you will see the returned data in JSON format.

Now, the next thing is to make an API call through Axios.

First of all, let's create a state so that we can store the fetched data.

Inside our App component, add a class constructor and then create the state.

constructor(props){ super(props) this.state = { users: [], store: [] } }

Here you see users and store states. One will be used for filtering purposes and will not be edited, and the other one will hold the filter results that will be shown in the DOM.

Now go ahead and create the componentDidMount() lifecycle hook.

Inside this lifecycle hook, we will fetch the data, and then by using the map method, we will create new intermediate data that we will use inside the setState method.

If you check the result of the API call in your browser, you will see that there are first and last key-value pairs inside the name object but no key-value pair for a full name. So we will be combining first and last to create a full name inside a new JavaScript Object. Note that JSON and JavaScript Object are different things, although they basically work the same way.

Let's move step by step.

Add the following code to your App component.

componentDidMount(){ axios.get('https://randomuser.me/api/?results=10&inc=name,registered&nat=fr') .then(json => console.log(json)) }

When you check the console, you will see an object output. If you open up this object, there is another object inside it named data, and inside data, there is an array named results.

Let's further change the console.log(json).

componentDidMount(){ axios.get('https://randomuser.me/api/?results=10&inc=name,registered&nat=fr') .then(json => console.log(json.data.results[0].name.first)) }

Here we reached the name of the first value inside the results array.

Now let's use the built-in map method of JavaScript in order to iterate through each element inside the array and create a new array of JavaScript Objects with a new structure.

componentDidMount(){ axios.get('https://randomuser.me/api/?results=10&inc=name,registered&nat=fr') .then(json => json.data.results.map(result => ( { name: `${result.name.first} ${result.name.last}`, id: result.registered }))) .then(newData => console.log(newData)) }

Here, we called the map method on json.data.results, which is an array, and then referred each element of the array as result (notice the singular/plural difference). Then, by using the key-value pair of each object inside the array, we created another object with name and id key-value pairs.

At the end, we used another then method in order to be able to refer to our new data. We referred it as newData, and then we just logged to the console to see if everything went as planned.

You should see a new array with objects having name and id pairs.

Storing the Data

Instead of logging the result to the console, we have to store it. In order to do that, we will use setState.

componentDidMount(){ axios.get('https://randomuser.me/api/?results=10&inc=name,registered&nat=fr') .then(json => json.data.results.map(result => ( { name: `${result.name.first} ${result.name.last}`, id: result.registered }))) .then(newData => this.setState({users: newData, store: newData})) .catch(error => alert(error)) }

Here, we initially set both users and store data with our new newData array.

We need two variables due to the fact that we need to store the original data and should never lose it. By using the information inside the store state, we can filter the data and then populate the users state and show it on the page. This will be clearer when we implement the filtering functionality.

Last but not least, we added catch to actually catch any possible errors during fetching and display the error as an alert message.

Filtering Functionality

The idea of filtering is quite simple. We have our store state, and it always keeps the original data without changing. Then, by using the filter function on this state, we only get the matching elements and then assign them to the users state.

this.state.store.filter(item => item.name.toLowerCase().includes(e.target.value.toLowerCase()))

The filter method requires a function as an argument, a function to be run for each element in the array. Here we refer each element inside the array as item. Then we take the name key of each item and convert it to lower case in order to make our filtering functionality case insensitive. 

After we have the name key for the item, we check if this one includes the search string we typed in. includes is another built-in JavaScript method. We pass the search string typed in the input field as an argument to includes, and it returns if this string is included in the variable it was called on. Again, we convert the input string to lower case so that it does not matter whether you type upper or lower case inputs. 

In the end, the filter method returns the matching elements. So we simply take these elements and store them inside the users state through setState.

Below you can find the final version of the function we created.

filterNames(e){ this.setState({users: this.state.store.filter(item => item.name.toLowerCase().includes(e.target.value.toLowerCase()))}) }Creating the Components

Although for this small example we could put everything inside the App component, let's take advantage of React and make some small functional/stateless components.

Let's add the following structure to the render method of the App component.

render() { const {users} = this.state return ( <div className="Card"> <div className="header">NAME LIST</div> <SearchBar searchFunc={(e) => this.filterNames(e)}/> <List usernames={users}/> </div> ); }

For the time being, we will be just focusing on the functionality. Later, I will provide the CSS file I have created.

Notice that we have the searchFunc prop for the SearchBar component and the usernames prop for the List component.

Note that we use the users state instead of the store state to show the data because the users state is the one containing the filtered results.

The SearchBar Component

This component is quite straightforward. It only takes the filterNames function as a prop and calls this function when the input field changes.

import React from 'react' const SearchBar = props => { return( <div> <input className="searchBar" type="text" placeholder="search user" onChange={props.searchFunc}/> </div> ) } export default SearchBar The List Component

This one will simply list the names of the users.

import React, {Component} from 'react' import LoadingHOC from './LoadingHOC' import '../styles/main.css' const List = (props) =>{ const{usernames} = props return( <ul> {usernames.map(user => <li key={user.id}>{user.name}</li>)} </ul> ) } export default LoadingHOC(List)

Here, we again used the map method to get each item in the array and create a <li> item out of it. Note that when you use map to create a list of items, you need to use a key in order for React to keep track of each list item.

Notice that we wrapped List with another component named LoadingHOC before exporting it. This is how Higher-Order Components (HOCs) work. 

What we did here is to pass our component as an argument to another component before exporting it. So this LoadingHOC component will be enhancing our component with new features.

The LoadingHOC Component

As I briefly explained before, a HOC takes a component as an input and then exports an enhanced version of the input component.

import React, {Component} from 'react' import spinner from '../spinner.gif' const LoadingHOC = (WrappedState) =>{ return( class LoadingHOC extends Component{ render(){ return this.props.usernames.length === 0 ? <img className="isLoading" src={spinner}/> : <WrappedState {...this.props}/> } } ) } export default LoadingHOC

Inside the HOC, we can directly access the props of the input component. So we just check whether the length of the usernames prop is 0 or not. If it is 0, this means that the data has yet to be fetched because it is an empty array by default. So we just show a spinner GIF that we imported. Otherwise, we just show the input component itself.

It's imported in order not to forget to pass any props and states back to the input component with a spread operator. Otherwise, your component would be deprived of them.

CSS File

Below you can find the CSS file specific to this example.

body, html { -webkit-font-smoothing: antialiased; margin: 0; padding: 0; background-color: #f1f1f1; font-family: 'Raleway', sans-serif; -webkit-text-size-adjust: 100%; } body { display: flex; justify-content: center; font-size: 1rem/16; margin-top: 50px; } li, ul { list-style: none; margin: 0; padding: 0; } ul { margin-top: 10px; } li { font-size: 0.8rem; margin-bottom: 8px; text-align: center; color: #959595; } li:last-of-type { margin-bottom: 50px; } .Card { font-size: 1.5rem; font-weight: bold; display: flex; flex-direction: column; align-items: center; width: 200px; border-radius: 10px; background-color: white; box-shadow: 0 5px 3px 0 #ebebeb; } .header { position: relative; font-size: 20px; margin: 12px 0; color: #575757; } .header::after { content: ''; position: absolute; left: -50%; bottom: -10px; width: 200%; height: 1px; background-color: #f1f1f1; } .searchBar { text-align: center; margin: 5px 0; border: 1px solid #c4c4c4; height: 20px; color: #575757; border-radius: 3px; } .searchBar:focus { outline-width: 0; } .searchBar::placeholder { color: #dadada; } .isLoading { margin: 30px 0; width: 150px; filter: opacity(0.3); } Conclusion

Throughout this tutorial, we took a quick look at the Random User Generator API as a source of random data. Then we fetched the data from an API endpoint and restructured the results inside a new JavaScript Object with the map method.

The next thing was to create a filtering function with the filter and includes methods. Finally, we created two different components and enhanced one of them with a Higher-Order Component (HOC) by introducing a loading indicator when the data is not there yet.

Over the last couple of years, React has grown in popularity. In fact, we have a number of items in Envato Market that are available for purchase, review, implementation, and so on. If you’re looking for additional resources around React, don’t hesitate to check them out.

Categories: Web Design

How To Deliver A Successful UX Project In The Healthcare Sector

Smashing Magazine - Mon, 05/28/2018 - 04:50
How To Deliver A Successful UX Project In The Healthcare Sector How To Deliver A Successful UX Project In The Healthcare Sector Sven Jungmann & Karolin Neubauer 2018-05-28T13:50:32+02:00 2018-06-14T13:28:26+00:00

A mid-career UX researcher was hired to understand the everyday needs, perceptions, and concerns of patients in a hospital in Berlin, Germany. She used rigorous observation and interviewing methods just like she teaches them to design thinking students at a nearby university. She returned with a handful of actionable insights that our product team found useful, somewhat at least.

However, we were surprised that her recommendations gravitated towards convenience issues such as “Patients want to know the food menu” or “Users struggle to remember who their doctors are.” Entirely missing were reports of physical and psychological complaints. We would at least have expected sleeping problems: Given that 80% of working Germans don’t sleep well and nearly 10% even appear to have severe sleeping disorders (link in German), why did no one mention it?

“We only see what we know.”

— Johann Wolfgang von Goethe (1749-1832)

If you are a UX researcher about to embark on a project with hospitalized patients and you want to avoid missing out on deep concerns and problems of users, then maybe this article can help you strengthen your awareness for particular challenges of clinical UX.

It is difficult to get in touch with real patients and get permission from clinical staff to access the right people. We are fortunate to have access to a network of more than 100 hospitals in Germany thanks to our sister Helios Kliniken GmbH, which is Europe’s largest private hospital provider. Our experience with clinical UX research taught us the importance of stressing that we cannot assume that patients bring up relevant concerns by themselves.

We describe three reasons we think are important to improve the quality and quantity of your findings. Generally speaking, this article emphasizes the need for UX practitioners to be mindful of their participants’ emotional and physical state. But we also discuss how we think UX researchers should prepare for and conduct a research project in the healthcare sector.

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

Table of Contents → The Three B’s That Complicate UX Research In Hospitals

We’ve been thinking much about user research in hospital settings recently. Our new company, smart Helios, a digital health development firm, is a spin-off of Helios Kliniken, Europe’s largest private hospital chain. To inform our lean software development, we thoroughly embrace iterative empathetic observation and end-user interviews at each step of a development cycle (i.e., ideation, prototyping, and testing).

We learned that qualitative research in a hospital setting brings its challenges. We think it is worth considering them, especially those we discuss here, called the three B’s: Biases, Barriers, and Background.

Here’s an overview:

  1. Biases
    Psychological mechanisms can affect our patients’ thinking and hence diminish the results of our findings.
  2. Barriers to trust
    Patients rarely share intimate needs with a non-medical interviewer easily. This can create blind spots in our research.
  3. Background
    Internal and external factors such as wealth, socio-economic status, sanitation, education, and access to healthcare can influence our health as well as the care patients receive. The quality of care also depends on the hospital’s infrastructure and staff experience with a particular disease or procedure. These differences make it challenging to generalize findings.

We also discuss remedies that can help overcome these challenges and distill more valuable insights. They include:

  • Conducting a thorough and well-prepared interview.
  • Including healthcare providers in the process.
  • Drawing on quantitative data to guide some of the qualitative user research.
Biases: We Are Fantastic At Lying To Ourselves, Whether Or Not We’re Patients

Psychologists call them cognitive biases: they negatively affect how accurately we perceive and remember events or feelings, and we possess impressive amounts of them.

For example, people remember information better if it is more recent or salient. If you ask a patient about the initial appointment with her oncologist (this is rarely good news), don’t be surprised if she remembers only a quarter of it. Hospitalized patients are typically overwhelmed by the unfamiliar situation they’re in and often under stress and that influences their memory.

Hence it makes a difference when you ask them in their patient journey. Even in one day, patients face different problems that affect what’s top of mind at the moment you observe or interview them:

  • In the morning, when the painkillers have worn off during sleep, regaining control over physical pain is all that matters.
  • During the day, worries about upcoming procedures might dominate their thoughts or they could be focused on their hunger while they’re not allowed to eat or drink ahead of a diagnostic test.
  • In the evening, they might be afraid that they won’t be able to update their relatives appropriately.
  • At night, some struggle to sleep because of the hospital noise or their worries.
Takeaways:
  • Try interviewing users at different times of the day and different moments of their journey and take note of how findings vary.
  • Always get an orientation about where your users stand within their patient journey. Explore what happened in the previous hours or days and what diagnostics or treatments lie ahead of them.
  • Beware that our psyches possess a plethora of mechanisms to limit rationality and prevent past events from entering our conscious mind. You cannot control them all, but it improves your research if you notice them.
Barriers To Trust: Who Is Asking Matters, Too

It’s not just about how and when; it also matters who is asking. Even if a patient agrees to speak with us, what she shares will highly depend on how much she trusts us. One of us observed as a clinician how often his patients need to build up trust, sometimes over days until they ‘confess’ certain concerns. That’s especially true when problems have a psychological component (e.g., sleeping disorders) or are stigmatized (e.g., certain infectious diseases).

The more knowledgeable you are about health problems, the better you can steer interviews towards relevant issues. If you do this empathetically, your interviewees might find it easier to speak about them. Don’t get frustrated, however, if they don’t. Some people need a lot of trust, and there’s rarely a shortcut to earning it. In these cases, there’s something else you can do: include subjects who are not your target users but still have crucial insights in your interviews.

Take the nurse, for example. She might know from her previous night shift how many patients had trouble sleeping and who might agree to talk about it. The doctors will know which crucial questions they get asked frequently. And the housekeeping staff can share stories about the patients’ hygiene concerns. Listen closely to them: many of the staffs’ pain points likely hint to patients’ pain points, too. The more observers you allow to shed light on one subject, the better your chances to understand your patients’ experiences and the broader your perception of the system will be.

Takeaways:
  • Try to interview people involved in your users’ care.
  • Ask the clinical staff for guidance on which patients to ask about specific problems.
  • Even if patients are your primary users, make sure to ask health care providers, such as doctors, nurses, or therapists about common patient needs.
  • Schedule repeated interviews with patients if possible to build the trust necessary for sharing critical concerns.
A large, printed and ‘living’ patient journey helps to constantly challenge and refine assumptions. (Large preview) Background: Mind The Worlds In And Around The Patients

Different patients have different needs. This is obvious, and part of the reason why UX researchers develop personas, conduct semi-structured interviews, focus group discussions, and observe subjects to explore the multiple realities of our participants. But there’s still a problem we can’t dismiss. Even within our hospitals inside Germany, people’s realities can differ greatly depending on their income, education, insurance, place of residence, etc.

What you discover in one hospital or region might not apply elsewhere. This can be a problem if you want to deploy your products at scale. If you have the opportunity, you should go the extra mile to conduct UX research in different hospitals to understand the needs and what drives adoption.

If some regions show poor sales, conduct field research in these regions to revisit your personas. In fact, don’t just challenge the personas, also explore the environment.

Here’s an example of why that matters: We developed a tool that relies on data from a hospital information system. This worked well in one clinic were staff was spread over different parts of the building, turning digital communication into an effective medium. In another hospital, however, the relevant people sat in the same room, making face-to-face communication significantly better than typing information into electronic records.

Takeaways:
  • Go beyond personas or archetypes and seek to understand the different realities between hospitals, wards, and regions.
  • Develop and constantly improve a rollout-playbook that lists local challenges and how you solved them to inform future expansions.
Sorry, Ignorance Is Not Bliss

Some UX researchers seem to believe that it is beneficial to enter an interview unprepared to avoid bias. Some shy away from acquiring relevant medical knowledge, thinking that (since they are not trained medical professionals) they won’t grasp the concepts anyway. Some feel that understanding the medical context of their interviewees' situation will not add value to their research since they solely focus on the subjective experience of the disease.

But in evidence-based healthcare, conducting research on patients without previous peer-reviewed literature and guideline research is not only unprofessional but often even considered unethical. We should not fall prey to the illusion that ignorance frees us from bias.

The good news is that in healthcare, we are privileged to have a large body of well-conducted studies and systematic reviews available online, many of them free to access. PubMed is an excellent and open source, tutorials on how to use are abundantly available online (we think this is a good primer). Or if you have the budget, paid sites like UpToDate provide comprehensive disease reviews written both for professionals and for laypeople.

We know that UX researchers who are rightfully focused on ‘getting out of the building’ might not enjoy spending many hours on literature research but we are convinced that this will help you form better hypotheses and questions.

Moreover, if you start with clearly predefined research questions and seek answers in the scientific medical literature, you might save time and discover questions that you wouldn’t have thought of. For example, it is advised that individuals undergoing hip surgery should practice using crutches before the operation because it is already difficult enough even without the postoperative pain and swelling. This knowledge, obtained from literature research, could help move from more open questions, such as:

  • “How do patients prepare for a hip replacement surgery?” or
  • “What perceived needs to patients have ahead of hip surgery?”

To more concrete questions such as:

  • “What are the most important preparatory measures that many patients are currently unaware of?”
Takeaway:
  • Do a systematic literature review to inform your research.
Let The Data Guide You And You Guide The Data

To take this further, we’re also developing methods to use quantitative analytics and Deep Learning to guide our qualitative research. Our machine learning engineer just deployed AI to crawl the web for colon cancer blogs to identify hot topics that remained unmentioned in qualitative reviews. We defined “hot” as having many views, many comments, and many likes.

Or you can uncover semantic structures (see picture). These findings can then guide the UX researchers. Similarly, qualitative research can yield hypotheses that we can try to validate with passively collected data. For example, if you think that sleeping problems are common, you could (user consent provided) use your app to measure phone use at night as a proxy for sleeplessness.

Deploying topic modeling to find semantic structures in texts on colon cancer to inform our qualitative researchers. (Large preview) Conclusion

Many of our suggestions are not new to well-trained UX researchers. We are aware of that. But in our experience, it is worth stressing the importance of mindfulness towards the three Bs: Biases, Barriers to trust, and Background. Here’s a summary of some of the recommendations to overcome the 3 Bs:

  • Prepare interviews with literature research on the topic (e.g., on Pubmed.gov).
  • Ask doctors which patients are suitable for interview.
  • Include those who care for your users, including nurses, therapists, and relatives.
  • Cooperate with the data scientists or web analysts in your team, if you have them.
  • Understand that it takes users time to build trust to tell you about some needs.
  • Explore how realities differ not only by personas, but also by regions and hospitals.
  • Stay aware that, no matter how much you try, the influence of the 3Bs can only be reduced, and not entirely removed.

We wish you well and thank you for making the world a healthier place.

The authors would like to thank their former colleague, Tim Leinert, for his thoughtful input to this piece.

(cc, ra, yk, il)
Categories: Web Design

10 UX Tips to Build a High Converting Landing Page

In the broader sense, a landing page is the web page through which a visitor “lands” a website. Homepages frequently serve as landing pages, however any other page can...

The post 10 UX Tips to Build a High Converting Landing Page appeared first on Onextrapixel.

Categories: Web Design

A Beginner's Guide to Regular Expressions in JavaScript

Tuts+ Code - Web Development - Fri, 05/25/2018 - 06:00

Everyone working with JavaScript will have to deal with strings at one point or other. Sometimes, you will just have to store a string inside another variable and then pass it over. Other times, you will have to inspect it and see if it contains a particular substring.

However, things are not always this easy. There will be times when you will not be looking for a particular substring but a set of substrings which follow a certain pattern.

Let's say you have to replace all occurrences of "Apples" in a string with "apples". You could simply use theMainString.replace("Apples", "apples"). Nice and easy.

Now let's say you have to replace "appLes" with "apples" as well. Similarly, "appLES" should become "apples" too. Basically, all case variations of "Apple" need to be changed to "apple". Passing simple strings as an argument will no longer be practical or efficient in such cases.

This is where regular expressions come in—you could simply use the case-insensitive flag i and be done with it. With the flag in place, it doesn't matter if the original string contained "Apples", "APPles", "ApPlEs", or "Apples". Every instance of the word will be replaced with "apples".

Just like the case-insensitive flag, regular expressions offer a lot of other features which will be covered in this tutorial.

Using Regular Expressions in JavaScript

You have to use a slightly different syntax to indicate a regular expression inside different String methods. Unlike a simple string, which is enclosed in quotes, a regular expression consists of a pattern enclosed between slashes. Any flags that you use in a regular expression will be appended after the second slash.

Going back to the previous example, here is what the replace() method would look like with a regular expression and a simple string.

"I ate Apples".replace("Apples", "apples"); // I ate apples "I ate Apples".replace(/Apples/i, "apples"); // I ate apples "I ate aPPles".replace("Apples", "apples"); // I ate aPPles "I ate aPPles".replace(/Apples/i, "apples"); // I ate apples

As you can see, the regular expression worked in both cases. We will now learn more about flags and special characters that make up the pattern inside a regular expression.

Backslash in Regular Expressions

You can turn normal characters into special characters by adding a backslash before them. Similarly, you can turn special characters into normal characters by adding a backslash before them.

For example, d is not a special character. However, \d is used to match a digit character in a string. Similarly, D is not a special character either, but \D is used to match non-digit characters in a string.

Digit characters include 0, 1, 2, 3, 4, 5, 6, 7, 8, and 9. When you use \d inside a regular expression, it will match any of these nine characters. When you use \D inside a regular expression, it will match all the non-digit characters.

The following example should make things clear.

"L8".replace(/\d/i, "E"); // LE "L8".replace(/\D/i, "E"); // E8 "LLLLL8".replace(/\D/i, "E"); // ELLLL8

You should note that only the first matched character is replaced in the third case. You can also use flags to replace all the matches. We will learn about such flags later.

Just like \d and \D, there are other special character sequences as well.

  1. You can use \w to match any "word" character in a string. Here, word character refers to A-Z, a-z, 0-9, and _. So, basically, it will match all digits, all lowercase and uppercase alphabets, and the underscore.
  2. You can use \W to match any non-word character in a string. It will match characters like %, $, #, ₹, etc.
  3. You can use \s to match a single white space character, which includes space, tab, form feed, and line feed. Similarly, you can use \S to match all other characters besides white space.
  4. You can also look for a specific white space character using \f, \n, \r, \t, and \v, which stand for form feed, line feed, carriage return, horizontal tab, and vertical tab.

Sometimes, you will face situations where you need to replace a word with its substitute, but only if it is not part of a larger word. For example, consider the following sentence:

"A lot of pineapple images were posted on the app".

In this case, we want to replace the word "app" with "board". However, using a simple regular expression pattern will turn "apple" into "boardle", and the final sentence would become:

"A lot of pineboardle images were posted on the app".

In such cases, you can use another special character sequence: \b. This checks for word boundaries. A word boundary is formed by use of any non-word characters like space, "$", "%", "#", etc. Watch out, though—it also includes accented characters like "ü".

"A lot of pineapple images were posted on the app".replace(/app/, "board"); // A lot of pineboardle images were posted on the app "A lot of pineapple images were posted on the app".replace(/\bapp/, "board"); // A lot of pineapple images were posted on the board

Similarly, you can use \B to match a non-word boundary. For example, you could use \B to only match "app" when it is within another word, like "pineapple".

Matching a Pattern "n" Number of Times

You can use ^ to tell JavaScript to only look at the beginning of the string for a match. Similarly, you can use $ to only look at the end of the string for a match.

You can use * to match the preceding expression 0 or more times. For example, /Ap*/ will match A, Ap, App, Appp, and so on.

In a similar manner, you can use + to match the preceding expression 1 or more times. For example, /Ap+/ will match Ap, App, Appp, and so on. The expression will not match the single A this time.

Sometimes, you only want to match a specific number of occurrences of a given pattern. In such cases, you should use the {n} character sequence, where n is a number. For instance, /Ap{2}/ will match App but not Ap. It will also match the first two 'p's in Appp and leave the third one untouched.

You can use {n,} to match at least 'n' occurrences of a given expression. This means that /Ap{2,}/ will match App but not Ap. It will also match all the 'p's in Apppp and replace them with your replacement string.

You can also use {n,m} to specify a minimum and maximum number and limit the number of times the given expression should be matched. For example, /Ap{2,4}/ will match App, Appp, and Apppp. It will also match the first four 'p's in Apppppp and leave the rest of them untouched.

"Apppppples".replace(/Ap*/, "App"); // Apples "Ales".replace(/Ap*/, "App"); // Apples "Appppples".replace(/Ap{2}/, "Add"); // Addppples "Appppples".replace(/Ap{2,}/, "Add"); // Addles "Appppples".replace(/Ap{2,4}/, "Add"); // AddplesUsing Parentheses to Remember Matches

So far, we have only replaced patterns with a constant string. For example, in the previous section, the replacement we used was always "Add". Sometimes, you will have to look for a pattern match inside the given string and then replace it with a part of the pattern.

Let's say you have to find a word with five or more letters in a string and then add an "s" at the end of the word. In such cases, you will not be able to use a constant string value as a replacement as the final value depends on the matching pattern itself.

"I like Apple".replace(/(\w{5,})/, '$1s'); // I like Apples "I like Banana".replace(/(\w{5,})/, '$1s'); // I like Bananas

This was a simple example, but you can use the same technique to keep more than one matching pattern in memory. The number of sub-patterns in the full match will be determined by the number of parentheses used.

Inside the replacement string, the first sub-match will be identified using $1, the second sub-match will be identified using $2, and so on. Here is another example to further clarify the usage of parentheses.

"I am looking for John and Jason".replace(/(\w+)\sand\s(\w+)/, '$2 and $1'); // I am looking for Jason and JohnUsing Flags With Regular Expressions

As I mentioned in the introduction, one more important feature of regular expressions is the use of special flags to modify how a search is performed. The flags are optional, but you can use them to do things like making a search global or case-insensitive.

These are the four commonly used flags to change how JavaScript searches or replaces a string.

  • g: This flag will perform a global search instead of stopping after the first match.
  • i: This flag will perform a search without checking for an exact case match. For instance, Apple, aPPLe, and apPLE are all treated the same during case-insensitive searches.
  • m: This flag will perform a multi-line search.
  • y: This flag will look for a match in the index indicated by the lastIndex property.

Here are some examples of regular expressions used with flags:

"I ate apples, you ate apples".replace(/apples/, "mangoes"); // "I ate mangoes, you ate apples" "I ate apples, you ate apples".replace(/apples/g, "mangoes"); // "I ate mangoes, you ate mangoes" "I ate apples, you ate APPLES".replace(/apples/, "mangoes"); // "I ate mangoes, you ate APPLES" "I ate apples, you ate APPLES".replace(/apples/gi, "mangoes"); // "I ate mangoes, you ate mangoes" var stickyRegex = /apples/y; stickyRegex.lastIndex = 3; "I ate apples, you ate apples".replace(stickyRegex, "mangoes"); // "I ate apples, you ate apples" var stickyRegex = /apples/y; stickyRegex.lastIndex = 6; "I ate apples, you ate apples".replace(stickyRegex, "mangoes"); // "I ate mangoes, you ate apples" var stickyRegex = /apples/y; stickyRegex.lastIndex = 8; "I ate apples, you ate apples".replace(stickyRegex, "mangoes"); // "I ate apples, you ate apples"Final Thoughts

The purpose of this tutorial was to introduce you to regular expressions in JavaScript and their importance. We began with the basics and then covered backslash and other special characters. We also learned how to check for a repeating pattern in a string and how to remember partial matches in a pattern in order to use them later.

Finally, we learned about commonly used flags which make regular expressions even more powerful. You can learn more about regular expressions in this article on MDN.

If there is anything that you would like me to clarify in this tutorial, feel free to let me know in the comments.

Categories: Web Design

Introduction to Popmotion: Custom Animation Scrubber

Tuts+ Code - Web Development - Fri, 05/25/2018 - 05:32

In the first part of the Popmotion introductory series, we learned how to use time-based animations like tween and keyframes. We also learned how to use those animations on the DOM, using the performant styler.

In part two, we learned how to use pointer tracking and record velocity. We then used that to power the velocity-based animations spring, decay, and physics.

In this final part, we're going to be creating a scrubber widget, and we're going to use it to scrub a keyframes animation. We'll make the widget itself from a combination of pointer tracking as well as spring and decay to give it a more visceral feel than run-of-the-mill scrubbers.

Try it for yourself:

Getting StartedMarkup

First, fork this CodePen for the HTML template. As before, because this is an intermediate tutorial, I won't go through everything.

The main twist of note is that the handle on the scrubber is made up of two div elements: .handle and .handle-hit-area.

.handle is the round blue visual indicator of where the scrubber handle is. We've wrapped it in an invisible hit area element to make grabbing the element easier for touchscreen users.

Import Functions

At the top of your JS panel, import everything we're going to use in this tutorial:

const { easing, keyframes, pointer, decay, spring, styler, transform, listen, value } = popmotion; const { pipe, clamp, conditional, linearSpring, interpolate } = transform;Select Elements

We're going to need three elements in this tutorial. We'll animate the .box, drag and animate the .handle-hit-area, and measure the .range.

Let's also create stylers for the elements we're going to animate:

const box = document.querySelector('.box'); const boxStyler = styler(box); const handle = document.querySelector('.handle-hit-area'); const handleStyler = styler(handle); const range = document.querySelector('.range');Keyframes Animation

For our scrubbable animation, we're going to make the .box move from left to right with keyframes. However, we could just as easily scrub a tween or timeline animation using the same method outlined later in this tutorial.

const boxAnimation = keyframes({ values: [0, -150, 150, 0], easings: [easing.backOut, easing.backOut, easing.easeOut], duration: 2000 }).start(boxStyler.set('x'));

Your animation will now be playing. But we don't want that! Let's pause it for now:

boxAnimation.pause();Dragging the x-axis

It's time to use pointer to drag our scrubber handle. In the previous tutorial, we used both x and y properties, but with a scrubber we only need x.

We prefer to keep our code reusable, and tracking a single pointer axis is quite a common use case. So let's create a new function called, imaginatively, pointerX.

It will work exactly like pointer except it'll take just a single number as its argument and output just a single number (x):

const pointerX = (x) => pointer({ x }).pipe(xy => xy.x);

Here, you can see we're using a method of pointer called pipe. pipe is available on all the Popmotion actions we've seen so far, including keyframes.

pipe accepts multiple functions. When the action is started, all output will be passed through each of these functions in turn, before the update function provided to start fires.

In this case, our function is simply:

xy => xy.x

All it is doing is taking the { x, y } object usually output by pointer and returning just the x axis.

Event Listeners

We need to know if the user has started pressing the handle before we start tracking with our new pointerX function.

In the last tutorial we used the traditional addEventListener function. This time, we're going to use another Popmotion function called listen. listen also provides a pipe method, as well as access to all action methods, but we're not going to use that here.

listen allows us to add event listeners to multiple events with a single function, similar to jQuery. So we can condense the previous four event listeners to two:

listen(handle, 'mousedown touchstart').start(startDrag); listen(document, 'mouseup touchend').start(stopDrag);Move the Handle

We'll be needing the handle's x velocity later on, so let's make it a value, which as we learned in the last tutorial allows us to query velocity. On the line after we define handleStyler, add:

const handleX = value(0, handleStyler.set('x'));

Now we can add our startDrag and stopDrag functions:

const startDrag = () => pointerX(handleX.get()) .start(handleX); const stopDrag = () => handleX.stop();

Right now, the handle can be scrubbed beyond the boundaries of the slider, but we'll come back to this later.

Scrubbing

Now we have a visually functional scrubber, but we're not scrubbing the actual animation.

Every value has a subscribe method. This allows us to attach multiple subscribers to fire when the value changes. We want to seek the keyframes animation whenever handleX updates.

First, measure the slider. On the line after we define range, add:

const rangeWidth = range.getBoundingClientRect().width;

keyframes.seek accepts a progress value as expressed from 0 to 1, whereas our handleX is set with pixel values from 0 to rangeWidth.

We can convert from the pixel measurement to a 0 to 1 range by dividing the current pixel measurement by rangeWidth. On the line after boxAnimation.pause(), add this subscribe method:

handleX.subscribe(v => boxAnimation.seek(v / rangeWidth));

Now, if you play with the scrubber, the animation will scrub successfully!

The Extra MileSpring Boundaries

The scrubber can still be pulled outside the boundaries of the full range. To solve this, we could simply use a clamp function to ensure we don't output values outside of 0, rangeWidth.

Instead, we're going to go the extra step and attach springs to the end of our slider. When a user pulls the handle beyond the permitted range, it will tug back towards it. If the user releases the handle while it's outside the range, we can use a spring animation to snap it back.

We'll make this process a single function that we can provide to the pointerX pipe method. By creating a single, reusable function, we can reuse this piece of code with any Popmotion animation, with configurable ranges and spring strengths.

First, let's apply a spring to the left-most limit. We'll use two transformers, conditional and linearSpring.

const springRange = (min, max, strength) => conditional( v => v < min, linearSpring(strength, min) );

conditional takes two functions, an assertion and a transformer. The assertion receives the provided value and returns either true or false. If it returns true, the second function will be provided the value to transform and return.

In this case, the assertion is saying, "If the provided value is smaller than min, pass this value through the linearSpring transformer." The linearSpring is a simple spring function that, unlike the physics or spring animations, has no concept of time. Provide it a strength and a target, and it will create a function that "attracts" any given value towards the target with the defined strength.

Replace our startDrag function with this:

const startDrag = () => pointerX(handleX.get()) .pipe(springRange(0, rangeWidth, 0.1)) .start(handleX);

We're now passing the pointer's x offset through our springRange function, so if you drag the handle past the left-most side, you'll notice it tugs back.

Applying the same to the right-most side is a matter of composing a second conditional with the first using the stand-alone pipe function:

const springRange = (min, max, strength) => pipe( conditional( v => v < min, linearSpring(strength, min) ), conditional( v => v > max, linearSpring(strength, max) ) );

Another benefit of composing a function like springRange is that it becomes very testable. The function it returns is, like all transformers, a pure function that takes a single value. You can test this function to see if it passes through values that lie within min and max unaltered, and if it applies springs to values that lie without.

If you let go of the handle while it lies outside the range, it should now spring back to within range. For that, we'll need to adjust the stopDrag function to fire a spring animation:

const stopDrag = () => { const x = handleX.get(); (x < 0 || x > rangeWidth) ? snapHandleToEnd(x) : handleX.stop(); };

Our snapHandleToEnd function looks like this:

const snapHandleToEnd = (x) => spring({ from: x, velocity: handleX.getVelocity(), to: x < 0 ? 0 : rangeWidth, damping: 30, stiffness: 5000 }).start(handleX);

You can see that to is set either as 0 or rangeWidth depending on which side of the slider the handle currently sits. By playing with damping and stiffness, you can play with a range of different spring-feels.

Momentum Scrolling

A nice touch on iOS scrubber that I always appreciated was that if you threw the handle, it would gradually slow down rather than come to a dead stop. We can replicate that easily using the decay animation.

In stopDrag, replace handleX.stop() with momentumScroll(x).

Then, on the line after the snapHandleToEnd function, add a new function called momentumScroll:

const momentumScroll = (x) => decay({ from: x, velocity: handleX.getVelocity() }).start(handleX);

Now, if you throw the handle, it will come to a gradual stop. It will also animate outside the range of the slider. We can stop this by passing the clamp transformer to the decay.pipe method:

const momentumScroll = (x) => decay({ from: x, velocity: handleX.getVelocity() }).pipe(clamp(0, rangeWidth)) .start(handleX);Conclusion

Using a combination of different Popmotion functions, we can create a scrubber that has a bit more life and playfulness than the usual.

By using pipe, we compose simple pure functions into more complex behaviours while leaving the composite pieces testable and reusable.

Next Steps

How about trying these challenges:

  • Make the momentum scroll end with a bounce if the handle hits either end of the scrubber.
  • Make the handle animate to any point on the scrubber when a user clicks on another part of the range bar.
  • Add full play controls, like a play/pause button. Update the scrubber handle position as the animation progresses.
Categories: Web Design

Lessons Learned While Developing WordPress Plugins

Smashing Magazine - Thu, 05/24/2018 - 04:30
Lessons Learned While Developing WordPress Plugins Lessons Learned While Developing WordPress Plugins Jakub Mikita 2018-05-24T13:30:28+02:00 2018-06-11T13:03:54+00:00

Every WordPress plugin developer struggles with tough problems and code that’s difficult to maintain. We spend late nights supporting our users and tear out our hair when an upgrade breaks our plugin. Let me show you how to make it easier.

In this article, I’ll share my five years of experience developing WordPress plugins. The first plugin I wrote was a simple marketing plugin. It displayed a call to action (CTA) button with Google’s search phrase. Since then, I’ve written another 11 free plugins, and I maintain almost all of them. I’ve written around 40 plugins for my clients, from really small ones to one that have been maintained for over a year now.

Measuring Performance With Heatmaps

Heatmaps can show you the exact spots that receive the most engagement on a given page. Find out why they’re so efficient for your marketing goals and how they can be integrated with your WordPress site. Read article →

Good development and support lead to more downloads. More downloads mean more money and a better reputation. This article will show you the lessons I’ve learned and the mistakes I’ve made, so that you can improve your plugin development.

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

Explore features → 1. Solve A Problem

If your plugin doesn’t solve a problem, it won’t get downloaded. It’s as simple as that.

Take the Advanced Cron Manager plugin (8,000+ active installations). It helps WordPress users who are having a hard time debugging their cron. The plugin was written out of a need — I needed something to help myself. I didn’t need to market this one, because people already needed it. It scratched their itch.

On the other hand, there’s the Bug — fly on the screen plugin (70+ active installations). It randomly simulates a fly on the screen. It doesn’t really solve a problem, so it’s not going to have a huge audience. It was a fun plugin to develop, though.

Focus on a problem. When people don’t see their SEO performing well, they install an SEO plugin. When people want to speed up their website, they install a caching plugin. When people can’t find a solution to their problem, then they find a developer who writes a solution for them.

As David Hehenberger attests in his article about writing a successful plugin, need is a key factor in the WordPress user’s decision of whether to install a particular plugin.

If you have an opportunity to solve someone’s problem, take a chance.

2. Support Your Product “3 out of 5 Americans would try a new brand or company for a better service experience. 7 out of 10 said they were willing to spend more with companies they believe provide excellent service.”

— Nykki Yeager

Don’t neglect your support. Don’t treat it like a must, but more like an opportunity.

Good-quality support is critical in order for your plugin to grow. Even a plugin with the best code will get some support tickets. The more people who use your plugin, the more tickets you’ll get. A better user experience will get you fewer tickets, but you will never reach inbox 0.

Every time someone posts a message in a support forum, I get an email notification immediately, and I respond as soon as I can. It pays off. The vast majority of my good reviews were earned because of the support. This is a side effect: Good support often translates to 5-star reviews.

When you provide excellent support, people start to trust you and your product. And a plugin is a product, even if it’s completely free and open-source.

Good support is more complex than about writing a short answer once a day. When your plugin gains traction, you’ll get several tickets per day. It’s a lot easier to manage if you’re proactive and answer customers’ questions before they even ask.

Here’s a list of some actions you can take:

  • Create an FAQ section in your repository.
  • Pin the “Before you ask” thread at the top of your support forum, highlighting the troubleshooting tips and FAQ.
  • Make sure your plugin is simple to use and that users know what they should do after they install it. UX is important.
  • Analyze the support questions and fix the pain points. Set up a board where people can vote for the features they want.
  • Create a video showing how the plugin works, and add it to your plugin’s main page in the WordPress.org repository.

It doesn’t really matter what software you use to support your product. The WordPress.org’s official support forum works just as well as email or your own support system. I use WordPress.org’s forum for the free plugins and my own system for the premium plugins.

3. Don’t Use Composer

Composer is package-manager software. A repository of packages is hosted on packagist.org, and you can easily download them to your project. It’s like NPM or Bower for PHP. Managing your third-party packages the way Composer does is a good practice, but don’t use it in your WordPress project.

I know, I dropped a bomb. Let me explain.

Composer is great software. I use it myself, but not in public WordPress projects. The problem lies in conflicts. WordPress doesn’t have any global package manager, so each and every plugin has to load dependencies of their own. When two plugins load the same dependency, it causes a fatal error.

There isn’t really an ideal solution to this problem, but Composer makes it worse. You can bundle the dependency in your source manually and always check whether you are safe to load it.

Composer’s issue with WordPress plugins is still not solved, and there won’t be any viable solution to this problem in the near future. The problem was raised many years ago, and, as you can read in WP Tavern’s article, many developers are trying to solve it, without any luck.

The best you can do is to make sure that the conditions and environment are good to run your code.

4. Reasonably Support Old PHP Versions

Don’t support very old versions of PHP, like 5.2. The security issues and maintenance aren’t worth it, and you’re not going to earn more installations from those older versions.

The Notification plugin’s usage on PHP versions from May 2018. (Large preview)

Go with PHP 5.6 as a minimal requirement, even though official support will be dropped by the end of 2018. WordPress itself requires PHP 7.2.

There’s a movement that discourages support of legacy PHP versions. The Yoast team released the Whip library, which you can include in your plugin and which displays to your users important information about their PHP version and why they should upgrade.

Tell your users which versions you do support, and make sure their website doesn’t break after your plugin is installed on too low a version.

5. Focus On Quality Code

Writing good code is tough in the beginning. It takes time to learn the “SOLID” principles and design patterns and to change old coding habits.

It once took me three days to display a simple string in WordPress, when I decided to rewrite one of my plugins using better coding practices. It was frustrating knowing that it should have taken 30 minutes. Switching my mindset was painful but worth it.

Why was it so hard? Because you start writing code that seems at first to be overkill and not very intuitive. I kept asking myself, “Is this really needed?” For example, you have to separate the logic into different classes and make sure each is responsible for a single thing. You also have to separate classes for the translation, custom post type registration, assets management, form handlers, etc. Then, you compose the bigger structures out of the simple small objects. That’s called dependency injection. That’s very different from having “front end” and “admin” classes, where you cram all your code.

The other counterintuitive practice was to keep all actions and filters outside of the constructor method. This way, you’re not invoking any actions while creating the objects, which is very helpful for unit testing. You also have better control over which methods are executed and when. I wish I knew this before I wrote a project with an infinite loop caused by the actions in the constructor methods. Those kinds of bugs are hard to trace and hard to fix. The project had to be refactored.

The above are but a few examples, but you should get to know the SOLID principles. These are valid for any system and any coding language.

When you follow all of the best practices, you reach the point where every new feature just fits in. You don’t have to tweak anything or make any exceptions to the existing code. It’s amazing. Instead of getting more complex, your code just gets more advanced, without losing flexibility.

Also, format your code properly, and make sure every member of your team follows a standard. Standards will make your code predictable and easier to read and test. WordPress has its own standards, which you can implement in your projects.

6. Test Your Plugin Ahead Of Time

I learned this lesson the hard way. Lack of testing led me to release a new version of a plugin with a fatal error. Twice. Both times, I got a 1-star rating, which I couldn’t turn into a positive review.

You can test manually or automatically. Travis CI is a continuous testing product that integrates with GitHub. I’ve built a really simple test suite for my Notification plugin that just checks whether the plugin can boot properly on every PHP version. This way, I can be sure the plugin is error-free, and I don’t have to pay much attention to testing it in every environment.

Each automated test takes a fraction of a second. 100 automated tests will take about 10 minutes to complete, whereas manual testing needs about 2 minutes for each case.

The more time you invest in testing your plugin up front, the more it will save you in the long run.

To get started with automated testing, you can use the WP-CLI \\`wp scaffold plugin-test\\` command, which installs all of the configuration you need.

7. Document Your Work

It’s a cliche that developers don’t like to write documentation. It’s the most boring part of the development process, but a little goes a long way.

Write self-documenting code. Pay attention to variable, function and class names. Don’t make any complicated structures, like cascades that can’t be read easily.

Another way to document code is to use the “doc block”, which is a comment for every file, function and class. If you write how the function works and what it does, it will be so much easier to understand when you need to debug it six months from now. WordPress Coding Standards covers this part by forcing you to write the doc blocks.

Using both techniques will save you the time of writing the documentation, but the code documentation is not going to be read by everyone.

For the end user, you have to write high-quality, short and easy-to-read articles explaining how the system works and how to use it. Videos are even better; many people prefer to watch a short tutorial than read an article. They are not going to look at the code, so make their lives easier. Good documentation also reduces support tickets.

Conclusion

These seven rules have helped me develop good-quality products, which are starting to be a core business at BracketSpace. I hope they’ll help you in your journey with WordPress plugins as well.

Let me know in the comments what your golden development rule is or whether you’ve found any of the above particularly helpful.

(il, ra, yk)
Categories: Web Design

Introduction to Popmotion: Pointers and Physics

Tuts+ Code - Web Development - Wed, 05/23/2018 - 05:32

Welcome back to the Introduction to Popmotion tutorial series. In part 1, we discovered how to use tweens and keyframes to make precise, time-scheduled animations.

In Part 2, we're going to look at pointer tracking and velocity-based animations.

Pointer tracking allows us to create scrollable product shelves, custom value sliders, or drag-and-drop interfaces.

Velocity-based animations are different to a time-based animation like tween in that the primary property that affects how the animation behaves is velocity. The animation itself might take any amount of time.

We'll look at the three velocity-based animations in Popmotion, spring, decay, and physics. We'll use the velocity of the pointer tracking animation to start these animations, and that'll demonstrate how velocity-based animations can create engaging and playful UIs in a way that time-based animations simply can't.

First, open this CodePen to play along.

Pointer Tracking

Popmotion provides the pointer function to track and output the coordinates of either a mouse or single touch pointer.

Let's import this along with styler, which will allow us to set the position of the ball.

const { pointer, styler } = popmotion; const ball = document.querySelector('.ball'); const ballStyler = styler(ball);

For this example, we want to drag the ball. Let's add an event that will output the pointer's position to the ball:

let pointerTracker; const startTracking = () => { pointerTracker = pointer().start(ballStyler.set); }; ball.addEventListener('mousedown', startTracking); ball.addEventListener('touchstart', startTracking);

We'll also want some code to stop tracking when we release the ball:

const stopTracking = () => pointerTracker && pointerTracker.stop(); document.addEventListener('mouseup', stopTracking); document.addEventListener('touchend', stopTracking);

If you try and drag the ball now, there's an obvious problem. The ball jumps away when we touch it! Not a great user experience.

This is because, by default, pointer outputs the pointer's position relative to the page.

To output the pointer's position relative to another point, in this case the ball's x/y transform, we can simply pass that position to pointer like this:

const startTracking = () => { pointerTracker = pointer({ x: ballStyler.get('x'), y: ballStyler.get('y') }).start(ballStyler.set); };

Now you've made the ball, in very few lines of code, draggable! However, when the user releases the ball, it stops dead.

This isn't satisfying: Imagine a scrollable carousel of products that a user can drag to scroll. If it just stopped dead instead of momentum scrolling, it'd be less pleasurable to use.

It'd be harder, too, because the overall physical effort needed to scroll the carousel would be higher.

To enable animations like this, we first need to know the velocity of the object being thrown.

Track Velocity

Popmotion provides a function that can help us track velocity. It's called value. Let's import that:

const { pointer, styler, value } = popmotion;

To speak technically for a moment, all of Popmotion's animations are known as actions. Actions are reactive streams of values that can be started and stopped.

A value is, conversely, a reaction. It can't be stopped or started. It just passively responds when its update method is called. It can keep track of values and can be used to query their velocity.

So, after we define ballStyler, let's define a new value for ballXY:

const ballXY = value({ x: 0, y: 0 });

Whenever ballXY updates, we want to update ballStyler. We can pass a second argument to value, a function that will run whenever ballXY updates:

const ballXY = value({ x: 0, y: 0 }, ballStyler.set);

Now we can rewrite our pointer to update ballXY instead of ballStyler.set:

const startTracking = () => { pointer(ballXY.get()) .start(ballXY); };

Now, at any pointer, we can call ballXY.getVelocity() and we'll receive the velocities of both x and y, ready to plug into our velocity-based animations.

Velocity-Based Animations spring

The first velocity-based animation to introduce is spring. It's based on the same equations that govern Apple's CASpringAnimation, the spring animation behind all that iOS springy playfulness.

Import:

const { pointer, spring, styler, value } = popmotion;

Now, amend stopTracking so that instead of stopping the pointerTracker animation, it starts a spring animation like this:

const stopTracking = () => spring({ from: ballXY.get(), velocity: ballXY.getVelocity(), to: 0, stiffness: 100, damping: 20 }).start(ballXY);

We provide it with the ball's current position, its velocity, and a target, and the simulation is run. It changes depending on how the user has thrown the ball.

The cool thing about springs is they're expressive. By adjusting the mass, stiffness and damping properties, you can end up with radically different spring-feels.

For instance, if you only change the stiffness above to 1000, you can create a motion that feels like high-energy snapping. Then, by changing mass to 20, you create motion that looks almost like gravity.

There's a combination that will feel right and satisfying for your users, and appropriate to your brand, under almost any circumstance. By playing with different spring-feels, you can communicate different feelings, like a strict out-of-bounds snap or a softer affirmative bounce.

decay

The decay animation, as the name suggests, decays the provided velocity so that the animation gradually slows to a complete stop.

This can be used to create the momentum scrolling effect found on smartphones, like this:

Import the decay function:

const { decay, pointer, spring, styler, value } = popmotion;

And replace the stopTracking function with the following:

const stopTracking = () => decay({ from: ballXY.get(), velocity: ballXY.getVelocity() }).start(ballXY);

decay automatically calculates a new target based on the provided from and velocity props.

It's possible to adjust the feel of the deceleration by messing with the props outlined in the docs linked above but, unlike spring and physics, decay is designed to work out of the box. 

physics

Finally, we have the physics animation. This is Popmotion's Swiss Army knife of velocity-based animations. With it, you can simulate:

  • constant velocity
  • acceleration
  • springs
  • friction

spring and decay offer super-precise motion and a wider variety of "feels". Soon, they'll both also be scrubbable.

But both are immutable. Once you've started either, their properties are set in stone. Perfect for when we want to start an animation based on the initial from/velocity state, but not so good if we want ongoing interaction.

physics, instead, is an integrated simulation closer to that of a video game. It works by, once per frame, taking the current state and then modifying it based on the current properties at that point in time.

This allows it to be mutable, which means we can change those properties, which then changes the outcome of the simulation.

To demonstrate this, let's make a twist on classic pointer smoothing, with elastic smoothing.

Import physics:

const { pointer, spring, physics, styler, value } = popmotion;

This time, we're going to change the startTracking function. Instead of changing ballXY with pointer, we'll use physics:

const startTracking = () => { const physicsAnimation = physics({ from: ballXY.get(), to: ballXY.get(), velocity: ballXY.getVelocity(), restSpeed: false, friction: 0.6, springStrength: 400 }).start(ballXY); };

Here, we're setting from and velocity as normal. friction and springStrength both adjust the properties of the spring.

restSpeed: false overrides the default behaviour of the animation stopping when motion stops. We want to stop it manually in stopTracking.

On its own, this animation won't do anything because we set to, the spring's target, to the same as from. So let's reimplement the pointer tracking this time to change the spring target of physics. On the last line of startTracking, add:

pointerTracker = pointer(ballXY.get()).start((v) => { physicsAnimation.setSpringTarget(v); });

Here, we're using a similar pointer animation as before. Except this time, we're using it to change the target of another animation. In doing so, we create this elasticated pointer tracking:

Conclusion

Velocity-based animations paired with pointer tracking can create engaging and playful interfaces.

spring can be used to create a wide-variety of spring-feels, while decay is specifically tailored for momentum scroll animations. physics is more limited than either in terms of configurability, but also provides the opportunity to change the simulation in progress, opening new interaction possibilities.

In the next and final part of this introductory series on Popmotion, we're going to take everything we've learned in the first two parts and use them along with some light functional composition to create a scrubbable animation, along with a scrubber to do the scrubbing with!

Categories: Web Design

Creating The Feature Queries Manager DevTools Extension

Smashing Magazine - Wed, 05/23/2018 - 03:00
Creating The Feature Queries Manager DevTools Extension Creating The Feature Queries Manager DevTools Extension Ire Aderinokun 2018-05-23T12:00:00+02:00 2018-06-11T13:03:54+00:00

Within the past couple of years, several game-changing CSS features have been rolled out to the major browsers. CSS Grid Layout, for example, went from 0 to 80% global support within the span of a few months, making it an incredibly useful and reliable tool in our arsenal. Even though the current support for a feature like CSS Grid Layout is relatively great, not all recent or current browsers support it. This means it’s very likely that you and I will currently be developing for a browser in which it is not supported.

The modern solution to developing for both modern and legacy browsers is feature queries. They allow us to write CSS that is conditional on browser support for a particular feature. Although working with feature queries is almost magical, testing them can be a pain. Unlike media queries, we can’t easily simulate the different states by just resizing the browser. That’s where the Feature Queries Manager comes in, an extension to DevTools to help you easily toggle your feature query conditions. In this article, I will cover how I built this extension, as well as give an introduction to how developer tools extensions are built.

Working With Unsupported CSS

If a property-value pair (e.g. display: grid), is not supported by the browser the page is viewed in, not much happens. Unlike other programming languages, if something is broken or unsupported in CSS, it only affects the broken or unsupported rule, leaving everything else around it intact.

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

Explore features →

Let’s take, for example, this simple layout:

Large preview

We have a header spanning across the top of the page, a main section directly below that to the left, a sidebar to the right, and a footer spanning across the bottom of the page.

Here’s how we could create this layout using CSS Grid:

See the Pen layout-grid by Ire Aderinokun (@ire) on CodePen.

In a supporting browser like Chrome, this works just as we want. But if we were to view this same page in a browser that doesn’t support CSS Grid Layout, this is what we would get:

Large preview

It is essentially the same as if we had not applied any of the grid-related styles in the first place. This behavior of CSS was always intentional. In the CSS specification, it says:

In some cases, user agents must ignore part of an illegal style sheet, [which means to act] as if it had not been there

Historically, the best way to handle this has been to make use of the cascading nature of CSS. According to the specification, “the last declaration in document order wins.” This means that if there are multiple of the same property being defined within a single declaration block, the latter prevails.

For example, if we have the follow declarations:

body { display: flex; display: grid; }

Assuming both Flexbox and Grid are supported in the browser, the latter — display: grid — will prevail. But if Grid is not supported by the browser, then that rule is ignored, and any previous valid and supported rules, in this case display: flex, are used instead.

body { display: flex; display: grid; } Cascading Problems

Using the cascade as a method for progressive enhancement is and has always been incredibly useful. Even today, there is no simpler or better way to handle simple one-liner fallbacks, such as this one for applying a solid colour where the rgba() syntax is not supported.

div { background-color: rgb(0,0,0); background-color: rgba(0,0,0,0.5); }

Using the cascade, however, has one major limitation, which comes into play when we have multiple, dependent CSS rules. Let’s again take the layout example. If we were to attempt to use this cascade technique to create a fallback, we would end up with competing CSS rules.

See the Pen layout-both by Ire Aderinokun (@ire) on CodePen.

In the fallback solution, we need to use certain properties such as margins and widths, that aren’t needed and in fact interfere with the “enhanced” Grid version. This makes it difficult to rely on the cascade for more complex progressive enhancement.

Feature Queries To The Rescue!

Feature queries solve the problem of needing to apply groups of styles that are dependent on the support of a CSS feature. Feature queries are a “nested at-rule” which, like the media queries we are used to, allow us to create a subset of CSS declarations that are applied based on a condition. Unlike media queries, whose condition is dependent on device and screen specs, feature query conditions are instead based on if the browser supports a given property-value pair.

A feature query is made up of three parts:

  1. The @supports keyword
  2. The condition, e.g. display: flex
  3. The nested CSS declarations.

Here is how it looks:

@supports (display: grid) { body { display: grid; } }

If the browser supports display: grid, then the nested styles will apply. If the browser does not support display: grid, then the block is skipped over entirely.

The above is an example of a positive condition within a feature query, but there are four flavors of feature queries:

  1. Positive condition, e.g. @supports (display grid)

  2. Negative condition, e.g. @supports not (display: grid)

  3. Conjunction, e.g. @supports (display:flex) and (display: grid)

  4. Disjunction, e.g. @supports (display:-ms-grid) or (display: grid)

Feature queries solve the problem of having separate fallback and enhancement groups of styles. Let’s see how we can apply this to our example layout:

See the Pen Run bunny run by Ire Aderinokun (@ire) on CodePen.

Introducing The Feature Queries Manager

When we write media queries, we test them by resizing our browser so that the styles at each breakpoint apply. So how do we test feature queries?

Since feature queries are dependent on whether a browser supports a feature, there is no easy way to simulate the alternative state. Currently, the only way to do this would be to edit your code to invalidate/reverse the feature query.

For example, if we wanted to simulate a state in which CSS Grid is not supported, we would have to do something like this:

/* fallback styles here */ @supports (display: grrrrrrrrid) { /* enhancement styles here */ }

This is where the Feature Queries Manager comes in. It is a way to reverse your feature queries without ever having to manually edit your code.

(Large preview)

It works by simply negating the feature query as it is written. So the following feature query:

@supports (display: grid) { body { display: grid; } }

Will become the following:

@supports not (display: grid) { body { display: grid; } }

Fun fact, this method works for negative feature queries as well. For example, the following negative feature query:

@supports not (display: grid) { body { display: block; } }

Will become the following:

@supports not (not (display: grid)) { body { display: block; } }

Which is actually essentially the same as removing the “not” from the feature query.

@supports (display: grid) { body { display: block; } } Building The Feature Queries Manager

FQM is an extension to your browser’s Developer Tools. It works by registering all the CSS on a page, filtering out the CSS that is nested within a feature query, and giving us the ability to toggle the normal or “inverted” version of that feature query.

Creating A DevTools Panel

Before I go on to how I specifically built the FQM, let’s cover how to create a new DevTools panel in the first place. Like any other browser extension, we register a DevTools extension with the manifest file.

{ "manifest_version": 2, "name": "Feature Queries Manager", "short_name": "FQM", "description": "Manage and toggle CSS on a page behind a @supports Feature Query.", "version": "0.1", "permissions": [ "tabs", "activeTab", "<all_urls>" ], "icons": { "128": "images/icon@128.png", "64": "images/icon@64.png", "16": "images/icon@16.png", "48": "images/icon@48.png" } }

To create a new panel in DevTools, we need two files — a devtools_page, which is an HTML page with an attached script that registers the second file, panel.html, which controls the actual panel in DevTools.

Large preview

First, we add the devtools_page to our manifest file:

{ "manifest_version": 2, "name": "Feature Queries Manager", ... "devtools_page": "devtools.html", }

Then, in our devtools.html file, we create a new panel in DevTools:

<!DOCTYPE html> <html> <head> <meta charset="utf-8"></head> <body> <!-- Note: I’m using the browser-polyfill to be able to use the Promise-based WebExtension API in Chrome --> <script src="../browser-polyfill.js"></script> <!-- Create FQM panel --> <script> browser.devtools.panels.create("FQM", "images/icon@64.png", "panel.html"); </script> </body> </html

Finally, we create our panel HTML page:

<!DOCTYPE html> <html> <head> <meta charset="utf-8"></head> <body> <h1>Hello, world!</h1> </body> </html>

If we open up our browser, we will see a new panel called “FQM” which loads the panel.html page.

Large preview

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

Table of Contents → Reading CSS From The Inspected Page

In the FQM, we need to access all the CSS referenced in the inspected document in order to know which are within feature queries. However, our DevTools panel doesn’t have direct access to anything on the page. If we want access to the inspected document, we need a content script.

Large preview

A content script is a javascript file that has the same access to the html page as any other piece of javascript embedded within it. To register a content script, we just add it to our manifest file:

{ "manifest_version": 2, "name": "Feature Queries Manager", ... "content_scripts": [{ "matches": [""], "js": ["browser-polyfill.js", "content.js"] }], }

In our content script, we can then read all the stylesheets and css within them by accessing document.styleSheets:

Array.from(document.styleSheets).forEach((stylesheet) => { let cssRules; try { cssRules = Array.from(stylesheet.cssRules); } catch(err) { return console.warn(`[FQM] Can't read cssRules from stylesheet: ${ stylesheet.href }`); } cssRules.forEach((rule, i) => { /* Check if css rule is a Feature Query */ if (rule instanceof CSSSupportsRule) { /* do something with the css rule */ } }); }); Connecting The Panel And The Content Scripts

Once we have the rules from the content script, we want to send them over to the panel so they can be visible there. Ideally, we would want something like this:

Large preview

However, we can’t exactly do this, because the panel and content files can’t actually talk directly to each other. To pass information between these two files, we need a middleman — a background script. The resulting connection looks something like this:

Large preview

As always, to register a background script, we need to add it to our manifest file:

{ "manifest_version": 2, "name": "Feature Queries Manager", ... "background": { "scripts": ["browser-polyfill.js", "background.js"] }, }

The background file will need to open up a connection to the panel script and listens for messages coming from there. When the background file receives a message from the panel, it passes it on to the content script, which is listening for messages from the background. The background script waits for a response from the content script and relays that message back to the panel.

Here’s a basic of example of how that works:

// Open up a connection to the background script const portToBackgroundScript = browser.runtime.connect(); // Send message to content (via background) portToBackgroundScript.postMessage("Hello from panel!"); // Listen for messages from content (via background) portToBackgroundScript.onMessage.addListener((msg) => { console.log(msg); // => "Hello from content!" }); // backrgound.js // Open up a connection to the panel script browser.runtime.onConnect.addListener((port) => { // Listen for messages from panel port.onMessage.addListener((request) => { // Send message from panel.js -> content.js // and return response from content.js -> panel.js browser.tabs.sendMessage(request.tabId, request) .then((res) => port.postMessage(res)); }); }); // content.js // Listen for messages from background browser.runtime.onMessage.addListener((msg) => { console.log(msg) // => "Hello from panel!" // Send message to panel return Promise.resolve("Hello from content!"); }); Managing Feature Queries

Lastly, we can get to the core of what the extension does, which is to “toggle” on/off the CSS related to a feature query.

If you recall, in the content script, we looped through all the CSS within feature queries. When we do this, we also need to save certain information about the CSS rule:

  1. The rule itself
  2. The stylesheet it belongs to
  3. The index of the rule within the stylesheet
  4. An “inverted” version of the rule.

This is what that looks like:

cssRules.forEach((rule, i) => { const cssRule = rule.cssText.substring(rule.cssText.indexOf("{")); const invertedCSSText = `@supports not ( ${ rule.conditionText } ) ${ cssRule }`; FEATURE_QUERY_DECLARATIONS.push({ rule: rule, stylesheet: stylesheet, index: i, invertedCSSText: invertedCSSText }); });

When the content script receives a message from the panel to invert all declarations relating to the feature query condition, we can easily replace the current rule with the inverted one (or vice versa).

function toggleCondition(condition, toggleOn) { FEATURE_QUERY_DECLARATIONS.forEach((declaration) => { if (declaration.rule.conditionText === condition) { // Remove current rule declaration.stylesheet.deleteRule(declaration.index); // Replace at index with either original or inverted declaration const rule = toggleOn ? declaration.rule.cssText : declaration.invertedCSSText; declaration.stylesheet.insertRule(rule, declaration.index); } }); }

And that is essentially it! The Feature Query Manager extension is currently available for Chrome and Firefox.

Limitations Of The FQM

The Feature Queries Manager works by “inverting” your feature queries, so that the opposite condition applies. This means that it cannot be used in every scenario.

Fallbacks

If your “enhancement” CSS is not written within a feature query, then the extension cannot be used as it is dependent on finding a CSS supports rule.

Unsupported Features

You need to take note of if the browser you are using the FQM in does or does not support the feature in question. This is particularly important if your original feature query is a negative condition, as inverting it will turn it into a positive condition. For example, if you wrote the following CSS:

div { background-color: blue; } @supports not (display: grid) { div { background-color: pink; } }

If you use the FQM to invert this condition, it will become the following:

div { background-color: blue; } @supports (display: grid) { div { background-color: pink; } }

For you to be able to actually see the difference, you would need to be using a browser which does in fact support display: grid.

I built the Feature Queries Manager as a way to more easily test the different CSS as I develop, but it isn’t a replacement for testing layout in the actual browsers and devices. Developer tools only go so far, nothing beats real device testing.

(ra, yk, il)
Categories: Web Design

New Course: Connect to a Database With Laravel's Eloquent ORM

Tuts+ Code - Web Development - Tue, 05/22/2018 - 04:54
What You'll Be Creating

In our new course, Connect to a Database With Laravel's Eloquent ORM, you'll learn all about Eloquent, which makes it easy to connect to relational data in a database and work with it using object-oriented models in your Laravel app. It is simple to set up, easy to use, and packs a lot of power.

What You’ll Learn

In this course, Envato Tuts+ instructor Jeremy McPeak will teach you how to use Eloquent, Laravel's object-relational mapper (ORM). 

Follow along as Jeremy builds the data back-end for a simple guitar database app. You'll learn how to create data tables with migrations, how to create data models, and how to use Eloquent for querying and mutating data.

Watch the Introduction Take the Course

You can take our new course straight away with a subscription to Envato Elements. For a single low monthly fee, you get access not only to this course, but also to our growing library of over 1,000 video courses and industry-leading eBooks on Envato Tuts+. 

Plus you now get unlimited downloads from the huge Envato Elements library of 580,000+ creative assets. Create with unique fonts, photos, graphics and templates, and deliver better projects faster.

Categories: Web Design

How To Reduce The Need To Hand-Code Theme Parts In Your WordPress Website

Smashing Magazine - Tue, 05/22/2018 - 02:45
How To Reduce The Need To Hand-Code Theme Parts In Your WordPress Website How To Reduce The Need To Hand-Code Theme Parts In Your WordPress Website Nick Babich 2018-05-22T11:45:05+02:00 2018-06-11T13:03:54+00:00

(This is a sponsored article.) Good design leads to sales and conversions on your website, but crafting great design is no easy task. It takes a lot of time and effort to achieve excellent results.

Design is a constantly evolving discipline. Product teams iterate on design to deliver the best possible experience to their users. A lot of things might change during each iteration. Designers will introduce changes, and developers will dive into the code to adjust the design. While jumping into code to solve an exciting problem might be fun, doing it to resolve a minor issue is the exact opposite. It’s dull. Imagine that you, as a web developer, continually get requests from the design team like:

  • Change the featured image.
  • Update the copy next to the logo in the header.
  • Add a custom header to the “About Us” page.

These requests happen all the time in big projects. It’s a never-ending stream of boring requests. Want to have fun while creating websites, focus on more challenging tasks, and complete your projects much faster?

Elementor helps with just that. It reduces the need to hand-code the theme parts of your website and frees you up to work on more interesting and valuable parts of the design.

Elementor Page Builder

For a long time, people dreamed that they would be able to put together a web page by dragging and dropping different elements together. That’s how page builders became popular. Page builders introduced a whole different experience of building a page — all actions involving content are done visually. They reduce the time required to produce a desirable structure.

What if we took the most popular CMS in the world and develop the most advanced page builder for it? That’s how Elementor 1.0 for WordPress was created. Here are a few features of the tool worth mentioning:

  • Live editing. Elementor provides instant live editing — what you see is what you get! The tool comes with a live drag-and-drop interface. This interface eliminates guesswork by allowing you to build your layout in real time.
  • Elementor comes with a ton of widgets, including for the most common website elements. Also, there are dozens of Elementor add-ons created by the community: https://wordpress.org/plugins/search/elementor/
  • Responsive design out of the box. The content you create using Elementor will automatically adapt to mobile devices, ensuring that your website is mobile-friendly. Your design will look pixel-perfect on any device.
  • Mobile-first design. The Elementor page builder lets you create truly a responsive website in a whole new visual way. Use different font sizes, padding and margins per device, or even reverse column ordering for users who are browsing your website using a mobile device.
  • Revision history. Elementor has a history browser that allows you to roll forward and backward through your changes. It gives you the freedom to experiment with a layout without fear of losing your progress.
  • Built-in custom CSS feature allow you to add your own styles. Elementor allows you to add custom CSS to every element, and to see it in action live in the editor.
  • Theme-independence. With Elementor, you’re not tied to a single theme. You can change the theme whenever you like, and your content will come along with you. This gives you, as a WordPress user, maximum flexibility and freedom to work with your favorite theme, or to switch themes and not have to worry about making changes.
  • Complete code reference and a lot of tutorials. Elementor is a developer-oriented product — it’s an open-source solution with a complete code reference. If you’re interested in creating your own solutions for Elementor, it’s worth checking the website https://developers.elementor.com. The website contains a lot of helpful tutorials and explanations.

There are two particular cases in which Elementor would be helpful to web developers:

  • Web developers who need to create an interactive prototype really quickly. Elementor can help in situations where a team needs to provide an interactive solution but doesn’t have enough time to code it.
  • Web developers who don’t want to be involved in post-development activities. Elementor is perfect when a website is developed for a client who wants to make a lot of changes themselves without having to write a single line of code.
Meet Elementor Pro 2.0 Theme Builder

Despite all of the advantages Elementor 1.0 had, it also had two severe limitations:

  • There were parts of a WordPress website that weren’t customizable. As a user, you were limited to a specific area of your website: the content that resides between the header and the footer. To modify other parts of the website (e.g. footer or header), you had to mess with the code.
  • It was impossible to create dynamic content. While this wouldn’t cause any problems if the website contained only static pages (such as an “About Us” page), it might be a roadblock if the website had a lot of dynamic content.

In an attempt to solve these problems, the Elementor team released the Elementor 2.0 Theme Builder, with true theme-building functionality. Elementor Pro 2.0 introduces a new way to build and customize websites. With Theme Builder, you don't have to code menial theme jobs anymore and can instead focus on deeper website functionality. You are able to design the entire page in the page builder. No header, no footer, just Elementor.

How Does Theme Builder Work?

The tool allows you to build a header, footer, single or archive templates, and other areas of a website using the same Elementor interface. To make that possible, Elementor 2.0 introduces the concept of global templates. Templates are design units. They’re capable of customizing each and every area of your website.

The process of creating a template is simple:

  1. Choose a template type.
  2. Build your page’s structure.
  3. Set the conditions that define where to apply your template.

Let’s explore each of these steps in more detail by creating a simple website. In the next section, we’ll build a company website that has a custom header and footer and dynamic content (a blog and archive). But before you start the process, make sure you have the latest version of WordPress, with the Elementor Pro plugin installed and activated. It is also worth mentioning that you should have a theme for your website. Elementor doesn’t replace your theme; rather, it gives you visual design capabilities over every part of the theme.

Custom Header And Footer

The header and footer are the backbone of every website. They are where users expect to see navigation options. Helping visitors navigate is a top priority for web designers.

Let’s start with creating a header. We’ll create a fairly standard header, with the company’s logo and main menu.

The process of creating a custom header starts with choosing a template. To create a new template, you’ll need to go to “Elementor” → “My Templates” → “Add New”.

Large preview

You’ll see a dialog box, “Choose Template Type”. Select “Header” from the list of options.

Choose the type of template you want to create. It can be a header, footer, single post page or archive page. (Large preview)

Once you choose a type of template, Elementor will display a list of blocks that fit that type of content. Blocks are predesigned layouts provided by Elementor. They save you time by proving common design patterns that you can modify to your own needs. Alternatively, you can create a template from scratch.

Choose either a predesigned block for your header, or build the entire menu from scratch. (Large preview)

Let’s choose the first option from the list (“Metro”). You can see that the top area of the page layout has a new object — a newly created header.

Large preview

Now, you need to customize the header according to your needs. Let’s choose a logo and define a menu. Click on the placeholder “Choose Your Image”, and select the logo from the gallery. It’s worth mentioning that the template embeds your website’s logo. This is good because if you ever change that logo at the website level, the header will automatically be updated on all pages. Next, click on the menu placeholder and select the website’s main menu.

Large preview

When the process of customization is finished, you need to implement the revised header on your website. Click the “Publish” button. The “Display Conditions” window will ask you to choose where to apply your template.

Every template contains the display conditions that define where it’s placed. Choose where the header will be shown. (Large preview)

The conditions define which pages your template will be applied to. It’s possible to show the header on all pages, to show it only on certain pages or to exclude some pages from showing the header. The latter case is helpful if you don’t want to show the header on particular pages.

Choose where you want to show the header. Want one header for the home page and another for the services page? Get it done in minutes. (Large preview)

As soon as you publish your template, Elementor will recognize it as a header and will use it on your website.

Now it’s time to create the footer for your website. The process is similar; the only difference is that this time you’ll need to choose the template named “Footer” and select the footer layout from the list of available blocks. Let’s pick the first option from the list (the one that says “Stay in Touch” on the dark background).

Choosing a block for a footer. (Large preview) Large preview

Next, we need to customize the footer. Change the color of the footer and the text label under the words “Stay in Touch”. Let’s reuse the color of the header for the footer. This will make the design more visually consistent.

Large preview

Finally, we need to choose display conditions. Similar to the header, we’ll choose to display the footer for the entire website.

Large preview

That’s all! You just built a brand new header and footer for your website without writing a single line of code. The other great news is that you don’t have to worry about how your design will look on mobile. Elementor does that for you. UI elements such as the top-level menu will automatically become a hamburger for mobile users.

Single Post for Blog

Let’s design a blog page. Unlike static pages, such as “About us”, the blog has dynamic content. Elementor 2.0 allows you to build a framework for your content. So, each time you write a new blog post, your content will automatically be added to this design framework.

The process of creating a blog page starts with selecting a template. For a single blog post, choose the template type named “Single.” We have two options of blocks to choose from. Let’s choose the first one.

Choosing a block for a single post. (Large preview)

The block you selected has all of the required widgets, so you don’t need to change anything. But it’s relatively easy to adjust the template if needed. A single post is made of dynamic widgets such as the post title, post content, featured image, meta data and so on. Unlike static widgets that display content that you enter manually, dynamic widgets draw content from the current pages where they’re applied. These widgets are in the “Elements” panel, under the category “Theme Elements”.

List of dynamic elements. A dynamic widget changes according to the page it’s used on. (Large preview)

When you work on dynamic content like a single post, you’ll want to see how it looks on different posts. Elementor gives you a preview mode so you can know exactly what your blog will look like.

To go into preview mode, you need to click on the Preview icon (the eye icon in the bottom-left part of the layout), and then “Settings”.

Never again work on the back end and guess what the front end will look like. Use preview mode to see how your templates will work for your content. (Large preview)

To see what your page will look like when it’s be filled with content, simply choose a source of content (e.g. a post from the “News” category).

Large preview Fill your template with content from your actual website to see what the result will look like. (Large preview)

Once you’ve finished creating dynamic content, you’ll need to choose when the template will be applied. Click on “Publish” button, and you’ll see a dialog that allows you to define conditions.

Choosing conditions for a single post template. (Large preview) Archive

The archive page is a page that shows an assortment of posts. Your archive page makes it easy for readers to see all of your content and to dive deeper into the website. It’s also a common place to show search results.

The Theme Builder enables you to build your own archive using a custom taxonomy. To create an archive page, you need to go through the usual steps: create a new template, and choose a block for it. For now, Elementor provides only one type of block for this type of template (you can see it in the image below).

Large preview

After selecting this block, all you need to do is either set a source for your data or stick to the default selection. By default, the archive page shows all available blog posts. Let’s leave it as is.

Large preview

As you can see, we’ve successfully customized the website’s header, footer, single post and archive page, without any roadblocks of coding.

What To Expect In The Near Future

Elementor is being actively developed, with new features and exciting enhancements released all the time. This means that the theme builder is only going to get better. The Elementor team plans to add integration for plugins such as WooCommerce, Advanced Custom Fields (ACF), and Toolset. The team also welcomes feedback from developers. So, if you have a feature that you would like to have in Elementor, feel free to reach out to the Elementor team and suggest it.

Conclusion

When WordPress was released 15 years ago, the idea behind it was to save valuable time for developers and to make the process of content management as easy as possible. Today, it is widely regarded as a developer-friendly tool. Elementor is no different. The tool now offers never-before-seen flexibility to visually design an entire website. Don’t believe me? Try it for yourself! Explore Elementor Pro today.

(ms, ra, il, al, yk)
Categories: Web Design

Building Diverse Design Teams To Drive Innovation

Smashing Magazine - Mon, 05/21/2018 - 03:00
Building Diverse Design Teams To Drive Innovation Building Diverse Design Teams To Drive Innovation Riri Nagao 2018-05-21T12:00:18+02:00 2018-06-11T13:03:54+00:00

There has been a surge of conversations about the tech industry lacking diversity. Companies are therefore encountering barriers in innovation. The current state of technology faces inequality and privilege, a consequence of having limited voices represented in the design and product development process. In addition, we live in a challenged political and socio-economic state where it’s easier to be divided than come together despite differences.

Design’s role in companies is becoming less about visual appeal and more about hitting business goals and creating value for users. Therefore, the need to build teams with diverse perspectives is becoming imperative. Design will not only be critical to solving problems on the product and experience level, but also relevant on a bigger scale to close social divides and to create inclusive communities.

Working Together

Creating a team who can work well together across different disciplines can be hard. Rachel Andrew solicits some suggestions from the speakers at our upcoming SmashingConf in Toronto. Read article →

What Is Diversity And Why Is It Important?

Diversity is in perspectives and values, which are influenced by both inherit traits (such as ethnicity, gender, age, sexual orientation) as well as acquired traits that are gained from various life experiences (cultural influences, education, social circle, etc.). A combination of traits shape people’s identity and the way they think.

In particular, conflicts and adversities experienced by people have a significant influence on how they develop their values. The more an individual has stepped outside their comfort zone, the more unique of a perspective they bring to the table and an expanded capacity to be compassionate towards others.

Diversity is important because it directly affects long-term success, innovation, and growth. Advantages of working on a diverse team include increased collaboration, effective communication, well-rounded sets of skills represented, less susception to complacency, and active efforts for inclusivity are made earlier in the process.

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

Table of Contents → What Is The Competing Values Framework?

The positive correlation between diversity and innovation are undeniable. So how exactly does it work? Having differing and oftentimes clashing perspectives on a team seems to hinder progress rather than drive it. But with the right balance of values, this dynamic is extremely advantageous. Design, as a problem-solving discipline, uses insights to drive innovation, which can only manifest between differences, not commonalities. When different perspectives and values are represented, blind spots become more apparent and implicit biases are challenged.

This is illustrated in the Competing Values Framework, a robust blueprint that was devised by Quinn and Rohrbaugh, based on researching qualities of companies that have sustainably produced a steady stream of innovative solutions over the years. This model for organizational effectiveness shows how different perspectives translate into business values, as well as show where their weaknesses are.

These are categorized into “quadrants” as follows:

The CVF can help you build teams that are optimized for any goal. (Image source) 1. Collaborate

People with characteristics from the Collaborate quadrant are committed to cooperating together based on shared values. They foster trust with each other and with their audience through compassion and empathy. Their priorities are long-term growth of communities and commit to learning and mentoring. While a sense of unity might help a team be more purpose-driven, this can discourage individuals who think differently to bring new ideas to the table because they are averse to taking risks. People here also lose sight of the realities of constraints because they look too far ahead.

2. Create

While most people are hesitant to change and innovation, those in this quadrant embrace it. They’re extremely flexible with a shifting landscape of user and business goals and aren’t afraid of taking risks. Creatives see risk as an opportunity for growth and embrace different ways of thinking to come up with solutions. Trends are set by creatives, not followed. In contrast, however, those in this quadrant aren’t as logical and practical with the execution needed to bring ideas to life. Their flexibility can become chaotic and unpredictable. Taking risks can pay off significantly but it’s more detrimental without a foundation.

3. Compete

As the name implies, people here are competitive and focus on high performance and big results. They’re excellent decision makers, which is why they get things done quickly. They know exactly how to utilize resources around them to beat competitors and get to the top of the market. Competitors stay focused on the business objectives of increasing revenue and hitting target metrics. On the other hand, they’re not as broad of a visionary in the long run. Since they prioritize immediate results. Because of this, they may not be as compassionate towards their audience and not consider the human side of company growth.

4. Control

People in this quadrant focus on creating systems that are reliable and efficient. They’re practical and can plan strategically for scaling, and they constantly revisit their design processes to optimize for productivity. They are extremely detail oriented and can identify areas of opportunities in the unexpected. They’re also experts at dealing with multiple moving parts and turn chaos into harmony. But if there are too many Control qualities on a team, they become vulnerable to falling into complacency since they depend on reliable systems. They are averse to taking risks and fear the nature of unpredictability.

People and their values don’t always neatly fit into categories but this framework is flexible in helping teams identify their strengths and weaknesses. Many individuals have traits that cover more than one quadrant but there are definitely dominant qualities. Being able to identify what they are on an individual level, as well as within a team and at the company level is important.

How Do We Use The CVF To Build Diverse Teams?

There are already many great design processes and frameworks that takes aspects of the CVF to help teams take advantage of diverse perspectives. The sprint model, developed by the design partners at Google Ventures, is an excellent workflow that brings together differing values and skill sets to solve problems, with an emphasis on completing it in a short amount of time. IDEO’s design thinking process, also referred to human-centered design, puts users at the forefront and drive decisions with empathy with collaboration being at the core.

Note: Learn more about GV’s Design Sprint model and IDEO’s Design Thinking approach.

The CVF complements many existing design processes to help teams bring their differing perspectives together and design more holistically. In order to do this, teams need to evaluate where they are, how to fit in the company and how well that aligns with their priorities. They should also identify the missing voices and assess areas for improvement. They need to be asking themselves,

What has the team dynamic been like for the past year? What progress has been made? What goals (business/user/team) are the most important?

The Competing Values Framework assessment is a practical way to (1) establish the desired organizational outcomes and goals, (2) evaluate the current practices of teams within the organization/company and how they manage workflows, and (3) the individual’s role and how they fit into the context of the team and company.

For example, a team that may not have had many roadblocks and disagreements may represent too much of the Collaborate quadrant and need people who represent more of the Compete quadrant to drive results. A team that has taken risks has had failures, and has dealt with many moving parts (Create) may need people who have characteristics of the Control quadrant for stability and scaling on a practical level to drive results and growth.

If teams can expand by hiring more, they should absolutely onboard more innovators who bring different perspectives and strengths. But teams should also keep in mind that it’s absolutely possible to work with what they already have and can utilize resources at their disposal. Here are some practical ways that teams can increase diversity:

Hire For Diversity

When hiring, it’s important to find people with unique perspectives to complement existing designers and stakeholders. Writing inclusive job descriptions to attract a wider range of candidates makes a big difference. Involving people from all levels and backgrounds within the company who are willing to embrace new perspectives is essential. Hiring managers should ask thoughtful questions to gage how well candidates exercise their problem-solving skills and empathy in real-life business cases. Not making assumptions about others, even with something simple like their pronouns, can establish safe work environments and encourage people to be open about their views and values.

Step Outside The Bubble

Whether this would be directly for client work or for building team rapport, it’s valuable to get people out of the office to experience things outside of their familiar scope. It’s worthwhile for design teams to interact with users and spend time in their shoes, not only for their own work as UX practitioners but also to help expand their worldview. They should be encouraged to constantly learn something new. They should be given opportunities to travel to places that are completely different from their comfort zone. Teams should also be encouraged go to design events and learn from industry experts who do similar work but in different contexts. Great ideas emerge when people experience things outside their routine and therefore, should always get out and learn!

Drive Diversity Initiatives Internally

Hosting in-house hackathons to get teams to interact differently allows designers to expand their skills while learning new approaches to problem solving. It is also an opportunity to work with people from other teams and acquire the skills to adapt quickly. Bringing in outside experts to share their wisdom is a great way for teams to learn new ways of thinking. Some companies, especially larger organizations, have communities based on interests outside of work such as the love for food or interest in outdoors activities. Teaching each other skills through internal workshops is also great.

Foster A Culture Of Appreciation

Some companies have weekly roundtable session where each person on the team shares one thing he or she is appreciative about another person. Not only does this encourage high morale but also empowers teams to produce better work. At the same time, teams are given a safe space to be vulnerable with each other and take risks. This is an excellent way to bond over goals and get teams with differing perspectives together to collaborate.

What Should Diverse Teams Keep In Mind?

Acknowledging that while different ideas and values are important, they can clash if conversations are not managed effectively. Discrimination and segregation can happen. But creating a workspace and team dynamic that is open to discussion and a safe space to challenge existing ideas is crucial. People should be open to being challenged and ask questions, rather than get defensive about their ideas. Compromise will be necessary in this process.

When diversity isn’t managed actively, or there is an imbalance of values on a team, several challenges arise:

  • Communication barriers — How people say things can be different from how others hear and understand them. Misunderstandings could lead to crucial voices not always being heard. If a particular style of communication is accepted over others, people fear speaking up. They might hold the wisdom to make design decisions that could impact the business. If a culture of openness doesn’t exist, a lot of those gold mines never get their opportunities to see the light of day.
  • Discrimination and segregation — As teams become more diverse, people can stray away from or avoid others who think differently. This can lead to increased feelings of resentment, leading to segregation and even discrimination. People might be quick to judge one another based on stereotypical references, rather than mustering the courage to understand where they come from.
  • Competition over collaboration — People on design teams need to work collaboratively but when different perspectives clash and aren’t encouraged to use their perspectives to create value for the company, they become competitive against each other rather than have the willingness to work together. It’s important to bring the team back to the main goal.

Embracing different perspectives takes courage but it’s everyone’s responsibility to be mindful of one another. Being surrounded by people with different perspectives is certainly uncomfortable and can be a stretch outside their comfort zones. Design teams are positioned advantageously to do so and be role models to others on its impact. Conversations about leveraging differing perspectives should happen as early in the process as possible to limit friction and encourage effective collaboration.

Conclusion And Next Steps

Rather than approach it as an obligation and something with a lot of risk, leaders should see it as a benefit to their company and team’s growth. It is often said that roadblocks are a sign of innovation. Therefore, when designers in a team are faced with challenges, they are able to innovate. And only through the existence different perspectives can such challenges emerge. Assessing where the company, teams, and individuals are within the CVF quadrants is a great start and taking steps to building a team with complementing perspectives will be key to driving long-term innovation.

I’d like to personally thank the following contributors for taking their time to providing me with insights on hiring for and building diverse design teams: Samantha Berg, Khanh Lam, Arin Bhowmick, Rob Strati, Shannon O’Brien, Diego Pulido, Nathan Gao, Christopher Taylor Edwards, among many others who engaged in discussions with me on this topic. Thank you for allowing me to take your experiences and being part of facilitating this dialogue on the value of diversity in design.

(cc, ra, yk, il)
Categories: Web Design

Improve Your Conversion Rate and Increase Revenue With These User Experience Design Essentials

Entrepreneur: Latest Web Design Articles - Fri, 05/18/2018 - 11:00
Don't deter your customers with a poor website design.
Categories: Web Design

How to Make a Real-Time Sports Application Using Node.js

Tuts+ Code - Web Development - Fri, 05/18/2018 - 05:32
What You'll Be Creating

In today's article I'm going to demonstrate how to make a web application that will display live game scores from the NHL. The scores will update automatically as the games progress.

This is a very exciting article for me, as it allows me the chance to bring two of my favorite passions together: development and sports.

The technologies that will be used to create the application are:

  1. Node.js
  2. Socket.io
  3. MySportsFeed.com

If you don't have Node.js installed, visit their download page now and set it up before continuing.

What Is Socket.io?

Socket.io is a technology that connects a client to a server. In this example, the client is a web browser and the server is the Node.js application. The server can have multiple clients connected to it at any given time.

Once the connection has been established, the server can send messages to all of the clients or an individual client. In return, the client can send a message to the server, allowing for bi-directional real-time communication.

Before Socket.io, web applications would commonly use AJAX, and both the client and server would poll each other looking for events. For example, every 10 seconds an AJAX call would occur to see if there were any messages to handle.

Polling for messages caused a significant amount of overhead on both the client and server as it would be constantly looking for messages when there were none.

With Socket.io, messages are received instantaneously, without needing to look for messages, reducing the overhead.

Sample Socket.io Application

Before we consume the real-time sports data, let's create an example application to demonstrate how Socket.io works.

To begin, I am going to create a new Node.js application. In a console window, I am going to navigate to C:\GitHub\NodeJS, create a new folder for my application, and create a new application:

cd \GitHub\NodeJS mkdir SocketExample cd SocketExample npm init

I used all the default settings.

Because we are making a web application, I'm going use an NPM package called Express to simplify the setup. In a command prompt, install it as follows: npm install express --save

And of course we will need to install the Socket.io package: npm install socket.io --save

Let's begin by creating the web server. Create a new file called index.js and place the following code within it to create the web server using Express:

var app = require('express')(); var http = require('http').Server(app); app.get('/', function(req, res){ res.sendFile(__dirname + '/index.html'); }); http.listen(3000, function(){ console.log('HTTP server started on port 3000'); });

If you are not familiar with Express, the above code example includes the Express library and creates a new HTTP server. In this example, the HTTP server is listening on port 3000, e.g. http://localhost:3000. A route is created at the root of the site "/". The result of the route returns an HTML file: index.html.

Before we create the index.html file, let's finish the server by setting up Socket.io. Append the following to your index.js file to create the Socket server:

var io = require('socket.io')(http); io.on('connection', function(socket){ console.log('Client connection received'); });

Similar to Express, the code begins by importing the Socket.io library. This is stored in a variable called io. Next, using the io variable, an event handler is created with the on function. The event being listened for is connection. This event is called each time a client connects to the server.

Let's now create our very basic client. Create a new file called index.html and place the following code within:

<!doctype html> <html> <head> <title>Socket.IO Example</title> </head> <body> <script src="/socket.io/socket.io.js"></script> <script> var socket = io(); </script> </body> </html>

The HTML above loads the Socket.io client JavaScript and initializes a connection to the server. To see the example, start your Node application: node index.js

Then, in your browser, navigate to http://localhost:3000. Nothing will appear on the page; however, if you look at the console where the Node application is running, two messages are logged:

  1. HTTP server started on port 3000
  2. Client connection received

Now that we have a successful socket connection, let's put it to use. Let's begin by sending a message from the server to the client. Then, when the client receives the message, it can send a response back to the server.

Let's look at the abbreviated index.js file:

io.on('connection', function(socket){ console.log('Client connection received'); socket.emit('sendToClient', { hello: 'world' }); socket.on('receivedFromClient', function (data) { console.log(data); }); });

The previous io.on function has been updated to include a few new lines of code. The first, socket.emit, sends the message to the client. The sendToClient is the name of the event. By naming events, you can send different types of messages so the client can interpret them differently. The second addition is the socket.on, which also contains an event name: receivedFromClient. This creates a function that accepts data from the client. In this case, the data is logged to the console window.

That completes the server-side amendments; it can now send and receive data from any connected clients.

Let's complete this example by updating the client to receive the sendToClient event. When it receives the event, it can respond with the receivedFromClient event back to the server.

This is accomplished in the JavaScript portion of the HTML, so in the index.html file, I have updated the JavaScript as follows:

var socket = io(); socket.on('sendToClient', function (data) { console.log(data); socket.emit('receivedFromClient', { my: 'data' }); });

Using the instantiated socket variable, we have very similar logic on the server with a socket.on function. For the client, it is listening to the sendToClient event. As soon as the client is connected, the server sends this message. When the client receives it, it is logged to the console in the browser. The client then uses the same socket.emit that the server used to send the original event. In this instance, the client sends back the receivedFromClient event to the server. When the server receives the message, it is logged to the console window.

Try it out for yourself. First, in a console, run your Node application: node index.js. Then load http://localhost:3000 in your browser.

Check the web browser console and you should see the following JSON data logged: {hello: "world"}

Then, in the command prompt where the Node application is running, you should see the following:

HTTP server started on port 3000 Client connection received { my: 'data' }

Both the client and server can use the JSON data received to perform specific tasks. We will learn more about that once we connect to the real-time sports data.

Sports Data

Now that we have mastered how to send and receive data to and from the client and server, this can be leveraged to provide real-time updates. I chose to use sports data, although the same theory is not limited to sports. Before I began this project, I researched different sports data. The one I settled on, because they offer free developer accounts, was MySportsFeeds (I am not affiliated with them in any way). To access the real-time data, I signed up for an account and then made a small donation. Donations start at $1 to have data updated every 10 minutes. This will be good for the example.

Once your account is set up, you can proceed to setting up access to their API. To assist with this, I am going to use their NPM package: npm install mysportsfeeds-node --save

After the package has been installed, API calls can be made as follows:

var MySportsFeeds = require("mysportsfeeds-node"); var msf = new MySportsFeeds("1.2", true); msf.authenticate("********", "*********"); var today = new Date(); msf.getData('nhl', '2017-2018-regular', 'scoreboard', 'json', { fordate: today.getFullYear() + ('0' + parseInt(today.getMonth() + 1)).slice(-2) + ('0' + today.getDate()).slice(-2), force: true });

In the example above, be sure to replace the call to the authenticate function with your username and password.

The following code executes an API call to the get the NHL scoreboard for today. The fordate variable is what specifies today. I've also set force to true so that a response is always returned, even when the data has not changed.

With the current setup, the results of the API call get written to a text file. In the final example, this will be changed; however, for demonstration purposes, the results file can be reviewed in a text editor to understand the contents of the response. The results contain a scoreboard object. This object contains an array called gameScore. This object stores the result of each game. Each object contains a child object called game. This object provides the information about who is playing.

Outside of the game object, there are a handful of variables that provide the current state of the game. The data changes based on the state of the game. For example, when the game hasn't started, there are only a few variables that tell us the game is not in progress and has not started.

When the game is in progress, additional data is provided about the score, what period the game is in, and how much time is remaining. We will see this in action when we get to the HTML to show the game in the next section.

Real-Time Updates

We have all the pieces to the puzzle, so it is now time to put the puzzle together to reveal the final picture. Currently, MySportsFeeds has limited support for pushing data to us, so we will have to poll the data from them. Luckily, we know the data only changes once every 10 minutes, so we don't need to add overhead by polling for changes too frequently. Once we poll the data from them, we can push those updates from the server to all clients connected.

To perform the polling, I will use the JavaScript setInterval function to call the API (in my case) every 10 minutes to look for updates. When the data is received, an event is sent to all of the connected clients. When the clients receive the event, the game scores will be updated with JavaScript in the web browser.

MySportsFeeds will also be called when the Node application first starts up. This data will be used for any clients who connect before the first 10-minute interval. This is stored in a global variable. This same global variable is updated as part of the interval polling. This will ensure that when any new clients connect after the polling, they will have the latest data.

To assist with some code cleanliness in the main index.js file, I have created a new file called data.js. This file will contain a function that is exported (available in the index.js file) that performs the previous call to the MySportsFeeds API. Here are the full contents of that file:

var MySportsFeeds = require("mysportsfeeds-node"); var msf = new MySportsFeeds("1.2", true, null); msf.authenticate("*******", "******"); var today = new Date(); exports.getData = function() { return msf.getData('nhl', '2017-2018-regular', 'scoreboard', 'json', { fordate: today.getFullYear() + ('0' + parseInt(today.getMonth() + 1)).slice(-2) + ('0' + today.getDate()).slice(-2), force: true }); };

A getData function is exported and returns the result of the call, which in this case is a Promise that will be resolved in the main application.

Now let's look at the final contents of the index.js file:

var app = require('express')(); var http = require('http').Server(app); var io = require('socket.io')(http); var data = require('./data.js'); // Global variable to store the latest NHL results var latestData; // Load the NHL data for when client's first connect // This will be updated every 10 minutes data.getData().then((result) => { latestData = result; }); app.get('/', function(req, res){ res.sendFile(__dirname + '/index.html'); }); http.listen(3000, function(){ console.log('HTTP server started on port 3000'); }); io.on('connection', function(socket){ // when clients connect, send the latest data socket.emit('data', latestData); }); // refresh data setInterval(function() { data.getData().then((result) => { // Update latest results for when new client's connect latestData = result; // send it to all connected clients io.emit('data', result); console.log('Last updated: ' + new Date()); }); }, 300000);

The first seven lines of code above instantiate the required libraries and the global latestData variable. The final list of libraries used are: Express, Http Server created with Express, Socket.io, and the aforementioned data.js file just created.

With the necessities taken care of, the application populates the latestData for clients who will connect when the server is first started:

// Global variable to store the latest NHL results var latestData; // Load the NHL data for when client's first connect // This will be updated every 10 minutes data.getData().then((result) => { latestData = result; });

The next few lines set up a route for the root page of the website (http://localhost:3000/) and start the HTTP server to listen on port 3000.

Next, the Socket.io is set up to look for connections. When a new connection is received, the server emits an event called data with the contents of the latestData variable.

And finally, the final chunk of code creates the polling interval. When the interval occurs, the latestData variable is updated with the results of the API call. This data then emits the same data event to all clients.

// refresh data setInterval(function() { data.getData().then((result) => { // Update latest results for when new client's connect latestData = result; // send it to all connected clients io.emit('data', result); console.log('Last updated: ' + new Date()); }); }, 300000);

You may notice that when the client connects and an event is emitted, it is emitting the event with the socket variable. This approach will send the event to that connected client only. Inside the interval, the global io is used to emit the event. This will send the event to all clients.

That completes the server. Let's work on the client front-end. In an earlier example, I created a basic index.html file that set up the client connection that would log events from the server and send one back. I am going to extend that file to contain the completed example.

Because the server is sending us a JSON object, I am going to use jQuery and leverage a jQuery extension called JsRender. This is a templating library. It will allow me to create a template with HTML that will be used to display the contents of each NHL game in an easy-to-use, consistent manner. In a moment, you will see the power of this library. The final code is over 40 lines of code, so I am going to break it down into smaller chunks, and then display the full HTML together at the end.

This first part creates the template that will be used to show the game data:

<script id="gameTemplate" type="text/x-jsrender"> <div class="game"> <div> {{:game.awayTeam.City}} {{:game.awayTeam.Name}} at {{:game.homeTeam.City}} {{:game.homeTeam.Name}} </div> <div> {{if isUnplayed == "true" }} Game starts at {{:game.time}} {{else isCompleted == "false"}} <div>Current Score: {{:awayScore}} - {{:homeScore}}</div> <div> {{if currentIntermission}} {{:~ordinal_suffix_of(currentIntermission)}} Intermission {{else currentPeriod}} {{:~ordinal_suffix_of(currentPeriod)}}<br/> {{:~time_left(currentPeriodSecondsRemaining)}} {{else}} 1st {{/if}} </div> {{else}} Final Score: {{:awayScore}} - {{:homeScore}} {{/if}} </div> </div> </script>

The template is defined using a script tag. It contains the id of the template and a special script type called text/x-jsrender. The template defines a container div for each game that contains a class game to apply some basic styling. Inside this div, the templating begins.

In the next div, the away and home team are displayed. This is done by concatenating the city and team name together from the game object from the MySportsFeed data.

{{:game.awayTeam.City}} is how I define an object that will be replaced with a physical value when the template is rendered. This syntax is defined by the JsRender library.

Once the teams are displayed, the next chunk of code does some conditional logic. When the game is unPlayed, a string will be outputted that the game will start at {{:game.time}}.

When the game is not completed, the current score is displayed: Current Score: {{:awayScore}} - {{:homeScore}}. And finally, some tricky little logic to identify what period the hockey game is in or if it is in intermission.

If the variable currentIntermission is provided in the results, then I use a function I defined called ordinal_suffix_of, which will convert the period number to read: 1st (2nd, 3rd, etc.) Intermission.

When it is not in intermission, I look for the currentPeriod value. This also uses the ordinal_suffix_of  to show that the game is in the 1st (2nd, 3rd, etc.) period.

Beneath this, another function I defined called time_left is used to convert the number of seconds remaining into the number of minutes and seconds remaining in the period. For example: 10:12.

The final part of the code displays the final score because we know the game has completed.

Here is an example of what it looks like when there is a mix of finished games, in progress games, and games that have not started yet (I'm not a very good designer, so it looks as you would expect when a developer makes their own User Interface).

Next up is a chunk of JavaScript that creates the socket, the helper functions ordinal_suffix_of and time_left, and a variable that references the jQuery template created.

<script> var socket = io(); var tmpl = $.templates("#gameTemplate"); var helpers = { ordinal_suffix_of: function(i) { var j = i % 10, k = i % 100; if (j == 1 && k != 11) { return i + "st"; } if (j == 2 && k != 12) { return i + "nd"; } if (j == 3 && k != 13) { return i + "rd"; } return i + "th"; }, time_left: function(time) { var minutes = Math.floor(time / 60); var seconds = time - minutes * 60; return minutes + ':' + ('0' + seconds).slice(-2); } }; </script>

The final piece of code is the code to receive the socket event and render the template:

socket.on('data', function (data) { console.log(data); $('#data').html(tmpl.render(data.scoreboard.gameScore, helpers)); });

I have a placeholder div with the id of data. The result of the template rendering (tmpl.render) writes the HTML to this container. What is really neat is that the JsRender library can accept an array of data, in this case data.scoreboard.gameScore, that iterates through each element in the array and creates one game per element.

Here is the final HTML and JavaScript all together:

<!doctype html> <html> <head> <title>Socket.IO Example</title> </head> <body> <div id="data"> </div> <script id="gameTemplate" type="text/x-jsrender"> <div class="game"> <div> {{:game.awayTeam.City}} {{:game.awayTeam.Name}} at {{:game.homeTeam.City}} {{:game.homeTeam.Name}} </div> <div> {{if isUnplayed == "true" }} Game starts at {{:game.time}} {{else isCompleted == "false"}} <div>Current Score: {{:awayScore}} - {{:homeScore}}</div> <div> {{if currentIntermission}} {{:~ordinal_suffix_of(currentIntermission)}} Intermission {{else currentPeriod}} {{:~ordinal_suffix_of(currentPeriod)}}<br/> {{:~time_left(currentPeriodSecondsRemaining)}} {{else}} 1st {{/if}} </div> {{else}} Final Score: {{:awayScore}} - {{:homeScore}} {{/if}} </div> </div> </script> <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/jsrender/0.9.90/jsrender.min.js"></script> <script src="/socket.io/socket.io.js"></script> <script> var socket = io(); var helpers = { ordinal_suffix_of: function(i) { var j = i % 10, k = i % 100; if (j == 1 && k != 11) { return i + "st"; } if (j == 2 && k != 12) { return i + "nd"; } if (j == 3 && k != 13) { return i + "rd"; } return i + "th"; }, time_left: function(time) { var minutes = Math.floor(time / 60); var seconds = time - minutes * 60; return minutes + ':' + ('0' + seconds).slice(-2); } }; var tmpl = $.templates("#gameTemplate"); socket.on('data', function (data) { console.log(data); $('#data').html(tmpl.render(data.scoreboard.gameScore, helpers)); }); </script> <style> .game { border: 1px solid #000; float: left; margin: 1%; padding: 1em; width: 25%; } </style> </body> </html>

Start the Node application and browse to http://localhost:3000 to see the results for yourself!

Every X minutes, the server will send an event to the client. The client will redraw the game elements with the updated data. So when you leave the site open and periodically look at it, you will see the game data refresh when games are currently in progress.

Conclusion

The final product uses Socket.io to create a server that clients connect to. The server fetches data and sends it to the client. When the client receives the data, it can seamlessly update the display. This reduces load on the server because the client only performs work when it receives an event from the server.

Sockets are not limited to one direction; the client can also send messages to the server. When the server receives the message, it can perform some processing.

Chat applications would commonly work this way. The server would receive a message from the client and then broadcast to all connected clients to show that someone has sent a new message.

Hopefully you enjoyed this article as I had a blast creating this real-time sports application for one of my favorite sports!

Categories: Web Design

Monthly Web Development Update 5/2018: Browser Performance, Iteration Zero, And Web Authentication

Smashing Magazine - Fri, 05/18/2018 - 04:51
Monthly Web Development Update 5/2018: Browser Performance, Iteration Zero, And Web Authentication Monthly Web Development Update 5/2018: Browser Performance, Iteration Zero, And Web Authentication Anselm Hannemann 2018-05-18T13:51:17+02:00 2018-05-29T17:22:14+00:00

As developers, we often talk about performance and request browsers to render things faster. But when they finally do, we demand even more performance.

Alex Russel from the Chrome team now shared some thoughts on developers abusing browser performance and explains why websites are still slow even though browsers reinvented themselves with incredibly fast rendering engines. This is in line with an article by Oliver Williams in which he states that we’re focusing on the wrong things, and instead of delivering the fastest solutions for slower machines and browsers, we’re serving even bigger bundles with polyfills and transpiled code to every browser.

It certainly isn’t easy to break out of this pattern and keep bundle size to a minimum in the interest of the user, but we have the technologies to achieve that. So let’s explore non-traditional ways and think about the actual user experience more often — before defining a project workflow instead of afterward.

Front-End Performance Checklist 2018

To help you cater for fast and smooth experiences, Vitaly Friedman summarized everything you need to know to optimize your site’s performance in one handy checklist. Read more →

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

Explore features →

News

General

  • Oliver Williams wrote about how important it is that we rethink how we’re building websites and implement “progressive enhancement” to make the web work great for everyone. After all, it’s us who make the experience worse for our users when blindly transpiling all our ECMAScript code or serving tons of JavaScript polyfills to those who already use slow machines and old software.
  • Ian Feather reveals that around 1% of all requests for JavaScript on BuzzFeed time out. That’s about 13 million requests per month. A good reminder of how important it is to provide a solid fallback, progressive enhancement, and workarounds.
  • The new GDPR (General Data Protection Regulation) directive is coming very soon, and while our inboxes are full of privacy policy updates, one thing that’s still very unclear is which services can already provide so-called DPAs (Data Processing Agreements). Joschi Kuphal collects services that offer a DPA, so that we can easily look them up and see how we can obtain a copy in order to continue using their services. You can help by contributing to this resource via Pull Requests.
UI/UX How to create a consistent, harmonious user experience when designing product cards? Mei Zhang shares some valuable tips. (Image credit) Security Privacy
  • The GDPR Checklist is another helpful resource for people to check whether a website is compliant with the upcoming EU directive.
  • Bloomberg published a story about the open-source privacy-protection project pi-hole, why it exists and what it wants to achieve. I use the software daily to keep my entire home and work network tracking-free.
Achieving GDPR Compliance shouldn’t be a struggle. The GDPR Compliance Checklist helps you see clearer. (Image credit)

Web Performance

  • Postgres 10 has been here for quite a while already, but I personally struggled to find good information on how to use all these amazing features it brings along. Gabriel Enslein now shares Postgres 10 performance updates in a slide deck, shedding light on how to use the built-in JSON support, native partitioning for large datasets, hash index resiliency, and more.
  • Andrew Betts found out that a lot of websites are using outdated headers. He now shares why we should drop old headers and which ones to serve instead.
Accessibility Page previews open possibilities in multiple areas, as Nirzar Pangarkar explains. (Image credit: Nirzar Pangarkar) CSS
  • Rarely talked about for years, CSS tables are still used on most websites to show (and that’s totally the correct way to do so) data in tables. But as they’re not responsive by default, we always struggled when making them responsive and most of us used JavaScript to make them work on mobile screens. Lea Verou now found two new ways to achieve responsive tables by using CSS: One is to use text-shadow to copy text to other rows, the other one uses element() to copy the entire <thead> to other rows — I still try to understand how Lea found these solutions, but this is amazing!
  • Rachel Andrew wrote an article about building and providing print stylesheets in 2018 and why they matter a lot for users even if they don’t own a printer anymore.
  • Osvaldas Valutis shares how to implement the so-called “Priority Plus” navigation pattern mostly with CSS, at least in modern browsers. If you need to support older browsers, you will need to extend this solution further, but it’s a great start to implement such a pattern without too much JavaScript.
  • Rachel Andrew shares what’s coming up in the CSS Grid Level 2 and Subgrid specifications and explains what it is, what it can solve, and how to use it once it is available in browsers.
JavaScript
  • Chris Ashton “used the web for a day with JavaScript turned off.” This piece highlights the importance of thinking about possible JavaScript failures on websites and why it matters if you provide fallbacks or not.
  • Sam Thorogood shares how we can build a “native undo & redo for the web”, as used in many text editors, games, planning or graphical software and other occasions such as a drag and drop reordering. And while it’s not easy to build, the article explains the concepts and technical aspects to help us understand this complicated matter.
  • There’s a new way to implement element/container queries into your application: eqio is a tiny library using IntersectionObserver.
Work & Life
  • Johannes Seitz shares his thoughts about project management at the start of projects. He calls the method “Iteration Zero”. An interesting concept to understand the scope and risks of a project better at a time when you still don’t have enough experience with the project itself but need to build a roadmap to get things started.
  • Arestia Rosenberg shares why her number one advice for freelancers is to ‘lean into the moment’. It’s about doing work when you can and using your chance to do something else when you don’t feel you can work productively. In the end, the summary results in a happy life and more productivity. I’d personally extend this to all people who can do that, but, of course, it’s best applicable to freelancers indeed.
  • Sam Altman shares a couple of handy productivity tips that are not just a ‘ten things to do’ list but actually really helpful thoughts about how to think about being productive.
Going Beyond…
  • Ethan Marcotte elaborates on the ethical issues with Google Duplex that is designed to imitate human voice so well that people don’t notice if it’s a machine or a human being. While this sounds quite interesting from a technical point of view, it will push the debate about fake news much further and cause more struggle to differentiate between something a human said or a machine imitated.
  • Our world is actually built on promises, and here’s why it’s so important to stick to your promises even if it’s hard sometimes.
  • I bet that most of you haven’t heard of Palantir yet. The company is funded by Peter Thiel and is a data-mining company that has the intention to collect as much data as possible about everybody in the world. It’s known to collaborate with various law enforcement authorities and even has connections to military services. What they do with data and which data they have from us isn’t known. My only hope right now is that this company will suffer a lot from the EU GDPR directive and that the European Union will try to stop their uncontrolled data collection. Facebook’s data practices are nothing compared to Palantir it seems.
  • Researchers sound the alarm after an analysis showed that buying a new smartphone consumes as much energy as using an existing phone for an entire decade. I guess I’ll not replace my iPhone 7 anytime soon — it’s still an absolutely great device and just enough for what I do with it.
  • Anton Sten shares his thoughts on Vanity Metrics, a common way to share numbers and statistics out of context. And since he realized what relevancy they have, he thinks differently about most of the commonly readable data such as investments or usage data of services now. Reading one number without having a context to compare it to doesn’t matter at all. We should keep that in mind.

We hope you enjoyed this Web Development Update. The next one is scheduled for Friday, June 15th. Stay tuned.

(cm)
Categories: Web Design

More Than Pixels: Selling Design Discovery

Smashing Magazine - Thu, 05/17/2018 - 05:10
More Than Pixels: Selling Design Discovery More Than Pixels: Selling Design Discovery Kyle Cassidy 2018-05-17T14:10:03+02:00 2018-05-29T17:22:14+00:00

As designers, we know that research should play a pivotal role in any design process. Sadly, however, there are still a lot of organizations that do not see the value of research and would rather jump straight into the visual design stage of the design process.

The excuses given here tend to be:

“We already know what our customers want.”

“We don’t have the time/budget/people.”

“We’ll figure out the flaws in BETA.”

As designers, it is important that we are equipped to be able to have conversations with senior stakeholders to be able to sell and justify the importance of the so-called “Design Discovery” within the design process.

In this article, I’ll demystify what is meant by the term “Design Discovery” to help you better establish the importance of research within the creative process. I’ll also be giving advice on how to handle common pushbacks, along with providing various hints and tips on how to select the best research methods when undertaking user research.

My hope is that by reading this article, you will become comfortable with being able to sell “Design Discovery” as part of the creative process. You will know how to build a “Discovery Plan” of activities that answers all the questions you and your client need to initiate the design process with a clear purpose and direction.

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

Table of Contents → Design With A Purpose

Digital design is not just about opening up Photoshop or Sketch and adding colors, shapes, textures, and animation to make a beautiful looking website or app.

As designers, before putting any pixels on canvas, we should have a solid understanding of:

  1. Who are the users we are designing for?
  2. What are the key tasks those users want to accomplish?

Ask yourself, is the purpose of what you are producing? Is it to help users:

  • Conduct research,
  • Find information,
  • Save time,
  • Track fitness,
  • Maintain a healthy lifestyle,
  • Feel safe,
  • Organize schedules,
  • Source goods,
  • Purchase products,
  • Gather ideas,
  • Manage finances,
  • Communicate,
  • Or something entirely different?

Understanding the answers to these questions should inform your design decisions. But before we design, we need to do some research.

Discovery Phase

Any design process worth its salt should start with a period of research, which (in agency terms) is often referred to as a “Discovery Phase”. The time and budget designers can allocate to a Discovery phase is determined by many factors such as the amount of the client’s existing project research and documentation as well as the client’s budget. Not to mention your own personal context, which we will come to later.

Business And User Goals

In a Discovery phase, we should ensure adequate time is dedicated to exploring both business and user goals.

Yes, we design experiences for users, but ultimately we produce our designs for clients (be that internal or external), too. Clients are the gatekeepers to what we design. They have the ultimate say over the project and they are the ones that hold the purse strings. Clients will have their own goals they want to achieve from a project and these do not always align with the users’ goals.

In order to ensure what we design throughout our design process hits the sweet spot, we need to make sure that we are spending time exploring both the business and user goals for the project (in the Research/Discovery phase).

Your Discovery phase should explore both user and business goals. (Large preview) Uncovering Business Goals

Typically, the quickest way to establish the business goals for a project is to host a stakeholder workshop with key project stakeholders. Your aim should be to get as many representatives from across different business functions as possible into one room to discuss the vision for the project (Marketing, Finance, Digital, Customer Services, and Sales).

Tip: Large organizations often tend to operate in organizational silos. This allows teams to focus on their core function such as marketing, customer care, etc. It allows staff to be effective without being distracted by activities where they have no knowledge and little or no skills. However, it often becomes a problem when the teams don’t have a singular vision/mission from leadership, and they begin to see their area as the driving force behind the company’s success. Often in these situations, cross-departmental communication can be poor to non-existent. By bringing different members from across the organization together in one room, you get to the source of the truth quicker and can link together internal business processes and ways of working.

The core purpose of the stakeholder workshop should be:

  1. To uncover the Current State (explore what exists today in terms of people, processes, systems, and tools);
  2. To define the Desired Future State (understand where the client wants to get to, i.e. their understandig of what the ideal state should look like);
  3. To align all stakeholders on the Vision for the project.
Use workshops to align stakeholders around the vision and define the Desired Future State. (Large preview)

There are a series of activities that you can employ within your stakeholder workshop. I tend to typically build a full workshop day (7-8 hours) around 4-5 activities allowing 45mins uptil 1 hour for lunch and two 15-min coffee breaks between exercises. Any more that than, and I find energy levels start to dwindle.

I will vary the workshop activities I do around the nature of the project. However, each workshop I lead tends to include the following three core activities:

Activity Purpose Business Model Canvas To explore the organizations business model and discuss where this project fits this model. Measurement Plan Define what are the most important business metrics the business wants to be able to measure and report on. Proto Personas and User Stories Explore who the business feels their users are and what are the key user stories we need to deliver against.

Tip: If you’re new to delivering client workshops, I’ve added a list of recommended reading to the references section at the bottom of this article which will give you useful ideas on workshop activities, materials, and group sizes.

Following the workshop, you’ll need to produce a write up of what happened in the workshop itself. It also helps to take lots of photos on the workshop day. The purpose of the write-up should be to not only explain the purpose of the day and key findings, but also recommendations of next steps. Write-ups can be especially helpful for internal communication within the organization and bringing non-attendees up to speed with what happened on the day as well as agreeing on the next steps for the project.

Uncovering User Goals

Of course, Discovery is not just about understanding what the organization wants. We need to validate what users actually want and need.

With the business goals defined, you can then move on to explore the user goals through conducting some user research. There are many different user research methods you can employ throughout the Discovery process from Customer Interviews and Heuristic Evaluations to Usability Tests and Competitor Reviews, and more.

Having a clear idea of the questions you are looking to answer and available budget is the key to helping select the right research methods. It is, for this reason, important that you have a good idea of what these are before you get to this point.

Before you start to select which are the best user research methods to employ, step back and ask yourself the following question:

“What are the questions I/we as a design team need answers to?”

For example, do you want to understand:

  • How many users are interacting with the current product?
  • How do users think your product compares to a competitor product?
  • What are the most common friction points within the current product?
  • How is the current product’s performance measured?
  • Do users struggle to find certain key pieces of information?

Grab a pen and write down what you want to achieve from your research in a list.

Tip: If you know you are going to be working on a fixed/tight budget, it is important to get confirmation on what that budget may look like at this point since this will have some bearing on the research methods you choose.

Another tip: User research does not have to happen after organizational research. I always find it helps to do some exploratory research prior to running stakeholder workshops. This ensures you go into the room with a baseline understanding of the organization its users and some common pain points. Some customers may not know what users do on their websites/apps nowadays; I like to go in prepared with some research to hand whether that be User Testing, Analytics Review or Tree Testing outputs.

Selecting Research Methods

The map below from the Nielsen Norman Group (NNG) shows an overview of 20 popular user research methods plotted on a 3-dimensional framework. It can provide a useful guide for helping you narrow down on a set of research methods to use.

A map of the top 20 research methods from NNG. (Large preview)

The diagram may look complicated, but let us break down some key terms.

Along the x-axis, research methods are separated by the types of data they produce.

  • Quantitative data involves numbers and figures. It is great for answering questions such as:

    • How much?
    • How many?
    • How long?
    • Impact tracking?
    • Benchmarking?
  • Qualitative data involves quote, observations, photos, videos, and notes.

    • What do users think?
    • How do users feel?
    • Why do users behave in a certain way?
    • What are users like?
    • What frustrates users?

Along the y-axis, research methods are separated by the user inputs.

  • Behavioral Data
    This data is based on what users do (outcomes).
  • Attitudinal Data
    This data is based on attitudes and opinions.

Finally, research methods are also classified by their context. Context explains the nature of the research, some research methods such as interviews require no product at all. Meanwhile, usability tests require users to complete scripted tasks and tell us how they think and feel.

Using the Model

Using your question list, firstly identify whether you are looking to understand users opinions (what people say) or actions (what people do) and secondly whether you are looking to understand why they behave in a certain way (why and how to fix) or how many of them are behaving in a certain way (how many and how much).

Now look at this simplified version of the matrix, and you should be able to work out which user research methods to focus in on.

Think about what questions you’re trying to answer when selecting research methods. (Large preview) Model Examples Example 1

If you’re looking to understand users’ attitudes and beliefs and you don’t have a working product then ‘Focus Groups’ or ‘Interviews’ would be suitable user research methods.

Large preview Example 2

If you want to understand how many users are interacting with the current website or app then an ‘Analytics Review’ would be the right research method to adopt. Meanwhile, if you want to test how many people will be impacted by a change, A/B testing would be a suitable method.

Large preview No Silver Bullet

By now you should realize there is no shortcut to the research process; not one single UX research method will provide all the answers you need for a project.

Analytics reviews, for example, are a great low-cost way to explore behavioral, quantitative data about how users interact with an existing website or application.

However, this data falls short of telling you:

  • Why users visited the site/app in the first place (motivation);
  • What tasks they were looking to accomplish (intent);
  • If users were successful in completing their tasks (task completion);
  • How users found their overall experience (satisfaction).

These types of questions are best answered by other research methods such as ‘Customer Feedback’ surveys (also known as ‘Intercept Surveys’) which are available from tools such as Hotjar, Usabilla, and Qualaroo.

Usabilla’s quick feedback button allows users to provide instant feedback on their experience. (Large preview) Costing Research/Discovery

In order to build a holistic view of the user experience, the Research/Discovery process should typically last around 3 to 4 weeks and combine a combination of the different research methods.

Use your list of questions and the NNG matrix to help you decide on the most suitable research methods for your project. Wherever possible, try to use complimentary research methods to build a bigger picture of users motivations, drivers, and behaviors.

Your Design Discovery process should combine different types of data. (Large preview)

Tip: The UX Recipe tool is a great website for helping you pull together the different research methods you feel you need for a project and to calculate the cost of doing so.

Which brings me on to my next point.

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

Table of Contents → Contexts And Budgets

The time and budget which you can allocate to Discovery will vary greatly depending on your role. Are you working in-house, freelance, or in an agency? Some typical scenarios are as follows:

  • Agency
    Clients employ agencies to build projects that generate the right results. To get the right results, you firstly need to ensure you understand both the business’ needs and the needs of the users as these are almost always not the same. Agencies almost always start with a detailed Discovery phase often led by the UX Design team. Budgets are generally included in the cost of the total project, as such ample time is available for research.
  • In-House: Large Company
    When working in a large company, you are likely to already have a suite of tools along with a program of activity you’re using to measure the customer experience. Secondly, you are likely to be working alongside colleagues with specialist skills such as Data Analysts, Market Researchers, and even a Content Team. Do not be afraid to say hello to these people and see if they will be willing to help you conduct some research. Customer service teams are also worth befriending. Customer service teams are the front line of a business where customer problems are aired for all to see. They can be a goldmine of useful information. Go spend some time with the team, listen to customer service calls, and review call/chat logs.
  • In-House: Smaller Company
    When working as part of an in-house team in a smaller company, you are likely to be working on a tight budget and are spread across a lot of activities. Nevertheless, with some creative thinking, you can still undertake some low-cost research tasks such as Site Intercept surveys, Analytics reviews, and Guerilla testing, or simply review applied research.
  • Freelance
    When working freelance, your client often seeks you out with a very fixed budget, timeline and set of deliverables in mind, i.e. “We need a new Logo” or “We need a landing page design.” Selling Discovery as part of the process can often be a challenge freelancers typically undertake since they mostly end up using their own time and even working overtime. But it doesn’t have to be like this. Clients can be willing to spend their time in the Discovery pre-project phase. However, you need to be confident to be able to sell yourself and defend your process. This video has some excellent tips on how to sell Discovery to clients as a freelancer.
Selling Design Discovery

As you can see from the above, selling Design Discovery can be a challenge depending on your context. It’s much harder to sell Design Discovery when working as a freelancer than it is working within an agency.

Some of the most commons excuses organizations put forward for discounting the research process are:

“We don’t have the budget.”

“We’ll find it out in BETA.”

“We don’t have time.”

“We already know what users want.”

When selling Design Discovery and combating these points of view, remember these key things:

It doesn’t have to be expensive.

Research does not have to be costly especially with all of the tools and resources we have available today. You can conduct a Guerilla User Testing session for the price of a basic coffee. Furthermore, you can often source willing participants from website intercepts, forums or social media groups who are more than willing to help.

It’s much harder to fix later.

The findings that come as an output from research can be invaluable. It is much more cost and time effective to spend some of the project budgets up front to ensure there are no assumptions and blind spots than it is to course correct later on if the project has shifted off tangent. Uncovering blockers or significant pain points later into the project can be a huge drain on time as well as monetary resources.

Organizational views can often be biased.

Within large organizations especially, a view of ‘what users want’ is often shaped by senior managers’ thoughts and opinions rather than any applied user research. These viewpoints then cascade down to more junior members of the team who start to adopt the same viewpoints. Validating these opinions are actually correct viewpoints is essential.

There are other cross-company benefits.

Furthermore, a Discovery process also brings with it internal benefits. By bringing members from other business functions together and setting a clear direction for the project, you should win advocates for the project across many business functions. Everyone should leave the room with a clear understanding of what the project is, its vision, and the problems you are trying to fix. This helps to alleviate an enormous amount of uncertainty within the organization.

I like to best explain the purpose of the discovery phase by using my adaptation of the Design Squiggle by Damien Newman:

See how the Discovery phase allows us time to tackle the most uncertainty?

An adaptation of the Design Squiggle by Damien Newman showing how uncertainty is reduced in projects over time. (Large preview) Waterfall And Agile

A Discovery phase can be integrated into both Waterfall and Agile project management methodologies.

In Waterfall projects, the Discovery phase happens at the very start of the project and can typically run for 4 to 12 weeks depending on the size of the project, the number of interdependent systems, and the areas which need to be explored.

In Agile projects, you may run a Discovery phase upfront to outline the purpose for the project and interconnect systems along with mini 1 to 2-week discovery process at the start of each sprint to gather the information you need to build out a feature.

Discovery process can be easily incorporated into both waterfall and agile projects. (Large preview) Final Thoughts

The next time you start on any digital project:

  • Make sure you allow time for a Discovery phase at the start of your project to define both business and user goals, and to set a clear vision that sets a clear purpose and direction for the project to all stakeholders.

  • Be sure to run a Stakeholder workshop with representatives from a variety of different business functions across the business (Marketing, Finance, Digital, Customer Services, Sales).

  • Before selecting which user research methods to use on your project, write down a list of questions you wish to understand and get a budget defined. From there, you can use the NNG matrix to help you understand what the best tool to use is.

Further Reading

If you found this article interesting, here is some recommended further reading:

Workshop Books

If you are interested in running Stakeholder workshops, I’d highly recommend reading the following books. Not only will they give you useful hints and tips on how to run workshops, they’re packed full of different workshop exercises to help you get answers to specific questions.

(cc, ra, yk, il)
Categories: Web Design

Managing SVG Interaction With The Pointer Events Property

Smashing Magazine - Wed, 05/16/2018 - 05:15
Managing SVG Interaction With The Pointer Events Property Managing SVG Interaction With The Pointer Events Property Tiffany Brown 2018-05-16T14:15:25+02:00 2018-05-29T17:22:14+00:00

Try clicking or tapping the SVG image below. If you put your pointer in the right place (the shaded path) then you should have Smashing Magazine’s homepage open in a new browser tab. If you tried to click on some white space, you might be really confused instead.

See the Pen Amethyst by Tiffany Brown (@webinista) on CodePen.

This is the dilemma I faced during a recent project that included links within SVG images. Sometimes when I clicked the image, the link worked. Other times it didn’t. Confusing, right?

I turned to the SVG specification to learn more about what might be happening and whether SVG offers a fix. The answer: pointer-events.

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

Explore Smashing Wizardry →

Not to be confused with DOM (Document Object Model) pointer events, pointer-events is both a CSS property and an SVG element attribute. With it, we can manage which parts of an SVG document or element can receive events from a pointing device such as a mouse, trackpad, or finger.

A note about terminology: "pointer events" is also the name of a device-agnostic, web platform feature for user input. However, in this article — and for the purposes of the pointer-events property — the phrase "pointer events" also includes mouse and touch events.

Outside Of The Box: SVG’s "Shape Model"

Using CSS with HTML imposes a box layout model on HTML. In the box layout model, every element generates a rectangle around its contents. That rectangle may be inline, inline-level, atomic inline-level, or block, but it’s still a rectangle with four right angles and four edges. When we add a link or an event listener to an element, the interactive area matches the dimensions of the rectangle.

Note: Adding a clip-path to an interactive element alters its interactive bounds. In other words, if you add a hexagonal clip-path path to an a element, only the points within the clipping path will be clickable. Similarly, adding a skew transformation will turn rectangles into rhomboids.

SVG does not have a box layout model. You see, when an SVG document is contained by an HTML document, within a CSS layout, the root SVG element adheres to the box layout model. Its child elements do not. As a result, most CSS layout-related properties don’t apply to SVG.

So instead, SVG has what I’ll call a ‘shape model’. When we add a link or an event listener to an SVG document or element, the interactive area will not necessarily be a rectangle. SVG elements do have a bounding box. The bounding box is defined as: the tightest fitting rectangle aligned with the axes of that element’s user coordinate system that entirely encloses it and its descendants. But initially, which parts of an SVG document are interactive depends on which parts are visible and/or painted.

Painted vs. Visible Elements

SVG elements can be “filled” but they can also be “stroked”. Fill refers to the interior of a shape. Stroke refers to its outline.

Together, “fill” and “stroke” are painting operations that render elements to the screen or page (also known as the canvas). When we talk about painted elements, we mean that the element has a fill and/or a stroke. Usually, this means the element is also visible.

However, an SVG element can be painted without being visible. This can happen if the visible attribute value or CSS property is hidden or when display is none. The element is there and occupies theoretical space. We just can’t see it (and assistive technology may not detect it).

Perhaps more confusingly, an element can also be visible — that is, have a computed visibility value of visible — without being painted. This happens when elements lack both a stroke and a fill.

Note: Color values with alpha transparency (e.g. rgba(0,0,0,0)) do not affect whether an element is painted or visible. In other words, if an element has an alpha transparent fill or stroke, it’s painted even if it can’t be seen.

Knowing when an element is painted, visible, or neither is crucial to understanding the impact of each pointer-events value.

All Or None Or Something In Between: The Values

pointer-events is both a CSS property and an SVG element attribute. Its initial value is auto, which means that only the painted and visible portions will receive pointer events. Most other values can be split into two groups:

  1. Values that require an element to be visible; and
  2. Values that do not.

painted, fill, stroke, and all fall into the latter category. Their visibility-dependent counterparts — visiblePainted, visibleFill, visibleStroke and visible — fall into the former.

The SVG 2.0 specification also defines a bounding-box value. When the value of pointer-events is bounding-box, the rectangular area around the element can also receive pointer events. As of this writing, only Chrome 65+ supports the bounding-box value.

none is also a valid value. It prevents the element and its children from receiving any pointer events. The pointer-events CSS property can be used with HTML elements too. But when used with HTML, only auto and none are valid values.

Since pointer-events values are better demonstrated than explained, let’s look at some demos.

Here we have a circle with a fill and a stroke applied. It’s both painted and visible. The entire circle can receive pointer events, but the area outside of the circle cannot.

See the Pen Visible vs painted in SVG by Tiffany Brown (@webinista) on CodePen.

Disable the fill, so that its value is none. Now if you try to hover, click, or tap the interior of the circle, nothing happens. But if you do the same for the stroke area, pointer events are still dispatched. Changing the fill value to none means that this area visible, but not painted.

Let’s make a small change to our markup. We’ll add pointer-events="visible" to our circle element, while keeping fill=none.

See the Pen How adding pointer-events: all affects interactivity by Tiffany Brown (@webinista) on CodePen.

Now the unpainted area encircled by the stroke can receive pointer events.

Augmenting The Clickable Area Of An SVG Image

Let’s return to the image from the beginning of this article. Our “amethyst” is a path element, as opposed to a group of polygons each with a stroke and fill. That means we can’t just add pointer-events="all" and call it a day.

Instead, we need to augment the click area. Let’s use what we know about painted and visible elements. In the example below, I’ve added a rectangle to our image markup.

See the Pen Augmenting the click area of an SVG image by Tiffany Brown (@webinista) on CodePen.

Even though this rectangle is unseen, it’s still technically visible (i.e. visibility: visible). Its lack of a fill, however, means that it is not painted. Our image looks the same. Indeed it still works the same — clicking white space still doesn’t trigger a navigation operation. We still need to add a pointer-events attribute to our a element. Using the visible or all values will work here.

See the Pen Augmenting the click area of an SVG image by Tiffany Brown (@webinista) on CodePen.

Now the entire image can receive pointer events.

Using bounding-box would eliminate the need for a phantom element. All points within the bounding box would receive pointer events, including the white space enclosed by the path. But again: pointer-events="bounding-box" isn’t widely supported. Until it is, we can use unpainted elements.

Using pointer-events When Mixing SVG And HTML

Another case where pointer-events may be helpful: using SVG inside of an HTML button.

See the Pen Ovxmmy by Tiffany Brown (@webinista) on CodePen.

In most browsers — Firefox and Internet Explorer 11 are exceptions here — the value of event.target will be an SVG element instead of our HTML button. Let’s add pointer-events="none" to our opening SVG tag.

See the Pen How pointer-events: none can be used with SVG and HTML by Tiffany Brown (@webinista) on CodePen.

Now when users click or tap our button, the event.target will refer to our button.

Those well-versed in the DOM and JavaScript will note that using the function keyword instead of an arrow function and this instead of event.target fixes this problem. Using pointer-events="none" (or pointer-events: none; in your CSS), however, means that you don’t have to commit that particular JavaScript quirk to memory.

Conclusion

SVG supports the same kind of interactivity we’re used to with HTML. We can use it to create charts that respond to clicks or taps. We can create linked areas that don’t adhere to the CSS and HTML box model. And with the addition of pointer-events, we can improve the way our SVG documents behave in response to user interaction.

Browser support for SVG pointer-events is robust. Every browser that supports SVG supports the property for SVG documents and elements. When used with HTML elements, support is slightly less robust. It isn’t available in Internet Explorer 10 or its predecessors, or any version of Opera Mini.

We’ve just scratched the surface of pointer-events in this piece. For a more in-depth, technical treatment, read through the SVG Specification. MDN (Mozilla Developer Network) Web Docs offers more web developer-friendly documentation for pointer-events, complete with examples.

(rb, ra, yk, il)
Categories: Web Design

Landing The Concept: Movie High-Concept Theory And UX Design

Smashing Magazine - Tue, 05/15/2018 - 04:00
Landing The Concept: Movie High-Concept Theory And UX Design Landing The Concept: Movie High-Concept Theory And UX Design Andy Duke 2018-05-15T13:00:58+02:00 2018-05-29T17:22:14+00:00

Steven Spielberg once famously said, “If a person can tell me the idea in 25 words or less, it's going to make a pretty good movie.” He was referring to the notion that the best mass-appeal ‘blockbuster’ movies are able to succinctly state their concept or premise in a single short sentence, such as Jaws (“It’s about a shark terrorizing a small town”) and Toy Story (“It’s about some toys that come to life when nobody's looking”).

What if the same were true for websites? Do sites that explain their ‘concept’ in a simple way have a better shot at mass-appeal with users? If we look at the super simple layout of Google's homepage, for example, it gives users a single clear message about its concept equally as well as the Jaws movie poster:

Google homepage: “It’s about letting you search for stuff.” (Large preview)

Being aware of the importance of ‘high-concept’ allows us — as designers — to really focus on user’s initial impressions. Taking the time to actually define what you want your simple ‘high-concept’ to be before you even begin designing can really help steer you towards the right user experience.

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

Explore features → What Does High-Concept Theory Mean For UX Design?

So let’s take this seriously and look at it from a UX Design standpoint. It stands to reason that if you can explain the ‘concept’ or purpose of your site in a simple way you are lowering the cognitive load on new users when they try and understand it and in doing so, you’re drastically increasing your chances of them engaging.

The parallels between ‘High-Concept’ theory and UX Design best practice are clear. Blockbuster audiences prefer simple easy to relate concepts presented in an uncomplicated way. Web users often prefer simpler, easy to digest, UI (User Interface) design, clean layouts, and no clutter.

Regardless of what your message is, presenting it in a simple way is critical to the success of your site’s user experience. But, what about the message itself? Understanding if your message is ‘high-concept’ enough might also be critical to the site’s success.

What Is The Concept Of ‘High-Concept’ In The Online World?

What do we mean when we say ‘high-concept’? For movies it’s simple — it’s what the film is about, the basic storyline that can be easy to put into a single sentence, e.g. Jurassic Park is “about a theme park where dinosaurs are brought back to life.”

When we look at ‘high-concept’ on a website, however, it can really apply to anything: a mission statement, a service offering, or even a new product line. It’s simply the primary message you want to share through your site. If we apply the theory of ‘high-concept’, it tells us that we need to ensure that we convey that message in a simple and succinct style.

What Happens If You Get It Right?

Why is ‘high-concept’ so important? What are the benefits of presenting a ‘high-concept’ UX Design? One of the mistakes we often fall foul of in UX Design is focussing in on the specifics of user tasks and forgetting about the critical importance of initial opinions. In other words, we focus on how users will interact with a site once they’ve chosen to engage with it and miss the decision-making process that comes before everything. Considering ‘high-concept’ allows us to focus on this initial stage.

The basic premise to consider is that we engage better with things we understand and things we feel comfortable with. Ensuring your site presents its message in a simple ‘high-concept’ way will aid initial user engagement. That initial engagement is the critical precursor to all the good stuff that follows: sales, interaction, and a better conversion rate.

How Much Concept Is Too Much Concept?

The real trick is figuring out how much complexity your users can comfortably handle when it comes to positioning your message. You need to focus initially on presenting only high-level information rather than bombarding users with everything upfront. Give users only the level of understanding they need to engage initially with your site and drive them deeper into the journey disclosing more detail as you go.

Netflix does a great job at this. The initial view new users are presented with on the homepage screen is upfront with its super high-concept — ‘we do video content’ once users have engaged with this premise they are taken further into the proposition — more information is disclosed, prices, process, and so on.

Netflix: “It lets you watch shows and movies anywhere.” (Large preview) When To Land Your High-Concept?

As you decide how to layout the site, another critical factor to consider is when you choose to introduce your initial ‘high-concept’ to your users. It’s key to remember how rare it is that users follow a nice simple linear journey through your site starting at the homepage. The reality is that organic user journeys sometimes start with search results. As a result, the actual interaction with your site begins on the page that’s most relevant to the user’s query. With this in mind, it’s critical to consider how the premise of your site appears to users on key entry pages for your site wherever they appear in the overall hierarchy.

Another key point to consider when introducing the message of your site is that in many scenarios users will be judging whether to engage with you way before they even reach your site. If the first time you present your concept to users is via a Facebook ad or an email campaign, then implementation is drastically different. However, the theory should be the same, i.e. to ensure you present your message in that single sentence ‘high-concept’ style way with potential users.

How To Communicate Your High-Concept

Thus far, we’ve talked about how aiming for ‘high-concept’ messages can increase engagement — but how do we do this? Firstly, let’s focus on the obvious methods such as the wording you use (or don’t use).

Before you even begin designing, sit down and focus in on what you want the premise of your site to be. From there, draw out your straplines or headings to reflect that premise. Make sure you rely on content hierarchy though, use your headings to land the concept, and don’t bury messages that are critical to understanding deep in your body copy.

Here’s a nice example from Spotify. They achieve a ‘high-concept’ way of positioning their service through a simple, uncluttered combination of imagery and wording:

Spotify: “It lets you listen to loads of music.” (Large preview) Single Sentence Wording

It’s key to be as succinct as possible: the shorter your message is, the more readable it becomes. The true balancing act comes in deciding where to draw the line between too little to give enough understanding and too much to make it easily readable.

If we take the example of Google Drive — it’s a relatively complex service, but it’s presented in a very basic high-concept way — initially a single sentence that suggests security and simplicity:

Then the next level of site lands just a little more of the concept of the service but still keeping in a simple single sentence under 25 words (Spielberg would be pleased):

Google Drive: “A place where you can safely store your files online.” (Large preview) Explainer Videos

It doesn’t just stop with your wording as there is a myriad of other elements on the page that you can leverage to land your concept. The explainer video is used to great effect by Amazon to introduce users to the concept of Amazon Go. In reality, it’s a highly complex technical trial of machine learning, computer visual recognition, and AI (artificial intelligence) to reimagine the shopping experience. As it’s simply framed on the site, it can be explained in a ‘high-concept’ way.

Amazon gives users a single sentence and also, crucially, makes the whole header section a simple explainer video about the service.

Amazon Go: “A real life shop with no checkouts.” (Large preview) Imagery

The imagery you use can be used to quickly and simply convey powerful messages about your concept without the need to complicate your UI with other elements. Save the Children use imagery to great effect to quickly show the users the critical importance of their work arguably better than they ever could with wording.

Save the children… “They’re a charity that helps children.” (Large preview) Font And Color

It’s key to consider every element of your site as a potential mechanism for helping you communicate your purpose to your users, through the font or the color choices. For example, rather than having to explicitly tell users that your site is aimed at academics or children you can craft your UI to help show that.

Users have existing mental models that you can appeal to. For example, bright colors and childlike fonts suggest the site is aimed at children, serif fonts and limited color use often suggest a much more serious or academic subject matter. Therefore, when it comes to landing the concept of your site, consider these as important allies to communicate with your users without having to complicate your message.

Legoland: “A big Lego theme park for kids.” (Large preview) Design Affordance

So far, we’ve focused primarily on using messaging to communicate the concept to users. Still, what if the primary goal of your page is just to get users to interact with a specific element? For example, if you offer some kind of tool? If that’s the case, then showing the interface of this tool itself is often the best way to communicate its purpose to users.

This ties in with the concept of ‘Design Affordance’ — the idea that the form of a design should communicate its purpose. It stands to reason that sometimes the best way to tell users about your simple tool with an easy to use interface — is to show them that interface.

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

Table of Contents →

If we look at Airbnb, a large part of the Airbnb concept is the online tool that allows the searching and viewing of results; they use this to great effect on this landing page design by showing the data entry view for that search. Showing users how easy it is to search while also presenting them the with simple messaging about the Airbnb concept.

Airbnb: “It let’s you rent people’s homes for trips.” (Large preview) How To Test You’ve Landed It

Now that you’ve designed your site and you’re happy that it pitches its concept almost as well as an 80s blockbuster — but how can you validate that? It would be lovely to check things over with a few rounds of in-depth lab-based user research, but in reality, you’ll seldom have the opportunity, and you’ll find yourself relying on more ‘guerilla’ methods.

One of the simplest and most effective methodologies to check how ‘high-concept’ your site is is the ‘5 second’ or ‘glance’ test. The simple test involves showing someone the site for 5 seconds and then hiding it from view. Then, users can then be asked questions about what they can recall about the site. The idea being that in 5 seconds they only have the opportunity to view what is immediately obvious.

Here are some examples of questions to ask to get a sense of how well the concept of your site comes across:

  • Can you remember the name of the site you just saw?
  • What do you think is the purpose of the page you just saw?
  • Was it obvious what the site you just saw offers?
  • Do you think you would use the site you just saw?

Using this test with a decent number of people who match your target users should give some really valuable insight into how well your design conveys the purpose of your site and if indeed you’ve managed to achieve ‘high-concept’.

Putting It All Into Practice

Let’s try implementing all this knowledge in the real world? In terms of taking this and turning it into a practical approach, I try and follow these simple steps for every project:

  1. Aim For High-Concept
    When you’re establishing the purpose of any new site (or page or ad) try and boil it down to a single, simple, overarching ‘High-Concept.’
  2. Write It Down
    Document what you want that key concept to be in 25 words or less.
  3. Refer Back
    Constantly refer back to that concept throughout the design process. From picking your fonts and colors to crafting your headline content — ensure that it all supports that High-Concept you wrote down.
  4. Test It
    Once complete use the 5-second test on your design with a number of users and compare their initial thoughts to your initial High-Concept. If they correlate, then great, if not head back to step 3 and try again.

In this article, we have discussed the simple rule of making blockbuster movies, and we have applied that wisdom to web design. No ‘shock plot twist’ — just some common sense. The first time someone comes into contact with your website, it’s vital to think about what you want the initial message to be. If you want mass market appeal, then craft it into a ‘high-concept’ message that Spielberg himself would be proud of!

(ah, ra, yk, il)
Categories: Web Design

Pages