다이얼로그 요소와 모달

dev | 2025-03-30

개인적으로는 alertconfirm과 같은 시스템 모달을 좋아하지만 이걸 그대로 쓰는 제품은 거의 없다. 어떻게든 디자인 아이덴티티를 적용하기위해 기존의 HTML 요소로 비슷하게 만드는 방법을 사용한다. 보기는 좋지만 시스템에서 제공하는 접근성이나 인터랙션을 비슷한 수준으로 만드려면 노력을 많이 해야 한다. 이러한 어려움을 없애기 위해서 dialog 요소와 관련 API가 나왔다.

대화 상자를 의미하는 dialog 요소는 단독으로 사용하면 그다지 인상적이지 않다. 기본적으로 화면에 나오지 않고 open 속성을 줘야 화면에 나오게 된다. 사용한 위치에 마치 절대위치를 지정한 것 처럼 다른 콘텐츠를 덮는 사각 박스가 나온다. 좌우 정렬만 가운데로 된다.

<div style="background: #ccc; height: 3em;">위 박스</div>

<dialog open>
	이게 바로 dialog
</dialog>

<div style="background: #ddd; height: 3em;">아래 박스</div>
위 박스
이게 바로 dialog
아래 박스

다이얼로그를 동적으로 열고 닫으려면 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>

다이얼로그와 서식을 같이 사용하면 내재되어 있는 좀 더 풍부한 기능을 사용할 수 있다. 다이얼로그 안에 methoddialogform을 사용하면 그 안의 버튼을 닫기 버튼으로 사용할 수 있다. 닫는 버튼에 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-discreteoverlay를 트랜지션 해주면 닫을때에도 애니메이션을 보여줄 수 있다. 이 속성이 아직 모든 브라우저에서 작동하지 않기 때문에 파이어폭스와 사파리에서는 애니메이션이 매끄럽게 나오지 않는다.

#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>
Styling and Animation for the dialog Element

The style is straightforward. The animation should use modern CSS features like allow-discrete and overlay.

Comments

Post a comment

:

: 공개 되지 않습니다. Gravatar를 표시 합니다.

:

: HTML 태그를 사용할 수 없습니다.