:focus, :focus-within, :focus-visible in CSS: A Comprehensive Guide

:focus, :focus-within, :focus-visible in CSS: A Comprehensive Guide

The user's focus state is often neglected among web developers. Imagine navigating a website with no clear indication of where you are or what you're interacting with; it can be a frustrating and confusing experience. This is where CSS pseudo-classes such as :focus, :focus-within, and :focus-visible come into play.

This tutorial aims to highlight the importance of the focus state in web development, specifically for web developers, particularly those new to the field or focusing on front-end development. These pseudo-classes offer straightforward solutions, from overcoming keyboard navigation issues to fine-tuning interactions within nested items. We'll delve into practical examples, discuss browser support, and also touch on best practices.

Keep in mind that this tutorial isn't just about lines of code; it's about making your websites more user-friendly. Whether you're a complete beginner or just starting with front-end development, this tutorial is for you. Now, let's get started!

Prerequisites

To follow along with this tutorial, you need:

  • A solid understanding of HTML syntax and structure, including familiarity with HTML elements and attributes.

  • A basic understanding of fundamental CSS properties and selectors, with the ability to style basic HTML elements with CSS.

  • Knowledge of how to navigate web browsers.

  • I recommend using a modern web browser with good CSS support for the best experience.

Understanding Focus States in CSS

The concept of focus states weaves an important thread, significantly contributing to the user experience. Understanding and using focus states in CSS effectively is important for creating accessible, user-friendly interfaces.

In CSS and web development in general, focus states refer to the styling that is applied to an element when it receives focus. This interaction is especially important for users who use keyboards or other assistive technologies to navigate a website. Focus states improve accessibility and usability by providing a visual indication of the currently selected element.

:focus - Solving Keyboard Navigation Problem

The :focus pseudo-class is a fundamental method in web development that addresses a critical challenge: providing clarity in keyboard navigation. When a user interacts with a webpage with their keyboard, such as by tabbing through links, forms, and interactive elements, the :focus pseudo-class becomes the beacon, highlighting the currently selected element.

Consider a situation in which keyboard navigation lacks the benefit of visual feedback. Users tab through elements, but the user experience becomes disorienting without a clear indication of which button, link, or input field is active. This problem is addressed by the :focus pseudo-class, which allows developers to define distinct styles for focused elements.

Developers can use :focus to make the element under keyboard focus stand out, providing a visual guide to users exploring the interface without a mouse. This straightforward but powerful pseudo-class makes web applications more inclusive and navigable for all users.

Let’s look at some real-world examples.

HTML:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Focus Pseudo-Class Example</title>
  </head>

  <body>
    <nav>
      <li><a href="#">Home</a></li>
      <li><a href="#">About</a></li>
      <li><a href="#">Services</a></li>
      <li><a href="#">Contact</a></li>
    </nav>
  </body>
</html>

The navigation menu is a straightforward, unordered list (<ul>) with list items (<li>) that contain anchor links (<a>). We’ll add some basic styling to make the links stand out, as well as a focus state.

CSS:

/* Basic styling for navigation items */
nav {
  display: flex;
  list-style: none;
  padding: 0;
}
li {
  margin: 0 10px;
}
a {
  text-decoration: none;
  padding: 8px 12px;
  border-radius: 5px;
  color: #333;
  background-color: #eee;
}

/* Apply styles when the link is focused */
a:focus {
  outline: none;
  box-shadow: 0 0 5px red;
}

The :focus pseudo-class is used to improve the appearance of the focused link. When a link receives focus (for example, by tabbing through elements), the default focus outline is removed and a subtle box shadow is added to make it visually clear which link is active.

Output:

When we talk about the :focus pseudo-class and its importance for keyboard navigation, we’re referring to its role in providing a visual cue for users who only use the keyboard to navigate through a webpage. It ensures that the focused element stands out when they tab through elements, indicating where their current point of interaction is.

For example, some people, particularly those with certain disabilities, may rely on keyboard navigation. They use the Tab key to move between interactive elements on a webpage, such as links and form fields, and activate them with the Enter or Space key.

Beginners may be confused by the :focus and :active pseudo-classes, but here is the difference:
When an element is currently selected or has focus, the :focus property is used. It’s frequently used to style elements accessed via keyboard navigation. In contrast, :active is used when an element is actively clicked or pressed. It represents the moment when the mouse button (for mouse users) or a key (for keyboard users) is clicked while over the element.

Browser Compatibility

The :focus pseudo-class has good support across modern browsers. Here are some supported browsers and their versions:

BrowsersVersion RangeSupport Level
Chrome3.0+Full support
Firefox3.0+Full support
Safari5.1+Full support
Edge12.0+Full support
Opera7.0+Partial support

:focus-within - Solving Nested Element Focus Problem

The :focus-within pseudo-class is activated when any child element within a parent comes into focus. While it may appear to be a minor addition to CSS, it is a game changer, particularly in resolving a critical issue: ensuring that nested elements receive clear visual feedback when they are in focus.

Consider a form with multiple nested components. Without :focus-within, users may be left wondering where their keyboard interactions are concentrated if they only style the individual-focused input or button. This is where the :focus-within pseudo-class comes in to help.

It ensures a cohesive and clear visual representation of the user’s current interaction within nested structures by applying styles to the parent when any of its children receive focus. This is particularly useful in complex layouts where understanding the hierarchy of focused elements is essential.

