导航!使用动画活动指示器构建导航菜单 (JavaScript)

今天,我们将学习如何创建一个花哨的菜单效果:每次我们点击或悬停在一个项目上时,都会有一个神奇的移动元素与活动项目一起出现。

在此旅程中,我们还将介绍一种有用的技术,在 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
喜欢就支持一下吧
点赞9 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容