모바일 반응형 구현

­이은재 ·2024년 11월 20일

https://github.com/eunjaelee1004/likesaju-frontend-seminar

메인 페이지의 ShareSection, FAQSection, 그리고 Header 컴포넌트, 좌측 텍스트 섹션에 tailwind media query와 애니메이션 적용하기를 했다.

1. ShareSection

return (
    <SectionLayout
      outerLayerClassName={'mobile:h-fit'}
      innerLayerClassName={'mobile:h-fit mobile:py-20'}
    >
      <div className="w-full h-full flex flex-col gap-[80px]">
        <div className="w-full flex mobile:flex-col justify-between items-center mobile:gap-4">
          <div className="space-y-6 mobile:space-y-2">
            <h3 className="text-left mobile:text-center text-4xl mobile:text-2xl nanum-extra-bold text-neutral-800 dark:text-white">
              AI가 알려주는 사주
            </h3>
            <p className="text-xl mobile:text-sm font-semibold text-neutral-800 dark:text-white">
              오늘의 사주 운세를 확인해보세요.
            </p>
          </div>
          <a href="/saju">
            <Button
              className="w-[250px] h-[50px] mobile:w-[180px] mobile:h-[40px] mobile:text-sm"
              isRounded={true}
            >
              내 사주 보러가기
            </Button>
          </a>
        </div>
        <div className="space-y-10 mobile:space-y-4 mobile:mx-auto">
          <p className="text-xl mobile:text-base text-neutral-800 font-semibold dark:text-white">
            어떤 내용을 확인할 수 있나요?
          </p>
          <div className="grid grid-cols-2 mobile:grid-cols-1 gap-[30px] mobile:w-fit">
            {sajuCardInfo.map((card) => (
              <SajuCard
                key={card.title}
  1. 모바일 뷰 레이아웃 개선
  • mobile:h-fit, mobile:py-20 등 Tailwind의 미디어 쿼리를 통해 작은 화면에서의 레이아웃 높이를 자동 조정하고 여백을 설정했다.
  • mobile:flex-col을 적용해 플렉스 컨테이너가 모바일에서는 세로로 정렬되도록 했다.
  1. 텍스트 크기 조정
  • mobile:text-2xl과 mobile:text-sm을 사용해 큰 화면에서는 더 큰 글씨를, 작은 화면에서는 가독성을 높이기 위해 글씨 크기를 줄였다.
  1. 버튼 크기 조정
  • 버튼은 mobile:w-[180px]처럼 화면 크기에 따라 적절한 크기를 설정해 클릭 편의성을 보장했다.

2. FAQSection

return (
    <SectionLayout>
      <div className="w-full h-full flex flex-col gap-10 md:gap-[80px] mt-20 md:mt-[100px]">
        <h3 className="text-left text-2xl md:text-4xl nanum-extra-bold">
          FAQs
        </h3>
        <div className="flex flex-col gap-6 md:gap-[30px] justify-center">
          {faqAccordionInfo.map((accordion) => (
            <FAQAccordion
              key={accordion.question}
              question={accordion.question}
              answer={accordion.answer}
            />
          ))}
        </div>
      </div>
    </SectionLayout>
  );
};
  1. 간격 조정
  • gap-6은 기본 간격으로 설정하고, md:gap-[30px]을 추가해 화면이 넓어질수록 간격이 늘어나도록 했다.
  1. 카드 크기 조정
  • 카드의 최대 너비는 max-w-[90%]로 기본 설정하고, md:max-w-[450px]을 통해 데스크탑에서 적절한 크기를 유지했다.
  1. 텍스트 크기 조정
  • text-sm에서 md:text-base로 크기를 유연하게 조정해 큰 화면에서도 읽기 편한 크기를 보장했다.

3. Header Component

return (
    <div className="w-full flex flex-row items-center justify-between bg-white drop-shadow h-[80px] px-4 md:px-[68px] z-[999]">
      <Link
        to="/"
        className="text-[26px] font-extrabold text-[#14142B] leading-9 tracking-tighter sm:text-[20px] sm:leading-none"
      >
        멋쟁이 사주처럼
      </Link>
      <div className="flex flex-row items-center gap-[50px] sm:gap-4">
        <Link
          to="/saju"
          className={`text-xl font-bold leading-6 sm:text-sm sm:leading-none ${
            location.pathname === '/saju'
              ? 'text-[#4A3AFF] font-extrabold'
              : 'text-[#14142B] hover:text-[#4A3AFF]'
          }`}
        >
          사주
        </Link>
        <Link
          to="/chat"
          className={`text-xl font-bold leading-6 sm:text-sm sm:leading-none ${
            location.pathname === '/chat'
              ? 'text-[#4A3AFF] font-extrabold'
              : 'text-[#14142B] hover:text-[#4A3AFF]'
          }`}
        >
          채팅
        </Link>
        {isLogin ? (
          <div
            className="relative"
            onMouseOver={() => setShowProfile(true)}
            onMouseLeave={() => setShowProfile(false)}
          >
            <span className="text-xl font-bold leading-6 text-[#14142B] hover:text-[#4A3AFF] sm:text-sm sm:leading-none">
              프로필
            </span>
            {showProfile && (
              <div className="absolute top-[25px] right-0 bg-white drop-shadow w-[180px] md:w-[221px] p-4 md:p-[25px] rounded-[12px] flex flex-col gap-4 md:gap-5">
                {profileImgIndex && (
                  <div className="flex flex-row gap-[10px] items-center">
                    <ProfileImage
                      profileImageId={profileImgIndex}
                      additionalClassName={'w-[30px] h-[30px]'}
                    />
                    <span className="text-sm md:text-lg font-bold text-[#170F49]">
                      {nickname}
                    </span>
                  </div>
                )}
                <div className="flex flex-row items-center justify-between">
                  <div className="flex flex-row gap-[10px] items-center">
                  <img
                      src={coin}
                      alt="coin"
                      className="w-[20px] md:w-[30px]"
                    />
                    <span className="text-sm md:text-lg font-bold text-[#170F49]">
                      포인트
                    </span>
                  </div>
                  <span className="text-sm md:text-lg font-bold text-[#4A3AFF]">
                    {point}
                    <span className="text-[#160F49]">P</span>
                  </span>
                </div>
                <button
                  onClick={onClickPoint}
                  className="bg-[#160F49] text-white text-sm md:text-base font-semibold rounded-[50px] px-4 md:px-6 py-[6px]"
                >
                  충전하기
                </button>
                <span
                  onClick={onClickLogout}
                  className="text-sm md:text-base font-normal underline text-[#160F49] cursor-pointer"
                >
                  로그아웃
                </span>
              </div>
            )}
          </div>
        ) : (
          <Link
          to="/login"
          className="text-xl font-bold text-[#4A3AFF] bg-[#F3F1FF] px-7 py-[17px] rounded-[50px] sm:text-sm sm:leading-none sm:px-5 sm:py-[10px]"
          >
            로그인
          </Link>
        )}
      </div>
      {isPointModalOpen && <PointModal setIsModalOpen={setIsPointModalOpen} />}
    </div>
  );
};
  1. 텍스트 크기와 간격 조정
  • sm:text-sm, sm:gap-4을 활용해 작은 화면에서는 글씨를 작게 하고 간격을 줄였다.
  1. 여백 조정
  • px-4와 md:px-[68px]을 사용해 데스크탑에서는 넓은 여백으로 여유 있는 레이아웃을 제공한다.

4. 텍스트 애니메이션

animation: {
        fadeIn: 'fadeIn 0.5s ease-in-out',
        'slide-in': 'slide-in 1s ease-out',
      },
      
keyframes: {
        fadeIn: {
          '0%': { opacity: '0' },
          '100%': { opacity: '1' },
        },
        'slide-in': {
          '0%': { transform: 'translateX(-100%)', opacity: '0' },
          '100%': { transform: 'translateX(0)', opacity: '1' },
        },
      },
  1. 커스텀 애니메이션 추가
  • Tailwind CSS에 slide-in 애니메이션을 추가해 텍스트가 좌측에서 부드럽게 나타나도록 설정했다.
  1. 부드러운 전환 기능 추가
  • ease-out을 사용해 자연스러운 종료 효과를 추가했다.
profile
이은재

0개의 댓글