Accessibility & Responsiveness in action – Why they matter

No, alt tags and burger menus aren't enough to make your site accessible. Let's find out why.

Many believe that making a website accessible and responsive means simply adding alt attributes to images and replacing header navigation with burger menus, right? But the truth is, accessibility goes much deeper than that.

Navigation

  1. The app’s users
  2. Responsiveness: adaptable pages
  3. The access to accessibility: WCAG
  4. Now, what?
  5. References

In this blog post, we’ll dive into how to use flexbox, media queries, and grid to make our websites more responsive. We’ll also explore the Web Content Accessibility Guidelines (WCAG) 2.2, which offer valuable insights on building accessible websites while explaining the “why” behind these principles.

But why should we care so much about making our web applications adaptable? Is it worth investing time and effort to revamp significant parts of your site just to meet these guidelines? Let’s unpack that together.

The app’s users

When building an application, it’s key to think about the users. Are we making sure everyone has a good experience?

Let’s explore something that might reshape how we design our websites: the age focus of our target audience. Below, you’ll find different user types and the kinds of websites they prefer.

Main reasons for using the Internet  for users from 16 to 64 years old— Jan 2024

[Image provided by Digital 2024: Global Overview Report]

A modern design might be super intuitive for younger users (16-24 years old), but it could be a challenge for those aged 55-64. For instance, about 38.9% of older users only browse the internet, while 66.9% use it to find information.

Think about how a 58-year-old might struggle with poorly designed informational or news websites—it’s something to consider, right?

The image above shows that all age groups are using messaging apps and social media regularly. This highlights why it’s so important for apps to address the challenges older adults face, ensuring a positive experience for everyone.

However, we must not forget that there are also users with visual impairments who need to be considered when developing our apps. This brings to light the importance of Semantic HTML according to MDN:

HTML is the technology that defines the content and structure of any website. Written properly, it should also define the semantics (meaning) of the content in a machine-readable way, which is vital for accessibility, search engine optimization, and making use of the built-in features browsers provide for content to work optimally.

For screen readers to work properly, our HTML must be semantic. That means avoiding HTML tags for styling—they should only be used for their actual purpose. For example, use proper tags for tables, rows, and headers where needed.

Want to see this in action? Check out this 4-minute video by the University of California, San Francisco. It shows how someone with visual impairments uses a screen reader to browse the web. The video also shares tips on navigation menus and using alt attributes for images. I highly recommend the watch.

And going back to the Digital 2024: Global Overview Report, about two-thirds of the global population is now online. The idea that only young people frequently use websites is quickly becoming outdated. It’s crucial to design websites that are accessible to people of all ages and abilities.

So, are web applications becoming more accessible today?

Let’s take a look at the WebAIM Million – The 2024 Report, which highlights common accessibility issues and the steps being taken to address them.

Chart with home pages with most WCAG failures. Low contrast: 81%
Missing alternative text for images: 54.5%
Missing form input labels: 48.6%
Empty links: 44.6%
Empty buttons: 28.2%
Missing document language: 17.1%

[Image provided by The WebAIM Million]

The two most common errors are related to contrast between colors and the alt attribute in image tags. These issues are not only common in 2024 but have been present in previous years as well. If these two main problems were resolved, most accessibility issues would be addressed. In fact, if you want to understand color theory and how to create palettes with a good level of contrast, check out this other blog post of mine.

By applying best practices to your website, you’ll boost its accessibility and minimize the errors we discussed earlier. There are also issues related to ARIA and homepage complexity that you can explore further in the full report.

Okay, so we got that the Internet connects people from all walks of life, and our websites are part of that global stage. Well, over 66% of the world’s population uses the Internet.

These users aren’t just on computers—they’re on tablets, smartphones, and all kinds of Internet-enabled devices.

Check out the image below to see this growing trend:

Image of the overview of the adoption and use of devices: Total population: 8.08billion, unique mobile phone subscribers: 5.61billion, individuals using the Internet: 5.35billion and social media entities: 5.04billion.

[Image provided by Digital 2024: Global Overview Report]

So, why does this matter?

