User agent reliability for VoiceOver iOS Screen reader compatibility

Screen Readers
Dec 12, 2023

Shows how well VoiceOver iOS supports ARIA and WCAG sufficient techniques.

Latest version tested

VoiceOver iOS 16.6 with Safari iOS 16.6

  • All tests: 59 pass of 78 tests (76%)
  • ARIA tests: 25 pass of 31 tests (81%)
  • WCAG tests: 39 pass of 52 tests (75%)

Reliability trend

100%80%60%40%20%0%201467%201564%201664%201764%201866%201967%202068%202168%202274%202376%

Failing tests

 TestModeWhat the user hearsNotes
FailPage with xml:lang set on the html and p elementsTouchAct-if tay-bill. Ray-day-oh.Pronounced as English. Ignores xml:lang.
Failapplication/xhtml+xml page with mismatching lang and xml:lang on the html elementTouchGa-raj. Doo-ble. Damm. Un, zway, dray.Speech pronounced as lang=fr, but CSS matches :lang(de) and German CSS content pronounced as French.
Failaudio with aria-label attributeTouch Nothing Nothing voiced for audio - no indication it exists
Failaudio with aria-labelledby attributeTouch Nothing Nothing voiced for audio - no indication it exists
Failaudio with title attributeTouch Nothing Nothing voiced for audio - no indication it exists
Failabbr with titleTouchT L NABBR expansion ignored.
Failbutton containing img with title attributeTouchButtonReads "button" without saying what button does.
Worsefieldset containing linksTouchLegend for enclosed links, form start. Home, link. About, link. Contact, link end, legend for enclosed links, form end.The fieldset is announced as a form, but contains no form controls.
Failimg with figcaptionTouchOne thousand, two hundred and thirty four PNG, image, test image. Violet, taken on twelve slash eleven slash two thousand and ten.Reads out meaningless filename, then FIGCAPTION.
Failarea and img with alt attributesTouchThis is alt text. (This is left alt text, link. This is right alt text, link)Very hard to find AREA links because image map links are not announced when reading. It is possible to find them by minesweeping, or using the Next Link gesture, but there are no audible cues to tell the user they're missing links.
Failarea with title attributeTouchThis is alt text. (This is left title text, link. This is right title text, link.)Very hard to find AREA links because image map links are not announced when reading. It is possible to find them by minesweeping, or using the Next Link gesture, but there are no audible cues to tell the user they're missing links.
Failarea with aria-label attributeTouchThis is alt text. (This is left ARIA label text, link. This is right ARIA label text, link.)Very hard to find AREA links because image map links are not announced when reading. It is possible to find them by minesweeping, but there are no audible cues to tell the user they're missing links.
Failarea with aria-labelledby attributeTouchThis is alt text. (Left arrow HTM, link. Right arrow HTM, link.)Very hard to find AREA links because image map links are not announced when reading. URLs read out instead of ARIA-LABELLEDBY when Next Link gesture is used.
FailData table with role=gridReadingMorning, row 1, column 1, table start, 2 rows 2 columns. Afternoon, row 1 column 2. Free, row 2 column 1. Busy, row 2 column 2. Table end, end, end.Voiced as table, but no headers read
FailData table with summary and thReadingMorning, row header, column header, row 1, column 1, table start, 2 rows 2 columns. Afternoon, column header, row 1 column 2. Morning, free, row 2 column 1. Afternoon, busy, row 2 column 2, table end, end, end.Summary not read out
WorseData table with caption and thTouchData table caption, row -90020023372036854775808, table start, 2 rows 2 columns. Morning, row header, column header, row 1 column 1. Afternoon, column header, row 1 column 2. Morning, free, row 2 column 1. Afternoon, busy, row 2 column 2, table end, end, data table caption, end.Meaningless row number read out for table caption.
FailData table with role=columnheader headers but no thReadingMorning, afternoon. Free, busy.Table treated as layout table - not announced as table, and no headers read.
FailData table with th scope on cell headersTouch Contact information, row -90020023372036854775808, table start, 4 rows, 5 columns. Name, row header, row 1 column 2. Phone hash symbol, row 1 column 3. Fax hash symbol, row 1 column 4. City, row 1 column 5. One, row 2 column 1. Joel Garner, row 2 column 2. 412 212 5421, row 2 column 3. 412 212 5400, row 2 column 4. Pittsburgh, row 2 column 5. Two, row 3 column 1. Clive Lloyd, row 3 column 2. 410 306 1420, row 3 column 3. 410 306 5400, row 3 column 4. Baltimore, row 3 column 5. Incomprehensible - doesn't read any cell headings, and reads out meaningless row number for caption.
FailData table with td headers attributeReading Homework, row header, column header, spans 2 rows, row 1 column 1, table start, 3 rows 7 columns. Exams, column header, spans 3 columns, row 1 column 2. Projects, column header, spans 3 columns, row 1 column 5. Exams, one, row 2 column 2. Exams, two, row 2 column 3. Exams, final, row 2 column 4. Projects, one, row 2 column 5. Projects, two, row 2 column 6. Projects, final, row 2 column 7. Homework, fifteen percent, row 3 column 1. Exams, fifteen percent, row 3 column 2. Exams, fifteen percent, row 3 column 3. Exams, twenty percent, row 3 column 4. Projects, ten percent, row 3 column 5. Projects, ten percent, row 3 column 6. Projects, fifteen percent, row 3 column 7, table end, end, end. Table incomprehensible - only first header in HEADERS list is voiced.

Passing tests

 TestModeWhat the user hearsNotes
