JavaScript 및 CSS로 “Move Highlight”네비게이션 바 생성 – Smashing Magazine
getBoundingClientRect
방법을 클릭 할 때 내비게이션 막대 항목 사이의 경계를 명시 적으로 애니메이션하는 방법. 두 번째 접근법은 새로운 뷰 전환 API를 사용하여 동일한 기능을 달성합니다.
나는 최근에 오래된 jQuery 튜토리얼을 보았습니다. “이동 하이라이트”내비게이션 바 그리고 개념은 현대적인 업그레이드에 의한 것으로 결정했습니다. 이 패턴을 사용하면 사용자가 메뉴 항목을 클릭 할 때 활성 내비게이션 항목 주변의 테두리가 한 요소에서 다른 요소로 직접 애니메이션됩니다. 2025 년에는 바닐라 JavaScript를 통해 DOM을 조작 할 수있는 훨씬 더 나은 도구가 있습니다. View Transition API와 같은 새로운 기능은 점진적 향상을보다 쉽게 달성 할 수 있으며 많은 애니메이션 미성년자를 처리합니다.

이 튜토리얼에서는 일반 JavaScript 및 CSS를 사용하여 “이동 하이라이트”네비게이션 바를 생성하는 두 가지 방법을 시연 할 것입니다. 첫 번째 예제는 getBoundingClientRect
방법을 클릭 할 때 내비게이션 막대 항목 사이의 경계를 명시 적으로 애니메이션하는 방법. 두 번째 예제는 새로운보기 전환 API를 사용하여 동일한 기능을 달성합니다.
초기 마크 업
페이지를 다시로드하지 않고 콘텐츠가 변경되는 단일 페이지 응용 프로그램이 있다고 가정 해 봅시다. 시작 HTML 및 CSS는 추가 기능이있는 표준 탐색 표시 줄입니다. div
an을 포함하는 요소 id
~의 #highlight
. 우리는 첫 번째 내비게이션 항목에 클래스를 제공합니다 .active
.
펜을 참조하십시오 [Moving Highlight Navbar Starting Markup [forked]](Blake Lundquist에 의해.
이 버전의 경우 #highlight
요소 주위의 요소 .active
국경을 만들기위한 클래스. 우리는 활용할 수 있습니다 absolute
내비게이션 바의 요소를 포지셔닝하고 애니메이션하여 원하는 효과를 만듭니다. 우리는 처음에 화면에서 그것을 숨기고 숨겨서 숨 깁니다 left: -200px
그리고 포함 transition
요소의 위치와 크기의 변경이 점차적으로 발생하도록 모든 속성에 대한 스타일.
#highlight {
z-index: 0;
position: absolute;
height: 100%;
width: 100px;
left: -200px;
border: 2px solid green;
box-sizing: border-box;
transition: all 0.2s ease;
}
클릭 상호 작용을 위해 보일러 플레이트 이벤트 핸들러를 추가하십시오
사용자가 변경할 때 하이라이트 요소가 애니메이션을 원합니다. .active
내비게이션 항목. 추가하자 click
이벤트 처리기 nav
요소, 원하는 선택기와 일치하는 요소로 인해 발생하는 이벤트를 필터링하십시오. 이 경우, 우리는 만 변경하고 싶습니다 .active
사용자가 아직없는 링크를 클릭하면 NAV 항목 .active
수업.
처음에는 전화 할 수 있습니다 console.log
예상되는 경우에만 처리기가 발생하는지 확인하십시오.
const navbar = document.querySelector('nav');
navbar.addEventListener('click', function (event) {
// return if the clicked element doesn't have the correct selector
if (!event.target.matches('nav a:not(active)')) {
return;
}
console.log('click');
});
브라우저 콘솔을 열고 내비게이션 바에서 다른 항목을 클릭하십시오. 당신은 단지 봐야합니다 "click"
내비게이션 바에서 새 항목을 선택할 때 기록됩니다.
이제 우리는 이벤트 핸들러가 올바른 요소를 사용하고 있음을 알았으므로 코드를 추가하여 .active
클릭 한 내비게이션 항목으로 클래스. 이벤트 핸들러에 전달 된 객체를 사용하여 이벤트를 초기화 한 요소를 찾아 해당 요소를 제공 할 수 있습니다. .active
이전에 활성 항목에서 제거한 후.
const navbar = document.querySelector('nav');
navbar.addEventListener('click', function (event) {
// return if the clicked element doesn't have the correct selector
if (!event.target.matches('nav a:not(active)')) {
return;
}
- console.log('click');
+ document.querySelector('nav a.active').classList.remove('active');
+ event.target.classList.add('active');
});
우리의 #highlight
요소는 내비게이션 표시 줄을 가로 질러 이동하여 활성 항목 주위에 자체 위치를 배치해야합니다. 새로운 위치와 너비를 계산하는 기능을 작성해 봅시다. 이후 #highlight
선택기가 있습니다 transition
스타일이 적용되면 위치가 변경되면 점진적으로 움직입니다.
사용 getBoundingClientRect
요소의 위치와 크기에 대한 정보를 얻을 수 있습니다. 활성 내비게이션 항목의 너비와 상위 요소의 왼쪽 경계에서 오프셋을 계산합니다. 그런 다음 크기와 위치 일치하도록 하이라이트 요소에 스타일을 할당합니다.
// handler for moving the highlight
const moveHighlight = () => {
const activeNavItem = document.querySelector('a.active');
const highlighterElement = document.querySelector('#highlight');
const width = activeNavItem.offsetWidth;
const itemPos = activeNavItem.getBoundingClientRect();
const navbarPos = navbar.getBoundingClientRect()
const relativePosX = itemPos.left - navbarPos.left;
const styles = {
left: `${relativePosX}px`,
width: `${width}px`,
};
Object.assign(highlighterElement.style, styles);
}
클릭 이벤트가 시작될 때 새로운 기능에 전화합시다.
navbar.addEventListener('click', function (event) {
// return if the clicked element doesn't have the correct selector
if (!event.target.matches('nav a:not(active)')) {
return;
}
document.querySelector('nav a.active').classList.remove('active');
event.target.classList.add('active');
+ moveHighlight();
});
마지막으로, 페이지가 처음로드 될 때 테두리가 초기 활성 항목 뒤에서 이동하도록 함수를 즉시 호출하겠습니다.
// handler for moving the highlight
const moveHighlight = () => {
// ...
}
// display the highlight when the page loads
moveHighlight();
이제 새 항목이 선택되면 국경이 내비게이션 표시 줄을 가로 질러 이동합니다. 네비게이션 바를 애니메이션하기 위해 다른 탐색 링크를 클릭하십시오.
펜을 참조하십시오 [Moving Highlight Navbar [forked]](Blake Lundquist에 의해.
그것은 바닐라 JavaScript의 몇 줄만 가져 왔으며 다른 상호 작용을 설명하기 위해 쉽게 확장 될 수 있습니다. mouseover
이벤트. 다음 섹션에서는 View Transition API를 사용 하여이 기능을 리팩토링 할 것입니다.
보기 전환 API 사용
View Transition API는 웹 사이트보기간에 애니메이션 전환을 생성하는 기능을 제공합니다. 후드 아래에서 API는 “이전”및 “후”뷰의 스냅 샷을 생성 한 다음 그 사이의 전환을 처리합니다. 전환보기는 문서간에 애니메이션을 만들고 제공하는 데 유용합니다. 기본 APP와 같은 사용자 경험 Astro와 같은 프레임 워크에 등장합니다. 그러나 API는 또한 핸들러를 제공합니다 스파 스타일 응용 프로그램. 우리는이를 사용하여 구현에 필요한 JavaScript를 줄이고보다 쉽게 폴백 기능을 생성 할 것입니다.
이 접근법의 경우 더 이상 별도가 필요하지 않습니다 #highlight
요소. 대신, 우리는 스타일을 만들 수 있습니다 .active
의사 선택자를 사용하여 직접 내비게이션 항목 및 View Transition API가 새로운 내비게이션 항목을 클릭 할 때 이전 및 후미 상태 간의 애니메이션을 처리하도록합니다.
우리는 그것을 제거함으로써 시작할 것입니다 #highlight
요소 및 관련 CSS 및이를 nav a::after
의사 선택기 :
- #highlight {
- z-index: 0;
- position: absolute;
- height: 100%;
- width: 0;
- left: 0;
- box-sizing: border-box;
- transition: all 0.2s ease;
- }
+ nav a::after {
+ content: " ";
+ position: absolute;
+ left: 0;
+ top: 0;
+ width: 100%;
+ height: 100%;
+ border: none;
+ box-sizing: border-box;
+ }
For the .active
클래스, 우리는 다음을 포함합니다 view-transition-name
따라서 View Transition API의 마법을 잠금 해제합니다. 뷰 전환을 트리거하고의 위치를 변경하면 .active
DOM의 내비게이션 항목, “이전”및 “After”스냅 샷이 취해지고 브라우저는 막대를 가로 질러 테두리를 애니메이션합니다. 우리는 우리의 견해 전환에 이름을 말할 것입니다 highlight
그러나 우리는 이론적으로 이름을 줄 수있었습니다.
nav a.active::after {
border: 2px solid green;
view-transition-name: highlight;
}
일단 우리는 a view-transition-name
속성, 나머지 단계는 다음을 사용하여 전환을 트리거하는 것입니다. startViewTransition
메소드 및 콜백 함수로 전달됩니다.
const navbar = document.querySelector('nav');
// Change the active nav item on click
navbar.addEventListener('click', async function (event) {
if (!event.target.matches('nav a:not(.active)')) {
return;
}
document.startViewTransition(() => {
document.querySelector('nav a.active').classList.remove('active');
event.target.classList.add('active');
});
});
위의 수정 된 버전입니다 click
매니저. 움직이는 국경의 크기와 위치에 대한 모든 계산을 수행하는 대신 View Transition API는 모든 것을 처리합니다. 우리는 전화하면됩니다 document.startViewTransition
콜백 함수를 전달하여 .active
수업!
보기 전환 조정
이 시점에서 내비게이션 링크를 클릭하면 전환이 작동하지만 이상한 크기 문제가 보입니다.

