이번 프론트엔드 스쿨 파이널 프로젝트 때 만들었던 웹 애플리케이션인 Suits에 페이지 상단 이동 버튼을 추가할 필요성을 느껴 스크롤 버튼 컴포넌트 및 그에 대한 로직을 추가하게 되었습니다.

(사용 기술: JavaScript, React, Styled-Components)

 

 


보통은 이렇게 네이버처럼 우측 하단에 scroll to top 버튼을 두는 게 일반적인 것 같은데요, 저희는 하단이 아닌 페이지 상단에 이 버튼을 위치시키고 싶었습니다.

 

네이버 메인페이지의 경우 화면의 우측 하단에 스크롤 버튼이 고정되어있습니다.

 

만약에 우측 하단에 스크롤 버튼을 위치시키려면 우측 하단에 이미 존재하는 다크모드 전환 버튼과 나란히 위치시켜야 했는데요(위 사진의 네이버 메인페이지처럼 말이죠~), 그렇게 할 경우 (특히 모바일의 경우) 사용자가 다크모드 버튼을 누르려다가 실수로 스크롤 버튼을 누르는 곤란한 상황이 생길 수도 있을 것 같아서 위치를 확실히 구분해두고 싶었습니다.

 

스크롤 버튼 추가 전 UI

 

그래서 스크롤 버튼을 페이지 상단에 위치시키기로 하고, 아래와 같이 설계를 해보았습니다.

 

 

<구현할 내용>

  • 화면 최상단 우측에 스크롤 버튼 위치 고정시키기
  • 스크롤 버튼 클릭 시 스크롤 위치가 페이지 최상단으로 이동하도록 구현

 


화면 최상단 우측에 스크롤 버튼 위치 고정시키기

스크롤 버튼에 사용될 svg 이미지는, Fontawesome에는 원하는 디자인이 유료길래 Figma에서 직접 모양을 만들고 svg 파일로 Export하기 기능을 사용하여 만들었습니다.

 

 

Figma에서 애용하는 기능입니다 ㅎㅎ

 

우선 스크롤 버튼의 위치를 조정하기 위해, 버튼을 감싸는 div 컴포넌트(PositionContainer) 하나를 만들고 그 안에 스크롤 버튼(TopButton)을 두었습니다. 그리고 이들을 묶어 ScrollToTop이라는 하나의 컴포넌트로 만들었습니다. 부모 요소인 PositionContainer에 position: fixed;를 주어 페이지 최상단에 고정시킨 후, 자식 요소인 TopButton에 position: absolute;를 주어 부모 요소를 기준으로 가장 위쪽의 가장 오른쪽 끝에 위치하도록 offset을 top: 0, right: 0으로 주었습니다.

 

const PositionContainer = styled.div`
  position: fixed;
  width: 100%;
  top: 90px;
  z-index: 1000;

  // 데스크탑
  @media screen and (min-width: 480px) {
    right: 5%;
  }
`;

const TopButton = styled.button.attrs(() => ({
  type: 'button',
  title: '맨 위로 가기',
  'aria-label': '맨 위로 가기'
}))`
  position: absolute;
  top: 0;
  right: 0;
  border: none;
  background-color: transparent;

  // 아이콘 스타일링
  svg {
    opacity: .7;
    filter: drop-shadow(2px 2px 10px var(--color-gray2));

    rect {
      fill: var(--color-body);
    }

    line {
      fill: none;
      stroke: var(--color-text);
      opacity: 1;
    }
  }
`;

스타일링 결과!

이제 버튼을 클릭할 때의 기능을 구현해보겠습니다.

 

스크롤 버튼 클릭 시 스크롤 위치가 페이지 최상단으로 이동하도록 구현

ScrollToTop 컴포넌트에 스크롤 위치를 조정하는 일을 하는 함수를 handleClick이라는 prop으로서 전달하기 위해 handleScroll이라는 함수를 아래와 같이 작성했습니다.

 

// 스크롤 버튼을 적용하는 페이지 컴포넌트(FollowingPage.js)
export default function FollowingPage() {
// 생략
    return (
    	// 생략
	<ScrollToTop handleClick={handleScroll} />
    	// 생략
    );
}

// ScrollToTop 컴포넌트(ScrollToTop.js)
export default function ScrollToTop({ handleClick }) {
  return (
    <PositionContainer>
      <TopButton onClick={handleClick}>
        <Icon type="arrow" height="40px" />
      </TopButton>
    </PositionContainer>
  );
}
// handleScroll.js
const handleScroll = e => {
  if (!window.scrollY) return;
  // 현재 위치가 이미 최상단일 경우 return

  window.scrollTo({
    top: 0,
    behavior: 'smooth'
  });

};

export default handleScroll;

 

window 객체의 scrollTo 메서드(MDN)를 이용하여 구현해보았는데요, window.scrollTo() 사용 방법에는 두 가지가 있다고 합니다. (이 메서드와 scrollY 프로퍼티는 IE에서는 지원을 하지 않네요. ㅠㅠ)

  • 첫 번째 인자로 x축 좌표를 전달하고 두 번째 인자로 y축 좌표를 전달하여 스크롤을 원하는 위치로 이동시키는 방법
  • 객체를 인자로 전달하는 방법
    • top(가로 위치), left(세로 위치), behavior(스크롤 효과) 속성을 지정해서 전달해주면 된다고 합니다. behavior 속성의 값으로는 'auto' 또는 'smooth'를 전달할 수 있는데요(참고), 'auto'는 원하는 위치로 아무 효과 없이 바로 이동하는 반면 'smooth'는 부드럽게 이동하는 애니메이션 효과를 줍니다.

auto로 지정했을 때
smooth로 지정했을 때

 

급작스럽게(?) 이동하는 느낌 보다는 부드럽게 이동하는 게 더 괜찮은 것 같아서 smooth로 지정을 해줬습니다.

 

비록 학습 차원에서 만든 애플리케이션이긴 하지만, 배포까지 했으니 앞으로도 유지보수할 부분을 발견하면 이렇게 시간날 때마다 보완해나가면 좋을 것 같습니다~~

 

 

복사했습니다!