원문: Stefan Judis, https://www.stefanjudis.com/blog/a-look-at-the-dialog-elements-super-powers
오래전, 2014년에 dialog
요소가 Chromium 37
에 등장했다. 이 HTML 요소는 모달, 다이얼로그와 팝업을 쉽게 생성하기 위해 만들어졌다.
dialog
요소는 사용자가 작업을 수행하기 위해 상호 작용하는 응용 프로그램(예: dialog, inspector 또는 window)의 일부를 나타낸다.
지금은 2022년이고 dialog
요소를 거의 사용할 수 있게 되었다! 🎉 3월에 Safari (Safari 릴리스 정보) 및 Firefox (Firefox 릴리스 정보) 를 시작으로 기능 배포가 누락된 두 브라우저 모두 오랫동안 Chromium (15.498
) 에 포함되었던 dialog 요소를 제공한다.
Dialog 요소에 대한 브라우저 지원 정보
접근성 있는 모달을 만드는 것은 항상 복잡하기 때문에 Firefox와 Safari에서 이 요소를 제공하는 것은 접근성 측면에서 아주 좋은 일이다. 모달 접근성에 대해 자세히 알아보려면 Scott O'Hara의 "Having an open dialog" 기사를 읽어보자.
필자는 이 새로운 dialog를 만드는 방법을 가지고 놀아보았고, 모달이 아닌 dialog와 모달인 dialog를 구별할 뿐만 아니라 제대로 구현하기 어려운 모달 기능도 함께 제공된다는 것을 발견했다.
자 이제 dialog 요소의 슈퍼 파워를 살펴보자!
dialog
요소의 기본시작하기 위해 요소를 페이지에 넣은 뒤에 찾아보면...
... 당신은 아무것도 볼 수 없다. 브라우저들은 유저 에이전트 스타일에 다음의 CSS를 포함한다.
dialog:not([open]) {
display: none;
}
dialog
요소는 기본적으로 숨겨져 있으며 표시 여부는 현재 open
속성에 따라 달라진다. HTML에 추가하자!
그리고 이제 dialog 요소가 보인다!
일반적으로 JavaScript를 통해 dialog 요소를 열지만, 폼 제출 후 페이지를 서버 렌더링하면 HTML로 모달을 정의하는 것이 페이지가 로드된 후 모달을 표시하는 것에 합리적일 수 있다.
이제 JavaScript를 통해 open
속성을 수정하여 dialog를 표시할 수 있지만 여기서 잠깐! dialog 요소는 동적 상호 작용을 위한 두 가지 추가 메소드를 제공한다.
show()
– 적절한 포커스 처리가 있는 절대 위치 dialogdialog를 모달이 아닌 것으로 표시하려면 DOM에서 dialog
요소에 접근하고 요소의 show
메소드를 호출한다.
const dialog = document.querySelector('dialog');
dialog.show();
// dialog를 닫기 위해 `close`를 사용하자
dialog.close();
아래에서 실제로 확인해보자.
이 기능이 단순한 요소 표시 토글처럼 보이지만 더 많은 일이 진행 중이다. 🎉
show
메소드는 open
속성을 dialog 요소에 추가하고 요소는 유저 에이전트 스타일에 따라 절대 위치에 배치되며 닫기 버튼은 자동으로 포커스된다.
:focus-visible를 사용하기 때문에 필자의 사이트에서 마우스로 트리거 된 포커스 상태를 볼 수 없다. 포커스 아웃라인을 보려면 키보드로 포커스를 맞추고 "Dialog 열기" 버튼을 눌러라.
그러나 브라우저는 사용자가 모달을 열 때 포커스를 모달로 옮기는 것만 하지 않는다. dialog.close()
로 모달을 닫으면 포커스가 이전에 포커스를 맞춘 요소로 다시 이동한다. 이는 접근성 및 키보드 사용성에 있어 매우 편리하고 매우 가치가 있다.
Dialog의 포커스 로직에 대해 자세히 알아보려면 사양을 확인하자. 경고: 사양의 이 부분은 파악하기 쉽지 않으며 설명된 포커스 동작을 변경하기 위한 논의도 진행 중이다.
(역자: 위 논의는 합의되었지만, 이슈 마지막에 해결되지 않은 다양한 이슈들이 존재하니 확인해보길 바란다.)
이러한 기능은 모달이 아닌 팝업을 만드는 데 유용하지만 기존의 전체 페이지를 덮는 모달은 어떨까? 모달 페이지 오버레이는 어떻게 만들고 사용자가 열린 dialog의 외부에서 버튼이나 링크를 클릭하지 못하게 할 수 있을까?
showModal
이 모든 기능을 제공한다!
showModal()
– 일부 슈퍼 파워가 있는 고정 위치 dialog다른 모든 페이지 콘텐츠를 포함하는 모달 dialog를 만들려면 이 showModal
메소드를 사용하자.
const dialog = document.querySelector('dialog');
dialog.showModal();
// to close the dialog use `close`
dialog.close();
아래 버튼을 클릭하여 작동하는 모습을 확인해보자.
showModal
메소드는 show
와 여러 면에서 다르다.
position: fixed
모달을 검사하면 Safari와 Chromium이 dialog:-internal-modal
또는 dialog:-internal-modal-dialog
를 통해 스타일을 제공하는 것을 알 수 있다.
Dialog 요소는 이제 고정된 위치에 있으며 화면에 렌더링된 모든 항목을 포함한다.
::backdrop
의사 요소를 제공한다.이에 더해 dialog 요소는 showModal
을 통해 열릴 때 ::backdrop
오버레이 의사 요소와 함께 제공된다.
/* 크롬 유저 에이전트 스타일에 포함된다. */
dialog::backdrop {
position: fixed;
top: 0px;
right: 0px;
bottom: 0px;
left: 0px;
background: rgba(0, 0, 0, 0.1);
}
불행히도 Chromium이나 Safari는 아직 요소 패널에 ::backdrop
의사 요소를 표시하지 않는다.
::backdrop
클릭 시 모달을 닫는 방법사람들이 지적하는 것 중 가장 중요한 것은 배경을 클릭할 때 dialog가 자동으로 닫히지 않는다는 것이다. 필자는 이 기능을 스펙에 넣는 것이 가치 있다고 주장하고 싶지만 그렇게 하지 않는 데에는 충분한 이유가 있다고 확신한다.
운 좋게도 dialog 요소에 클릭 핸들러를 추가하고 이벤트 버블링 같은 특성을 사용하여 이 문제를 해결할 수 있다.
dialog.addEventListener('click', (event) => {
if (event.target.nodeName === 'DIALOG') {
dialog.close();
}
});
클릭 이벤트는 DOM 트리를 버블링한다. html
에 div
와 그 내부에 있는 button
이 존재하는 경우, div
요소에 클릭 핸들러를 연결하고 버튼 클릭에 반응할 수 있다.
Adam은 누군가가 배경 오버레이를 클릭할 때 이 이벤트 동작을 활용하고 dialog를 닫을 수 있다고 공유했다. 누군가 버튼이나 폼과 같은 dialog 요소 내부의 요소를 클릭하면 event.target.nodeName
이 특정 노드 이름(BUTTON
또는 FORM
)이 된다. 그러나 누군가 오버레이를 클릭하면 의사 요소가 dialog에 속하기 때문에 DIALOLG
가 된다.
아래에서 작동 중인 멋진 트릭을 참조하자.
하지만 더 멋진 것들이 있다!
ESC
를 통해 닫을 수 있다.여기저기서 keypress 이벤트 핸들러를 추가할 필요가 없다는 것 외에는 더 이상 할 말이 없다. 🎉 또한, ESC
를 눌러 dialog를 닫으면 cancel
이벤트가 발생한다.
모달 dialog를 열면 더 이상 다른 요소를 클릭할 수 없으며 배경이 요소를 덮기 때문만은 아니다. TAB
키를 누르면 다른 모든 대화형 요소에 액세스할 수 없다는 것도 알게 된다.
상호 작용할 수 있는 것은 열린 dialog 요소뿐이다!
inert
요소는 이론적으로 요소에 액세스할 수 없도록 만드는 방법을 제공
하지만 아직 이 속성을 구현하기 위한 브라우저 움직임은 없는 것 같다. (역주: 현재 브라우저에서 구현 중에 있습니다. Safari, Chrome, Firefox)
dialog
– 웹 플랫폼에 대한 반가운 추가필자는 웹 플랫폼에 들어가는 더 일반적인 UI 사용 사례를 보는 것을 좋아한다. 그리고 접근성 좋은 모달을 모달만 만드는 것은 CSS display
속성을 바꾸는 것 이상의 작업이 필요하기 때문에 dialog
요소는 더욱 환영받는다. 브라우저가 더 많은 기능을 제공할수록 모두에게 더 좋다.
이 dialog요소는 Interop 2022 initiative
에도 포함되어 있다. 이 계획에서는 브라우저가 함께 협력하여 개발자가 더 쉽게 웹을 만들 수 있도록 만든다.
최근 브라우저의 모든 움직임을 보니 기분이 상쾌하다. 다음에 뭐가 나올지 너무 기대된다!
dialog 요소에 대해 더 자세히 알고 싶다면 여기에 더 많은 리소스가 있다.
MDN 에서 HTMLDialogElement
Dialog 요소 소개
JavaScript dialog를 새 HTML dialog 요소로 바꾸기