当前位置: 首页 > news >正文

使用JavaScript和CSS创建动态高亮导航栏

使用JavaScript和CSS创建"动态高亮"导航栏

在本教程中,Blake Lundquist将带领我们使用纯JavaScript和CSS实现"动态高亮"导航模式的两种方法。第一种技术使用getBoundingClientRect方法,在导航栏项目被点击时显式地动画化边框。第二种方法使用新的View Transition API实现相同的功能。

初始标记

假设我们有一个单页面应用,内容变化时页面不会重新加载。起始的HTML和CSS是标准的导航栏,额外包含一个id为#highlight的div元素。我们给第一个导航项添加.active类。

#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导航项时产生动画效果。让我们为nav元素添加点击事件处理程序:

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获取元素位置和尺寸信息:

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

对于这种方法,我们不再需要单独的#highlight元素:

nav a::after {content: " ";position: absolute;left: 0;top: 0;width: 100%;height: 100%;border: none;box-sizing: border-box;
}nav a.active::after {border: 2px solid green;view-transition-name: highlight;
}

使用startViewTransition方法触发过渡:

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(highlight) {height: 100%;
}::view-transition-new(highlight) {height: 100%;
}

最终代码重构

添加回退支持:

const setActiveElement = (elem) => {document.querySelector('nav a.active').classList.remove('active');elem.classList.add('active');
}navbar.addEventListener('click', async function (event) {if (!event.target.matches('nav a:not(.active)')) {return;}if (!document.startViewTransition) {setActiveElement(event.target);return;}document.startViewTransition(() => setActiveElement(event.target));
});

结论

网站UI状态之间的动画和过渡曾经需要大量外部库和复杂代码,但现在vanilla JavaScript和CSS已经包含了实现类原生应用交互的功能。我们通过两种方法演示了这一点:使用CSS过渡结合getBoundingClientRect()方法,以及使用View Transition API。

资源

  • getBoundingClientRect()方法文档
  • View Transition API文档
  • Jake Archibald的"视图过渡:处理宽高比变化"
    更多精彩内容 请关注我的个人公众号 公众号(办公AI智能小助手)
    公众号二维码
http://www.hskmm.com/?act=detail&tid=10245

相关文章:

  • Gridspech 全通关
  • 1967
  • 20253320蒋丰任
  • .
  • 又有两位智驾大牛联手入局具身智能机器人赛道创业,已完成数亿元融资!
  • 纯国产GPU性能对比,谁才是国产算力之王?
  • 地平线明年发布并争取量产舱驾一体芯片;比亚迪补强智舱团队,斑马智行原 CTO 加入
  • 英伟达入股英特尔,当竞争对手便成协作者,真正受益的......
  • ODT/珂朵莉树 入门
  • 在AI技术快速实现功能的时代,挖掘新需求成为关键突破点——某知名游戏资源分析工具需求洞察
  • 蜜罐
  • 【光照】[漫反射]UnityURP兰伯特有光照衰减吗?
  • prenotami.esteri.it 意大利签证预约error
  • reLeetCode 热题 100- 15. 三数之和 - MKT
  • XXL-TOOL v2.1.0 发布 | Java工具类库
  • Python-Pathlib库
  • 反省
  • [Nacos/Docker/MCP] Nacos 3.x : 为 AI MCP 而生
  • 牛客周赛 Round 108 CDEF题解
  • Redis的使用问题
  • AIGC拾遗:Flash Attention
  • 深度好文-风雨飘摇信竞路
  • Python-CSV库
  • C++小白修仙记_LeetCode刷题_位运算
  • C++小白修仙记_LeetCode刷题_双指针
  • 前路漫漫亦灿灿 往事堪堪亦澜澜
  • 使用uv和pycharm搭建python开发环境
  • lc1032-字符流
  • C++小白修仙记_LeetCode刷题_哈希表
  • 【F#学习】字符串String