CSS 애니메이션과 미디어 쿼리: 화면 크기 변화에 따른 애니메이션 문제 해결하기 (문제 해결)

Devinix·2024년 1월 22일
0

[문제 해결]

목록 보기
14/29
post-thumbnail

개요

현재 개발중인 웹의 레이아웃에 사이드바가 있다. 이 사이드바는 반응형으로 넓은 화면에서만 렌더링 하고 있으며, 사이드바 우측의 버튼을 클릭할때마다 사이드바를 부드럽게 열고 닫기 위해 keyframes를 이용해 애니메이션 처리 하고 있는 상황이었다.

코드를 살펴보자.

Sidebar.tsx

interface IProps {
  isSidebarOpen: boolean | null;
  setIsSidebarOpen: Dispatch<SetStateAction<boolean | null>>;
}

function Sidebar({ isSidebarOpen, setIsSidebarOpen }: IProps): JSX.Element {
  const closeButtonClass = `${styles.closeButton} ${
    isSidebarOpen || isSidebarOpen === null ? styles.open : styles.close
  }`;
  const openButtonClass = `${styles.openButton} ${
    isSidebarOpen || isSidebarOpen === null ? styles.open : styles.close
  }`;
  const sidebarClass = `${styles.container} ${
    isSidebarOpen ? styles.open : styles.close
  }`;

  return (
    <nav className={sidebarClass}>
      <LeftOutlined
        className={closeButtonClass}
        onClick={() => {
          setIsSidebarOpen(() => false);
        }}
      />
      <RightOutlined
        className={openButtonClass}
        onClick={() => {
          setIsSidebarOpen(() => true);
        }}
      />
    </nav>
  );
}

export default Sidebar;

상위 컴포넌트로부터 props로 내려받은 isSidebarOpen 상태를 이용하여 class를 동적으로 할당하고 있는 상황이다.

Sidebar.module.scss

@import "/src/styles/breakpoints";
@import "/src/styles/mixins";

@keyframes openSidebar {
  0% {
    min-width: 0;
  }
  100% {
    min-width: 28rem;
  }
}

@keyframes closeSidebar {
  0% {
    min-width: 28rem;
  }
  100% {
    min-width: 0;
  }
}

.container {
  position: relative;
  display: none;

  &.close {
    animation: closeSidebar 0.3s ease forwards;
  }

  &.open {
    animation: openSidebar 0.3s ease forwards;
  }

  @include respond-above("md") {
    display: block;
    min-width: 28rem;
    background-color: #001529;
  }

  ... 생략
}

keyframes를 이용하여 상태가 변함에 따라 애니메이션을 주고 있다.

문제 상황

작은 화면에서는 사이드바가 보이지 않고, 큰 화면에서는 버튼을 통해 사이드바를 열고 닫을 수 있다. 하지만, 작은 화면에서 큰 화면으로 전환할 때, 미디어 쿼리의 변경에 따라 애니메이션이 불필요하게 트리거되는 문제가 발생했다. 내가 원하는 것은 버튼을 클릭 할 때에만 애니메이션이 활성화되는 것이었다.

원인

문제의 원인은 미디어 쿼리와 CSS 애니메이션 간의 상호작용에 있었다. 화면 크기가 변경될 때, .container 요소에 적용되는 스타일이 미디어 쿼리에 의해 변경되었고, 이로 인해 정의된 @keyframes 애니메이션이 트리거되었던 것이다.

해결 과정

생각보다 간단하게 해결할 수 있었다. CSS transition 속성을 사용하는 방법을 시도했다. transition은 요소의 특정 속성(여기서는 min-width)의 변화에 시간에 따른 부드러운 전환 효과를 적용한다. 이 방식으로, 화면 크기가 변경되어도 불필요한 애니메이션이 트리거되지 않게 되었다.

수정된 코드

Sidebar.module.scss

@import "/src/styles/breakpoints";
@import "/src/styles/mixins";

// keyframes 애니메이션 제거!

.container {
  position: relative;
  display: none;
  // min-width 속성에 지연효과 추가
  transition: min-width 0.3s ease;

  &.open {
    // 직접 min-width 변경
    min-width: 28rem;
  }

  &.close {
    // 직접 min-width 변경
    min-width: 0;
  }
  
  @include respond-above("md") {
    display: block;
    min-width: 28rem;
    background-color: #001529;
  }

  ...생략
}

결론

이 사례는 CSS transition 속성을 활용함으로써, 화면 크기 변화에 따른 불필요한 애니메이션 트리거를 효과적으로 방지할 수 있음을 보여준다. 이로 인해 더 나은 UX를 제공하고, 브라우저 환경에서의 예측 가능한 UI 동작을 보장하는 방법을 제시할 수 있었다.

profile
프론트엔드 개발

0개의 댓글