나만의 홈페이지 작성(기능 구현하기 3)

박희주·2022년 5월 13일
0

홈페이지에 Back to Top버튼 구현하기

CSSJavaScript를 활용한 Back to Top버튼 기능 구현

저번 게시글에서 주간야간 모드 버튼 기능 구현에 이어서 홈페이지 내 Back to Top버튼을 만들어 적용시켜보았다.
적용하는데 있어서 시행착오가 있었으나 구글링과 다른 프론튼엔드분들이 계시는 카톡방을 활용하여 문제를 해결내 나갔다.

1. 기능구현하기

TOP버튼을 만들기 위해 HTML은 물론 CSSJavaScript모두를 활용해서 구현하였다.

1-1 HTML

기능을 구현하기에 앞서 TOP버튼을 HTML의 최하단에 div로 감싸주어 class이름을 "top_button"으로 지어주고 button을 만들어 classonclick특성을 넣어주었다.

<!-- TOP버튼 제작 -->
<div class="top_button">
	<button class="top_button_link" onclick="handleScroll()">TOP</button>
</div>

위 처럼 HTML내에는 최하단부분에 해당코드를 작성해서 넣어주었다

1-2 CSS

스타일링 간에 문제가 발생했던 부분은 CSS부분이였는데 이건 추후에 오류 및 해결부분에서 설명하겠다.

.top_button {
    position: fixed;
    bottom: 50px;
    right: 50px;
    z-index: 100;
    display: none;
}
.top_button_link {
    top: 85vh;
    text-decoration: none;
    background-color: #9dcdb3;
    padding: 1rem;
    color: white;
    font-weight: 700;
    opacity: .5;
    cursor: pointer;
}
.top_button_link:hover {
    opacity: initial;
}

버튼에 대한 스타일링은 이렇게 하였다. 버튼을 감싸고 있는 div태그(.top_button)에 포지션을 지정해주고 bottomright로 위치를 조절해준뒤 추후 JavaScript에서 구현할 스크롤되었을 때 보여지는거랑 안보여지는걸 구현하기 위해 display: none;으로 셋팅하였다.
z-index: 100;은 홈페이지에 다른 HTML요소들에 가려지지 않고 최상위로 노출시키기 위해 사용했으며 숫자는 1로만 해도 충분했지만 나중에 수정사항이 발생하여 이것저것 추가될 때 가려지는것을 방지하기 위해 100으로 설정을 해두었다.

그리고 button에 직접적인 효과를 주기위해 작성된 CSS코드로 버튼의 데코를 없애버리고 배경색을 지정해주어 글자를 주변으로 패딩값을 넣어 버튼을 확대시켰다. 글자는 배경색과 겹치지 않게 흰색으로 지정했으며 글자가 좀 더 잘 보이기 위해 font-weight를 사용해 두껍게 만들었고 해당 버튼에 마우스를 올렸을때 그냥 마우스 포인터가 나오는게 밋밋해보여 cursor: pointer;로 클릭표시가 나오게끔 넣어주었다. 그리고 아래 hover기능을 구현하기 위해 opacity: 0.5;로 설정해 주었다.

마지막으로 hover기능을 구현하기 위해 "버튼기능":hover을 활용해 투명도를 초기값으로 바꾸는 opacity: initial;로 설정을 하였다. 값을 1로 설정해줘도 색이 아예 불투명해지지만 좀 더 안정적으로 하기위해 초기값을 의미하는 initial을 사용하였다.

1-3 JavaScript

스크립트로 구현한 방법은 크게 두 가지로 작성했다.

  • 스크롤했을 때 일정구간에서 버튼이 보여지는 여부를 결정하는 함수
  • "버튼을 눌렀을 때 최상단으로 올려주는 역할을 하는 함수"
/* Back To Top 버튼 */
document.addEventListener("scroll", handleScroll);

let scrollToTopBtn = document.querySelector(".top_button");

// 스크롤 했을 때 일정구간에서 버튼의 등장여부 결정 (더 깔끔한 코드)
function handleScroll() {
  if (
    document.body.scrollTop > 650 || // Safari에서 작동
    document.documentElement.scrollTop > 650 // 그 외 브라우저에서 작동
  ) {
    scrollToTopBtn.style.display = "block";
  } else {
    scrollToTopBtn.style.display = "none";
  }
}

scrollToTopBtn.addEventListener("click", scrollToTop);
function scrollToTop() {
  // Safari에서 작동
  document.body.scrollTo({
    top: 0,
    // behavior: "smooth", 이미 CSS에서 :root로 선언해 활용 중
  });
  // 그외 브라우저에서 작동
  document.documentElement.scrollTo({
    top: 0,
    // behavior: "smooth", 이미 CSS에서 :root로 선언해 활용 중
  });
}

최종적으로 작성한 코드는 이렇게 되지만 중간에 스크롤 했을 때 일정구간에서 버튼이 보여지는 코드를 기존에는 이렇게 작성했기에 작동이 원활하게 되지 않아 지금의 코드로 바꾸게 되었다.
기존의 코드는 다음과 같다.

