Fixing the keyboard navigation order of radio buttons reversed by flex-direction

情到浓时终转凉″ 提交于 2021-01-29 09:34:31

问题


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

  1. 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).

  2. 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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!