본문 바로가기
WEB Basic/HTML & CSS

HTML, CSS, JavaScript로 인터렉티브한 모달 구현하기 (with transition)

by Devinus 2024. 1. 20.

1. 구현 결과 미리보기

Basic Modal

2. 분석

웹 페이지에서 모달 창은 사용자에게 추가 정보를 제공하거나 특정 작업을 수행할 수 있는 효과적인 방법 중 하나입니다. 이번 글에서는 HTML, CSS, JavaScript를 활용하여 인터렉티브한 모달 창을 구현하고 부드러운 애니메이션 효과를 적용하는 방법을 살펴보겠습니다.

인터렉티브한 모달의 필요성

  1. UI/UX 개선을 통한 사용자 상호작용 강화:
    모달 창은 특정 작업이나 추가 정보를 제공할 때 현재 화면을 가리지 않으면서 사용자와의 상호작용을 강화합니다. 이는 사용자에게 흐름을 방해하지 않으면서 필요한 정보를 제공하는 좋은 방법입니다. 
  2. 집중력 유지 및 작업 단순화:
    모달 창은 주로 컨텍스트 내에서 중요한 정보를 제공하는 데 사용됩니다. 화면을 전환하지 않고 모달을 통해 정보를 표시하면 사용자의 집중력을 유지하면서 작업을 단순화할 수 있습니다. 
  3. 컴포넌트 재활용을 통한 개발 효율성 향상:
    모달 창은 개별적으로 구현하여 컴포넌트로 만들어 두면 필요한 곳에서 쉽게 재사용할 수 있습니다. 이는 개발 효율성을 향상시키고 일관된 UI를 유지하는 데 도움이 됩니다. 
  4. 상태 및 액션 처리의 명확한 표현:
    모달 창은 특정 상태나 액션에 대한 응답으로 나타낼 수 있습니다. 사용자에게 명확한 피드백을 제공함으로써 어떤 동작이 이루어지고 있는지를 시각적으로 표현할 수 있습니다. 
  5. 유연한 디자인 패턴 적용:
    모달은 유연한 디자인 패턴을 제공합니다. 다양한 컨텍스트에서 적용 가능하며, 디자인 시스템에 통합하여 일관성 있게 사용할 수 있습니다. 이는 전반적인 UI/UX의 일관성을 유지하면서도 다양한 상황에 대응할 수 있음을 의미합니다.

기능 구현 방법

기본적으로 모달은 전체 페이지를 감싸는 컨테이너, 실제 정보를 제공하는 컨텐츠, 모달 창을 닫기 위한 닫기 버튼 으로 구성됩니다.

그리고 해당 모달을 열기 위한 열기 버튼을 따로 만듭니다.

따라서 html 골격은 다음과 같이 구성합니다.

<!-- 모달 열기 버튼 -->
<button id="modalBtn">모달 열기</button>

<!-- 모달 컨테이너 -->
<div id="myModal" class="modal">
  <!-- 모달 컨텐츠 -->
  <div class="modal-content">
    <!-- 모달 닫기 버튼 -->
    <span class="close" id="closeBtn">&times;</span>
    <p>모달 내용이 여기에 들어갑니다.</p>
    <p>
      사용자가 원하는대로 해당 엘리먼트 부분을 수정하여 사용할 수 있습니다.
    </p>
  </div>
</div>

 

위와 같은 HTML구조에 맞춰서 CSS를 작성하면 되는데, 다음 세 가지 방법으로 모달을 풀스크린으로 감싸며,

  • 컨테이너가 전체 페이지를 감싸는 방법
.modal {
    /* 컨테이너가 화면 전체를 덮게하는 코드 */
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
}
  • 컨텐츠를 중앙에 오게 하는 방법
.modal {
    /* 컨텐츠를 중앙에 오게하는 코드 */
    display: flex;
    justify-content: center;
    align-items: center;
}
  • 트랜지션이 발생하게 하는 방법 (ex; 서서히 나타나기)
.modal {
    /* 트랜지션 효과 */
    transition: opacity 0.3s ease-in-out;
    opacity: 0;
}
.modal.show {
    /* 모달이 열렸을 때 보여지게 하는 코드 */
    opacity: 1;
    pointer-events: auto;
}
  • 화면 사이즈가 달라지더라도 온전한 콘텐츠 보여주는 방법
.modal-content {
    /* PC일땐 width가 500px이다가, 
    모바일 기기일 때(화면 width가 500px 이하로 내려갔을 떄) 
    화면 크기에 맞춰서 줄어들게 하는 코드 */
    max-width: 500px;
    width: 100%;
}

 

 

설명한 코어 개념들을 바탕으로 구현한 코드는 아래에 있습니다.

해당 코드는 사용자 경험을 향상시키고, 효율적이며 트랜지션을 통해 인터렉티브한 모달 창을 구현한 예시입니다.

커스터마이징을 원한다면 코어 개념들을 제외한 스타일에 대해서는 본인의 입맛에 맞게 커스터마이징할 수 있도록 설계되어 있습니다.

 

3. 구현

3.1. HTML

<!-- 모달 버튼 -->
<button id="modalBtn">모달 열기</button>

