How to Hide Content Accessibly

There are many ways to hide something on a web page.

That is part of the problem.

These all look like they might do the same thing:

display: none;
visibility: hidden;
opacity: 0;

And HTML gives us more options:

hidden
aria-hidden="true"

But they do not behave the same way.

Choosing the wrong one can create confusing keyboard behaviour or make important content disappear for screen reader users.

display: none

.message {
  display: none;
}

The element is removed from normal layout.

It also is not exposed as normal content to assistive technology.

Use it when the content should genuinely not be available right now.

The hidden attribute

HTML already has:

<div hidden>
  Hidden content
</div>

For simple show and hide states, this is often clearer than adding a class only to set display: none.

JavaScript can toggle it:

message.hidden = false;

visibility: hidden

.message {
  visibility: hidden;
}

The element is hidden but still keeps its layout space.

You may end up with:

[ visible item ]
[ empty space  ]
[ visible item ]

This can be useful when the layout should not move.

opacity: 0

This is very different.

.message {
  opacity: 0;
}

The element is invisible, but it still exists in layout.

Interactive children may still be focusable or clickable.

<div class="menu" style="opacity: 0">
  <a href="/account/">Account</a>
</div>

A keyboard user may still tab to the invisible link.

That is usually a bug.

If you use opacity, manage interaction

For a visual transition, you may use:

.menu {
  opacity: 0;
  pointer-events: none;
}

But pointer-events: none does not solve keyboard focus by itself.

This is why native hidden states, popovers, dialogs, or inert are often better choices.

aria-hidden="true"

aria-hidden hides an element from the accessibility tree.

<span aria-hidden="true">
  ★
</span>

The star is still visible, but a screen reader does not need to announce it.

This is useful for decorative icons.

Do not hide focusable content from screen readers

This is bad:

<div aria-hidden="true">
  <button>Save</button>
</div>

The button may still be focusable while assistive technology has been told that it does not exist.

MDN warns against using aria-hidden="true" on focusable elements or their ancestors.

If a whole section should be inactive, inert may be the better tool.

Decorative icons

A good use:

<button>
  <span aria-hidden="true">✓</span>
  Save
</button>

The word “Save” already explains the button.

The checkmark does not need to be announced too.

Visually hidden text

Sometimes you want the opposite:

A common class is:

.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

Then:

<a href="/search/">
  <svg aria-hidden="true">...</svg>
  <span class="visually-hidden">
    Search
  </span>
</a>

The visible UI can show only an icon while the link still has a useful text name.

Off-screen menus

Older sites often hid menus like this:

.menu {
  left: -9999px;
}

That can create strange focus and scrolling behaviour.

For a menu that is closed, use a real hidden state, popover, or inert depending on the component.

A simple decision guide

Should nobody access it?
→ hidden / display: none

Should it keep layout space?
→ visibility: hidden

Should it only be visually transparent?
→ opacity: 0, but manage interaction carefully

Should screen readers ignore visible decoration?
→ aria-hidden="true"

Should screen readers get text that is not visible?
→ visually-hidden class

Should a whole section be temporarily inactive?
→ inert

That covers most normal cases.

Test with a keyboard

Whenever you hide interactive UI, press Tab.

Can focus move to something you cannot see?

If yes, the hidden state is probably incomplete.

This one test catches many mistakes.

Hiding is part of interaction design

The important question is not only:

Can I make this invisible?

It is:

Who should still be able to find, read, focus, or use it?

CSS and ARIA answer different parts of that question.

Choose the method based on the behaviour you actually want, not only on what looks hidden on your screen.