다이얼로그 요소와 모달
dev | 2025-03-30
개인적으로는 alert
와 confirm
과 같은 시스템 모달을 좋아하지만 이걸 그대로 쓰는 제품은 거의 없다. 어떻게든 디자인 아이덴티티를 적용하기위해 기존의 HTML 요소로 비슷하게 만드는 방법을 사용한다. 보기는 좋지만 시스템에서 제공하는 접근성이나 인터랙션을 비슷한 수준으로 만드려면 노력을 많이 해야 한다. 이러한 어려움을 없애기 위해서 dialog
요소와 관련 API가 나왔다.
대화 상자를 의미하는 dialog
요소는 단독으로 사용하면 그다지 인상적이지 않다. 기본적으로 화면에 나오지 않고 open
속성을 줘야 화면에 나오게 된다. 사용한 위치에 마치 절대위치를 지정한 것 처럼 다른 콘텐츠를 덮는 사각 박스가 나온다. 좌우 정렬만 가운데로 된다.
<div style="background: #ccc; height: 3em;">위 박스</div>
<dialog open>
이게 바로 dialog
</dialog>
<div style="background: #ddd; height: 3em;">아래 박스</div>
다이얼로그를 동적으로 열고 닫으려면 show
또는 showModal
메서드를 사용하면 된다. show
는 다이얼로그를 보여주기만 하고 모달처럼 동작하지는 않는다. showModal
은 뒤 배경과의 인터랙션을 막아준다. 보통 딤(dim)이라고 하는 어두운 배경(backdrop)도 깔아준다. 닫을때는 close
를 사용한다.
<button onclick="document.getElementById('dialog-show-modal').showModal()">open modal dialog</button>
<dialog id="dialog-show-modal">
<button onclick="document.getElementById('dialog-show-modal').close()">close</button>
</dialog>
다이얼로그와 서식을 같이 사용하면 내재되어 있는 좀 더 풍부한 기능을 사용할 수 있다. 다이얼로그 안에 method
가 dialog
인 form
을 사용하면 그 안의 버튼을 닫기 버튼으로 사용할 수 있다. 닫는 버튼에 value
를 설정하면 그 값이 모달의 returnValue
로 설정이 되어서 버튼이 여러개 있어도 어느 버튼을 눌러서 닫았는지 파악할 수 있다. close
메서드에 스트링을 인자로 넘겨도 동일하게 returnValue
값을 설정할 수 있어서 사용자가 다이얼로그 안의 컨트롤에 설정한 값을 알 수 있다.
<button onclick="document.getElementById('dialog-with-form').showModal()">
open dialog with form
</button>
<dialog id="dialog-with-form">
<form method="dialog">
<button value="Banana">Banana</button>
<button value="Apple">Apple</button>
<button value="Tomato">Tomato</button>
</form>
</dialog>
<script>
document.getElementById('dialog-with-form').addEventListener('close', e => {
const output = document.getElementById('dialog-with-form-output');
output.innerHTML = e.target.returnValue;
});
</script>
<p>returnValue: <output id="dialog-with-form-output"></output></p>
returnValue:
다이얼로그가 열려 있을 때에는 배경 콘텐츠와 인터랙션이 되지 않는다. 다이얼로그를 열면 포커스가 다이얼로그로 왔다가 닫을때 다시 이전 콘텐츠로 이동하는 등 시스템에서 제공하는 접근성 기능을 공짜로 사용할 수 있다. ESC키를 눌러서 다이얼로그를 닫는 기능도 제공된다. 한가지 많이 아쉬운 점은 다이얼로그를 열었을 때 배경이 스크롤되는 동작을 막아주지는 않는다.
다이얼로그가 열릴 때 애니메이션을 적용하기 위해서는 조금 까다로운 작업을 해야 한다. 기본적으로 display: none
이나 block
으로 작동하고 상위 레이어에서 바로 없어지기 때문에 애니메이션을 적용하기가 힘들다. 결론부터 얘기 하자면 transition-behavior: allow-discrete
와 overlay
를 트랜지션 해주면 닫을때에도 애니메이션을 보여줄 수 있다. 이 속성이 아직 모든 브라우저에서 작동하지 않기 때문에 파이어폭스와 사파리에서는 애니메이션이 매끄럽게 나오지 않는다.
#dialog-styled,
#dialog-styled::backdrop {
transition: display 0.2s allow-discrete, overlay 0.2s allow-discrete;
animation: hide-modal 0.2s forwards;
}
#dialog-styled {
background: #fff;
border: 1px solid #ccc;
border-radius: 12px;
padding: 16px;
width: 24em;
box-shadow: 0 10px 25px rgba(0, 0, 0, 0.2);
}
#dialog-styled::backdrop {
background: rgba(0, 0, 0, 0.4);
}
#dialog-styled[open],
#dialog-styled[open]::backdrop {
animation: show-modal 0.2s forwards;
}
@keyframes show-modal {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
@keyframes hide-modal {
0% {
opacity: 1;
}
100% {
opacity: 0;
}
}
<button onclick="document.getElementById('dialog-styled').showModal()">open styled dialog</button>
<dialog id="dialog-styled">
<b>Styling and Animation for the dialog Element</b>
<p>The style is straightforward. The animation should use modern CSS features like allow-discrete and overlay.</p>
<button onclick="document.getElementById('dialog-styled').close()">close</button>
</dialog>
Comments