dialog 태그 사용하기
By Sera on
2022년 하반기부터 모든 브라우저에서 dialog
를 지원하게 되었다.
dialog는 js를 통해 조작해야 하며 아래의 인스턴스 메소드를 상속한다.
- open() : boolean으로 사용 여부를 나타냄
- returnValue() : 반환값을 설정/반환하는 문자열
- close() : 선택적 문자열을 인수로 전달하여 returnValue를 업데이트 함
- show() : 대화 상자 모델을 불필요하게 표시, 대화상자 밖의 내용과 상호작용을 계속 허용함
- showModal() : 존재할 수 있는 다른 대화 상자 위에 대화 상자를 모달로 표시합니다. 대화 외부의 모든 것은 대화 외부의 상호 작용이 차단되어 비활성화됩니다.
버튼을 누르면 대화창이 나옵니다.
결과 값 :
section {
max-width: 300px;
margin: 0 auto;
border: 1px solid #ccc;
padding: 1rem;
}
:modal {
/*:modal은 모달 상태의 대화상자 박스에 대한 선택자이다. 비모달 대화상자는 dialog 태그 선택자로 정의가 가능하다. */
border: none;
padding: 0;
}
:modal form {
/* 모달 안에 있는 서식 컨테이너를 grid로 만들겁니다. 3개의 행을 가지며, 각 행은, header, body, bottom 영역으로 나뉩니다.*/
display: grid;
grid-template-rows: auto 1fr auto;
}
:modal form > * {
/* 서식 컨테이너 바로 아래에 있을 각 row에 padding 여백을 주어서 보기 시원한 디자인을 만듭니다. */
box-sizing: border-box;
padding: 0.5em;
}
:modal .header {
/* header에는 display를 flex로 주고, 안에 있는 모든 내용이 옆으로 달라붙도록 합니다. */
display: flex;
}
:modal .header > .tit {
flex: 1; /*class="tit"은 타이틀 텍스트 요소입니다. flex:1;을 주면, 이 요소가 주변 요소가 있는 자리를 침범하지 않고 .header의 대부분을 차지합니다. */
}
:modal .body {
min-height: 150px; /* 최소 세로 넓이를 150픽셀로 줘서 너무 작은 대화상자가 나오는 것을 방지합니다. */
}
:modal .bottom {
display: flex;
justify-content: end; /* bottom 영역 역시 display:flex;를 줘서 가로로 정렬되게 합니다. bottom에는 대화상자 내에 있는 버튼을 넣을겁니다. 오른쪽에 버튼이 나타나길 원하니, justify-content를 end로 줍니다.*/
}
:modal button {
/* 버튼 스타일을 무력화합니다. */
appearance: none;
border: none;
background-color: transparent;
font-weight: bold;
}
:modal #negative.default {
/* 부정적인 답변에 대한 버튼이 .default이면 부정답변 버튼의 텍스트를 빨강색으로 표시 */
color: red;
}
:modal #postive.default {
/* 긍정적인 답변에 대한 버튼이 .default면 긍정 답변 버튼의 텍스트를 파란색으로 표시*/
color: #2264ff;
}
<section>
<h3>버튼을 누르면 대화창이 나옵니다.</h3>
<button id="btnOpen" aria-haspopup="dialog">버튼 😋</button>
<p>결과 값 : <span id="message" aria-live="assertive"></span></p>
</section>
<dialog id="myDialog" aria-labelledby="wyn_title" aria-describedby="wyn_desc">
<!--대화상자를 만듭니다. 대화상자에 스크린리더가 접근하면, 대화상자 타이틀과 메시지를 안내하도록 aria-labelledby와 describedby를 활용해 줍니다.-->
<form method="dialog">
<!--form의 새로운 method, dialog값은 대화상자 내에서 form이 전송되었을 때에 대한 동작을 얘기합니다.-->
<div class="header">
<strong id="wyn_title" class="tit">선호하는 색 조사</strong
><button id="btnClose" aria-label="close" value="cancel">X</button>
</div>
<!--제목 표시줄과 닫기 버튼입니다.-->
<div class="body">
<!--대화상자 내부에 표시될 질문 내용입니다.-->
<p id="wyn_desc">안녕? 😋 다음 질문에 답을 해줘.</p>
<div>
<label for="typeName">
좋아하는 색이 뭐야?
<input type="text" name="typeName" id="typeName" autofocus />.
</label>
</div>
</div>
<div class="bottom">
<button id="negative" name="negative" type="submit" value="negative">
나중에
</button>
<button
class="default"
name="postive"
type="submit"
id="postive"
value="postive"
>
확인
</button>
</div>
</form>
</dialog>
const dialog = document.querySelector("dialog#myDialog");
const message = document.querySelector("#message");
const [btnOpen, btnClose, typeName] = [
document.querySelector("#btnOpen"),
document.querySelector("#btnClose"),
document.querySelector("#typeName"),
];
// HTMLDialogElement.show()로 열면 비모달 대화상자, HTMLDialogElement.showModal()로 열면 모달 대화상자가 열림. show()함수에 showModal() 메소드가 사용됨
btnOpen.addEventListener("click", () => dialog.showModal());
// X 버튼을 눌러 닫으면
btnClose.addEventListener("click", () => dialog.close());
// 편집창 값 바뀔 때 긍정 버튼의 value 속성을 바꿔서 반환시킨다.
typeName.addEventListener("keydown", (evt) => {
if (evt.code === "Enter") {
// evt.code의 반환값이 "Enter" 스트링이면,
evt.preventDefault(); //preventDefault로 기본 키 동작을 무시
dialog.querySelector(".default").click(); // Enter가 눌리면 dialog의 기본 응답 동작을 무시하고, default 클래스가 부여된 버튼이 눌리도록함.
}
});
// dialog가 닫혔을 때에 대한 Event
dialog.addEventListener("close", () => {
switch (dialog.returnValue) {
case "cancel":
return false;
case "negative":
message.innerHTML = "왜쥬? 지금 답해요";
break;
case "postive":
dialog.returnValue = typeName.value;
if (dialog.returnValue) {
message.innerHTML = `난, ${dialog.returnValue} 좋아효❤`;
} else {
message.innerHTML = "비어있습니다. 다시 입력하세요.";
}
break;
}
});
참고자료 | MDN web docs, NULI |