이 크기의 불일치는 뷰 전환 과정에서 종횡비 변화로 인해 발생합니다. 우리는 여기서 자세히 설명하지는 않지만 Jake Archibald는 자세한 정보를 읽을 수있는 자세한 설명을 가지고 있습니다. 요컨대, 국경의 높이가 전환 내내 균일하게 유지되도록하기 위해서는 명시 적으로 선언해야합니다. height
for the ::view-transition-old
그리고 ::view-transition-new
의사 선택자는 각각 구형과 새로운보기의 정적 스냅 샷을 나타냅니다.
::view-transition-old(highlight) {
height: 100%;
}
::view-transition-new(highlight) {
height: 100%;
}
콜백을 별도의 함수로 옮기고 뷰 전환이 지원되지 않을 때의 폴백을 추가하여 코드를 정리하기 위해 최종 리팩토링을하겠습니다.
const navbar = document.querySelector('nav');
// change the item that has the .active class applied
const setActiveElement = (elem) => {
document.querySelector('nav a.active').classList.remove('active');
elem.classList.add('active');
}
// Start view transition and pass in a callback on click
navbar.addEventListener('click', async function (event) {
if (!event.target.matches('nav a:not(.active)')) {
return;
}
// Fallback for browsers that don't support View Transitions:
if (!document.startViewTransition) {
setActiveElement(event.target);
return;
}
document.startViewTransition(() => setActiveElement(event.target));
});
다음은 View 전환 구동 내비게이션 바가 있습니다! 다른 링크를 클릭하면 부드러운 전환을 관찰하십시오.
펜을 참조하십시오 [Moving Highlight Navbar with View Transition [forked]](Blake Lundquist에 의해.
결론
웹 사이트 UI 상태 간의 애니메이션 및 전환은 Verbose, Confusing 및 Error가 발생하기 쉬운 코드와 함께 많은 킬로바이트의 외부 라이브러리를 요구하는 데 사용되었지만 Vanilla JavaScript와 CSS는 달성 기능을 통합했습니다. 은행을 깨뜨리지 않고 원시 애플과 같은 상호 작용. 우리는 두 가지 접근법을 사용하여 “이동 하이라이트”내비게이션 패턴을 구현하여이를 시연했습니다. CSS 전환은 getBoundingClientRect()
방법 및 뷰 전이 API.
자원

(GG, YK)
Post Comment