On large devices you need to do a couple of things.
Hide the button properly
First make sure the button is display:none
, not visibility:hidden
or anything else or it will still show up in the accessibility tree.
The main (<main>
) problem
A modal should appear outside of your <main>
.
This is so you can add aria-hidden="true"
to the <main>
element when the modal is active, so as to stop people navigating outside of the modal on a screen reader. (Screen reader users use headings, links etc. to navigate a page so you can't just intercept the tab key.)
Now I come from a mobile first philosophy so I would say your markup should be mobile first. That means putting the modal outside of your <main>
as discussed earlier.
This obviously causes a huge problem on a desktop. You now have the content sat somewhere it shouldn't be.
Because of this you only really have two options here.
Option 1
Use JavaScript to reposition the modal content in a predefined placeholder <div>
.
So you keep your mobile first design, then use JavaScript to find the innerHTML
of your modal and move it into the body within your holder. Then delete the modal itself just to be sure.
While you are at it I would also delete the button, just in case someone resizes the screen to a mobile view, we don't want a button leading nowhere.
Alternatively don't delete the second content then people can resize the browser, just means a few extra DOM nodes (so as long as your modal content isn't over 100 DOM elements I would say do this.)
If you decide to keep the modal make sure that is also display: none
for the same reason as the button, we don't want people accidentally accessing it.
Option 2
Duplicate content.
I know, I know, duplicate content is just, urgh.
But sometimes you just have to put up with it if it is for the best.
By duplicating the content into a div from the start you do get a few advantages.
Advantages
- If the user resizes the screen you can just use CSS to switch between views.
- No need for JavaScript, great for if your site functions without JS or when your JavaScript fails.
- Although it adds page weight it is likely to be better for performance overall, the potential for layout shifts with the first option resulting in a high Cumulative Layout Shift is quite high (although avoidable). With Google putting so much emphasis on Web Vitals I would start considering them now. Additionally you might find you write nearly as much JavaScript as there is HTML if your modal only contains a couple of elements.
Disadvantages
- You would have extra page weight due to duplicated HTML.
- You may have to adjust scripts etc. to account for the second duplicate item (although this should be minor).
This would still be my preference, Keep It Simple! This is far more robust
Option 3 (for the future)
Client Hints are one way you could solve this, turning responsive design into a hybrid of mobile vs desktop and responsive.
When client hints has enough of a market share you could simply use the header to decide which version of the page to send from the initial request.
You could possibly implement this today if you are willing for 25% of users to see the mobile version of your information on desktop, depends how important the info is.
Other considerations
There are a few other things to consider that you haven't mentioned so I thought I would add for reference.
I already mentioned adding aria-hidden
to all elements outside of the modal when it is active.
To future proof your application use inert
on items outside of the modal. Support isn't great (none existent!), but every little helps and it is quite likely to get implemented!
You can polyfill it if you want but I don't think it has moved outside of the draft spec yet so we just use it as is.
Also add aria-modal="true"
to your modal.
I covered a lot of these points in a bit more detail in this answer if you want a bit more info.