label_visibility="hidden" since Streamlit 1.11: does the accessible name still reach screen readers after re-runs?
0 reputation · 10 Jul 2020, 10:15 UTC
0 reputation · 10 Jul 2020, 10:15 UTC
I'm designing a Streamlit app (1.11 or newer) that uses label_visibility="hidden" on several st.text_input and st.selectbox widgets to reduce visual clutter, while still relying on the label parameter as the accessible name for assistive technology.
The documentation states the label is retained for accessibility when hidden, but Streamlit re-runs the full script on every interaction, and I have not found a documented conformance claim (e.g., a WCAG level) covering how the rendered DOM behaves across those re-runs. It is unclear whether the hidden label is consistently exposed as an aria-label or an associated <label> element, and whether dynamic widget updates are announced reliably by screen readers such as NVDA or VoiceOver.
Keyboard focus order after a re-run is also a concern, since hidden labels remove a visible anchor for sighted keyboard users.
label_visibility="hidden", what does the current Streamlit version actually render for the accessible name, and does it differ between hidden and collapsed?30775 reputation · 10 Jul 2020, 11:08 UTC
Yes. In Streamlit 1.11 and later, a widget created with label_visibility="hidden" renders the label text as an aria-label attribute on the underlying <input> or <select> element. The attribute is added every time the script runs, so the accessible name is preserved across re‑runs triggered by any widget interaction.
<input type="text" id="st-text-0" aria-label="Secret">
When label_visibility="collapsed" is used instead, Streamlit adds a hidden <label> element that is visually hidden but still part of the DOM. The aria-label is omitted in that case, and the hidden <label> becomes the source of the accessible name.
aria-label is regenerated with the same value on each re‑run, screen readers such as NVDA and VoiceOver announce the widget’s name normally when it receives focus.With label_visibility="hidden", there is no visible anchor for sighted users, but the focus order remains the same as in the source code. If you need to keep a visible label for keyboard users, consider using label_visibility="collapsed" or providing an aria-labelledby that points to a hidden <label> that is still focusable.
<div> with tabindex="0" if you need a custom focus ring.aria-label is present after each re‑run.<label> and reference it via aria-labelledby instead of aria-label.# Minimal Streamlit example
import streamlit as st
st.text_input('Secret', label_visibility='hidden')
# Trigger a re‑run
if st.button('Change'): st.session_state['dummy'] = 1
1. Open the browser’s developer tools and locate the <input> element. Confirm it has aria-label="Secret".
2. Click the Change button to trigger a re‑run. Inspect the element again; the attribute should still be present.
3. Use NVDA or VoiceOver to focus the input and ensure the screen reader announces “Secret”.
If you notice that the screen reader does not announce the label after a re‑run, check which browser and screen‑reader combination you are using, as some older combinations may not honor aria-label on re‑created elements.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.