今天,我们将学习如何创建一个花哨的菜单效果:每次我们点击或悬停在一个项目上时,都会有一个神奇的移动元素与活动项目一起出现。
在此旅程中,我们还将介绍一种有用的技术,在 CSS 变量的帮助下通过 JavaScript 更新 CSS 伪元素样式。
1. 从 HTML 标记开始
为了开发这个组件,我们将定义一个元素,该元素将包含包装在容器中的菜单。默认情况下,我们将该类提供给第一个列表项,但我们可以同样地将此类分配给其中任何一个。nav,
active
下面是所需的结构:
<div class="container">
<nav>
<ul class="menu">
<li class="active">
<a href="">Home</a>
</li>
<li>
<a href="">Information About Us</a>
</li>
<li>
<a href="">Clients</a>
</li>
<li>
<a href="">Contact</a>
</li>
</ul>
</nav>
</div>
2. 添加 CSS
令人高兴的是,我们只需要几种样式。
正如我们所说,菜单将位于最大宽度为 1000px 的容器中。
要创建具有移动背景的元素,该元素将充当活动菜单指示器,我们不会使用任何额外的 HTML 元素。相反,我们将定义菜单的伪元素,然后通过 JavaScript 动态更新其 and 值。::before,
transform,
width
在小于 801px 的屏幕上,我们将隐藏移动荧光笔,只使用一些类似的样式来指示活动菜单项。
以下是我们主要感兴趣的菜单样式:
/*CUSTOM VATIABLES HERE*/
.menu {
list-style: none;
position: relative;
display: inline-flex;
background: var(--pink);
padding: 10px;
border-radius: 15px;
box-shadow: rgba(17, 12, 46, 0.15) 0px 48px 100px 0px;
}
.menu::before {
content: "";
position: absolute;
top: 10px;
left: 0;
transform: translateX(var(--transformJS));
width: var(--widthJS);
height: calc(100% - 20px);
border-radius: var(--active-link-border-radius);
background: var(--light-pink);
box-shadow: var(--active-link-box-shadow);
transition: all 0.3s linear;
}
.menu li a {
display: inline-block;
position: relative;
padding: 10px 20px;
font-size: 20px;
font-weight: 500;
z-index: 1;
}
.menu li:not(:last-child) {
margin-right: 20px;
}
@media (max-width: 800px) {
.menu,
.menu li {
display: inline-block;
}
.menu li.active a {
background: var(--light-pink);
border-radius: var(--active-link-border-radius);
box-shadow: var(--active-link-box-shadow);
}
.menu::before {
display: none;
}
}
3. 应用JavaScript
现在是有趣的部分。
我们将指定将活动项作为参数获取的函数,并执行以下操作:doCalculations()
- 计算其宽度和相对于父列表的偏移量左位置。
- 相应地更新 和 CSS 变量,这些变量将反过来设置菜单伪元素的 and 值。
transformJS,
widthJS,
transform,
width,
::before
此函数将在以下情况下运行:
- 当 DOM 准备就绪时。在这种情况下,活动项将是具有类的项。默认情况下,这将是第一个。
active
- 每次我们单击或将鼠标悬停在菜单链接上时。
- 当我们调整浏览器窗口的大小时。这很重要,因为请记住,在较小的屏幕上,我们遵循不同的方法。
以下是单击动画所需的 JavaScript 代码:
const menu = document.querySelector(".menu");
const menuLinks = menu.querySelectorAll("a");
const menuLinkActive = menu.querySelector("li.active");
const activeClass = "active";
doCalculations(menuLinkActive);
for (const menuLink of menuLinks) {
menuLink.addEventListener("click", function (e) {
e.preventDefault();
menu.querySelector("li.active").classList.remove(activeClass);
menuLink.parentElement.classList.add(activeClass);
doCalculations(menuLink);
});
}
function doCalculations(link) {
menu.style.setProperty("--transformJS", `${link.offsetLeft}px`);
menu.style.setProperty("--widthJS", `${link.offsetWidth}px`);
}
window.addEventListener("resize", function() {
const menuLinkActive = menu.querySelector("li.active");
doCalculations(menuLinkActive);
});
对于悬停动画,我们将用如下所示的事件替换事件:click,mouseenter
...
menuLink.addEventListener("mouseenter", function () {
document.querySelector(".menu li.active").classList.remove(activeClass);
menuLink.parentElement.classList.add(activeClass);
doCalculations(menuLink);
});
结论
做!很快,我们设法开发了一个实用的导航菜单动画,可以在单击或悬停时发生。除了动画本身,另一件需要记住的事情是我们使用 CSS 变量来更新伪元素样式的方式。如果您因通过 JavaScript 操作伪元素而头疼,这是一个很好的知识来源。
© 版权声明
免责声明:得设创意所发布的信息来自网络和用户自行分享,仅限用于学习和研究目的,版权争议与本站无关。
THE END
暂无评论内容