问题
Context:
We have some cards that are radio buttons in a radio group, that we want to display in a different order for small and large breakpoints. I want to know if there is a way to do this nicely that doesn't involve duplicating the html for the different breakpoints, and doesn't break accessibility.
Desired large breakpoint:
|Large|Medium|Small|
Desired small breakpoint:
|Small|
|Medium|
|Large|
Desired accessibility behaviour:
With a radio group, you'd normally expect to hit tab
to get to the first option in the radio group, and then use the arrow keys to select different options.
What I've tried:
I've tried using display:flex
and changing flex-direction
to either row
or column-reverse
depending on the breakpoint. And then because flex is visual only, I have also put tabindex
onto the radio inputs. Although it fixes the tab behaviour, the arrow keys are the reverse of what you'd expect.
Super cut down example:
<html lang="en">
<head>
<meta charset="utf-8">
</head>
<body>
<p>Standard view:</p>
<div style="display:flex;">
<div>
<input type="radio" id="featured" name="tier2" value="featured" tabindex="1">
<label for="featured">Featured</label><br>
</div>
<div>
<input type="radio" id="standard" name="tier2" value="standard" tabindex="2">
<label for="standard">Standard</label><br>
</div>
<div>
<input type="radio" id="basic" name="tier2" value="basic" tabindex="3">
<label for="basic">Basic</label>
</div>
</div>
<p>Mobile view:</p>
<div style="display:flex; flex-direction:column-reverse">
<div>
<input type="radio" id="featured" name="tier" value="featured" tabindex="3">
<label for="featured">Featured</label><br>
</div>
<div>
<input type="radio" id="standard" name="tier" value="standard" tabindex="2">
<label for="standard">Standard</label><br>
</div>
<div>
<input type="radio" id="basic" name="tier" value="basic" tabindex="1">
<label for="basic">Basic</label>
</div>
</div>
</body>
</html>
Questions:
- Is there another attribute like
tabindex
that you can use to define the order the arrow keys work? - Is there any other way of doing this that doesn't involve duplicating html?
Thanks!
回答1:
Short Answer
Don't use tabindex, flex etc.
Instead serve the mobile version of the HTML and reorder the DOM order of your component using JavaScript on page load for larger screens.
Longer Answer
Is there another attribute like tabindex that you can use to define the order the arrow keys work?
No, sadly there isn't.
Also using tabindex
is a terrible idea as you will break logical tab order for the rest of your application. Avoid it at (nearly) all costs!
Is there any other way of doing this that doesn't involve duplicating html?
There is no clean way to do it without duplicating the HTML (that will work with all screen reader and browser combinations).
You do have a few options though
Reorder the HTML on the server - You could load the component via AJAX after querying the screen width. Decide which version to send based on the screen size (send the screen size to the server with the AJAX request).
Reorder the HTML on page load - I would start with your mobile layout as the base HTML (to minimise JS work on mobiles as they are less powerful). Then if the screen size is over your break point rearrange the items using JS on page load for larger screens.
The key to both is that DOM order is correct. It will save you a lot of headaches if you can somehow get your DOM order as you want it rather than trying to change it with CSS, tabindex
etc.
Both options do the same thing but both have pros and cons:-
Option 1 - Reorder the HTML on the server
Pro - the page will load faster and lazy loading the item in has performance benefits.
Pro - your HTML is clean and exactly what is required, it even gives the option for different lists entirely if you desire.
Pro - probably easier to maintain as you just have a raw HTML file to edit on the server (albeit 2 files, one for each view) and don't need to do mental gymnastics to work out reordering if the list grows longer.
Con - when you JavaScript fails the item will not load in at all
Con - an extra network call may actually end up slower, you would have to test. Yes this conflicts with the first "Pro" so you would have to test it!
Option 2 - Reorder the HTML on page load
Pro - By going mobile first it will not add anything other than maybe a KB of JavaScript to the page needed to reorder on desktop.
Pro - when your JavaScript fails the item will still render, it just might not be in the order you desire.
Con - As your list grows it may be harder to maintain the reordering.
Con - Despite the earlier "Pro" about JavaScript size, it is also a "con", you are still sending extra info down the wire and have to do a screen size check. Minor points but if performance is important something to consider.
What would I do?
If I had to do this I would probably go for option 2.
The main reason being that the tiny amount of JS is nothing compared to a full AJAX call and performance is key.
This is assuming the form is not "above the fold", in which case I would go for option 1 to avoid Cumulative Layout Shift, as that would annoy users seeing the list reorder while the page loads.
来源:https://stackoverflow.com/questions/64237695/fixing-the-keyboard-navigation-order-of-radio-buttons-reversed-by-flex-direction