Friday, August 7, 2020

Higher-Order Components In React

In this tutorial, we are going to learn about higher-order components, the syntax of higher-order components, as well as use cases for them. In the process, we will build a higher-order component from an existing React component. By the end of this tutorial, you will understand the basics of higher-order components and how to build them.
Higher-order components (HOCs) in React were inspired by higher-order functions in JavaScript. A HOC is an advanced technique for reusing logic in React components. It is a pattern created out of React’s compositional nature.
HOCs basically incorporate the don’t-repeat-yourself (DRY) principle of programming, which you’ve most likely come across at some point in your career as a software developer. It is one of the best-known principles of software development, and observing it is very important when building an application or writing code in general.
In this tutorial, we will learn what a HOC is, its basic structure, some use cases, and finally an example.
Note: Basic knowledge of React and JavaScript will come in handy as you work through this tutorial.

Higher-Order Functions In JavaScript

Before jumping into HOCs in React, let’s briefly discuss higher-order functions in JavaScript. Understanding them is critical to understanding our topic of focus.
Higher-order functions in JavaScript take some functions as arguments and return another function. They enable us to abstract over actions, not just values, They come in several forms, and they help us to write less code when operating on functions and even arrays.
The most interesting part of using higher-order functions is composition. We can write small functions that handle one piece of logic. Then, we can compose complex functions by using the different small functions we have created. This reduces bugs in our code base and makes our code much easier to read and understand.
JavaScript has some of these functions already built in. Some examples of higher-order functions are the following:
  • .forEach()
    This iterates over every element in an array with the same code, but does not change or mutate the array, and it returns undefined.
  • .map()
    This method transforms an array by applying a function to all of its elements, and then building a new array from the returned values.
  • .reduce()
    This method executes a provided function for each value of the array (from left to right).
  • .filter()
    This checks every single element in an array to see whether it meets certain criteria as specified in the filter method, and then it returns a new array with the elements that match the criteria.
So many higher-order functions are built into JavaScript, and you can make your own custom ones.

An Example Of Custom Higher-Order Function

Suppose we are asked to write a function that formats integers as currencies, including some customization of specifying the currency symbol and adding a decimal separator for the currency amount. We can write a higher-other function that takes the currency symbol and also the decimal separator. This same function would then format the value passed to it with the currency symbol and decimal operators. We would name our higher-order function formatCurrency.
const formatCurrency = function( 
    currencySymbol,
    decimalSeparator  ) {
    return function( value ) {
        const wholePart = Math.trunc( value / 100 );
        let fractionalPart = value % 100;
        if ( fractionalPart < 10 ) {
            fractionalPart = '0' + fractionalPart;
        }
        return `${currencySymbol}${wholePart}${decimalSeparator}${fractionalPart}`;
    }
}
formatCurrency returns a function with a fixed currency symbol and decimal separator.
We then pass the formatter a value, and format this value with the function by extracting its whole part and the fractional part. The returned value of this function is constructed by a template literal, concatenating the currency symbol, the whole part, the decimal separator, and the fractional part.
Let’s use this higher-order function by assigning a value to it and seeing the result.
> getLabel = formatCurrency( '$', '.' );
 
> getLabel( 1999 )
"$19.99" //formatted value
 
> getLabel( 2499 )
"$24.99" //formatted value
You might have noticed that we created a variable named getLabel, then assigned our formatCurrency higher-order function, and then passed the currency formatters to the function, which is the currency symbol and a decimal separator. To make use of the function, we call getLabel, which is now a function, and we pass in the value that needs to be formatted. That’s all! We have created a custom higher order of our choice.

What Is A Higher-Order Component?

A higher-order component (HOC) is an advanced element for reusing logic in React components. Components take one or more components as arguments, and return a new upgraded component. Sounds familiar, right? They are similar to higher-order functions, which take some functions as an argument and produce a new function.
HOCs are commonly used to design components with certain shared behavior in a way that makes them connected differently than normal state-to-props pattern.

Facts About HOCs

  1. We don’t modify or mutate components. We create new ones.
  2. A HOC is used to compose components for code reuse.
  3. A HOC is a pure function. It has no side effects, returning only a new component.
Here are some examples of real-world HOCs you might have come across:
react-reduxconnect(mapStateToProps, mapDispatchToProps)(UserPage)
react-routerwithRouter(UserPage)
material-uiwithStyles(styles)(UserPage)

Structure Of A Higher-Order Component

A HOC is structured like a higher-order function:
  • It is a component.
  • It takes another component as an argument.
  • Then, it returns a new component.
  • The component it returns can render the original component that was passed to it.
The snippet below shows how a HOC is structured in React:

import React from 'react';
// Take in a component as argument WrappedComponent
const higherOrderComponent = (WrappedComponent) => {
// And return another component
  class HOC extends React.Component {
    render() {
      return <WrappedComponent />;
    }
  }
  return HOC;
};
We can see that higherOrderComponent takes a component (WrappedComponent) and returns another component inside of it. With this technique, whenever we need to reuse a particular component’s logic for something, we can create a HOC out of that component and use it wherever we like.

Use Cases