Understanding your audience helps you design a website that respects their needs and limitations. This ensures you capture their attention in the right ways when creating the UI (user interface) and deliver a great UX (user experience).

For example, building a website just for desktop users would exclude a massive audience that prefers mobile devices. As highlighted in the Digital 2024: Global Overview Report:

The number of unique mobile phone users sits at 5.61 billion at the start of 2024. The latest data from GSMA Intelligence reveals that 69.4 percent of the world’s total population now uses a mobile device, with the global total up by 138 million (+2.5 percent) since early 2023.

Making your web app responsive is a must, especially since most online activities now happen on smartphones. Tools like grid and flexbox make it easier to organize items on the screen in a responsive manner. Plus, using media queries lets you fine-tune responsiveness for different scenarios—we’ll dive deeper into the next topic.

As we’ve seen, almost any app online can have a diverse audience. That’s why it’s key to understand the devices users rely on to access the web and ensure a great experience for everyone.

But how can we make sure an app is usable, no matter the device size?

Responsiveness: adaptable pages

Let’s dive into how we can make our websites responsive, ensuring they display correctly on all kinds of devices.

Below, I’ll break down some key techniques used in responsive web design. Later, I’ll share some resources where you can learn more.

  1. Media Queries: used to modify the styling of a page or component based on defined conditions.

One common condition is the screen width. Below, we can see some of the most commonly used screen sizes when developing for different device sizes:

Media query css code with multiple device sizes.

The interesting thing is that not only the width of the viewport can be used as the focus of the condition. It can also be device orientation, system preferences, and others. Below, you can see another example:

Media query orientation landscape.

You can adjust the styling based on the screen orientation. For example, our main content will now take up a single line since the landscape orientation has a wider layout. And you’ll learn more about flexbox in the following topics in the blog post, don’t worry.

Another commonly used condition in React applications initialized with Vite is the preference for dark mode:

Media query preference dark.

You can combine these conditions to modify the styling in a more specific way:

Media query with combined conditions.

But it’s important to remember that if you try to accommodate every single case, your code will definitely become very complex. There needs to be a balance, so aim to cover most screen sizes without getting too specific, depending on your application’s needs. After all, there are many apps with simple styling that can be “easily” adapted without needing all the media queries with the widths I mentioned above.

  1. Flexbox: a very useful tool when trying to keep our pages flexible depending on the device variation. As we saw earlier, when using media queries, in many cases, we modify the styling of our items with flex.

As per MDN:

Flexbox is a one-dimensional layout method for arranging items in rows or columns. Items flex (expand) to fill additional space or shrink to fit into smaller spaces.

With this tool, we can center items or make all items inside a container occupy the same space, for example. Another useful point is that you can make all the columns in a layout have the same height, even if the amount of content in them is different.

But an important point is that flexbox is very useful for one-dimensional layouts. Otherwise, you should probably use grid, which we’ll talk about shortly.

For better understanding, let’s apply Flexbox to a simple HTML page:

Html with flex container wrapper with three flex items inside

And we’ll apply this styling:

CSS using display flex

Will this give us the desired result? Using Programiz, we can see:

Three blocks to the left with spaces in between them.

With the example above, Flexbox allows us to make some modifications:

  • Modify the direction by adding flex-direction:
/* Change flex-direction to stack items vertically */
.wrapper {
    /* How it was previously... */
    display: flex;
    flex-direction: column; /* Stack items vertically */
    /* How it was previously... */
}

The items will now take up the full width of their parent component because they will be organized in a vertical row. Our result will look like this:

Three blocks occupying the wrapper's width, flex direction vertical.

Cool, right? Behind the scenes, when elements become flex items, they are laid out along two axes. The main axis is the axis we can define as we did above (it can be a row or a column, and it’s a row by default). There is also the start and end of this main axis. The cross axis is the axis perpendicular to the direction the flex items are in. Finally, the wrapper for the flex items in this case is called the flex container.

If you want to read more details, check out this MDN article which explores more examples. Here, we’ll just cover the basic concepts to help you get started.

Going back to our example, maybe we want to better space our items and keep them in a horizontal direction. How could we do that? We can use space-around:

