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
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()