Learn Math Foundations in about a week!
Learning should be fun and quick; no need to spend ages in just one single course.
What is the difference between :focus, :focus-visible, and :focus-within in CSS?
Understand the difference between the three seemingly similar pseudo-classes in CSS: :focus, :focus-visible, and :focus-within.
As you may know, there are three similar sounding pseudo-classes in CSS, namely :focus, :focus-visible, and :focus-within.
At the first glance, one might get confused about the difference between these and when to use which one. The good news is: these three pseudo-classes are extremely simple to understand and distinguish from one another.
In this article, you'll learn what exactly is :focus, :focus-visible, and :focus-within, and when and how to use each one of these pseudo-classes.
The :focus pseudo-class
First things first, the :focus pseudo-class applies to an element when it's focused. This focus can be made using the mouse (when we click on the element), the keyboard (when we navigate to it by pressing Tab), or JavaScript.
Furthermore, only focusable elements are allowed to receive focus and, therefore, be the subject of :focus. These are typically interactive elements in HTML — the likes of <input>, <a>, <button>, etc.
<p>, <h1>, <blockquote>, <code>, etc., aren't focusable and therefore can't be the subject of :focus. It's only if we explicitly make them focusable, by setting the tabindex attribute, that we can expect :focus to apply to them.Coming back to :focus, this pseudo-class is used to select and, thereafter, apply styles to elements when they are in the focused state.
Perhaps, the most naive example of doing so would be to consider an input field as demonstrated below:
<label>
<span>Name</span>
<input type="text" name="name">
</label>The moment we click on the input field, it receives focus and, consequently, the browser applies a black outline to it, as illustrated below:

This helps us immediately see which input field are we currently in within a form of many fields.
To better appreciate the benefit of this, imagine the opposite. Suppose you click on an input field and there is no special styling applied to it for the focused state. Do you think it would be possible for you to determine which input field are you currently in among many? Well, it clearly won't be impossible to do so but not that quick either.
The ideal thing in designing user interfaces of any kind is to make everything as easy as possible. And in this case, this ideal world can very easily be achieved just by employing the :focus pseudo-class.
In essence, the :focus pseudo-class (and even the other two focus pseudo-classes) helps us improve the accessibility of a webpage.
By clearly communicating to the user visually as to where he currently is on the webpage, we make it easy enough for him to interact with the webpage and get his work done without any confusion. In other words, :focus is more important of a pseudo-class than we might think it is.
But it's not the only important focus-based pseudo-class; we have :focus-visible as well.
The problem with :focus
In the example above for :focus, we considered a basic, text input field. Let's now shift to a button in order to see a shortcoming of :focus.
Consider the following button, with the added :focus rule for it:
<button>A button</button>button:focus {
outline: 3px solid blue;
}The moment we click on the button, we get the blue outline, as illustrated below:

But wait a second? Is this desirable?
Said another way: Is it a wise decision to showcase the outline when we click on the button using the mouse? As it turns out, NO, it's not!
Let's understand why...
When we click on a button — or any interactive element, in general, that is meant to perform an action — we already know where we are on the webpage. Obviously, because we click consciously on the button, we certainly can't be confused as to which element on the webpage currently has focus — we clearly know that it's the button we just clicked.
In this respect, it does NOT make much sense, if at all, to visually emphasize the button to be the currently focused element when we click on it using the mouse.
But why does such visual emphasis make sense for input fields?
Good question. You're right in your observation that :focus works absolutely fine when we use it on input fields and there's a simple reason for it. When we click on an input field using the mouse, our job doesn't finish; we still have to enter data into the field.
And because our work isn't done yet, we quickly and clearly need to know which input is currently active.
Notice the important, yet subtle, distinction between input fields and buttons (and other suchlike interactive elements):
- An input field doesn't accomplish a task immediately and therefore requires focus to be visualized even when we use the mouse to interact with it.
- A button accomplishes a task immediately (for e.g. adds an item to a cart) and therefore doesn't pose the need to visually showcase it in its focused state when we interact with it using the mouse.
So, at this point, we know that input fields gel nicely with the :focus pseudo-class but that's not the case with buttons.
But keep in mind that this reasoning only applies to when we focus on these interactive elements using the mouse. What about using the keyboard to do so?
Interactions using the keyboard
As you may know, it isn't only possible to navigate around a webpage using the mouse; we can use the keyboard as well, and equally well.
In fact, if a webpage is built this way to only entertain mouse interactions, it's extremely inaccessible.
Imagine someone broke his mouse device and now wants to prepare for his exam on his computer. However, there's no way to order another mouse at the moment. The worst case would be if that person wanted to prepare from a website built around only mouse interactions.
As CSS developers, we must acknowledge web accessibility and design websites to be as accessible without a mouse as with it. In this respect, we must make sure to provide necessary visual emphasis on interactive elements when they receive focus without the mouse.
And this, of course, includes buttons as well.
Let me state this again.
When we're using the mouse to interact with a webpage, creating visual emphasis for buttons in their focused state isn't necessary; in fact, it's undesirable as we saw above. This is because the user already knows that after clicking on the button, it is the one that's in focus.
But when we're using the keyboard instead, creating visual emphasis is utmost necessary. This is because, now, the user isn't aware of which button is in focus. We need to visually showcase this.
The problem is that we can't use :focus for this styling concern because it applies to buttons even when we interact with them using the mouse. Now what?
No need to worry, for we have :focus-visible to the rescue!
The :focus-visible pseudo-class
I stress a lot on the fact that before getting to learn anything in programming, please first ponder over its nomenclature (a fancy word for "naming"). Chances are high that the meaning lies in the name itself.
Following this, if we analyze the name :focus-visible, it clearly has something to do with "focus" and also with "visible". Can you figure out just by the name what this pseudo-class means?
Well, :focus-visible applies to an element that is in focus and whose focus needs to be made visible (ideally). Compactly, you could also say that :focus-visible applies to an element that needs to have its focus visible.
:focus-visible only applies when we bring an element in focus using the keyboard or some other non-mouse interaction (e.g. JavaScript).
Most importantly — and this is really important — :focus-visible does NOT apply to buttons (and other similar elements) when they receive focus by virtue of mouse interactions.
With this, let's go back to our <button> example above and replace the :focus rule with :focus-visible so that the outline is only presented when the button receives focus via the keyboard:
button:focus-visible {
outline: 3px solid blue;
}Here's what we get when we click on the button (using the mouse):

