React

[React/CSS-in-JS] Styled-Components를 사용하여 고정 푸터(버튼)와 스크롤 가능한 콘텐츠 구현하기

solfa 2024. 7. 27. 17:59

 

이거는 사실 css 카테고리인데... 그냥 여기에 씀


 

문제 상황

웹앱 st로 세로가 긴 화면을 개발하는 중에 화면 안의 컴포넌트들이 많아서 화면의 세로 길이를 넘어갈 때 스크롤이 되지 않거나 하단에 고정해둔 다음으로 넘어가는 버튼에 가려지는 문제가 생겼다.

이게 내가 개발중인 화면이다.

보통의 비율의 핸드폰에서는 평범한 화면이겠지만

이제 se같은 극단적인 화면 비율의 상황에서는 이런 상황이 발생한다.

 


문제 원인

다음 버튼을 bottom 스타일을 적용해서 화면의 하단에 footer마냥 위치해둬서 생기는 문제이다.

다음 버튼도 그냥 화면의 컴포넌트의 가장 밑에 위치해두고 scroll 여부를 허용하면 금방 해결 될 문제겠지만 나는 다음 버튼을 footer처럼 모든 스크린의 바닥에 위치하게 하고 싶었다.

 

이유 : 그게 더 예쁘니까! 그리고 그게 더 일관된 화면 디자인을 보여주니까!

 

 

내가 개발할 페이지를 보면 단계별로 구성되어 있고 단계마다 다음 버튼이 하단에 위치해 있다.

만약 버튼을 단순히 컴포넌트들 밑에 넣어버리면 다음을 누를 때 마다 이전 버튼의 위치에서 달라져 여기저기 위치할 것이다. 혹은 오른쪽 처럼 다음 버튼이 아예 나타나지 않아 노란색 포인트도 주지 못한다는!

물론 디자이너/pm과 상의 후 결정해야 하는 문제이지만 나는 이 디자인을 살리는 게 낫다고 판단했다.

 


문제 해결 방안

따라서 선택한 방법은

버튼은 footer 처럼 하단에 위치를 fixed 해두고 안의 내용은 화면 비율이 넘어가는 경우에만 스크롤이 되도록 설정하기!

이다.

 


코드 수정

현재 모든 컴포넌트를 감싸는 ContainerButton 스타일은 다음과 같다.

export const StyledContainer = styled.div`
  display: flex;
  flex-direction: column;
  width: 100%;
  max-width: 400px;
  margin: 0 auto;
  padding: 16px;
  box-sizing: border-box;
  height: 100vh;
  `
  
  ...
  
  export const StyledButton = styled.button`
  width: 342px;
  height: 47px;
  background-color: #fdd100;
  color: white;
  font-size: 15px;
  font-weight: 800;
  border-radius: 10px;
  text-align: center;
  position: absolute;
  bottom: 16px;
`

 

현재 렌더링 하고있는 코드이다. 

return (
    <StyledContainer>
      <StyledRow>
        <StyledBackIcon onClick={handleBack} src={Back} />
        <StyledTitle>가게 정보 등록</StyledTitle>
      </StyledRow>
      <StyledNavImgWrapper>
        <StyledNavImg src={nav} />
        <StyledNavText>
          <div>기본 정보</div>
          <div>영업 시간</div>
          <div>메뉴 등록</div>
        </StyledNavText>
      </StyledNavImgWrapper>
     ...
      <StyledButton onClick={handleNext}>다음</StyledButton>
    </StyledContainer>
  )

 

이렇게 렌더링을 하면

 

이렇게 다음 버튼에 가려지게 된다!

 

수정하는 방법은 간단하다! 세로 길이가 화면 길이를 넘어가면 자동으로 스크롤을 허용해주는

overflow-y: auto;
 

이 스타일을 추가한 컴포넌트로 컨텐츠를 감싸주면 된다.

 

export const StyledContainer = styled.div`
  display: flex;
  flex-direction: column;
  width: 100%;
  max-width: 400px;
  margin: 0 auto;
  padding: 16px;
  box-sizing: border-box;
  height: 100vh;
  position: relative; // 이 부분 추가
  padding-bottom: 80px; // 이 부분 추가
`
export const StyledScrollableContent = styled.div`
  flex: 1;
  overflow-y: auto;
`

 

container의 position을 추가하고 bottom에 패딩을 주어 스크롤시 bottom에 패딩이 생기는! 형식~

 

수정한 return 코드는 다음과 같다.

return (
    <StyledContainer>
      <StyledRow>
        <StyledBackIcon onClick={handleBack} src={Back} />
        <StyledTitle>가게 정보 등록</StyledTitle>
      </StyledRow>
      <StyledNavImgWrapper>
        <StyledNavImg src={nav} />
        <StyledNavText>
          <div>기본 정보</div>
          <div>영업 시간</div>
          <div>메뉴 등록</div>
        </StyledNavText>
      </StyledNavImgWrapper>
      <StyledScrollableContent> // 스크롤 추가!
        <StyledFormContainer>
          <StyledLabel>가게 이름</StyledLabel>
          <StyledFormInput type="text" placeholder="밥이득 김치찌개" />
          <StyledLabel>가게 링크</StyledLabel>
          <StyledFormInput type="text" placeholder="링크를 입력해 주세요." />
          <StyledSection onClick={handleUpload}>
            <StyledLabel>가게 배너 사진 등록</StyledLabel>
            <StyledUploadBox>
              <StyledUploadImg src={UploadImg} alt="업로드 아이콘" />
              <StyledUploadText>갤러리에서 이미지 등록하기</StyledUploadText>
            </StyledUploadBox>
          </StyledSection>
          <StyledLabel>학교 선택</StyledLabel>
          <StyledSearchInput type="text" placeholder="학교 선택" />
        </StyledFormContainer>
      </StyledScrollableContent> // 스크롤 추가!
      <StyledButton onClick={handleNext}>다음</StyledButton> // 버튼은 스크롤 외부에
    </StyledContainer>
  )

 

이렇게 코드를 수정했다.

 


완성된 화면

 

굿 마음에든다!

반응형 너무 어렵다 흐악

728x90