Is the button focusable?

posted on

Let’s play a game. I’ll hide a button using different techniques in HTML and CSS, and you have to guess whether it’s still focusable.

That's our button.

<div>
  <button>
    Catch me if you can
  </button>
</div>

Now, let's hide it.

CSS

First, we’ll use CSS to hide the button visually.
We aim to ensure the button isn’t focusable when it’s not visible. So, if the answer to the question “Is the button focusable?” is yup, that’s bad, and if it’s nope, it’s good. You’ll find the answer after each code snippet.

Zero height

div {
  height: 0;
  overflow: hidden;
}
Is the button focusable with height: 0;? Yup.
I often see this as a solution for hiding submenus visually, which is a problem because links or buttons are visually hidden but still focusable.

Transform

div {
  transform: translateX(-100vw);
}
Is the button focusable with transform: translateX(-100%);? Yup.
I often see this as a solution for hiding menus or sidebars visually, which is a problem because it's visually hidden but interactive elements inside are still focusable.

Visibility

button {
  visibility: hidden;
}
Is the button focusable with visibility: hidden;? Nope.
It takes up space in the page but it's not focusable.

Opacity

button {
  opacity: 0;
}
Is the button focusable with opacity: 0;? Yup.
It takes up space in the page and it's focusable.

Position

button {
  position: absolute;
  left: -9999px;
}
Is the button focusable with position: absolute;? Yup.
It's not visibile in the viewport but still focusable.

Display

button {
  display: none;
}
Is the button focusable with display: none;? Nope.
It doesn't take up space in the page and it's not focusable.

Clip-path

button {
  clip-path: inset(50%); /* or similar values like circle(0)*/
}
Is the button focusable with clip-path: inset(50%)? Yup.
It takes up space in the page and it's focusable.

visually-hidden/sr-only class

.visually-hidden {
    clip: rect(0 0 0 0);
    clip-path: inset(50%);
    height: 1px;
    overflow: hidden;
    position: absolute;
    white-space: nowrap;
    width: 1px;
}
<div>
  <button class="visually-hidden">
    Catch me if you can
  </button>
</div>
Is the button focusable with a visually-hidden class? Yup.
It's not visibile in the viewport but still focusable.

content-visibility

div {
  content-visibility: hidden;
}
Is the button focusable with content-visibility: hidden;? Nope.
No, the behaviour is similar to display: none;.

HTML

Now, we'll hide it with HTML.

[hidden]

<div>
  <button hidden>
    Catch me if you can
  </button>
</div>
Is the button focusable with [hidden]? Nope.
It doesn't take up space in the page and it's not focusable.

[aria-hidden="true"]

<div>
  <button aria-hidden="true">
    Catch me if you can
  </button>
</div>
Is the button focusable with [aria-hidden="true"]? Yup.
It's not in the accessibility tree but focusable via keyboard which means that screen reader users can also focus it using the Tab key.

[disabled]

<div>
  <button disabled>
    Catch me if you can
  </button>
</div>
Is the button focusable with [disabled]? Nope.
It takes up space in the page, but it's not focusable.

[inert]

<div>
  <button inert>
    Catch me if you can
  </button>
</div>
Is the button focusable with [inert]? Nope.
It takes up space in the page, but it's not focusable.

I've tested all techniques in Firefox 135, Safari 18.2, and Chrome 133.

You can try it yourself on this demo page.