dialog 요소가 가진 슈퍼 파워 알아보기


원문: 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 요소를 제공한다.

MDN 호환 데이터 (출처)

Dialog 요소에 대한 브라우저 지원 정보

image

접근성 있는 모달을 만드는 것은 항상 복잡하기 때문에 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() – 적절한 포커스 처리가 있는 절대 위치 dialog

dialog를 모달이 아닌 것으로 표시하려면 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와 여러 면에서 다르다.

모달 dialog는 position: fixed

모달을 검사하면 Safari와 Chromium이 dialog:-internal-modal 또는 dialog:-internal-modal-dialog를 통해 스타일을 제공하는 것을 알 수 있다.

모달 이미지

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 트리를 버블링한다. htmldiv와 그 내부에 있는 button이 존재하는 경우, div 요소에 클릭 핸들러를 연결하고 버튼 클릭에 반응할 수 있다.

Adam은 누군가가 배경 오버레이를 클릭할 때 이 이벤트 동작을 활용하고 dialog를 닫을 수 있다고 공유했다. 누군가 버튼이나 폼과 같은 dialog 요소 내부의 요소를 클릭하면 event.target.nodeName이 특정 노드 이름(BUTTON 또는 FORM)이 된다. 그러나 누군가 오버레이를 클릭하면 의사 요소가 dialog에 속하기 때문에 DIALOLG가 된다.

아래에서 작동 중인 멋진 트릭을 참조하자.

하지만 더 멋진 것들이 있다!

모달 dialog는 ESC를 통해 닫을 수 있다.

여기저기서 keypress 이벤트 핸들러를 추가할 필요가 없다는 것 외에는 더 이상 할 말이 없다. 🎉 또한, ESC를 눌러 dialog를 닫으면 cancel 이벤트가 발생한다.

모달 dialog는 다른 모든 항목에 액세스할 수 없게 만든다.

모달 dialog를 열면 더 이상 다른 요소를 클릭할 수 없으며 배경이 요소를 덮기 때문만은 아니다. TAB키를 누르면 다른 모든 대화형 요소에 액세스할 수 없다는 것도 알게 된다.

상호 작용할 수 있는 것은 열린 dialog 요소뿐이다!

inert 요소는 이론적으로 요소에 액세스할 수 없도록 만드는 방법을 제공 하지만 아직 이 속성을 구현하기 위한 브라우저 움직임은 없는 것 같다. (역주: 현재 브라우저에서 구현 중에 있습니다. Safari, Chrome, Firefox)

dialog – 웹 플랫폼에 대한 반가운 추가

필자는 웹 플랫폼에 들어가는 더 일반적인 UI 사용 사례를 보는 것을 좋아한다. 그리고 접근성 좋은 모달을 모달만 만드는 것은 CSS display 속성을 바꾸는 것 이상의 작업이 필요하기 때문에 dialog 요소는 더욱 환영받는다. 브라우저가 더 많은 기능을 제공할수록 모두에게 더 좋다.

이 dialog요소는 Interop 2022 initiative에도 포함되어 있다. 이 계획에서는 브라우저가 함께 협력하여 개발자가 더 쉽게 웹을 만들 수 있도록 만든다.

최근 브라우저의 모든 움직임을 보니 기분이 상쾌하다. 다음에 뭐가 나올지 너무 기대된다!

추가 읽을거리

dialog 요소에 대해 더 자세히 알고 싶다면 여기에 더 많은 리소스가 있다.

MDN 에서 HTMLDialogElement
Dialog 요소 소개
JavaScript dialog를 새 HTML dialog 요소로 바꾸기

조종현2022.05.18
Back to list