skip to Main Content

I’m trying to ensure that a button inside a Shadow DOM gets tab focus before a regular button in the main DOM. one button have tabindex="0", and the other one is 10 but the regular button outside the shadow is always focused first.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        button{
            padding: 1%;
            border-radius: 10px;
            width: 100px;
            height: 50px;   
            
        }
        button:focus {
        background-color: red;
        }

    </style>
</head>
<body>
      
        <div id="shdow">
            
        </div>

        <button  tabindex="10">focus me </button>


        <script>
            // set shadow root with button taindex 0
            document.querySelector('#shdow').attachShadow({mode: 'open'}).innerHTML = `
                <style>
        button{
            padding: 1%;
            border-radius: 10px;
            width: 100px;
            height: 50px;   
            
        }
        button:focus {
        background-color: green;
        }

    </style>
            <button tabindex="0">focus me </button>`;

        </script>

</body>
</html>

2

Answers


  1. Shadow DOM Button Integration: The button inside the Shadow DOM is included in a focusSequence array, along with the main document button.

    Custom Tabbing Logic:

    The keydown event listens for the Tab key.
    The currentIndex determines which element in focusSequence gets focus next.
    The default browser tabbing is disabled (event.preventDefault()).
    Focus Cycling: The focusSequence ensures that the Shadow DOM button is treated as part of the global focus order, giving it priority when cycling through focusable elements.

    Testing Steps:
    Load the page.
    Press the Tab key.
    The focus will first land on the Shadow DOM button, then the main DOM button.
    This approach directly manages focus order and should resolve any issues with Shadow DOM focus priority.

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Shadow DOM Focus</title>
        <style>
            button {
                padding: 1%;
                border-radius: 10px;
                width: 100px;
                height: 50px;
            }
            button:focus {
                background-color: red;
            }
        </style>
    </head>
    <body>
        <div id="shadow-container"></div>
        <button tabindex="10">Main DOM Button</button>
    
        <script>
            // Attach Shadow DOM and add the shadow button
            const shadowContainer = document.querySelector('#shadow-container');
            const shadowRoot = shadowContainer.attachShadow({ mode: 'open' });
            shadowRoot.innerHTML = `
                <style>
                    button {
                        padding: 1%;
                        border-radius: 10px;
                        width: 100px;
                        height: 50px;
                    }
                    button:focus {
                        background-color: green;
                    }
                </style>
                <button tabindex="0">Shadow DOM Button</button>
            `;
    
            const shadowButton = shadowRoot.querySelector('button');
            const mainButton = document.querySelector('button[tabindex="10"]');
    
            // Custom focus management
            let focusSequence = [shadowButton, mainButton];
            let currentIndex = 0;
    
            document.addEventListener('keydown', (event) => {
                if (event.key === 'Tab') {
                    // Prevent default tabbing behavior
                    event.preventDefault();
    
                    // Determine the next element to focus
                    currentIndex = (currentIndex + 1) % focusSequence.length;
                    focusSequence[currentIndex].focus();
                }
            });
        </script>
    </body>
    </html>
    
    Login or Signup to reply.
  2. That’s something known. You shouldn’t use tabindex with values other than 0 and -1.

    When there are naturally focusable elements without tabindex and elements having tabindex=0 mixed with elements having tabindex>0, then all the former ones get the focus after all the later ones, or the converse. The tab order quickly becomes uncontrollable.

    If you use somewhere tabindex>0, then all focusable elements must have tabindex>0 to make sure it remains consistent. Hence it’s very easy to completely break the tab order and accessibility.

    See
    https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/tabindex
    for more info: in particular, well note tabindex="0" means that the element should be focusable in sequential keyboard navigation, after any positive tabindex values. but in fact, it can be the opposite, have all tabindex>0 first and then all others.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search