使用JavaScript和CSS创建"动态高亮"导航栏
在本教程中,Blake Lundquist将带我们学习使用纯JavaScript和CSS创建"动态高亮"导航模式的两种方法。第一种技术使用getBoundingClientRect方法在点击时显式动画导航栏项之间的边框。第二种方法使用新的View Transition API实现相同的功能。
初始标记
假设我们有一个单页应用程序,内容更改时页面不会重新加载。起始HTML和CSS是标准的导航栏,带有一个id为#highlight的额外div元素。我们给第一个导航项添加.active类。
1
2
3
4
5
6
7
|
<nav>
<div id="highlight"></div>
<a href="#" class="active">Home</a>
<a href="#services">Services</a>
<a href="#about">About</a>
<a href="#contact">Contact</a>
</nav>
|
添加点击事件处理程序
我们希望当用户更改.active导航项时高亮元素能够动画移动。我们为nav元素添加点击事件处理程序,然后筛选仅由匹配我们选择器元素引发的事件。
1
2
3
4
5
6
7
8
9
10
|
const navbar = document.querySelector('nav');
navbar.addEventListener('click', function (event) {
if (!event.target.matches('nav a:not(active)')) {
return;
}
document.querySelector('nav a.active').classList.remove('active');
event.target.classList.add('active');
});
|
移动高亮效果
使用getBoundingClientRect,我们可以获取元素位置和大小信息。我们计算活动导航项的宽度及其相对于父元素左边界的偏移量,然后将样式分配给高亮元素使其大小和位置匹配。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
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);
}
|
使用View Transition API
View Transition API提供了在网站视图之间创建动画过渡的功能。对于这种方法,我们不再需要单独的#highlight元素,而是可以直接使用伪选择器设置.active导航项的样式,并让View Transition API处理新导航项被点击时前后UI状态之间的动画。
1
2
3
4
5
6
7
8
9
10
|
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');
});
});
|
调整视图过渡
为确保边框高度在整个过渡过程中保持一致,我们需要为表示旧视图和新视图静态快照的::view-transition-old和::view-transition-new伪选择器声明明确的高度。
1
2
3
4
5
6
7
|
::view-transition-old(highlight) {
height: 100%;
}
::view-transition-new(highlight) {
height: 100%;
}
|
结论
网站UI状态之间的动画和过渡曾经需要大量外部库以及冗长、混乱且容易出错的代码,但原生JavaScript和CSS已经包含了实现类似原生应用交互的功能。我们通过两种方法实现了"动态高亮"导航模式:结合CSS过渡和getBoundingClientRect()方法,以及View Transition API。