/* Align items vertically along the cross axis */
.wrapper {
  display: flex;
  justify-content: space-around; /* Here */
  align-items: center; /* Centers items vertically */
  height: 20rem; /* Give height for vertical alignment to be visible */
}

This value distributes the items along the main axis with spacing between them. There is spacing before and after each item, which usually creates a balanced appearance of spacing.

Note also that I used 20rem for the height. Using px fixes the size. It’s usually used when we don’t want that size to be modified under any circumstances, while using rem or em adapts to the system’s scaling.

To better understand that concept, I recommend reading this short tutorial called CSS Units of Measurement – Absolute vs. Relative, if you’re interested.

But, in short, according to MDN:

em is relative to the font size of this element, or the font size of the parent element when used for font-size. rem is relative to the font size of the root element.

Assuming that the root font size is 16px (you can define this in the root styling by setting the font-size in the html selector in CSS, for example), rem will be relative to this size already defined in the root. Therefore, in some cases, you can benefit from using rem instead of px, especially when considering responsiveness.

Now, after applying these styles and understanding the use of rem, let’s take a look at the result on the page.

Three blocks  centered with more space between them reaching the end of the wrapper's width, with flex direction row.

Finally, let’s understand how each flex item can define its positioning and how we can add a gap to flex items through the flex container.

Let’s say I want to position the first item at the start, and the last two at the end. To better visualize this, let’s change the background colors of the items as well.

Here’s the code:

CSS for the wrapper and its children using nth-child

Notice that we used align-self to position each item specifically as we wanted. The values start and end refer to the cross axis. This property can override the behavior of align-items, for example.

Also, notice that we started using gap. This value is different from margin in some ways: the gap spacing applies only between the items. In other words, that extra space around the items that you’ve probably noticed when styling items with CSS doesn’t occur, for instance. The “leakage” of spacing doesn’t happen. You can read more about the difference between gap and margin in this article. In our case, the spacing will happen between the three items, so right after the padding of the flex container wrapper, we’ll have our items distributed without any extra gaps at the ends. Shall we see the result?

The items have different colors: the first item is darker and occupies the left superior side and the other two items occupy the inferior area. All items have a gap in between them.

Notice that the wrapper takes up the full width because we didn’t define the width. And, aside from the padding, the items don’t have extra unnecessary margins. Also, see how each item takes the positioning we defined. Flexbox is extremely useful when we need flexibility in how we distribute items on the page. So, creating adaptable layouts with flexbox is very important.

  1. Grid: now that you’ve understood the basics of flexbox, it will be easier to understand grid. Both have many similarities, but they have different use cases. One doesn’t cancel out the other, and with the help of the media queries you saw earlier, we can create responsive layouts.

According to MDN:

CSS grid layout is a two-dimensional layout system for the web. It lets you organize content into rows and columns and offers many features to simplify the creation of complex layouts. This article will explain all you need to know to get started with grid layout.

The main difference between flexbox and CSS grid is that flexbox is one-dimensional, as I mentioned earlier. This creates different focuses for the two tools.

Flexbox is used when we want to align items vertically and/or horizontally or when we need precise positioning for individual items. It’s typically used in simpler layouts. On the other hand, CSS grid can control items both vertically and horizontally. When it’s necessary to define rows and columns and have more control over a more structured layout, for example, CSS grid is recommended. Additionally, if the order of the HTML items doesn’t depend on the layout, it’s also recommended to use CSS grid, as it allows positioning items freely without modifying the document.

Let’s see this in practice using the same HTML structure from the flexbox examples. Simply typing display: grid; won’t automatically change your page appearance as it often does with flexbox. First, you need to define the columns and/or rows. After that, we need to specify in which column or row each item will be placed. See the CSS below:

/* Define the wrapper as a grid container */
.wrapper {
  display: grid; /* Enables grid layout */
  grid-template-columns: repeat(3, 10rem); /* Creates 3 equal columns, each 10rem wide */
  grid-template-rows: repeat(2, 5rem); /* Creates 2 rows, each 5rem tall */
  gap: 2rem; /* Adds space between rows and columns */
  width: 34rem; /* Total width: 3 columns + 2 gaps (10rem * 3 + 2rem * 2) */
  background-color: #f0f0f0; /* Light background for visualization */
  padding: 2rem; /* Padding around the grid */
}

