Describe the bug
gr.Tabs renders a duplicate, measurement-only copy of every tab button inside a .tab-container.visually-hidden wrapper. The wrapper has aria-hidden="true" but the duplicate buttons remain keyboard-focusable, so:
- The first Tab keypress on the page lands on an invisible 1px-high button. Every tab gets one duplicate (N tabs → N invisible stops). Because they sit inside
aria-hidden="true", screen readers announce nothing while keyboard focus is parked on them — focus effectively disappears.
- At narrow viewport widths (e.g. 320px), the tab overflow menu button is an icon-only
<button> with no accessible name (no text, no aria-label, no title), so assistive-technology users get an unnamed control.
Accessibility impact: WCAG 2.4.3 (focus order) and 4.1.2 (name, role, value); focusable content inside aria-hidden regions is also flagged by axe as a critical issue (aria-hidden-focus).
Suggested fix: add tabindex="-1" (or inert) to the visually-hidden measurement copies, and an aria-label (e.g. "More tabs") to the overflow button.
Have you searched existing issues? 🔎
Reproduction
import gradio as gr
with gr.Blocks() as demo:
with gr.Tabs():
with gr.Tab("First"):
gr.Markdown("first tab content")
with gr.Tab("Second"):
gr.Markdown("second tab content")
with gr.Tab("A Longer Third Tab"):
gr.Markdown("third")
with gr.Tab("Fourth Tab Name"):
gr.Markdown("fourth")
with gr.Tab("Fifth And Final"):
gr.Markdown("fifth")
demo.launch()
- Open the app in Chromium at a 1280px-wide viewport, click the address bar, then press Tab once:
document.activeElement is <button class="svelte-11gaq1">First</button> with a bounding rect height of 1px, inside .tab-container.visually-hidden[aria-hidden="true"]. Pressing Tab repeatedly walks through all five invisible duplicates before reaching the real tabs.
- Resize to 320px width: the overflow control appears as
<button class="svelte-11gaq1"><svg …> with no text content, aria-label, or title.
Programmatic check used (Playwright, Chromium 1280×800):
[...document.querySelectorAll('a[href], button, input, select, textarea, [tabindex]')]
.filter(el => el.tabIndex >= 0 && !el.disabled && el.offsetParent)
.filter(el => el.getBoundingClientRect().height < 10)
// → 5 matches, all inside .tab-container.visually-hidden with an
// aria-hidden="true" ancestor
Screenshot
Not applicable — the affected elements are invisible; the reproduction steps above show them programmatically.
Logs
No console errors; this is a DOM/accessibility-tree defect.
System Info
Gradio version: 6.20.0
gradio_client version: 2.5.0
Python: 3.12.7
OS: macOS 26.3.1 (arm64); also confirmed on Chromium via Playwright
Browser: Chromium (Playwright) and Chrome
Severity
I can work around it (replaced gr.Tabs with plain buttons), but it blocks accessible keyboard/screen-reader use of any app that keeps gr.Tabs.
\n\n## Before / after Spaces\n\n- Before fix\n- After fix — draft PR #13639
Before / after Spaces
Describe the bug
gr.Tabsrenders a duplicate, measurement-only copy of every tab button inside a.tab-container.visually-hiddenwrapper. The wrapper hasaria-hidden="true"but the duplicate buttons remain keyboard-focusable, so:aria-hidden="true", screen readers announce nothing while keyboard focus is parked on them — focus effectively disappears.<button>with no accessible name (no text, noaria-label, notitle), so assistive-technology users get an unnamed control.Accessibility impact: WCAG 2.4.3 (focus order) and 4.1.2 (name, role, value); focusable content inside
aria-hiddenregions is also flagged by axe as a critical issue (aria-hidden-focus).Suggested fix: add
tabindex="-1"(orinert) to the visually-hidden measurement copies, and anaria-label(e.g. "More tabs") to the overflow button.Have you searched existing issues? 🔎
gr.Tab#9853 concerns overflow behavior generally, not the missing accessible name; nothing covers the focusable hidden duplicates)Reproduction
document.activeElementis<button class="svelte-11gaq1">First</button>with a bounding rect height of 1px, inside.tab-container.visually-hidden[aria-hidden="true"]. Pressing Tab repeatedly walks through all five invisible duplicates before reaching the real tabs.<button class="svelte-11gaq1"><svg …>with no text content,aria-label, ortitle.Programmatic check used (Playwright, Chromium 1280×800):
Screenshot
Not applicable — the affected elements are invisible; the reproduction steps above show them programmatically.
Logs
No console errors; this is a DOM/accessibility-tree defect.System Info
Gradio version: 6.20.0 gradio_client version: 2.5.0 Python: 3.12.7 OS: macOS 26.3.1 (arm64); also confirmed on Chromium via Playwright Browser: Chromium (Playwright) and ChromeSeverity
I can work around it (replaced
gr.Tabswith plain buttons), but it blocks accessible keyboard/screen-reader use of any app that keepsgr.Tabs.\n\n## Before / after Spaces\n\n- Before fix\n- After fix — draft PR #13639
Before / after Spaces