I spent last night making a quiz usable with a keyboard and a screen reader. It is a nine-question drill with four options per question, a live score, and a result screen. None of it is exotic, and three things broke in ways that are worth writing down.
1. The details/summary block is not a button
I moved a chunk of questions into details / summary blocks so they would be in the initial HTML and still collapsed for a human reader.
Inside the summary I had a "Show answer" label next to the question text. VoiceOver read the whole summary as one blob, including the label, which made the question unlistenable. The fix is boring: keep the summary to the question text only, and let the disclosure triangle do the announcing. Screen readers already say "collapsed" and "expanded", and my label was fighting the platform.
The second thing: details is not focusable by default in every browser I tested, and Safari behaves differently from Chrome when the element is inside a list. Rather than patch it with tabindex, I left it as a plain disclosure and made sure the answer text itself contained no interactive elements. An answer that is pure text has no focus trap to get wrong.
2. Radio inputs beat buttons, and it is not close
My first version made each option a button. It looks like the right call because you want a click handler and you want to style it. It is the wrong call:
- A radio group gives arrow-key navigation, roving tabindex and the "1 of 4" position announcement for free.
- A
fieldsetwith alegendgives the group a name, so the screen reader says the question before the options. - A list of buttons gives the user four separate stops and no idea where they are in the set.
I kept the visual design and swapped the element. The markup went from four focusable buttons to one focusable radio group.
3. Announcing the score without interrupting
The score updates on every answer. The naive fix is an assertive live region, which means a screen reader user gets cut off mid-question every time they pick an option.
What worked:
- polite (not assertive) live region on the score only, never on the feedback text
- do not update the live region on page load, only on change, or the reader announces "0 of 0" before the user has done anything
- keep the live region in the DOM from the start and empty, rather than inserting it; a region that appears together with its content is announced inconsistently across screen readers
The feedback text after an answer is the interesting case. It is long, it matters, and it must not be a live region because it will talk over the next question. The pattern that worked was to move focus to the feedback container after submission, so the user chooses when to read it and the question stays in the reading order behind them.
What I would check first on any quiz
- Can you answer every question with the keyboard alone, and do you always know which option is selected?
- Does the answer feedback interrupt the question?
- Does the score region announce on load?
Those three cover most of the real failures. The rest is contrast and font size, which are easier to see and easier to fix.
The quiz this came from is a ServSafe Manager trainer, but the markup problems are the same ones any four-option quiz has: https://foodsafeprep.com/
Top comments (0)