/* Style each grid item */
.item {
  display: flex; /* Flex inside the grid for easy content alignment */
  justify-content: center; /* Horizontally centers content */
  align-items: center; /* Vertically centers content */
  background-color: darkgray; /* Darker background for items */
  color: white; /* Text color */
  font-size: 1.5rem; /* Large font for visibility */
  height: 100%; /* Make items fill the row height */
}

/* Example of freely positioning an item */
.item:nth-child(1) {
  grid-column: 1 / 3; /* Item spans from column 1 to 3 */
  grid-row: 1 / 2; /* Item stays in the first row */
}

.item:nth-child(2) {
  grid-column: 3 / 4; /* Item is placed in the last column */
  grid-row: 1 / 2; /* Item stays in the first row */
}

.item:nth-child(3) {
  grid-column: 2 / 4; /* Item spans from column 2 to the last column */
  grid-row: 2 / 3; /* Item is placed in the second row */
}
}

Note that in our layout, we use both CSS grid and flexbox. This happens frequently, as while CSS grid is used to define the structural positioning, flexbox is, in many cases, used to modify the interior of those items positioned by the grid. In our simple page with three items, we centralized the content of each item with flexbox and positioned each item within the layout using CSS grid. Now, let’s check the visual result below:

Three blocks: the first one occupies 2/3 of the width and the second one occupies the rest of the line. In the second line, the third item occupies 2/3 as well but with a space to the left.

We can define the positioning of items in a specific way. First, we define three columns and two rows. Then, each item is placed in a column position, either in the first or second row.

Trying to mimic the layout of a website, we can use grid-template-areas to help us define a structure more easily. The definition according to MDN:

An alternative way to arrange items on your grid is to use the grid-template-areas property and give the various elements of your design a name.

Previously, we were defining the rows and columns separately, but by using grid-template-areas, we can speed up the process in a more intuitive way by using semantic names for the areas. In our case, we can slightly modify our HTML structure to follow this idea:

  <body>

    <div class="wrapper">
      <div class="logo">Logo</div>
      <div class="header">Header</div>
      <div class="intro">Side intro</div>
      <div class="blog-post">Blog post</div>
      <div class="footer">Footer</div>
    </div>

  </body>

We can use grid-template-areas in the following way:

/* Define the wrapper as a grid container */
.wrapper {
  display: grid;
  grid-template-columns: 10rem 1fr 2fr; /* Define 3 columns, where second column is wider */
  grid-template-rows: 4rem 1fr 2fr 4rem; /* Define 4 rows with different heights */
  grid-template-areas:
    "logo header header"  /* Logo takes the first column, header takes the rest */
    "intro blog-post blog-post"  /* Intro takes the first column, blog post takes the next two */
    ". blog-post blog-post"  /* Space on the left, blog post in the second and third columns */
    "footer footer footer"; /* Footer spans the whole row */
  gap: 2rem; /* Space between the grid items */
  padding: 2rem; /* Padding around the grid container */
}

/* Define styles for each grid item */
.logo {
  grid-area: logo;
  background-color: #87ceeb;
  padding: 1rem;
  color: white;
  font-size: 1.5rem;
  text-align: center;
}

.header {
  grid-area: header;
  background-color: #4682b4;
  padding: 1rem;
  color: white;
  font-size: 1.5rem;
  text-align: center;
}

.intro {
  grid-area: intro;
  background-color: #dcdcdc;
  padding: 2rem;
  color: black;
  font-size: 1.2rem;
}

.blog-post {
  grid-area: blog-post;
  background-color: #f0f8ff;
  padding: 2rem;
  color: black;
  font-size: 1.2rem;
}

.footer {
  grid-area: footer;
  background-color: #4682b4;
  padding: 1rem;
  color: white;
  text-align: center;
}

Notice that each item has its grid-area defined. Also, the code would work without the row and column definitions. If we remove those two lines, we would still see the divisions in the content. We only kept the row and column definitions later on because they were useful for defining the specific size of some of the content. Now, let’s check what the visual result looks like:

