Hajime, the duck guy

Friday, June 7, 2024, by Hajime Yamasaki Vukelic

What is visual hiding?

When creating accessible interfaces, we sometimes provide text alternatives. These are similar to the alt attribute on the <img> tag. These text alternatives usually describe a form control or an icon whose purpose is visually obvious but not obvious to users with reduced visual ability.

Why not display: none or visbility: hidden?

Let's get the obvious out of the way. There is no out-of-the-box way to hide an element for just the visually able users but keep it available to the accessibility technologies. Neither the HTML attributes nor CSS properties provide such a mechanism. Both display: none and visibility: hidden will cause screen readers to suppress the text as if it does not exist.

The right way™

Whether it's the right way aside, a way to visually hide text in a way that is still accessible to screen readers is this:

.text-alt {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip-path: inset(50%);
}

Let's break down the code:

  • position: absolute takes the element out of the document flow so that it takes up no space in the layout.
  • width: 1px and height: 1px makes the element take up a square pixel on the screen. The reason we are not using 0 here is that some user agents may still treat an element with 0 dimensions as "effectively invisible".
  • overflow: hidden prevents the contents of the element from showing outside the 1x1px square.
  • clip-path: inset(50%) causes the element to become completely invisible.

Technically we could use just the first and last line to achieve the same effect in all browsers that support clip-path, but not all of them do.

A few examples

When a button only contains an icon, we may provide a text alternative in a hidden span:

<button>
    <svg class="icon" aria-hidden="true"><use href="icons.svg#folder"></svg>
    <span class="text-alt">Open</span>
</button>

When a fieldset has a legend that visually able people do not need, we might hide it visually:

<fieldset>
    <legend class="text-alt">Pick a day</legend>
    <label>
        <input type="radio" name="day" value="1">
        <span>Monday</span>
    </label>
    <label>
        <input type="radio" name="day" value="2">
        <span>Tuesday</span>
    </label>
    <label>
        <input type="radio" name="day" value="3">
        <span>Wednesday</span>
    </label>
    <!-- .... -->
</fieldset>

When a section heading should remain visually hidden but still exist to allow navigation:

<section aria-labelledby="sidebar">
    <h3 id="sidebar" class="text-alt">Sidebar</h3>

    <menu><!-- .... --></menu>
</section>

Do not abuse

Visual hiding should really be the last resort. Ideally you (or your product team) should plan your layout so that the text can be included. Visual hiding should only be used in cases where the visual presentation is self-evident but the UI is unusable for those that receive no visual cues.

Posted in Programming tips
Back to top