웹 기능:
<dialog closedby>
최신 모달 대화상자는 '가벼운 닫기'를 지원하는 경우가 많으므로 사용자가 배경 (대화상자 외부 영역)을 클릭하거나 탭하여 대화상자를 닫을 수 있습니다. closedby 속성은 커스텀 JavaScript 없이 이 동작을 사용 설정하는 선언적 방법을 제공합니다.
구현
가벼운 닫기를 사용 설정하려면 다음 단계를 따르세요.
<dialog>요소에closedby="any"를 추가합니다.dialog.showModal()를 사용하여 대화상자를 엽니다.
속성 값
any: 가벼운 닫기 (배경 클릭), '닫기 요청'(Esc키), 개발자 메커니즘 (예:dialog.close())을 사용 설정합니다.closerequest: '요청 종료' 및 개발자 메커니즘만 사용 설정합니다. 이는 모달 대화상자의 기본값입니다.none: 개발자 메커니즘만 대화상자를 닫을 수 있습니다.
배경 스타일 지정
showModal()를 사용하여 대화상자를 모달로 열면 브라우저에서 ::backdrop 의사 요소를 생성합니다. 이 배경은 전체 표시 영역을 덮고 대화상자 바로 뒤에 있습니다.
/* Style the backdrop to indicate the dialog is modal */
dialog::backdrop {
background-color: rgba(0, 0, 0, 0.5);
backdrop-filter: blur(2px); /* Optional: add blur for modern browsers */
}
예
<!-- MANDATORY: Use closedby="any" to enable light-dismiss behavior -->
<dialog id="myDialog" closedby="any" aria-labelledby="dialogTitle">
<form method="dialog">
<h2 id="dialogTitle">Feedback</h2>
<p>Click outside this box or press Esc to dismiss.</p>
<button type="submit">Close</button>
</form>
</dialog>
<button onclick="document.getElementById('myDialog').showModal()">Open Dialog</button>
제약 조건 및 접근성
- 필수:
closedby="any"를 사용하여 선언적으로 가벼운 닫기를 사용 설정합니다. - 필수: 항상
showModal()를 사용하여 모달 대화상자를 엽니다. 이렇게 하면 대화상자가 최상위 레이어에 있고 포커스가 트랩되며Esc키가 처리됩니다. - 권장사항:
aria-labelledby또는aria-label를 사용하여 대화상자에 액세스 가능한 이름을 제공합니다. - 금지사항: 비모달 대화상자(
show()로 열림)에는closedby를 사용하지 마세요. 배경이 없고 라이트 닫기를 트리거하지 않기 때문입니다. - 금지사항: 닫기 전에 실행되어야 하는 중요한 로직에
click이벤트를 사용하지 마세요. 대신close또는cancel이벤트를 수신 대기하세요.
대체 전략
필수: 아직 closedby를 지원하지 않는 브라우저의 경우 다음 스크립트를 사용하여 대화상자 콘텐츠 경계 외부에서 클릭이 발생했는지 확인하여 가벼운 닫기의 대체 기능을 구현해야 합니다.
const dialog = document.querySelector('dialog');
// Fallback for browsers without closedby support
if (!('closedBy' in HTMLDialogElement.prototype)) {
dialog.addEventListener('click', (event) => {
// 1. When clicking the backdrop, the event target is the dialog element itself.
// Ignore clicks where the target is a child element inside the dialog.
if (event.target !== dialog) return;
// 2. Check if the click coordinates fall within the dialog's content box.
// This distinguishes between a click on the backdrop vs a click on the dialog's background/padding.
const rect = dialog.getBoundingClientRect();
const isDialogContent = (
rect.top <= event.clientY &&
event.clientY <= rect.top + rect.height &&
rect.left <= event.clientX &&
event.clientX <= rect.left + rect.width
);
if (isDialogContent) return;
// 3. Since the click was outside the content area (on the backdrop), manually close the dialog.
dialog.close();
});
}