The image looks like a page for a blog post made of colorful blocks: a small superior room for the logo, and the rest of the superior space is occupied by a block to exemplify the header. There's a side intro beside the blog post big block, that occupies two lines. Finally, the footer occupies the whole final inferior line.

Pretty cool, right? This way, we can easily organize items on the screen. There are also other grid positioning details that you can check out in this great guide here., like the use of minmax() and repeat() for responsive layouts, which is extremely useful.

By understanding a bit more about CSS Grid and Flexbox, you’ll be able to improve your layouts and responsiveness level. And finally, a great tool that helps us test our page’s responsiveness is the Dev Tools, available in a browser. With it, we can see our page in different screen sizes. To access it, you can press F12. Once in the Dev Tools tab, look for an icon with a screen and different device sizes:

Image with the text: Toggle device toolbar with CTRL + SHIFT + M

Using a Pokédex application as an example, we can see below how easy it is to test the page’s responsiveness:

Peek 18-11-2024 15-14

With the help of these tools and practice, your web pages will adapt to various devices with different sizes. Now, let’s move on to accessibility and how to apply it to our apps!

The access to accessibility: WCAG

Let’s break down some key principles that will help us make websites more accessible. I’ll also share a few tools you can use to check how accessible your apps really are. However, if you wanna know some other aspects not mentioned here about accessibility, I recommend reading this other blog post of ours.

Now, let’s get clear on what WCAG stands for—Web Content Accessibility Guidelines. These guidelines are like a roadmap for creating websites that are not just accessible, but also adaptable.

Before we dive into the specifics of these guidelines, it’s important to understand the different compliance levels that WCAG defines:

  1. Level A — Basic accessibility
  2. Level AA — Strong accessibility
  3. Level AAA — Excellent accessibility

When it comes to which level to aim for in our apps, the rules vary depending on the country. For example, it’s important to aim for a high level that ensures your users feel comfortable and can use your app.

The most recent version of the WCAG is 2.2 at the time of writing this blog post. So, let’s take a look at some of the new success criteria that caught my attention. You can see what the others are here.

  1. 2.5.8 Target Size (Minimum) (AA)

Targets typically refer to clickable icons on various websites we encounter on the internet. These are usually icons that represent actions like going back, marking, or entering the user’s profile area, for example.

It is mentioned that the ideal size would be 24×24 pixels. However, if there is enough spacing, the size can be smaller.

Icons one after the other being portrayed with enough gap to avoid misclicking.

[Image provided by Tetralogical]

But why does this matter? When icons are too close together or too small, they are not easily accessed. Usually, people with difficulties in making specific movements may not be able to click on these buttons easily.

  1. 2.4.11 Focus Not Obscured (Minimum) (AA)

This requirement is quite interesting because it mentions that a component should have its focus state visible, even if some items might overlap each other with scrolling. An example of this would be when items on the screen have position: sticky, for example. After scrolling the page, the item could end up in front of an input field with focus, which would need to remain visible.

A simple way to fix this kind of issue is by styling your component so that sticky headers or menus always have a little bit of space between them and the page content. You can also use a background with some opacity, which lets the focused input be at least partially visible. That way, form elements won’t get completely hidden.

The upgraded version of this rule still emphasizes that the focused item should never be hidden by the focus styling.

  1. 2.5.7 Dragging Movements (AA)

You can notice this requirement in things like carousels or drag-and-drop file components. Basically, it says there should be an easy way to perform the action with simple clicks, not just by relying on dragging.

But why does this matter? Well, dragging can be tricky, whether you’re using a mouse or touch inputs. Not everyone has the same level of dexterity, and some people might find it hard to do. So, it makes sense to offer a simpler alternative to make this feature more accessible.

See how understanding these little things can help us plan better websites? Now, let’s dive into one of the biggest accessibility issues on the web: color contrast.

Color Contrast & importance

According to Smart Interface Design Patterns:

In general, color contrast captures the difference in brightness between two or more colors. We often use it to measure how well one foreground color works against a background color. Under the hood, the contrast is calculated using the relative luminance of colors.

