Why a dialog modal needs to be placed as last direct child of the body?[Accessibility, a11y]

Viewed 283

I am investigating how to build an accessible dialog modal in React.

I saw few sources suggesting to place the modal at the end of the DOM tree as direct child of the E.g: https://assortment.io/posts/accessible-modal-component-react-portals-part-1 (Look for the When rendered, the Modal is appended to the end of document.body.. section.)

My question is.. WHY? What benefit is this bringing? If I am not wrong, some of these sources meant that in this way the screen reader would ignore the other children of the body, so save the user from focusing on not desired elements.

If this is the reason, is this the suggested and only way of doing it? My idea was to simply "trap" the user inside the modal not allowing them to focus on anything else outside the modal. My idea was that if the user is on the first or last element of of the modal and is trying to go back or forward they will still be focusing on the first or last element of the modal. That using JS.

So, going back to the main question, why should I place the modal as a direct child of the DOM? Thank you!

1 Answers

Not necessarily a direct descendant, you just need to separate the modal from other content in order to hide all content when the modal is opened

Here is a detailed description of your situation: http://web-accessibility.carnegiemuseums.org/code/dialogs/

<body>
<!--    Add aria-hidden="true" if there is at least one pop-up window (Modal) -->
    <div class="page" aria-hidden="true">
        ...
    </div>
    <div class="dynamic-place">
        <div hidden role="dialog" aria-describedby="" aria-labelledby=""></div>
        <div hidden role="dialog" aria-describedby="" aria-labelledby=""></div>

        <!-- Only one active modal per page: -->
        <div role="dialog" aria-describedby="" aria-labelledby="">
            Active modal
        </div>
    </div>
</body>

but you can also do the following: to give all elements except the modal window aria-hidden=true, nobody forces you to wrap all content in a single block (as in the first example), this is just a suggestion that simplifies this task

<body>
    <div aria-hidden="true">
        ...
    </div>
    <main aria-hidden="true">
        ...
    </main>
    <footer aria-hidden="true">
        ...
    </footer>

    <div class="dynamic-place">
        <div hidden role="dialog" aria-describedby="" aria-labelledby=""></div>
        <div hidden role="dialog" aria-describedby="" aria-labelledby=""></div>

        <!-- Only one active modal (opened) per page: -->
        <div role="dialog" aria-describedby="" aria-labelledby="">
            Active modal
        </div>
    </div>
</body>
Related