Hiding Elements

There are different methods of hiding content, that have different use-cases depending on the user group you want to hide it from.

Hiding elements for All users

  • Using CSS: visibility: hidden; 1 This method has the advantage of enabling animations on show or hide.
  • Using CSS: display: none; 1
  • Using the HTML hidden attribute. It will not get hidden to assistive technology users, if the element is referenced by another element for example by the aria-labelledby attribute. It also has the advantage of working without CSS, like in reader modes and it does not create an additional reading stop. But be careful not to overwrite this by other CSS rules 1

Hiding elements only for assistive technology users

There are multiple ways of hiding elements only to assistive technologies that can be used in different use-cases.

Hide non-interactive elements and it‘s children to assistive technologies

To hide an element and it‘s children use the aria-hidden=“true”attribute. Be very cautious when using only hiding elements for assistive technologies. Only do it when it improves the experience for users using assistive technologies, for example by removing redundant information. Always make sure that the removed information is still accessible through other elements. 6 Furthermore don‘t use the aria-hidden attribute on interactive or focusable elements, because the element will still be focusable and wil remain in the tab index. 2 Also don’t use aria-hidden=“false” to expose the element to assistive technologies, since this also does not work reliably. A better way is to remove the attribute completely. 6

Hide (interactive) elements and it‘s children to assistive technologies

To completely hide non-interactive and interactive elements to assistive technologies use the inert attribute. This attribute will also cause interactive elements from not being focusable anymore and removes them from the tab index. Using inert is also better for assistive technologies then using a focus trap implemented in JavaScript, because the focus trap will not always trigger. For example screen reader users, that use the equivalent of tabbing with their reader will not trigger the focus trap. Make sure to visually indicate this state, since by default there is no special styling applied to inert elements. A common use-case for this is for the background of modals or loading indicators, where the content is still shown but is not interactive until the modal is closed or the loading process is finished. 7

Hide an element semantics to assistive technologies

To hide an element semantics without actually hiding it‘s content use role=“none” or role=“presentation". Both do exactly the same. But it‘s recommended to use role="none" since it meaning is more intuitive. This can be helpful to improve legacy code, like <table> elements that are only used for styling purposes. 2

Hiding elements only for sighted users

How you hide elements for sighted users depends on what elements you want to hide.

Visually hide textual elements

The most commonly used practice to do hide textual elements only visually is using a CSS class called visually-hidden that is defined like below. 4 Only use this technique for textual content and not for interactive elements. Since this can lead to users, who rely on assistive technologies where they touch an element to hear what is beneath them, to not see the elements. Tailwind for example also provides sr-only utility for this. 5

.visually-hidden:not(:focus):not(:active) {
  clip: rect(0 0 0 0); 
  clip-path: inset(50%);
  height: 1px;
  overflow: hidden;
  position: absolute;
  white-space: nowrap; 
  width: 1px;
}

Visually hide interactive elements

For interactive elements that need to be hidden like <input> elements, use code like below. The code creates an custom checkbox, that places the actual <input> element above the custom visual checkbox and hides it for visual users. 3

<label for=“check” class=“c-sustom-checkbox”>
    <input type=“checkbox id=“check”>

    <!-- custom checkbox, use aria-hidden="true" to hide it from the accessibility tree, 
         don‘t forget to style all states like focus, checked, unchecked, ... -->
    <svg width=“16” height=“16” aria-hidden=“true”>
    </svg>
</label>
.c-custom-checkbox {
    position: relative:
}
/* position the input above the svg element and hide it visually */
.c-custom-checkbox input[type=“checkbox”] {
    position: absolute;
    opacity: 0;
}

Visually hide content that slides in

For content that needs to slide in from the edge of the viewport you can use use code like below: 1

.element-class {
    position: fixed;
    left: 0;
    top: 0;
    transform: translateY(<element height>);
    transition: transform .2s ease-in-out;
}

.element-class:focus {
    transform: translateY(0em);
}

Hiding Borders and Outlines

  • Use border-color: transparent; instead of border: 0; or border: none;. 8
  • Use outline-color: transparent; instead of outline: none;. 8
    • Make sure you know what you do when hiding a outline, since all interactive elements should have a focus indicator!
  • The reason why you should use transparent is that high contrast modes will still show them this way. If you completly disable them the will not show up in those scenarios. 8
  • The source also has a code example on how to fix this issue if you already implemented it the wrong way using the forced-colors media-query. 8

Sources 

  1. Scott Ohara: Inclusively Hidden by Scott Ohara
  2. Scott Ohara: Know your ARIA: "Hidden" vs "None" by Scott Ohara
  3. Sara Soueidan: Inclusively Hiding & Styling Checkboxes and Radio Buttons by Sara Soueidan © Sara Soueidan
  4. A11Y Project: Hide content by Dave Rupert is licensed under APACHE LICENSE, VERSION 2.0
  5. Tailwind sr-only utility
  6. W3C: Accessible Rich Internet Applications (WAI-ARIA) 1.1 is licensed under W3C Document License
  7. HTML Spec: Living Standard, 6 User interaction, the inert attribute is licensed under Creative Commons Attribution 4.0 International License
  8. Frontend Masters: You Want border-color: transparent, Not border: none by Dave Rupert
Created at: 28.05.2023, Last updated at: 08.11.2024