Don't Override CSS Outline Focus Styles
Tags: css, a11y, designsystems
Published: 2020-07-30 03:59:33

---
title: Don't Override CSS Outline Focus Styles
published: true
date: 2020-07-20 05:00:00 UTC
tags: css, accessibility, designsystems
canonical_url: https://coryrylan.com/blog/dont-override-css-outline-focus-styles
---

It’s common to see websites remove the focus outline of focusable items. Removing outline styles, however, causes problems for many users. To keep your websites and web apps accessible focusable items must have a focus outline. Users with mobility disabilities may only be able to use a keyboard or non-mouse interaction with your web app. By removing the outline, your web app can quickly become unusable.

```css
button {
  outline: 0; /* don't do this! */
}
```

Many developers and designers do not like the default system focus most browsers provide and often override it with a custom outline style.

```css
button:focus {
  outline: 4px solid blue;
}
```

Custom outlines can introduce a new set of usability problems that we will cover in this post. First, let’s look at a set of blue buttons for our demo.

![Default Focus Style for Buttons](https://coryrylan.com/assets/images/posts/2020-07-21-dont-override-css-outline-focus-styles/buttons.png)

These are native HTML buttons with some minor style changes for the background color. These buttons can have some issues when focused. The focus outline can blend into the button, making it difficult to see.

#### Chrome Focus Styles

![Improved Focus Styles for Chrome](https://coryrylan.com/assets/images/posts/2020-07-21-dont-override-css-outline-focus-styles/focus-chrome.png)

This screenshot is an example running in Chrome. Each button is focused in the screenshot, and each looks slightly different. The first button is the default focus style in Chrome. We can see it blends in with the button. The second button shows a custom style that makes the outline larger but still blends in. We could change the color but will have to maintain multiple colors for each button color we may provide.

The last two buttons have native focus styles with some offset adjustments. As of Chrome 83 [(announcement here)](https://blog.chromium.org/2020/03/updates-to-form-controls-and-focus.html), the focus styles have changed as well as the latest Edge. The new native focus style has two borders a light and dark that can be seen and altered by the browser-based on the background color. This feature is great to help ensure the focus is visible regardless of the surrounding colors.

But there is still a slight problem with this approach. The outline is directly next to our first button, making it difficult to see if the colors are similar. Some browsers mitigate this. For example, Safari adds an offset space between the button and the outline automatically.

#### Safari Focus Styles

![Improved Focus Styles for Safari](https://coryrylan.com/assets/images/posts/2020-07-21-dont-override-css-outline-focus-styles/focus-safari.png)

As you can see, the offset Safari provides makes the focus much more visible. Unfortunately, Safari is currently the only browser that provides this default offset spacing. As we can see in Edge and Firefox, the first two buttons in each have no default offset.

#### Edge Focus Styles

![Improved Focus Styles for Edge](https://coryrylan.com/assets/images/posts/2020-07-21-dont-override-css-outline-focus-styles/focus-edge.png)

#### Firefox Focus Styles

![Improved Focus Styles for Firefox](https://coryrylan.com/assets/images/posts/2020-07-21-dont-override-css-outline-focus-styles/focus-firefox.png)

Even though only Safari provides an offset, we can still adjust the CSS outline offset ourselves.

```css
button {
  outline-offset: 2px;
}
```

The [`outline-offset` CSS property](https://developer.mozilla.org/en-US/docs/Web/CSS/outline-offset) will add space between the element and the focus outline, making a visual distinction. But again, we run into some browser compatibility problems.

## Offset Outline with Native Defaults

In Chrome and Edge, the `outline-offset` property does not work on the default outline style. The `outline-offset` will work only on custom outline styles. We don’t want to override the default outline since Chrome and Edge provide the helpful [multi background outline support](https://blog.chromium.org/2020/03/updates-to-form-controls-and-focus.html) for accessibility.

So what can we do to improve this? We don’t want to override the native behavior as it provides the best accessibility support, but we cant apply the `outline-offset` needed. We can use a trick to create a pseudo-element around our focusable item that is slightly larger to create an offset space.

```css
button {
  /* for browsers that support native offset without custom outline */
  outline-offset: 2px;
}

button:focus {
  position: relative;
}

button:focus::after {
  content: '';
  position: absolute;
  top: -2px;
  left: -2px;
  right: -2px;
  bottom: -2px;
  outline: 5px auto -webkit-focus-ring-color;
}
```

When the button is focused, we can create a pseudo-element and position it slightly larger, about two pixels, and around the focused button. To apply the native focus style to the pseudo-element, we use this CSS property:

```css
outline: 5px auto -webkit-focus-ring-color;
```

This CSS line is the CSS that triggers the internal native outline style in Chrome and Edge, which will preserve the multi background color support. Looking back at our examples, the last two buttons have the space between the button and the outline. Since we did not override the native outline style, the outline is automatically visible on light and dark backgrounds.

### Chrome Focus Styles

![Improved Focus Styles for Chrome](https://coryrylan.com/assets/images/posts/2020-07-21-dont-override-css-outline-focus-styles/focus-chrome.png)

Accessibility can be tricky to get right across several browsers. Often browsers built-in defaults provide a solid foundation and are always improving. When adding custom overrides, we remove the browser’s chance to provide better defaults in the future. As Web Developers, we must find that balance between customization and using what is built-in. Check out the [full demo code](https://codepen.io/coryrylan/pen/ZEQmYKb)!