In my experience as a front-end engineer who has been writing React for a while now, here are some use cases for HOCs.
Show a loader while a component waits for data
Most of the time, when building a web application, we would need to use a loader of some sort that is displayed while a component is waiting for data to be passed to its props. We could easily use an in-component solution to render the loader, which would work, but it wouldn’t be the most elegant solution. Better would be to write a common HOC that can track those props; and while those props haven’t been injected or are in an empty state, it can show a loading state.
To explain this properly, let’s build a list of categories of public APIs, using its open API. We tend to handle list-loading, so that our clients don’t panic when the API we are getting data from takes so much time to respond.
Let’s generate a React app:
npx create-react-app repos-list
A basic list component can be written as follows:
//List.js
import React from 'react';
const List = (props) => {
  const { repos } = props;
  if (!repos) return null;
  if (!repos.length) return <p>No repos, sorry</p>;
  return (
    <ul>
      {repos.map((repo) => {
        return <li key={repo.id}>{repo.full_name}</li>;
      })}
    </ul>
  );
};
export default List;
The code above is a list component. Let’s break down the code into tiny bits so that we can understand what is happening.
const List = (props) => {};
Above, we initialize our functional component, named List, and pass props to it.
const { repos } = props;
Then, we create a constant, named repos, and pass it to our component props, so that it can be used to modify our component.
if (!repos) return null;
if (!repos.length) return <p>No repos, sorry</p>;
Above, we are basically saying that, if after fetching has completed and the repos prop is still empty, then it should return null. We are also carrying out a conditional render here: If the length of the repos prop is still empty, then it should render “No repos, sorry” in our browser.
return (
    <ul>
      {repos.map((repo) => {
        return <li key={repo.id}>{repo.full_name}</li>;
      })}
    </ul>
  );
