Modale Accessibile con Focus Trap
by murgiaMarco
HTML
<button id="openModal">Apri Modale</button>
<div class="overlay" id="overlay">
<div class="modal" role="dialog" aria-modal="true" aria-labelledby="modalTitle" aria-describedby="modalDesc">
<h2 id="modalTitle">Titolo Modale</h2>
<p id="modalDesc">Questa è una modale accessibile con trap del focus.</p>
<button id="closeModal">Chiudi</button>
</div>
</div>
CSS
body {
font-family: Arial, sans-serif;
margin: 0;
padding: 20px;
}
.overlay {
position: fixed;
top: 0; left: 0;
width: 100%; height: 100%;
background: rgba(0,0,0,0.5);
display: none;
align-items: center;
justify-content: center;
}
.modal {
background: #fff;
padding: 20px;
border-radius: 8px;
width: 300px;
max-width: 90%;
box-shadow: 0 2px 8px rgba(0,0,0,0.3);
}
.modal h2 {
margin-top: 0;
}
.modal button {
margin-top: 15px;
padding: 10px;
background: #0078d7;
color: #fff;
border: none;
border-radius: 4px;
cursor: pointer;
}
.modal button:hover {
background: #005fa3;
}
JavaScript
const openBtn = document.getElementById('openModal');
const closeBtn = document.getElementById('closeModal');
const overlay = document.getElementById('overlay');
const modal = overlay.querySelector('.modal');
let lastFocusedElement = null;
// Funzione per aprire la modale
openBtn.addEventListener('click', () => {
lastFocusedElement = document.activeElement;
overlay.style.display = 'flex';
modal.setAttribute('tabindex', '-1');
modal.focus();
trapFocus(modal);
});
// Funzione per chiudere la modale
function closeModal() {
overlay.style.display = 'none';
lastFocusedElement.focus();
}
closeBtn.addEventListener('click', closeModal);
// Chiudi con ESC
document.addEventListener('keydown', (e) => {
if (e.key === 'Escape' && overlay.style.display === 'flex') {
closeModal();
}
});
// Trap del focus
function trapFocus(element) {
const focusableSelectors = 'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])';
const focusableElements = element.querySelectorAll(focusableSelectors);
const firstEl = focusableElements[0];
const lastEl = focusableElements[focusableElements.length - 1];
document.addEventListener('keydown', function(e) {
if (overlay.style.display !== 'flex') return;
if (e.key === 'Tab') {
if (e.shiftKey) {
// SHIFT + TAB
if (document.activeElement === firstEl) {
e.preventDefault();
lastEl.focus();
}
} else {
// TAB normale
if (document.activeElement === lastEl) {
e.preventDefault();
firstEl.focus();
}
}
...