I have a time picker component, composed by two separate input
fields that work together to create the illusion of being one.
This is how the skeleton looks like
<div> {/* component container */}
<div> {/* container for hours:minutes */}
<input /> {/* hours */}
<input /> {/* minutes */}
</div>
<Select /> {/* custom React component, for AM/PM */}
</div>
Everything works great for "regular" users, but the accessibility is poor.
Because of pre-existing limitation in the codebase, it's hard for me to simply wrap everything in a label
, which would solve my problem.
What I'm thinking of doing is the following, and I would like the community input (ha!) on whether this can be really useful to a screen reader or not.
<label htmlFor="myUniqueId">Here goes my label</label>
<div id="myUniqueId"> {/* component container */}
<div> {/* container for hours:minutes */}
<input /> {/* hours */}
<input /> {/* minutes */}
</div>
<Select /> {/* custom React component, for AM/PM */}
</div>
So basically, set an ID on the container, instead of the inputs, and then attach a label using htmlFor
.
Would this work for screen readers?
No, the for
attribute must point at a labelable
element:
The for attribute may be specified to indicate a form control with which the caption is to be associated. If the attribute is specified, the attribute’s value must be the ID of a labelable element in the same Document as the label element.
labelable
elements are: input
, button
, select
, textarea
, fieldset
, output
, object
, meter
, progress
, label
, img
.
I would structure it this way:
<label htmlFor="myUniqueId">Select time</label>
<fieldset id="myUniqueId"> {/* component container */}
<div> {/* container for hours:minutes */}
<input aria-label="hours" /> {/* hours */}
<input aria-label="minutes" /> {/* minutes */}
</div>
<Select aria-label="AM or PM" /> {/* custom React component, for AM/PM */}
</fieldset>