It doesn’t seem necessary that the screen reader says “Country name” before “Switzerland”, “Germany” or “India” every time, as they are obviously country names.
Repeating “Country name” all the time is going to become annoying at the end, as it doesn’t really bring any useful information. It’s enough if it is said just once.
I suggest something like the following HTML:
<table> <tr> <th scope="row">Country name</th> <th scope="col" id="switzerland">Switzerland</th> <th hscope="col" id="germany">Germany</th> <th scope="col" id="india">India</th> </tr> <tr> <td> </td> <td><input type="checkbox" aria-labelledby="switzerland" /></td> <td><input type="checkbox" aria-labelledby="germany" /></td> <td><input type="checkbox" aria-labelledby="india" /></td> </tr> . . . </table>
Notice the following:
- The “country name” header cell is scope=row, meaning that “Country name” will normally be said only once, when landing on the row for the first time
- “Switzerland”, “Germany” and “India” header celles are scope=col, meaning that they will be announced when landing on the corresponding column
- This is absolutely not a problem to have a th with scope=row in the same row as several th with scope=col, as it isn’t a problem conversely either
- Attribute aria-labelledby is set on the checkboxes in order to be sure that they are announced when reaching the checkboxes with tab. They shouldn’t be necessary, as the screen reader is smart enough to already announce the header celll while changing column, but just in doubt, it’s probably better to have them so we are sure that the checkboxes have an explicit accessible label. There is a small risk to get “Switzerland”, “Germany” and “India” announced twice every time, but since it’s short, it isn’t so dramatic
- It’s perfectly possible to reference several IDs in aria-labelledby and for example make “Country name” be announced each time, but note again how I didn’t do it because, as already said, “Country name” repeated all the time doesn’t bring any useful information