javascripthtmlaccessibility

Accessibility for customized file input


I have this kind of customized file input:

#file-uploader {
  display: none
  }
<input type="file" id="file-uploader" multiple accept=".stl"/>
<label for="file-uploader" role="button" aria-labelledby="drop-file-instructions" tabIndex=0>
  Add files
</label>

I simplified this a lot for the sake of readability, but the problem remains: In this accessibility tree, the label is well detected as a button and focusable but the only way to trigger the file selector is by clicking on the button.

Does anyone have a solution to trigger this by keyboard ?

edit: this is a from a react project, so any react solution is fine with me too


Solution

  • You need to hide the file input visually – applying display:none or visibility:hidden removes an element from the accessibility tree and prevents it from being focused via keyboard/tab navigation.

    A common technique is to shrink the element to 1px and apply some clipping

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

    See also "The a11y project: Hide content".

    .label-file:focus-within{
      outline: 1px solid red
    }
    
    .visually-hidden {
      clip-path: inset(50%);
      height: 1px;
      overflow: hidden;
      position: absolute;
      white-space: nowrap;
      width: 1px;
    }
    <label class="label-file">
      Add files
        <input type="file" id="file-uploader" class="visually-hidden" multiple accept=".stl"/>
    </label>

    The example above wraps the <input> in the label. This way we don't need a for or an ARIA label attribute as the label itself contains a descriptive text. Besides, we don't need to add a manual tab-index. So we can simply focus the input via keyboard.

    For a focus style you could use :focus-within pseudo selector or :has()