본문 바로가기
공부/프론트

[html/css/js] 모달 창 구현 방법 정리

by 웅대 2024. 3. 26.
728x90
반응형

이번 포스팅에서는 모달 창을 구현해보려고 한다.

 

이번 포스팅에서 우리가 구현할 모달 창의 기능들은 다음과 같다.

 

  1. 모달 창이 띄워지면 주변 화면이 어두워지면서 모달 창을 제외한 다른 요소들을 클릭할 수 없다.
  2. 모달 창 내부의 X 버튼을 눌러서 모달 창을 닫을 수 있다.
  3. 모달 창을 제외한 배경을 클릭해서 모달 창을 닫을 수 있다.
  4. 모달 창은 화면의 정중앙에 위치한다.

모달 창 구현

모달 창은 아래와 같이 간단하게 구현할 것이다.

 

 

html 코드는 다음과 같다.

    <div id="modal-wrapper" onclick="closeModal()">
    </div>    
    <div id="modal">
        <div id="header">
            <h1>모달 창</h1>
            <button onclick="closeModal()">X</button>
        </div>
        <div id="content">
            모달 창 내용
        </div>
    </div>

 

아이디가 modal-wrapper인 div 태그는 모달 창이 띄워졌을 때 주변 배경을 어둡게 만들기 위한 요소이다.

 

또한 모달 창을 닫기 위해 클릭하는 요소이기도 하다.

 

modal-wrapper의 형제 요소로 아이디가 modal인 요소가 있다.

 

이 요소가 우리가 보게 될 모달이다.

 

여기서 주의깊게 봐야하는 점은 modal-wrapper가 modal을 포함하고 있지 않다는 점이다.

 

 

만약 modal-wrapper가 modal을 포함하고 있다면 어떨까?

 

우리는 modal-wrapper, 즉 modal을 제외한 배경을 클릭했을 때 modal이 닫히게 만드려고 한다.

 

그런데 modal-wrapper가 modal을 포함하고 있다면 modal을 눌러도 modal-wrapper에 적용된 click 이벤트가 발생하게 된다.

 

이렇게 자식 요소를 눌러도 그 위의 요소들까지 모두 영향을 주는 것을 이벤트 버블링 (Event Bubbling)이라고 한다.

 

CSS

 

먼저 modal-wrapper의 css 코드부터 살펴보자.

 

#modal-wrapper{
    position: fixed;
    left: 0;
    top: 0;
    width: 100vw;
    height: 100vh;
    background-color : rgba(0,0,0,0.2);
    z-index: 1;
}

 

이 modal-wrapper는 모든 화면을 덮어야 하기 때문에 100vw, 100vh 값으로 화면의 크기에 맞게 꽉 차도록 만든다.

 

살짝 어둡게 만들기 위해 검은색에 투명도를 주었다.

 

z-index는 높을 수록 해당 요소가 높이 있다고 보면 된다.

 

z-index를 준 이유는 다른 요소들을 덮기 위함이다.

 

이 modal-wrapper보다 높이 있어야 하는 요소는 modal 하나 뿐이다.

 

다음은 modal css이다.

#modal{
    width: 200px;
    height: 300px;
    display: flex;
    flex-direction: column;   
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    z-index: 2;
}

 

display: flex로 주고 direction을 column으로 준 이유는 header와 content를 세로로 배치하기 위함이다.

 

우리가 만드려는 modal 창을 다시 보자.

그리고 모달 창을 화면 가운데에 정렬하기 위해 아래 코드를 넣어주었다.    

position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);

 

z-index 값은 modal-wrapper보다 큰 것을 확인할 수 있다.

 

다음은 hidden css이다.


.hidden{
    visibility: hidden;
}

 

위를 정의한 이유는 modal과 modal-wrapper에 클래스 이름을 추가하는 것으로 visibility를 조절하기 위함이다.

 

클래스 이름에 hidden이 붙으면 보이지 않고 hidden 사라지면 보이게 된다.

 

다음은 header css이다.

#header{
    width: 100%;
    height: 25%;
    position: relative;
    display: flex;
    justify-content: center;
    align-items: center;
    background-color: aqua;
}
#header button{
    position: absolute;
    right: 5px;
    top: 5px;
    bottom: 5px;
}

header를 다시 한 번 보자.

모달 이름이 중앙에 위치하고 그 옆에 버튼이 존재한다.

 

버튼의 위치가 모달 이름에 영향을 주지 않기 위해 부모 요소인 header의 position을 relative로 설정하고 button의 position을 absolute로 설정하였다.

 

우측에 위치시키기 위해 left를 제외한 3곳에 픽셀 값을 넣어주었다.

 

header 내부 요소인 h1 태그를 정중앙에 위치시키기 위해 flex 속성을 넣어주었다.

    display: flex;
    justify-content: center;
    align-items: center;

 

다음은 content css이다.

#content{
    width: 100%;
    height: 75%;
    display: flex;
    justify-content: center;
    align-items: center;
    background-color: red;
}

역시 내부 요소를 정중앙에 위치시키기 위해 flex 속성을 주었다.

 

modal 내부 요소가 modal에 꽉 차게 만들기 위해 width는 100%, height는 1:3 비율로 나누었다.

 

JS

이제 클릭 이벤트를 발생시키기 위해 js를 정의해보자.

    const wrapper = document.getElementById("modal-wrapper")
    const modal = document.getElementById("modal")
    function closeModal(){
        const wrapper = document.getElementById("modal-wrapper")
        const modal = document.getElementById("modal")
        wrapper.classList.add("hidden");
        modal.classList.add("hidden");
    }
    function openModal(){
        const wrapper = document.getElementById("modal-wrapper")
        const modal = document.getElementById("modal")
        wrapper.classList.remove("hidden");
        modal.classList.remove("hidden");

    }

 

위에서 html 코드를 다시보면 modal과 modal-wrapper에 onclick 이벤트가 정의되어있는 모습을 확인할 수 있다.

 

닫을 때는 클래스 이름에 hidden을 추가해서 visibility를 hidden으로 만들고 열 때는 클래스 이름에 hidden을 제거하여 보이게 만드는 모습을 확인할 수 있다.

 

이제 테스트를 해보자.

 

 

728x90
반응형

댓글