Here, we are basically mapping through the repos array and returning a list of repos according to their full names, with a unique key for each entry.
Now, let’s write a HOC that handles loading, to make our users happy.
//withdLoading.js
import React from 'react';
function WithLoading(Component) {
  return function WihLoadingComponent({ isLoading, ...props }) {
    if (!isLoading) return <Component {...props} />;
    return <p>Hold on, fetching data might take some time.</p>;
  };
}
export default WithLoading;
This would display the text “Hold on, fetching data might take some time” when the app is still fetching data and the props are being injected into state. We make use of isLoading to determine whether the component should be rendered.
Now, in your App.js file, you could pass the loading logic to WithLoading, without worrying about it in your List .
import React from 'react';
import List from './components/List.js';
import WithLoading from './components/withLoading.js';
const ListWithLoading = WithLoading(List);
class App extends React.Component {
  state = {
{
  };
  componentDidMount() {
    this.setState({ loading: true });
    fetch(`https://api.github.com/users/hacktivist123/repos`)
      .then((json) => json.json())
      .then((repos) => {
        this.setState({ loading: false, repos: repos });
      });
  }
  render() {
    return (
      <ListWithLoading
        isLoading={this.state.loading}
        repos={this.state.repos}
      />
    );
  }
}
export default App;
The code above is our entire app. Let’s break it down to see what is happening.
class App extends React.Component {
  state = {
    loading: false,
    repos: null,
  };
  componentDidMount() {
    this.setState({ loading: true });
    fetch(`https://api.github.com/users/hacktivist123/repos`)
      .then((json) => json.json())
      .then((repos) => {
        this.setState({ loading: false, repos: repos });
      });
  }
All we are doing here is creating a class component named App(), then initializing state with two properties, loading: false, and repos: null,. The initial state of loading is false, while the initial state of repos is also null.
Then, when our component is mounting, we set the state of the loading property to true, and immediately make a fetch request to the API URL that holds the data we need to populate our List component. Once the request is complete, we set the loading state to false and populate the repos state with the data we have pulled from the API request.
const ListWithLoading = WithLoading(List);
Here, we create a new component named ListWithLoading and pass the WithLoading HOC that we created and also the List component in it.
render() {
    return (
      <ListWithLoading
        isLoading={this.state.loading}
        repos={this.state.repos}
      />
    );
  }
Above, we render the ListWithLoading component, which has been supercharged by the WithLoading HOC that we created and also the List component in it. Also, we pass the loading state’s value and the repos state’s value as props to the component.

Conditionally Render Components

Suppose we have a component that needs to be rendered only when a user is authenticated — it is a protected component. We can create a HOC named WithAuth() to wrap that protected component, and then do a check in the HOC that will render only that particular component if the user has been authenticated.
A basic withAuth() HOC, according to the example above, can be written as follows:
// withAuth.js
import React from "react";
export function withAuth(Component) {
    return class AuthenticatedComponent extends React.Component {
        isAuthenticated() {
            return this.props.isAuthenticated;
        }

        /**
         * Render
         */
        render() {
            const loginErrorMessage = (
                <div>
                    Please <a href="/login">login</a> in order to view this part of the application.
                </div>
            );

            return (
                <div>
                    { this.isAuthenticated === true ? <Component {...this.props} /> : loginErrorMessage }
                </div>
            );
        }
    };
}

export default withAuth;
The code above is a HOC named withAuth. It basically takes a component and returns a new component, named AuthenticatedComponent, that checks whether the user is authenticated. If the user is not authenticated, it returns the loginErrorMessage component; if the user is authenticated, it returns the wrapped component.
Note: this.props.isAuthenticated has to be set from your application’s logic. (Or else use react-redux to retrieve it from the global state.)
To make use of our HOC in a protected component, we’d use it like so:
// MyProtectedComponent.js
import React from "react";
import {withAuth} from "./withAuth.js";

export class MyProectedComponent extends React.Component {
    /**
     * Render
     */
    render() {
        return (
            <div>
                This is only viewable  by authenticated users.
            </div>
        );
    }
}

// Now wrap MyPrivateComponent with the requireAuthentication function 
export default withAuth(MyPrivateComponent);
Here, we create a component that is viewable only by users who are authenticated. We wrap that component in our withAuth HOC to protect the component from users who are not authenticated.

Provide Components With Specific Styling

Continuing the use case above, based on whatever UI state you get from the HOC, you can render specific styles for specific UI states. For example, if the need arises in multiple places for styles like backgroundColor, fontSize and so on, they can be provided via a HOC by wrapping the component with one that just injects props with the specific className.
Take a very simple component that renders “hello” and the name of a person. It takes a name prop and some other prop that can affect the rendered JavaScript XML (JSX).
// A simple component 
const HelloComponent = ({ name, ...otherProps }) => (
 <div {...otherProps}>Hello {name}!/div>
);
Let’s create a HOC named withStyling that adds some styling to the “hello” text.
const withStyling = (BaseComponent) => (props) => (
  <BaseComponent {...props} style={{ fontWeight: 700, color: 'green' }} />
);
In order to make use of the HOC on our HelloComponent, we wrap the HOC around the component. We create a pure component, named EnhancedHello, and assign the HOC and our HelloComponent, like so :
const EnhancedHello = withStyling(HelloComponent);
To make a change to our HelloComponent, we render the EnhancedHello component:
<EnhancedHello name='World' />
Now, the text in our HelloComponent becomes this:
<div style={{fontWeight: 700, color: 'green' }}>Hello World</div>

Provide A Component With Any Prop You Want

This is a popular use case for HOCs. We can study our code base and note what reusable prop is needed across components. Then, we can have a wrapper HOC to provide those components with the reusable prop.
Let’s use the example above:
// A simple component 
const HelloComponent = ({ name, ...otherProps }) => (
 <div {...otherProps}>Hello {name}!</div>
);
Let’s create a HOC named withNameChange that sets a name prop on a base component to “New Name”.
const withNameChange = (BaseComponent) => (props) => (
  <BaseComponent {...props} name='New Name' />
);
In order to use the HOC on our HelloComponent, we wrap the HOC around the component, create a pure component named EnhancedHello2, and assign the HOC and our HelloComponent like so:
const EnhancedHello2 = withNameChange(HelloComponent);
To make a change to our HelloComponent, we can render the EnhancedHello component like so:
<EnhancedHello />
Now, the text in our HelloComponent becomes this:
<div>Hello New World</div>
To change the name prop, all we have to do is this:
<EnhancedHello name='Shedrack' />
The text in our HelloComponent becomes this:
<div>Hello Shedrack</div>

Let’s Build A Higher-Order Component

In this section, we will build a HOC that takes a component that has a name prop, and then we will make use of the name prop in our HOC.
So, generate a new React app with create-react-app, like so:
npx create-react-app my-app
After it is generated, replace the code in your index.js file with the following snippet.
import React from 'react';
import { render } from 'react-dom';
const Hello = ({ name }) =>
  <h1>
    Hello {name}!
  </h1>;

function withName(WrappedComponent) {
  return class extends React.Component {
    render() {
      return <WrappedComponent name="Smashing Magazine" {...this.props} />;
    }
  };
}
const NewComponent = withName(Hello);
const App = () =>
  <div>
    <NewComponent />
  </div>;
render(<App />, document.getElementById('root')); 
 
 
Let’s go through the snippet bit by bit.
const Hello = ({ name }) =>
  <h1>
    Hello {name}!
  </h1>;
Here, we create a functional component that has a prop called name. In this functional component, we render the “Hello” and the value of the name prop in an h1 tag.
function withName(WrappedComponent) {
  return class extends React.Component {
    render() {
      return <WrappedComponent name="Smashing Magazine" {...this.props} />;
    }
  };
}
Above, we create a higher-order functional component named withName(). Then, we return an anonymous class component inside that renders the component wrapped in the HOC. And we assign a value to the prop of the wrapped component.
const NewComponent = withName(Hello);
Here, we create a new component named NewComponent. We use the HOC that we created, and assign to it the functional component that we created at the start of the code base, named hello.
const App = () =>
  <div>
    <NewComponent />
  </div>;
render(<App />, document.getElementById('root'));
All we are doing above is creating another functional component, named App. It renders the NewComponent that we upgraded with our HOC in a div. Then, we use the react-dom function render to display the component in the browser.
That’s all we need to do! Our withName function takes a component as an argument and returns a HOC. A few months from now, if we decide to change things around, we only have to edit our HOC.

Conclusion

I hope you’ve enjoyed working through this tutorial. You can read more about higher-order components in the references listed below. If you have any questions, leave them in the comments section below. I’ll be happy to answer every one.

Resources And References

 

Saturday, July 25, 2020

Is Your Website Stressing Out Visitors?

Stress isn’t just something that makes people feel uncomfortable. It stimulates the urge to “fight” or “flight”. The very last thing you want is to design a website that stresses visitors out, leading them to dread the experience or abandon it entirely. There are many things that might invoke this response from your visitors, including the design. In the following guide, we’re going to look at some ways to de-stress your design.
Stress is a nasty thing and many of us deal with it on a regular basis. Our jobs, school, homes, relationships, and even things going on around the world can trigger feelings of panic, unease, and depression. And those are just chronic stressors. Think about the small things that send your body into instant fight-or-flight mode on a daily basis (e.g. traffic jams, unhelpful customer service reps, getting sick when you have a big project due).
The last thing you want is for someone to visit one of the websites you’ve built, only to feel like they:
  • Need to battle their way through it, or
  • Leave immediately and never come back.
There are a variety of ways a website can cause stress and leave visitors wondering if their response should be to fight or flight. Slow loading times. Overwhelming navigations. Excessive 404 errors. You get the point. But the design itself could be a problem, too.
If your bounce rates are really high and performance isn’t an issue, then this is something you need to look into. Today, we’re going to look at some ways for web designers to take traditional stress-busting tips and apply them to websites.

How To De-stress Your Web Design

Most stress relief guides provide a similar set of tips. But how exactly do you apply something like “Get outside for fresh air” to a website?
Here are some ideas:

1. Draw from Nature

There’s a reason why stress relief articles always suggest that people get outside. There’s something about nature that’s very calming.
If you think about the way we live our lives today — always on, always connected, always trying to make a better life for ourselves — it’s the exact opposite of nature. That’s probably why we’re so attracted to its simplicity and healing qualities in times of stress.
Companies with “natural” initiatives (think REI or CLIF) can get away with using imagery containing nature scenes and drawing on the feel-good vibes associated with them.

For other companies, however, you’re going to have to think outside the box as nature photographs won’t make sense for most.
Something I’d recommend instead is to look at your color palette.
One of the great things about spending time in nature is the abundance of color you’ll find. Look at any travel blog or social media account and you’ll find proof of this immediately.

There is such a vast array of colors in nature that you could draw from.
That said, nature’s colors aren’t always peaceful or safe. Take, for instance, aposematism. This is the ability animals have to signal that there’s danger here — and they do it with color.
“The function of aposematism is to prevent attack, by warning potential predators that the prey animal has defenses such as being unpalatable or poisonous.”
The most commonly seen colors in aposematism are:
  • Red,
  • Yellow,
  • Black,
  • White.
Generally, when these colors are used, it’s in high contrast to the surrounding colors and scenery, so it’s not like the actual appearance of red or black is alarming. It has to do with the context.
What I’d recommend is that you take a look at your website and note if there are any colors sending the wrong signals.
Does a dark mode-like design seem too ominous for the lighter personality of the brand? Are red accents reminiscent of blood against the stark white background? Does the bright yellow coloring feel out of place?

I suspect the web designer went out of their way to imbue the website with the sharp black and red accent colors that appear here. Bear Grylls doesn’t run some feel-good travel show. He’s always putting himself (and others) in life-or-death situations. So, in this case, the aposematism-inspired color palette is a good choice.
For your website, though, I highly doubt you want your visitors to associate the brand with danger or death. So, spend some time studying nature photography (the stuff that makes you feel good) as well as reading up on color psychology to fix the signals your website is sending to visitors.

2. Create a Predictable Rhythm

Yoga is one of those activities often recommended for people experiencing stress. As the Mayo Clinic explains:
“Yoga brings together physical and mental disciplines that may help you achieve peacefulness of body and mind. This can help you relax and manage stress and anxiety.”
At the core of yoga, is a composite of physical poses and steady breathing. If you’ve ever practiced it before, you know how good it feels when you get into the rhythm of it. Breathing in… and breathing out.
Yoga isn’t the only mindfulness practice that draws on steady breathing to calm the nerves.
If you’ve ever used a meditation app like Calm before, you’re familiar with breath exercises





As you focus on breathing in, holding that breath and releasing, your body and mind relax. Breathing exercises also help people calm hyperventilation and other erratic breathing patterns that get the heart rate up and send the mind racing.
So, how does this correlate to your website? Well, what we need to do is identify elements and interactions that feel unpredictable and shocking — ones that make visitors feel as if they have no control over the experience, like they can’t slow down and take it one bit at a time.
Rhythm and repetition play an important role in this, but you know this already. That’s why button shapes and colors are designed consistently site-wide. That’s why you choose no more than two or three fonts to establish a rhythm and dictate hierarchy in your content. That’s why you build mobile-first websites within a grid (even if the design sometimes appears asymmetrical).
The thing is, when new design patterns or elements become popular, it’s easy for these good and calming practices to go out the window.
Take, for instance, websites that use scroll-triggered animations like Unleashed.





While it’s certainly an attractive website and one that’s going to stand out from the competition, it presents an uneven experience from start to finish. Visitors are more likely to focus on the surprises that wait for them around the corner instead of on reading the content on the site (which is difficult with the way it’s presented).
This website is all about building anticipation; not value.

The big difference here is that hover-triggered animations don’t have to come at the expense of the predictability of the design or your visitors’ comfort levels.
Just be mindful of this. While it might seem like trying something new is what your site needs to stand out, don’t forget that you’re designing primarily for the user experience. And if users aren’t responding well to the creative choices you’ve made, it’s time to bring back a more stable rhythm to it.

3. Remove the Excess Noise

For a long time now, researchers have studied and reported on the damaging and stress-inducing effects environmental noise can have on people.
“Babisch established the modern noise reaction model, postulating an ‘indirect pathway,’ in which disturbance of sleep, communication and activity by low-level noise exposure causes changes of emotional and cognitive parameters and annoyance, followed by chronic stress reactions and adverse health effects.”
That’s no surprise to anyone who’s lived in a major city or visited one before. They’re polluted with sounds of people honking and shouting, loud buses or trains passing by, construction workers chipping away at the streets and buildings. At a certain point, it eventually gets to be too much.
This is one of the reasons why white noise machines, nature sounds and classical music are a popular means of drowning out the excess noise in our environments. They take all of the harshness and overwhelming nature of our surroundings and mute it or, at the very least, turn it down to a minimum.
When a website is designed with too much “noise”, a similar solution is needed.
But how do we define noise on websites? It’s not as though we all have auto-playing music on them anymore (at least, I hope not).
The big thing is to look for things that don’t belong there. If your design is overcrowded, remove the elements that contribute little to the user experience and conversion rate.
For example, how frequently do people engage with your live chat window? If it’s not happening frequently or the interactions aren’t meaningful, just get rid of it. The same goes for other non-essential elements. Banner ads. Auto-play on videos. Exit-intent pop-ups.
Is the interruption to the user’s experience really worth it?

When visitors enter the home page, they’re asked: “Do you want more traffic?”
Let’s say the answer to that is “no” because the visitor has come here to read more about marketing and SEO on the blog. However, the top of the blog page again asks them the same question.

Logic would dictate that clicking “No, I have enough traffic” would remove the banner from view since no “X” is available to dismiss it. Instead, visitors who click it are taken away from the blog and returned to the home page to start the loop all over again.
This type of website friction is no different than an environmental noise or irritant — kind of like a child asking “But why?” over and over again until you give them the answer they want. Eventually, visitors are going to get fed up with the pressure to convert and leave for good (maybe not in Patel’s case, but definitely on a website for lesser-known brands).
If you notice your visitors ignoring the noise you’ve placed before them on the website, don’t try and jam it down their throats even further. Just get rid of it.

They’re either going to suffer through the experience and be left with a sour taste in their mouth… or they’re going to immediately bounce off the site and be left with a sour taste in their mouth.
If you want to remove the stress from your web design, look to traditional stress relief activities to iron out the issues. If you can turn your website into a relaxing and welcoming environment — while still pushing all the right buttons to drive visitors to conversion — you’ll lower your bounce rates as well as visitors’ stress levels.




Saturday, July 11, 2020

Accessible Images For When They Matter Most

Creating accessible images seems like a simple topic at first glance — you just need to add alt text to an image, right? But the topic is much more nuanced than some people think. In this article, we will review the different types of images, dive into some real-world examples of inaccessible public service announcements (PSAs), and discuss which elements matter most when critical messages need to reach everyone.


When it comes to informing the public about critical health issues, timing is everything. The information you consume today could save your life tomorrow. And with more than 65% of the population being visual learners — meaning they learn and remember best through visual communication — the job of creating and sharing accessible images has never been more important. This is especially true for public service announcements (PSAs) aimed at providing crucial and urgent information to the public.
But what happens when your users have visual impairments? Or dyslexia? Or cognitive disorders? How do they receive and understand this visual information? What elements make an image accessible or inaccessible?

Image Types And Alts

Before we dissect an image and examine each element that can make or break its accessibility, we first need to take a step back and think about the purpose of the image. Is it to inform a user? Elicit an emotion? Is the image acting as a link? Or is it purely eye-candy?
There are a number of questions that can help you determine how best to convey the image information to a person using an assistive technology (AT) device, like a screen reader.
“What type of message is the image trying to convey?”

“Is the message simple, complex, emotional, or actionable?”
Using a tool such as an online image decision tree or the simplified chart shown below can help you decide which category your image belongs to. Or just imagine your image has — poof! — vanished. Then ask yourself:
“Do I understand the content that remains?”
If the answer is yes, it is decorative. If not, the image is informative and contextually necessary. Once you determine what kind of image you are working with, there are some basic accessibility guidelines to consider.

Decorative Images

If you decide your image is decorative, then programmatically the image needs to be hidden. One way to do this is to use an empty/null alternative text attribute. This sends a signal to the AT devices to ignore this image as it is not needed to understand the content or action on the page. There are many ways to hide alternative text including using an empty/null alt (e.g. <img alt="">), using ARIA (e.g. <img role="presentation">, <img role="none">, or <img aria-hidden="true">), or by implementing the image as a CSS background.
Note: An empty/null alternative text attribute is not the same as a missing alternative text attribute. If the alternative text attribute is missing, the AT device might read out the file name or surrounding content in an attempt to give the user more information about the image. While aria-hidden="true" is an option to hide images, be cautious where you apply it as it will remove the entire element from the accessibility API.

<div class="drop-caps" aria-hidden="true">
    <img src=".../images/drop-caps/s.svg" alt="">
    <img src=".../images/drop-caps/character-12.svg" alt="">
</div>
In this drop cap example, both aria-hidden="true" and an empty/null alt <img alt=""> were used to hide the images from assistive technology devices. While this kind of redundancy is not necessary to make it accessible — it is also not harmful in this particular situation since the drop caps <div> does not contain any additional information we would need to expose to an AT user. Just remember: when it comes to accessible code, more is not always better.
Beyond programmatically hiding your image — there is not much more you need to consider when it comes to decorative images. If you are saying “But wait, what about X?” or “How about Y?” then you might need to go back to the image decision tree tools and re-evaluate your image — it might not be 100% decorative after all. One of the most difficult types of images to categorize tends to be the “emotional/mood” based images since this subtype is a bit subjective. What one person considers decorative another person might consider informative, so use your best judgment.

Informative Images

If you decide your image is informative, there are a lot more things to consider. For AT devices to understand the message or intent of an image, informative images must have programmatically-discernible alternative text. Typically, this is accomplished using the alt="[some description]" method, but there are many alternative ways to add image information depending on its subtype, type of image, and context (e.g. complex vs simple, SVG vs img). But having alternate text is not enough — it must also be meaningful. For example, if your image is about feeling safe at home, but your alternative information says “house” — does that convey the full message?
An example of an informative image is the following Smashing Magazine logo. If we ask the same question as before (does the context or content change if this image is missing?), then the answer is “yes.” In this example, the logo is both informative and actionable since it is both an image and a link. We can see from the code snippet that <a title="Back to the homepage"> is the link title and the image alternative text is <img alt="Smashing Magazine">. When we fire up an AT device — like a screen reader — we should hear both pieces of information conveyed.


<div class="logo">
    <a href="/" title="Back to the homepage">
        <picture>
        <source media="(min-width: 1350px)" srcset=".../images/logo-full.svg">
        <img src=".../images/logo/logo.svg" alt="Smashing Magazine">
        </picture>
    </a>
</div>
Hearing both the phrase “back to the homepage” and “Smashing Magazine” in one feature is OK since each phrase is unique and connected to a different purpose.
For more complex alternative text phrases, conduct the telephone test. For example, if you called up a friend and said “purple slug” and hung up the phone your friend would probably be confused, but also might think of a purple slug — but in what context? If you called a friend and said “the purple slug is eating my hydrangeas,” that would paint a more vivid picture — without adding a lot of additional characters or effort.
Of course, an AT user will have to listen to your alternative text, so don’t go overboard. That is why it is suggested to cap your text at 150 characters. If you need to add more context to the image (e.g. complex image), there are other, more descriptive patterns or methods you can use to add more detail.

World Beyond Image Alts

Now that we covered image types and alternative text attribute basics, let’s look beyond and consider some additional image elements:
In each real-world PSA example, we will look at the image through the lens of a different type of disability — keeping in mind that simulators are tools and may not represent an individual’s true experience. Yet, by using such tools, we can begin to build empathy into our designs and really consider the different ways our images are being consumed.
Note: To be clear, the following examples are for illustrative and educational purposes only and not meant to call-out or otherwise pass judgment about the designs in question. Also, there may be multiple issues in one PSA, but we will just focus on one issue type per example. There will be a lot of opportunities for improvement in the area of digital communications when the dust settles on COVID-19 and accessibility is just one more area to consider reviewing.

Color And Contrast

The beating heart of design arguably is color, and if color is the heart of design, then contrast is the muscle. Without good color contrast levels in place elements like words, icons, and other graphical shapes are hard to discern and the design can quickly become inaccessible. But what happens when you perceive color and contrast differently than others — does the same message and intent come through? How can we reach people with color-sensing issues? Color blindness — is a real concern for accessibility-focused designers.
Who Color And Contrast Can Affect
  • It is estimated that 300 million people worldwide are color blind, and approximately 95% of those inflicted are male (1 in 12 men vs 1 in 200 women are color blind). There are many different variants of color blindness, with red/green color blindness being the most common, followed by blue/yellow, and total color blindness being the most rare.
  • Globally there are 246 million people with low vision. People with visual impairments such as glaucoma, cataracts, macular degeneration, diabetic retinopathy, corneal clouding, etc, may have issues with text contrast. People with partial sight and older adults also often experience limited color vision.
  • People using monochrome displays or in certain situations (e.g. low lighting in a room) might have trouble with contrast. People using text-only, limited-color stylesheets, or in certain situations (e.g. too much glare on a screen) might have trouble discerning colors, too.
PSA Color Review
In the first example, we are reviewing PSAs from the non-profit group called the Ad Council — one of the oldest and most prolific producers of such material in the US. The aim of these “higher risk assets” is to reach populations considered more susceptible to contracting and becoming seriously ill by the novel coronavirus (one of the groups that need this information the most).

Next, we can see two types of color blindness simulated using the ChromeLens extension. ChromeLens is a Google Chrome extension that provides a suite of tools to help with web accessibility development and includes the Lens Vision Simulator, which transforms the colors on a website simulating what a colorblind person might see.
Simulated PSA with Deuteranopia (red/green-blindness)

Below is a breakdown of some color contrast ratios found on the PSAs between the different color blindness simulators.
Original PSA — color contrast ratio of 1.26:1 with the text “Have” against the background:

Simulated PSAs with Protanomaly (red-weak)


Deuteranopia simulation filter applied — color contrast ratio of 1.07:1 with the text “Have” against the background

Protanomaly simulation filter applied — color contrast ratio of 1:15:1 with the text “Have” against the background


While these PSAs incorporate a variety of striking color choices and are visually appealing (when testing the text against the background in these images), many of the combinations do not pass the Web Content Accessibility Guidelines (WCAG) color contrast ratios. This is true even for the unedited versions of these designs, but when we apply the ChromeLens color blindness simulator for Deuteranopia (red/green-blindness) Protanomaly (red-weak), the color contrast ratios get even worse (1.26:1 vs 1.07:1 and 1:15:1). To make these PSAs more accessible, we would want to bump up the contrast so people with color-related vision disorders could read the text.
PSA Contrast Review
Going back to the “higher-risk assets” from the Ad Council, we can see how the PSAs look like to people in two different low vision situations.
First, we see the unedited version of the PSAs

Next, using the NoCoffee Vision Simulator tool, we can see how the PSAs might look to someone with low vision and cataracts.
PSAs with simulated low vision filter applied

Below is a breakdown of some color contrast ratios found on the PSAs between the different low vision simulators.
Original PSA — color contrast ratio of 1.33:1 with the word “Undergoing” against the background

PSA with low vision simulation filter applied — color contrast ratio of 1.25:1 with the word “Undergoing” against the background

PSA with cataract simulation filter applied — color contrast ratio of 1.06:1 with the word “Undergoing” against the background

A lot of people blame color for their design accessibility issues, but these examples show that contrast plays a key role as well. Without changing the colors on these PSAs, but by changing the user perspective and blurring or obfuscating the text, we can see that the text on the images is more difficult to read — even though the contrast ratios didn’t change by much (1.33:1 vs 1.25:1 and 1.06:1). Similar to the color examples (to make these PSAs more accessible), we need to increase the contrast on these images so people with low vision and eye disorders could read the text.
Next Steps For Accessible Color And Contrast
Review the WCAG color contrast ratio guidelines and use tools like the Colour Contrast Analyser to check your designs. Your images with copy need a color contrast ratio of at least 4.5:1 for regular-sized text, and at least 3:1 for large-sized text (18pt and larger). The color contrast ratio of 3:1 also applies to essential icons. Try a tool like the A11y Color Palette where you can quickly review all the possible accessible color combinations and create a palette with accessibility in mind. Or use the accessibility features built-in into the palette generator Coolors.
Next, utilize solid color backgrounds (reading text on busy backgrounds, overlays, textures, or gradients is difficult in general), but especially when the text does not have enough contrast. By picking colors on the opposite ends of the color spectrum and avoiding red/green and blue/yellow combinations, you will increase the likelihood that your color and contrast ratios are robust. Use a tool like the ChromeLens extension to double-check the color contrast with color blindness in mind. Also, be careful with light shades of color — especially grays — they are difficult to see for people with low vision. Use tools like NoCoffee Vision Simulator to simulate low vision issues and see how your design holds up in these situations.
Going beyond color contrast ratios, it is also important to not use color alone to convey information. For example, “contact information can be seen in red” or “click the blue button to learn more.” The same is true for sensory characteristics such as shape, color, size, visual location, orientation, or sound — they cannot be used on their own. For example, if you said "Please click the link to the left of the image for more information," an AT user could have difficulty finding the correct link.

Typography and Layout

In a perfect world, we would keep our text and images separated. This would allow users to manipulate the typography and layout in any way they would want: font size, letter spacing/kerning, justification, margins/padding, and more. But unfortunately, there are a lot of formats that this kind of separation is difficult or impossible, such as social media posts, emails, PDFs, and other fixed form media.
Who Typography And Layout Can Affect
  • Typography is especially important to the estimated 15–20% of the world’s population with dyslexia — a learning disorder in which certain letters, numbers, or combinations of letters can be confusing or seem to flip/move around.
  • People with low vision can have issues with tight letter spacing/kerning, morphing words like “barn” into “bam” or “modern” into “modem” while reading.
  • For people with attention-deficit disorders and reading or vision-based disabilities, a complex layout is a real barrier. These users have trouble keeping their place and following the flow of the content due to the lack of whitespace and clear linear pathways.
PSA Typography And Layout Review
Let’s first take a look at a PSA from California’s Long Beach Health and Human Services.
If we are looking at this PSA from an accessibility point of view, what typography and layout issues do you see? In what ways could we improve this image?

If we focus on the typography and layout the following elements stand out:
Red hand-drawn linesIllustrating the multiple “rivers of space” created by the justified alignment.
Blue dotted boxesOutlining six different layout changes.
Pink numbersHighlighting the 14 different typography treatments discovered (ignoring the logo). Some changes are more obvious like font family or color changes, some are more subtle like alignment, size, or weight changes in the typography.
Green question marksWhat does this equation even mean? Cognitively this is a difficult thing to ascertain given the odd layout.
Black lines and dotsExpected 12 points of visual interest in an UX eye-tracking test based on the order of the content blocks (top to bottom, left to right) and typical equation flow (X + Y = Z).
Let’s look at another PSA and again evaluate the typography and layout from an accessibility point of view.
The third PSA example is more consistent when it comes to typography and layout, and has more overall whitespace and a linear visual pathway compared to the first two examples.
Next Steps For Accessible Typography And Layout
Less is more when it comes to accessible typography, so limit the number of different font families and variations such as italic, bold, ALL CAPS, or other styling methods that may make the content difficult to read. The research is not conclusive about whether serif or sans-serif typefaces are easier to read, but if you choose font families that have clearly defined letter shapes it is more likely that the font will be accessible. Some common offenders to look out for when choosing an inclusive font include the “I” (ex. India), “l” (ex. lettuce), and “1” (ex. one). Likewise, characters like “b” and “d” and “q” and “p” can sometimes be mirrored (either left-right or up-down), and the letter “B” and the number “8” oftentimes look too similar.
In regards to layout, less is also more. Try and repeat patterns whenever possible and limit the width of any blocked section to 80 characters (or 40 characters for logograms). Likewise, avoid paragraph alignment which creates whitespace or “rivers of space” within the content (e.g. justified alignment). Line spacing (leading) is at least space-and-a-half within paragraphs, and paragraph spacing is at least 1.5 times larger than the line spacing. Incorporating all of these layout guidelines will help people with attention-deficit disorders, reading and vision-based disabilities focus more on the content.

Copy And Icons

Last but not least, let’s focus on the actual PSA message. Arguably, copy is the key element in informing the public on the latest COVID-19 updates and providing information about preventing the spread of the virus. But icons in this situation serve up more than just decoration; these elements visually repeat the same message as the copy. No pressure, but both copy and icons need to be spot-on to reach the widest array of people.
Who Copy and Icons Can Affect
  • People with attention-deficit disorders — estimated at 129 million people worldwide — can have issues focusing on copy that is too long, does not break items into lists, and lacks whitespace (think: line height, paragraph margins, etc).
  • For people with certain cognitive disabilities, it is difficult to understand figurative language or specialized usage like the phrases “it’s raining cats and dogs” or “that test was a piece of cake.”
  • People with cognitive, language, and learning disabilities may need visual icons, graphics, and symbols to understand the accompanying copy.
PSA Copy Review
For this example, let’s test the copy of two PSAs from the Centers for Disease Control and Prevention (CDC) for readability. Readability is the ease with which a reader can understand a written text. Readability of copy depends on both the content and presentation.
Blue dotted boxesOutlining three different layout changes.
Pink numbersHighlighting the four different typography treatments discovered (ignoring the logos). In this case, only one font family was used, with variations only on size, color, and weight.
Black lines and dotsExpected eight points of visual interest in an UX eye-tracking test based on the order of the content blocks (top to bottom).

If we focus on the typography and layout the following elements stand out:
Blue dotted boxesOutlining nine different layout changes.
Green numbersHighlighting the 11 different typography treatments discovered (ignoring the logos). Some changes are more obvious like font family or color changes, some are more subtle like alignment, size, or weight changes in the typography.
Black lines and dotsExpected 10 points of visual interest in an UX eye-tracking test based on the order of the content blocks (top to bottom, left to right) and numbering order (1 to 6) forming a zig-zag type eye movement.
So far we’ve seen some examples where there are a lot of typography changes and the layouts are complex. Now, let’s review a cleaner PSA. This one is from the Prevention Action Alliance out of Columbus, Ohio.




If we evaluate the main body copy using readability indicator tools like Readable and The Readability Test, we see that the “What you should know about COVID-19 to protect yourself and others” PSA has 388 words at an average reading grade level of 9 and a Flesch Kincaid Reading Ease1 of 64.6. In addition to those metrics (for accessible copy), we also want to look at the number of complex words and their frequency — in this case, 35 and 9.02% respectively.