Let’s look at an example to see how :focus-within improves the user experience in nested component scenarios.

HTML:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Focus-Within Example</title>
</head>
<body>
  <form>
    <label for="username">Username:</label>
    <input type="text" id="username" name="username" placeholder="Enter your username">

    <label for="password">Password:</label>
    <input type="password" id="password" name="password" placeholder="Enter your password">
  </form>
</body>
</html>

For clarity, we labeled each input field separately.

CSS:

/* Basic styling for form and nested components */
form {
  padding: 20px;
  border: 1px solid #ddd;
  border-radius: 8px;
}
label {
  display: block;
  margin-bottom: 10px;
}
input {
  padding: 8px;
  width: 100%;
  box-sizing: border-box;
}

/* Apply styles to the form when any child has focus */
form:focus-within {
  border-color: red;
  box-shadow: 0 0 10px red;
}

Output:

When a form’s child element (such as the input fields) gains focus, the entire form is given a distinct border color and a subtle box shadow. This gives the user a clear visual indication that they are interacting with form elements.

Browser Compatibility

The :focus-within pseudo-class is supported across modern browsers. Here are some supported browsers and their versions:

BrowsersVersion RangeSupport Level
Chrome4.0+Full support
Firefox52.0+Full support
Safari10.1+Full support
Edge79.0+Full support
Opera48.0+full support

:focus-visible - Solving Unwanted Focus Indicators

The :focus-visible pseudo-class also emerges as a thoughtful solution in web development. When an element receives keyboard focus, it applies styles to it, but not when the focus is triggered by mouse clicks or taps. This refined pseudo-class provides a smooth and subtle user experience for that.

Consider a scenario in which focus styles are essential for keyboard navigation but may be distracting when using a mouse or touchscreen. Without :focus-visible, focus styles would be applied universally, resulting in unwanted and potentially jarring visual cues for mouse users.

:focus-visible addresses this by allowing developers to tailor focus styles specifically for keyboard users, resulting in a polished and device-appropriate experience for all.

Let’s look at some examples to get a better understanding.

HTML:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Focus-Visible Example</title>
</head>
<body>
  <p>Try clicking on the links and navigating with the Tab key.</p>

  <a href="#">Link 1</a>
  <a href="#">Link 2</a>
  <a href="#">Link 3</a>
</body>
</html>

CSS:

/* Basic styling for links */
a {
  text-decoration: none;
  padding: 8px 12px;
  border-radius: 5px;
  color: #333;
  background-color: #eee;
  margin: 5px;
}

/* Apply styles only when the link is focused via keyboard */
a:focus {
  outline: none;
  box-shadow: 0 0 5px red;
}

/* Apply styles only when the link is focused, but not when clicked with a mouse */
a:focus:not(:focus-visible) {
  box-shadow: none;
}

When a link receives focus (via keyboard navigation), it gets a box shadow to indicate focus.

:focus:not(:focus-visible) applies styles when the link is focused but not when it’s focused by a mouse click or tap. This prevents unwanted focus styles for mouse users.

Output:

Browser Compatibility

The :focus-visible pseudo-class is also supported across modern browsers. Here are some supported browsers and their versions:

BrowsersVersion RangeSupport Level
Chrome76.0+Full support
Firefox65.0+Full support
Safari13.1+Full support
Edge81.0+Full support
Opera64.0+full support

You can visit caniuse.com for more information about browser versions and compatibility with :focus, :focus-within, and :focus-visible.

Best Practices

These are some of the best practices for designing a focus state:

  • Subtle Visual Cues: To avoid overwhelming users, keep focus styles subtle. A subtle color, border, or shadow change can be effective without being distracting.

  • Clear Contrast: Make sure the focused element stands out against its background with enough contrast. This is important for accessibility because it helps users identify where they are on the page.

  • Avoid Removing Outlines Entirely: While customizing focus styles is common, avoid completely removing outlines. Outlines include a focus indicator by default that is easily accessible. Instead, think about styling outlines to fit your design.

  • Test Across Devices: Try out different focus styles on different devices, such as desktops, laptops, tablets, and smartphones. Maintain a consistent and pleasant user experience regardless of input method.

  • Consider Touchscreen Users: When using :focus-visible, keep in mind that touchscreen users may also benefit from customized focus styles. Try out different styles and see how they work with keyboard and touchscreen interactions.

  • Consider Animation: When using animations for focus states, keep them subtle and quick to avoid discomfort or distraction for users.

  • Accessibility First: When designing focus states, prioritize accessibility. Aim for a unified experience for disabled users who rely on keyboard navigation or assistive technologies.

  • Pseudo-classes should be combined for complex interactions: For more complex UI interactions, combine :focus, :focus-within, and :focus-visible as needed. These fictitious classes can collaborate to create nuanced and inclusive designs.

Conclusion

The :focus, :focus-within, and :focus-visible pseudo-classes are essential tools for creating accessible and user-friendly interfaces. They enable developers to design with clarity and inclusivity in mind, from refining keyboard navigation with :focus to handling nested components with :focus-within and ensuring unobtrusive focus states with :focus-visible.

By following best practices, testing across devices, and embracing subtle visual cues, you can elevate your interfaces and provide a seamless user experience for all users.

If you found this tutorial helpful, please consider subscribing to my newsletter to receive updates when my next article is published. I'm also eager to hear your thoughts and questions in the comments section below. Happy coding!