Bottom modal 애니메이션 구현

JH.P·2024년 7월 9일

구현 목표

  • 아래와 같이, 클릭시 아래에서 위로 올라오는 애니메이션과 함께 모달을 구현하고 싶었다.

문제 현상

  • 초기에 아래와 같이 코드를 작성하였으나, 애니메이션은 작동하지 않고 컴포넌트만 딱딱하게 렌더링되었다.

스타일 코드

import styled from "styled-components";

const Container = styled.div<{ display: string }>`
  display: ${(props) => props.display || "none"};
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  justify-content: center;
  align-items: center;
  background-color: rgba(0, 0, 0, 0.6);
  z-index: 1000; /* 다른 요소들보다 위에 위치하도록 설정 */
`;

const ModalBackground = styled.div`
  position: fixed;
  left: 0;
  top: 0;
  right: 0;
  bottom: 0;
`;

const ModalWindow = styled.div<{ display: string }>`
  display: flex;
  flex-direction: column;
  align-items: center;

  position: fixed;
  bottom: 0px;
  transform: ${(props) =>
    props.display === "flex" ? "translateY(0)" : "translateY(100%)"};
  transition: transform 0.3s ease;

  border-radius: 10px;
  background: ${(props) => props.theme.modalBgColor};
  padding: 40px 30px 30px 30px;

  z-index: 1001; /* 모달 배경이 컨테이너 뒤에 위치하도록 설정 */

  .close {
    position: absolute;
    right: 10px;
    top: -15px;
    cursor: pointer;
    font-size: 25px;
  }
`;

export default { Container, ModalBackground, ModalWindow };

JSX 코드

<Style.Container display={display}>
  <Style.ModalBackground onClick={controlFunc} />
  <Style.ModalWindow>
    <p className="close" onClick={controlFunc}>
      &times;
    </p>
    {children}
  </Style.ModalWindow>
</Style.Container>

원인

  • 앞서 작성한 글의 display 속성의 transition 적용 글과 관련이 있다.
    해당 글 링크
  • 부모 태그인 Container이 렌더 트리 내에 존재하지 않기 때문에, 자식 태그도 마찬가지로 렌더 트리 내에 존재하지 않게 되어 transition 속성이 적용될 수 없는게 원인이였다.

해결

  • 따라서 아래와 같이 부모 태그와 자식 태그를 분리하였다.
  • 즉, Background 역할을 하는 Container 태그는 display 속성에 따라 조건부 렌더링 하도록 하고(렌더 트리 내 조건부로 존재해도 무방하기 때문에)
  • 실질적인 애니메이션이 적용되어야하는 모달 컴포넌트인 ModalWindow 태그는 항상 렌더 트리 내에 존재하도록 하며 transform 속성을 통해 하단에 숨겨놓았다가, 활성화 될 때 위로 올라오도록 하여 구현하였다.

JSX 코드

    <>
      <Style.Container display={display}>
        <Style.ModalBackground onClick={controlFunc} />
      </Style.Container>

      <Style.ModalWindow display={display}>
        <p className="close" onClick={controlFunc}>
          &times;
        </p>
        {children}
      </Style.ModalWindow>
    </>
profile
꾸준한 기록

0개의 댓글