:focus-visible style) focused againNothing.
But when we press the Tab key in order to navigate to the button and bring it in focus, we get the same outline as before:

This brings us right to the ultimate conclusion that when styling buttons (or other suchlike elements, for e.g. <a>), we must preferably use :focus-visible instead of :focus (for reasons we saw above).
:focus-visible is basically a win-win situation in that
- we don't apply styles when buttons are clicked using the mouse and
- we do make sure that our webpage remains accessible when using the keyboard with necessary focus styles applied to buttons.
:focus-visible is basically a hero! (But I don't know the movie's name!)
What about :focus-within?
Obviously, I couldn't end this article without going over the relatively less useful :focus-within pseudo-class. Let's do that now.
:focus-within, as the name suggests (again, remember to analyze names carefully), applies to an element that has focus within it.
In other words, any element that contains a descendant element that matches :focus, or itself matches :focus, is a candidate for :focus-within.
Following is an example. Here we have a button contained inside a <div>. Our goal is to style the <div> specially when its button is in focus.
<div>
<p>This is a paragraph</p>
<button>A button</button>
</div>The following CSS accomplishes this:
div:focus-within {
background-color: pink;
}The moment the button receives focus, the <div> gets a pink background color. Pretty basic.
:focus-within behaves exactly like :focus in that it also shows up on mouse interactions on buttons, for example. It does NOT exhibit a behavior similar to :focus-visible.Now you might be looking for a more practical example of :focus-within and that's precisely what I have up next for you.
As stated earlier, :focus-within isn't that commonly used in CSS but some cases are such that they can be solved pretty elegantly using :focus-within. Here's such a case...
Practical use case for :focus-within
Suppose we have an accessibility bar on a website that only shows up using keyboard navigation. Initially, it's positioned out of view. The moment any of the buttons in it come into focus, it's required to bring the bar into view.
But how to select the bar when either of its buttons has focus? Well, supposing that the bar can be selected by the class selector .a11y-bar ("a11y" is a short form for "accessibility"), the desired selector would be .a11y-bar:focus-within.
.a11y-bar:focus-within selects the .a11y-bar whenever focus resides within it, which is exactly what we need to achieve here.
The following link demonstrates this example: Live Example
Further reading
Despite the fact that you've covered almost everything that you need to know about :focus, :focus-visible, and :focus-within, there still is value in reading further from some resources mentioned below:
- Using CSS :focus-visible to provide keyboard focus indication — WCAG 2.1 Techniques
- Understanding Success Criterion 2.4.7: Focus Visible | WAI | W3C
- 9.3. The Input Focus Pseudo-class:
:focus— Selectors Level 4 | W3C - 9.4. The Focus-Indicated Pseudo-class::
:focus-visible— Selectors Level 4 | W3C - 9.5. The Focus Container Pseudo-class:
:focus-within— Selectors Level 4 | W3C