 This PSA has a lot more imagery and a lot less text. If we again evaluate the main copy, we see that our copy now has a total of 90 words with an average grade of 6 and a Flesch Kincaid Reading Ease of 83.6. The number of complex words is now down to 4 with a frequency of 4.44%.

Compared to the first PSA, the “Stop the Spread of Germs” PSA one has 298 fewer words and is easier to read by 3rd-grade levels. It has a reading ease level increase of 19 points, and is less complex. Based on these numbers, we can extrapolate that the second PSA is more inclusive than the first when looking at copy alone.
PSA Icon Review
But testing the readability of copy isn’t the only way to measure the effectiveness of a PSA when it comes to message accessibility. Another element we need to look at are the icons accompanying the copy. If we are presented only the icons, will the same message be received?
Let’s now look at a couple of examples. Based on the icons alone, what is the message that the image is trying to convey about riding your bicycle safely during COVID-19?

This is the unedited PSA. Were you able to figure out the full message? While you might have been able to guess correctly for a couple of icons, were there parts of the message you missed not having the copy?
OK, let’s take a look at another example. This next PSA comes from the Pennsylvania Department of Health. Let’s do the same exercise as before: can you understand the message in this PSA (without the icon copy)?



Now we can see the PSA with copy. Were you able to figure out the full message? While there may have been an icon or two that tripped you up, was it easier to decipher the icons on the second PSA versus the first? Hopefully, this quick exercise helped you understand the critical role icons play in the message.
Next Steps for Accessible Copy and Icons
Be clear and concise. The unofficial rule of thumb is to write for a 9th-grade reading level. This level is based on the assumption that most people reach the 12th-grade reading level, but in times of peak stress, they might not be reading at their highest level. Try and use plain language and avoid technical jargon, fancy words, colloquialisms, and expressions. Likewise, make sure any acronyms, abbreviations, or unusual words are explained in more detail or linked out to additional resources. Tools like Readable and The Readability Test can help you determine the reading level of your copy, while tools like Hemingway Editor or Grammarly can suggest edits to make your copy more inclusive.
Use icons, graphics, and symbols to supplement copy whenever possible. Adding imagery allows you to break down some language and cognitive barriers and not rely on your typography to carry all the weight. Just be sure to choose icons that are common or don’t require a lot of thought.

Wrapping Up

Creating accessible images involves a lot more than just adding alt text. It is important to consider how all image elements — color, contrast, typography, layout, copy, and icons — affect your users as well. By taking a bit more time and building these accessibility principles into your images you will undoubtedly reach more people — on their terms. In uncertain times like these, we need to be sure we are addressing all the ways we can improve our images to be more inclusive in our messaging.