PassPage with lang set on the html and p elementsTouchAct-eef tab-le. Rah-di-oh.Pronounced as French and German.  
Passtext/html page with mismatching lang and xml:lang on the html elementTouchGa-raj. Doo-ble. Damm. Un, deux, trois.Speech pronounced as lang=fr, and CSS matches :lang(fr).  
PassMatch lang subtagsTouchDam-he. Dam-he. Dam-he.All pronounced as German.  
PassARIA role=headingTouchFirst level heading, heading level 1. Second level heading, heading level 2  
PassHeading is img with altTouchSecond level alt, heading level 2, image, test image.Reads out text in image as well as alt text.  
Passapplet with title attributeTouch Nothing iOS does not support applets, and does not render them on screen  
Passapplet with fallback contentTouchFallback content for appletiOS does not support applets  
Passapplet with aria-label attributeTouch Nothing iOS does not support applets, and does not render them on screen  
Passapplet with aria-labelledby attributeTouch Nothing iOS does not support applets, and does not render them on screen  
Passapplet inside figure with figcaption elementTouchFigure caption for applet  
Betterembed with title attributeTouchTitle text for embed  
Passembed inside figure with figcaptionTouchFigure caption for embed  
Betterembed with aria-label attributeTouchAria label for embed  
Betterembed with aria-labelledby attributeTouchThis is ARIA-LABELLEDBY text  
Passobject with fallback contentTouchFallback content for object  
Betterobject with title attributeTouchTitle for object  
Betterobject with aria-label attributeTouchAria label for object  
Betterobject with aria-labelledby attributeTouchThis is ARIA-LABELLEDBY text.  
Bettervideo with aria-label attributeTouchVideo aria label, 5 seconds, video playback, end article, elapsed time 0 seconds, double-tap to play or pause.  
Bettervideo with aria-labelledby attributeTouchThis is ARIA-LABELLEDBY text, 5 seconds, video playback, end article, elapsed time 0 seconds, double-tap to play or pause.  
Bettervideo with title attributeTouchVideo title, 5 seconds, video playback, end article, elapsed time 0 seconds, double-tap to play or pause.  
Passiframe with fallback contentTouchThis is an. Example hyperlink, link. In the target page.Fallback content is ignored  
Passiframe with title attributeTouchThis is an. Example hyperlink, link. In the target page.  
PassInteractive iframe with role=presentation and no accessible nameTouchThis is an. Example hyperlink, link. In the target page.  
PassInteractive iframe with role=presentation and negative tabindex and no accessible nameTouchThis is an. Example hyperlink, link. In the target page.  
Passbutton containing img with altTouchThis is image alt, button  
Passbutton containing img with aria-labelTouchThis is image aria label, button  
Passbutton containing img with aria-labelledbyTouchThis is aria labelled by, button  
Passbutton with title containing img with null altTouchThis is button title, button  
Passbutton with aria-label containing img with null altTouchThis is button aria label, button  
Passinput type=image with altTouchThis is image button alt text, button  
Passinput type=image with title attributeTouchThis is image button title text, button  
Passinput type=image with aria-label attributeTouchThis is image button aria label text, button  
Passinput type=image with aria-labelledby attributeTouchThis is image button aria-labelled by text, button  
Passinput type=text with aria-describedby attributeTouchFirst name, text field, a bit of instructions for this field linked with aria describedby  
Passinput type=text with title attributeTouchEnter search text, text field  
Passinput type=text with aria-label attributeTouchEnter search text, text field  
Passinput type=text with aria-labelledby attributeTouchEnter search text, text field, double tap to edit  
Passinput type=text with label forTouchEnter search text, text field, end article, double tap to edit  
Passinput type=text inside label with text before controlTouchEnter search text, text field, end article, double tap to edit  
Passinput type=text inside label with text after controlTouchEnter search text, text field, double tap to edit  
Passinput type=text inside label with text before and after controlTouchEnter search text blanks not allowed, text field, double tap to edit  
BetterYes/No radio buttons inside fieldset elementTouchI agree to terms and conditions, form start. Yes, radio button, ticked, one of two. No, radio button, unticked, two of two. Sign me up to the newsletter, form start. Yes, radio button, ticked, one of two. No, radio button, unticked, two of two.  
Passimg with null altTouch Nothing Ignored as expected  
Passimg with altTouchThis is alt text, image, test imageText in image captured via OCR  
Passimg with titleTouchThis is title text, image, test image  
Passimg with aria-labelTouchThis is an aria label, image, test image  
Passimg with aria-labelledbyTouchThis is an aria labelled by, image, test image  
Passarea with alt attribute and img with null altTouchThis is left alt text, link. This is right alt text, link.Link role only announced when reading if owner IMG has null alt.  
PassLink containing img with altTouchThis is a link alt, link image  
PassLink containing img with titleTouchThis is an image title, link image  
BetterClick Here link with title attributeTouchClick here, link, this is a link title  
PassLink text replaced by aria-label attributeTouchThis is an aria label, link  
PassLink text replaced by aria-labelledby attributeTouchThis is an aria labelled by, link  
PassClick Here link with aria-describedby attributeTouchClick here, link, this is an aria described by  
BetterLayout table with single cellReadingThis is some text.Treated as a layout table.  
BetterLayout table with role=presentationReadingExample, Navigation. Links, Content.Table treated as layout table - not announced as table.  
BetterData table with role=tableReadingThis is some text. Table start, end.Treated as a data table.  
BetterData table with th cell headersReadingMorning, row header, column header, row 1 column 1, table start, 2 rows 2 columns. Afternoon, column header, row 1 column 2. Morning, free, row 2 column 1. Afternoon, busy, row 2 column 2, table end, end, end.Column headers are not read by the Read Screen gesture, but are read by the Read Item gesture.