The main point mentioned is the difference in luminance between the compared colors, for example:

  • White with white: 1:1, meaning the minimum possible contrast level.
  • White with black: 21:1, meaning the maximum contrast level.

Neither of these extremes is desired, however. The main goal of balanced contrast between colors is to help the readability of items.

Some interesting tips provided by ## WCAG 2.1 Level AA, Minimum Contrast Cheat Sheet:

  • Level AA is currently considered acceptable.
  • Level: 4.5:1 contrast ratio between normal text and background. To reach level AAA, it should be 7.1:1.
  • Level: 3:1 for text larger than 24px, icons, buttons, underlines, and related elements.

But how do we put this into practice?

Well, we can use Coolors to create a random color palette for us. So, we can assume that this would be a fictional palette for an application:

Palette made with Coolors website.

Using the really cool tool Colorable, we can test various color combinations for text and background that wouldn’t affect our design but would still meet the correct contrast level.

Let’s test Process Cyan as the text color and Bittersweet as the background. The result:

Image with poor color contrast.

It’s pretty clear that the contrast limits are off, and honestly, it’s something you can notice right away—it can even be a bit uncomfortable for some people. The colors on their own are nice, but when put together, they can make it tough to read for a lot of users.

But hey, what if we switch the text color to Magnolia?

Image with slightly better color contrast, but not good enough.

The contrast level has increased, but it’s still not ideal. We can use the color Ultra Violet as the background to create more contrast and visual comfort:

Image with comfortable color contrast.

This way, we also meet the color contrast accessibility test while still being able to use the colors from our palette.

But what about color blindness? Depending on our color combination, people with this condition may not be able to have the same experience as other users on the website. We can test how our palette is seen by people with different types of color blindness on the website itself Coolors by clicking on the glasses icon at the top of our palette:

Accessing Coolors website and accessing the color blind features.

To avoid compromising part of the functionality of your website by relying too heavily on colors, you can apply the following:

  • Don’t use green, red, and brown in the same functionality to indicate something important.
  • Also, avoid using blue and purple together.
  • You can use two colors that vary in lightness; this will make it more noticeable for those with color blindness.
  • Colorblind people cannot distinguish between red and brown.
  • The safest color palettes can combine blue with orange or red.
  • Don’t rely solely on color when creating functionality. Use icons and text to make it more accessible to all users.

Another important point about colors on the web is the growing use of dark mode. As we’ve seen, no extreme is desirable. A pure black background with completely white text is not ideal. Pure black is used only in specific cases, such as for users with low vision who are sight impaired. However, for users who don’t have these impairments, dark gray should be used instead of pure black.

Finally, a browser extension that can be useful for measuring some accessibility levels on your page is WAVE. We can apply the Wave analysis to the Pokédex app I mentioned earlier. Let’s see what the result is:

WAVE being used on a page alerting problems related to alt on image tags and providing accessibility feedback.

As you can see, Wave alters the page slightly but shows some subtle alerts, including the accessibility level. You should apply this tool to some of your current projects to check for improvements! But, be careful, this analysis is superficial, and it’s always important to deepen your knowledge of accessibility guidelines.

Now, what?

We’ve just scratched the surface of ways to improve our apps, but don’t worry – I’ve got more references for you below to help you explore other ways to ensure your website is accessible to all users, no matter their needs.

By thinking about our applications from the perspective of our users and their diverse backgrounds, we’ll be better equipped to consider a variety of scenarios and keep our apps top-notch.

There are many ways to make our websites accessible and responsive, and the key to making it all happen is truly understanding why it matters. So, dive deeper into WCAG guidelines and get hands-on with media queries, flexbox, and CSS grid – this way, your applications will shine for everyone. 🙂

References

Previously: How to consume APIs in React using Fetch and Async/Await

Next Up: What you need to know about frontend design patterns

This post is part of our ‘The Miners’ Guide to Code Crafting’ series, designed to help aspiring developers learn and grow. Stay tuned for more!

We want to work with you. Check out our Services page!

Iasmim Cristina

Frontend developer and UX enthusiast. Passionate about expanding my knowledge through projects, tools, and broad perspectives.

View all posts by Iasmim Cristina →