[VanillaJS]모달 페이드 인/아웃 애니메이션

개굴맹꽁·2024년 6월 4일

개요

vanillaJS 과제 테스트 중 모달에 fade in/fade out 애니메이션을 적용하면서 겪은 문제와 해결 과정입니다.

0. 기본 모달 구현

<!--HTML해당 모달 부분을 간단하게 구현-->
<button class="button-open">모달 열기</button> 

<div class="modal">
  <div class="modal-content">
    <div>모달이달</div>
    <button class='button-close'>모달 닫기</button>
  </div>
</div>
.modal{
  position:fixed;
  top:0;
  bottom:0;
  left:0;
  right:0;
  background-color:rgba(0,0,0,.5);

}
.modal.hidden{
   visibility:hidden;
}
const $openButton=document.querySelector('.button-open');
const $closeButton=document.querySelector('.button-close');

const $modal=document.querySelector('.modal')
//'모달 엵기' 버튼을 click시 class 제거
$openButton.addEventListener('click', ()=>{
  $modal.classList.remove('hidden')  
})
//'모달 닫기'버튼을 click class 추가
$closeButton.addEventListener('click', ()=>{
  $modal.classList.add('hidden');
})


기본적인 모달 구현으로 닫힐 때는 안보이도록 visibility:hidden을 적용했습니다. 애니메이션 없이 바로 바로 사라지고 나타는 모달입니다.

1. fade 애니메이션 적용

처음에는 transition으로 opacity를 조절해서 서서히 사라지고, 나타나도록 적용했습니다.

.modal{
	...기존 코드...
 	/*추가된 부분 transition 과 opacity*/
 	transition: opacity 2s;
 	opacity:1;
}
.modal.hidden{
	visibility:hidden;
   /*추가된 부분*/
   opacity:0;
}


나타날 때는 서서히 나타나지만 사라질 때는 이전과 같이 한 번에 사라졌습니다.😭

CSS에서 visibility:hidden 과 opacity 애니메이션이 동시에 적용했고 해당 애니메이션이 다 보이기 전에 visibility: hidden으로 인해서 애니메이션을 볼 수 없는 문제였습니다. 이 문제를 해결하려면은 opacity 애니메이션이 모두 처리되고 visibility:hidden을 적용해야 합니다. 처음으로 생각하고 찾은 방식은 setTimeout을 통해서 transition duration 시간 이후에 visibility:hidden을 적용해 주는 방식을 생각하고 적용했습니다.

2. setTimeout 적용

.modal.hidden{
/*css에서는 opacity 관리*/
   opacity:0; 
}
const $openButton=document.querySelector('.button-open');
const $closeButton=document.querySelector('.button-close');

const $modal=document.querySelector('.modal')

$openButton.addEventListener('click', ()=>{
  $modal.classList.remove('hidden')  
   //js에서 직접 visibility를 적용해준다.
  $modal.style.visibility='visible';

})

$closeButton.addEventListener('click', ()=>{
  $modal.classList.add('hidden');
//setTimeout을 통해서 애니메이션이 끝나는 시간에 hidden이 적용되도록한다. 
  setTimeout(()=>{$modal.style.visibility='hidden'},2000);
  
})

js에서 '모달 닫기' 버튼이 click 된다면 class를 추가해서 애니메이션을 적용하고 setTimeout을 통해서 transition duration이 지나고 visibility:hidden을 적용 되도록 했다.

의도한 대로 fade out 애니메이션도 적용이 됐다. 🎉🎉
우선 setTimeout 방식으로 과제를 제출했으며 팀원들과 이야기를 나눈 결과 보통은 이런 방식으로 많이 구현한다고 했습니다. 하지만 이 방식은 transition duration과 setTimeout의 시간을 동시에 관리해야 하는 번거로움이 있습니다.

3. transitionend event 적용

팀원을 통해 transitionend 이벤트를 활용하는 방식을 알게 되었습니다. 이 이벤트를 사용하면 transition이 종료될 때 트리거되는 addEventListener를 만들 수 있습니다.

전환 종료 이벤트는 CSS transition이 완료되면 발생합니다.
MDN: transitionend event

const $openButton=document.querySelector('.button-open');
const $closeButton=document.querySelector('.button-close');

const $modal=document.querySelector('.modal')

$openButton.addEventListener('click', ()=>{
  $modal.classList.remove('hidden')  
  $modal.style.visibility='visible';
})

$closeButton.addEventListener('click', ()=>{
  $modal.classList.add('hidden');
  //이제 transition의 duration을 몰라도 된다.
})
//해당 이벤트리슨너를 추가해준다. transitionend 시 호출이 된다.
$modal.addEventListener('transitionend',(event)=>{
  //event.target==$modal
 // class="hidden"인 경우에만 visibility="hidden"을 적용해 준다. 
if(event.target.classList.contains('hidden'))event.target.style.visibility='hidden'
})

이제 페이드아웃 애니메이션 종료되면 자동으로 visibility:'hidden'이 적용된다. 그리고 transition duration을 몰라도 자동으로 적용이 되기 때문에 관리 측면에서도 더 좋은 것 같다.

0개의 댓글