Lesson 20: Focus
On your webpage, you click a link that skips the user to the main content of the website. These are often called skip links, or anchor links. When that link is activated by a keyboard, using the tab and enter keys, the main content container has a focus ring around it. Why is that?
This is because the <main> has a tabindex="-1" attribute value, which means it can be focused by code.
When the <main> is targeted, because the #main-content in the browser URL bar matches the id, it receives focus from code.
It is tempting to remove the focus styles in these situations.
But handling focus with care helps create a good, accessible experience.
It can also be a great place to add some interest to interactions.
Why is focus important?
As a web developer, it’s your job to make a website work for everyone. Creating accessible focus states with CSS is a part of this responsibility.
Focus styles help people who use a device such as a keyboard or a switch control to move around and use a website. If an element receives focus and there is no visual sign of it, a user may lose track of what is in focus. This can cause navigation problems and lead to unwanted results if, say, the wrong link is followed.
[!NOTE] Learn more about why focus matters for accessibility in Learn Accessibility: Focus. You can find more about how to manage focus in HTML in Learn HTML: Focus.
How elements get focus
Certain elements can be focused on their own.
These are elements that accept interaction and input, such as <a>, <button>, <input> and <select>.
In short, all form elements, buttons, and links.
You can usually move through a website’s focusable elements using the tab key to go forward on the page, and shift plus tab to go backward.
There is also an HTML attribute called tabindex which lets you change the tabbing order.
The tabbing order is the order in which elements are focused every time someone presses their tab key, or focus is moved by a hash change in the URL or by a JavaScript event.
If tabindex on an HTML element is set to 0, it can receive focus with the tab key and it will follow the global tab order, which is set by the document source order.
If you set tabindex to -1, it can only receive focus from code.
That means only when a JavaScript event happens or a hash change occurs that matches the element’s id in the URL.
If you set tabindex to be anything higher than 0, it will be taken out of the global tab order set by document source order.
Tabbing order is then set by the value of tabindex.
So an element with tabindex="1" will receive focus before an element with tabindex="2", for example.
[!WARNING] Honoring document source order is really important. Focus order should only be changed if you absolutely have to change it. This applies both when setting
tabindexand when changing visual order with CSS layout, such as flexbox and grid. Anything that creates unpredictable focus on the web can make the experience hard to use.
Styling focus
The default browser behavior when an element receives focus is to show a focus ring. This focus ring looks different between browsers and operating systems.
This behavior can be changed with CSS, using the :focus, :focus-within and :focus-visible pseudo-classes that you learned about in the pseudo-classes lesson.
It’s important to set a focus style that has contrast with the default style of an element.
For example, a common approach is to use the outline property.
a:focus {
outline: 2px solid slateblue;
}The outline property could appear too close to the text of a link.
The outline-offset property can help with that, since it adds extra visual padding without changing the size the element takes up.
A positive number value for outline-offset will push the outline outwards.
A negative value will pull the outline inwards.
Right now in some browsers, if you have a border-radius set on your element and use outline, it won’t match.
The outline will have sharp corners.
Because of this, it’s tempting to use a box-shadow with a small blur radius, since box-shadow clips to the shape and follows border-radius.
But this style won’t show in Windows High Contrast Mode.
This is because Windows High Contrast Mode doesn’t apply shadows, and it mostly ignores background images so it can use the user’s preferred settings.
In summary
Creating a focus state that has contrast with an element’s default state is really important. The default browser styles do this already for you. But if you want to change this behavior, remember the following.
- Avoid using
outline: noneon an element that can receive keyboard focus. - Avoid replacing
outlinestyles withbox-shadow, since they don’t show up in Windows High Contrast Mode. - Only set a positive value for
tabindexon an HTML element if you absolutely have to. - Make sure the focus state is very clear next to the default state.
Adapted from Learn CSS © Google and contributors, licensed under CC BY 4.0 (prose) and Apache 2.0 (code samples).