// 스크롤 했을 때 일정구간에서 버튼의 등장여부 결정
function handleScroll() {
  let scrollableHeight =
    document.documentElement.scrollHeight -
    document.documentElement.clientHeight;
  let GOLDEN_RATIO = 0.5;

  if (document.documentElement.scrollTop / scrollableHeight > GOLDEN_RATIO) {
    // 버튼을 보여주기
    scrollToTopBtn.style.display = "block";
  } else {
    // 버튼을 숨기기
    scrollToTopBtn.style.display = "none";
  }
}

기존의 사용한 위의 코드는 구글링을 통해 나온 코드를 거의 그대로 복사해서 붙여넣기 하듯 사용한터라 고민을 해보지 않고 그냥 때려박은 형식인데 막상 해당코드를 사용해보니 문제는 내가 원하는 곳에서 버튼이 등장하는 것이 아니고 한참 페이지를 내려야 버튼이 나오기에 지금의 코드로 수정하게 되었다.
함수의 조건을 다시보니 너무 복잡하게 되어있다고 생각돼서 그냥 내 기준으로 보기 편한 방식으로 바꾸자해서 지금의 코드로 작성했다.

이번에 저 함수들을 작성하면서 새롭게 알게된 점이 있었는데
document.body.scrollTodocument.documentElement.scrollTo의 차이를 알게되었다. 두 가지가 무슨차이가 있나 싶었는데 간단하게 요약해서 얘기하자면

  • body : Safari브라우저에서 작동
  • docuemntElement : 그 외 IE, Chrome, FireFox 브라우저에서 작동

설마라는 생각으로 크롬과 사파리 두 브라우저를 켜놓고 함수를 차례대로 주석처리하면서 실행했는데 정말로 body는 Safari에서만 작동을했고 documentElement는 Chrome에서만 작동을 했다.

스크립트를 작성하면서는 큰 문제라고 뽑자면 스크롤 부분의 함수부분이라고 할 수 있는데 해당문제는 쉽게 해결하고 넘어가서 정체되진 않았었다.

2. 오류 및 해결

앞서 CSS부분에서 오류가 발생했었다고 했는데 해당 오류지점에 대해 얘기를 하자면 현재 코드는 수정된 코드로 문제가 없지만 기존의 코드에 overflow를 넣은적이 있었다. 또한 지금 페이지를 작성하면서 스타일링 CSS파일들은 일부러 쪼개고 하나의 HTML파일에 link로 연결해서 작성한 상태 였었는데 이러한 코딩방식의 문제점이 내가 낸 오류의 문제점이였다.

직면했던 문제
1. TOP버튼을 누르면 최상단으로 올라가는 것이 아닌 찔끔찔끔 올라가는 것
2. 버튼을 눌렀을 때 스크립트상으로는 최상단으로 올라간것으로 인식되어 버튼이 다시 재생성이 안돼는 점

버튼 스타일링과 기능구현을 위한 topBtn_style.cssbodyoverflow-y: hidden;을 적용한 상태였고 page_style.cssprofile_sections라는 각 페이지들에 대한 스타일링에 overflow: scroll;이 작성되어 있어서 해당부분이 충돌을 일으키고 2중 스크롤이 생겨서 문제가 됐던 것이었다.

/* topBtn_style.css */
body {
	overflow-y: hidden;/* 이 부분과 */
}
/* page_style.css */
.profile_sections {
	order: 1;
    width: calc(100%);
    height: 100vh;
    overflow: scroll;/* 이 부분 */
}

해당 문제가 되는 두 부분을 모두 주석처리 해보고 스크롤과 버튼을 눌러보니 스크립트에서 구현한것 처럼 애니메이션들이 정상작동하기 시작했다.

2-1 시도했던 방법

해당 문제를 식별하고 시도했던 방법은 CSS에서의 문제를 찾는 방법이 아니라 나는 계속 스크립트의 문제인 줄 알고 스크립트 부분만 계속 수정했었다. 결론적으로는 스타일링의 문제였었던 것을 알고 허탈감이 몰려오긴 했었다.
왜냐하면 지금까지 동적인것, 애니메이션 등 홈페이지를 움직이게 하는 모든 것은 JavaScript가 하는것이라는 인식이 강하게 박혀있었기 때문에 버튼의 함수가 문제있는 줄 알고 주구장창 3일내내 함수만 수정했던 것이였다.
구글링도 하고 지인들에게 질의하며 이틀동안 해답을 찾아보려했으나 뚜렷한 답이 나오지않아 결국 포기하고 마지막 심정으로 카톡방에 코드와 함께 문제를 질문하니 한 개발자 분께서 CSS의 부분을 수정해보라는 나에게 있어서 뜬금없는 답을 제시해주셨는데 그 부분을 수정하고 정상적으로 작동되는 홈페이지를 보니 엄청난 허탈감이 몰려왔었다.

3. 깨달음

이번에 TOP버튼을 만들면서 문제를 직면하고 그 해결과정의 계기를 통해 JavaScript도 열심히 해야하지만 HTMLCSS도 게을리해서는 안돼겠구나 라는 생각이 강하게 들었다.....

profile
하나부터 열까지, 머리부터 발 끝까지

0개의 댓글