HTML, CSS 및 JS로 애니메이션 탐색 표시기 만들기

일반 프로젝트에서 이런 종류의 메뉴를 사용할 기회가 없었기 때문에 재미로 하나 만들어 보기로 했습니다. 최종 결과에 정말 만족했기 때문에 커뮤니티와 공유하기로 결정했습니다. React를 사용하여 만들었지만 어떤 프로젝트에서도 사용할 수 있도록 바닐라 JavaScript로 만들고 싶었습니다.

HTML 설정



몇 개의 링크가 포함된 간단한 목록으로 간단한 탐색 마크업을 만들어 시작해 보겠습니다. 루트id 요소와 포인터로 사용할 nav 요소에 div 특성을 추가합니다. 탐색, 목록 및 포인터 요소에 스타일을 지정할 수 있도록 몇 가지 클래스가 필요합니다.

<nav class="nav" id="js-nav">
  <div id="js-pointer" class="nav__pointer"></div>
  <ul class="nav__list">
    <li><a href="#">Overview</a></li>
    <li><a href="#">Goals</a></li>
    <li><a href="#">Inspiration</a></li>
    <li><a href="#">Profile</a></li>
  </ul>
</nav>


CSS 마크업



몇 가지 스타일을 추가해 보겠습니다. 다음 코드 스니펫은 필수 스타일만 보여줍니다.
nav 요소를 상대적으로 배치하고 약간의 패딩을 추가해야 합니다. JavaScript에 해당 값이 필요합니다. nav__pointer보다 낮은 z-index 값으로 절대적으로 nav__list를 배치하여 표시기가 링크 아래에 배치되도록 합니다.

모든 링크 컨테이너의 너비가 같도록 링크를 4 * 1fr 열 그리드에 배치해야 합니다.

.nav {
  position: relative;
  padding: 1em;
}

.nav__pointer {
  z-index: 1;
  position: absolute;
  top: 0.6em;
  left: 1em;
  background-color: #bada55;
  height: 1.8em;
  transition: transform 0.25s ease-in-out;
  border-radius: 0.3em;
  will-change: transform;
  backface-visibility: hidden;
}

.nav__list {
  position: relative;
  z-index: 2;
  display: grid;
  grid-template-columns: repeat(4, 1fr);
}



자바스크립트



JavaScript로 탐색, 표시기 및 링크 요소를 선택해야 합니다. CSS의 값 패딩1em을 기억하십니까? 포인터를 적절하게 배치할 수 있도록 해당 값의 절반을 사용합니다.

매직 넘버 사용을 피하기 위해 그리드의 열 수(링크 수)에 따라 표시기의 너비를 동적으로 계산합니다.

var CONTAINER_PADDING_HALF = "0.5em";

pointer.style.width = "calc(100% /"+links.length+" - "+CONTAINER_PADDING_HALF+")"

nav 요소 내에서 선택한 각 링크에 대해 주문에 따라 백분율 값을 저장하는 data 속성을 추가합니다. 링크가 목록의 첫 번째인 경우 0% 값을 가지며, 두 번째인 경우 100% 값을 갖습니다. 이 값을 변환에 사용합니다.

또한 각 링크에 대해 클릭 이벤트 리스너를 연결합니다.

for(var i=0; i<links.length; i++){
  var current = links[i];
  current.dataset.order = i * 100 + "%";  
  current.addEventListener("click", movePointer);
}


링크 클릭 이벤트 핸들러는 매우 간단합니다. 탐색 표시기에 CSS 변환 속성만 적용합니다. 적용되는 값은 우리가 설정한 data-order 속성에 따라 다릅니다.

function movePointer(e) {
  var order = e.currentTarget.dataset.order;
  pointer.style.transform = "translate3d("+order+",0,0)"
}


표시기의 너비가 그리드에 있는 각 탐색 링크의 너비와 일치하고 표시기를 첫 번째 링크의 시작 부분에 절대적으로 배치했기 때문에 100% 단위로 변환을 적용하기만 하면 됩니다. 첫 번째 링크의 값은 0%, 두 번째 링크의 값은 100%, 세 번째 링크의 값은 200% 등입니다.

3D CSS 변환을 사용함으로써 이 애니메이션은 GPU 기반이 되며 매끄럽고 성능이 좋습니다.

최종 결과



다음은 최종 결과에 대한 CodePen 링크입니다.




이 기사는 커피에 의해 연료가 공급됩니다. 그러니 내 작업이 마음에 들고 도움이 된다면 커피 한 잔 사주세요! 정말 감사하겠습니다.



시간을 내어 이 게시물을 읽어주셔서 감사합니다. 이 정보가 유용했다면 ❤️ 또는 🦄를 표시하고 공유하고 댓글을 달아주세요.

좋은 웹페이지 즐겨찾기