<!-- 모달 창 -->
<div id="myModal" class="modal">
  <div class="modal-content">
    <span class="close" id="closeBtn">&times;</span>
    <p>모달 내용이 여기에 들어갑니다.</p>
    <p>
      사용자가 원하는대로 해당 엘리먼트 부분을 수정하여 사용할 수 있습니다.
    </p>
  </div>
</div>

3.2. CSS

* {
  box-sizing: border-box;
}

.modal {
  /* 스타일 - customize */
  background-color: rgba(0, 0, 0, 0.7);
  pointer-events: none;
  padding: 20px;

  /* 트랜지션 효과 */
  transition: opacity 0.3s ease-in-out;
  opacity: 0;

  /* 화면 전체를 덮게하는 코드 */
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;

  /* 중앙에 오게하는 코드 */
  display: flex;
  justify-content: center;
  align-items: center;
}

.modal-content {
  /* 스타일 - customize */
  max-width: 500px;
  width: 100%;
  height: 150px;
  background-color: white;
  padding: 20px;
  border-radius: 5px;
  box-shadow: 0 0 10px rgba(0, 0, 0, 0.3);

  /* 트랜지션 효과 */
  opacity: 0;
  transition: opacity 0.3s ease-in-out, transform 0.3s ease-in-out;

  transform: scale(0.8);
}

.modal.show {
  /* 모달이 열렸을 때 보여지게 하는 코드 */
  opacity: 1;
  pointer-events: auto;
}

.modal.show .modal-content {
  /* 모달이 열렸을 때 보여지게 하는 코드 */
  opacity: 1;
  transform: scale(1);
}

.close {
  color: #aaa;
  float: right;
  font-size: 28px;
  font-weight: bold;
  cursor: pointer;
}

.close:hover {
  color: black;
}

3.3. JS

// HTML 문서의 로딩이 완료되었을 때, 해당 함수를 실행
document.addEventListener("DOMContentLoaded", function () {
  // elements
  var modalBtn = document.getElementById("modalBtn");
  var modal = document.getElementById("myModal");
  var closeBtn = document.getElementById("closeBtn");

  // functions
  function toggleModal() {
    modal.classList.toggle("show");
  }

  // events
  modalBtn.addEventListener("click", toggleModal);
  closeBtn.addEventListener("click", toggleModal);

  window.addEventListener("click", function (event) {
    // 모달의 검은색 배경 부분이 클릭된 경우 닫히도록 하는 코드
    if (event.target === modal) {
      toggleModal();
    }
  });
});

3.4. 전체 코드

더보기
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Basic Modal</title>
    <style>
      * {
        box-sizing: border-box;
      }

      .modal {
        /* 스타일 - customize */
        background-color: rgba(0, 0, 0, 0.7);
        pointer-events: none;
        padding: 20px;

        /* 트랜지션 효과 */
        transition: opacity 0.3s ease-in-out;
        opacity: 0;

        /* 화면 전체를 덮게하는 코드 */
        position: fixed;
        top: 0;
        left: 0;
        width: 100%;
        height: 100%;

        /* 중앙에 오게하는 코드 */
        display: flex;
        justify-content: center;
        align-items: center;
      }

      .modal-content {
        /* 스타일 - customize */
        max-width: 500px;
        width: 100%;
        height: 150px;
        background-color: white;
        padding: 20px;
        border-radius: 5px;
        box-shadow: 0 0 10px rgba(0, 0, 0, 0.3);

        /* 트랜지션 효과 */
        opacity: 0;
        transition: opacity 0.3s ease-in-out, transform 0.3s ease-in-out;

        transform: scale(0.8);
      }

      .modal.show {
        /* 모달이 열렸을 때 보여지게 하는 코드 */
        opacity: 1;
        pointer-events: auto;
      }

      .modal.show .modal-content {
        /* 모달이 열렸을 때 보여지게 하는 코드 */
        opacity: 1;
        transform: scale(1);
      }

      .close {
        color: #aaa;
        float: right;
        font-size: 28px;
        font-weight: bold;
        cursor: pointer;
      }

      .close:hover {
        color: black;
      }
    </style>
  </head>
  <body>
    <!-- 모달 버튼 -->
    <button id="modalBtn">모달 열기</button>

    <!-- 모달 창 -->
    <div id="myModal" class="modal">
      <div class="modal-content">
        <span class="close" id="closeBtn">&times;</span>
        <p>모달 내용이 여기에 들어갑니다.</p>
        <p>
          사용자가 원하는대로 해당 엘리먼트 부분을 수정하여 사용할 수 있습니다.
        </p>
      </div>
    </div>

    <script>
      // HTML 문서의 로딩이 완료되었을 때, 해당 함수를 실행
      document.addEventListener("DOMContentLoaded", function () {
        // elements
        var modalBtn = document.getElementById("modalBtn");
        var modal = document.getElementById("myModal");
        var closeBtn = document.getElementById("closeBtn");

        // functions
        function toggleModal() {
          modal.classList.toggle("show");
        }

        // events
        modalBtn.addEventListener("click", toggleModal);
        closeBtn.addEventListener("click", toggleModal);

        window.addEventListener("click", function (event) {
          // 모달의 검은색 배경 부분이 클릭된 경우 닫히도록 하는 코드
          if (event.target === modal) {
            toggleModal();
          }
        });
      });
    </script>
  </body>
</html>