css鼠标悬停下划线_如何使用CSS和JavaScript构建下划线悬停效果

本教程将教你如何结合CSS和JavaScript创建一个动态的菜单悬停效果,涉及JavaScript事件监听、元素样式变换及视口适应性处理。

css鼠标悬停下划线

在今天的教程中,我们将使用一些CSS和JavaScript来创建精美的菜单悬停效果。 这不是复杂的最终结果,但是构建它将是练习我们的前端技能的绝好机会。

在不做进一步介绍的情况下,让我们检查一下要构建的内容:

标记

我们从一些非常基本的标记开始; 包含菜单的nav元素和一个空的span元素:

<nav class="mynav">
  <ul>
    <li>
      <a href="">Home</a>
    </li>
    <li>
      <a href="">About</a>
    </li>
    <li>
      <a href="">Company</a>
    </li>
    <li>
      <a href="">Work</a>
    </li>
    <li>
      <a href="">Clients</a>
    </li>
    <li>
      <a href="">Contact</a>
    </li>
  </ul>
</nav>

<span class="target"></span>

CSS

准备好标记后,接下来我们为相关元素指定一些基本样式:

.mynav ul {
  display: flex;
  justify-content: center;
  flex-wrap: wrap;
  list-style-type: none;
  padding: 0;
}

.mynav li:not(:last-child) {
  margin-right: 20px;
}

.mynav a {
  display: block;
  font-size: 20px;
  color: black;
  text-decoration: none;
  padding: 7px 15px;
}

.target {
  position: absolute;
  border-bottom: 4px solid transparent;
  z-index: -1;
  transform: translateX(-60px);
}

.mynav a,
.target {
  transition: all .35s ease-in-out;
}

JavaScript

在这一点上,让我们将注意力集中在必需JavaScript上。 首先,我们针对所需的元素。 我们还定义了一系列颜色,将在以后使用。

const target = document.querySelector(".target");
const links = document.querySelectorAll(".mynav a");
const colors = ["deepskyblue", "orange", "firebrick", "gold", "magenta", "black", "darkblue"];

大事记

接下来,我们监听菜单链接的clickmouseenter事件。

当发生click事件时,我们将阻止重新加载页面。 当然,在我们的情况下,这是可行的,因为所有链接都具有空的href属性。 但是,在实际项目中,每个菜单链接可能会打开不同的页面。

最重要的是,一旦mouseenter事件触发,就会执行mouseenterFunc回调函数:

for (let i = 0; i < links.length; i++) {
  links[i].addEventListener("click", (e) => e.preventDefault());
  links[i].addEventListener("mouseenter", mouseenterFunc);
}

mouseenterFunc

mouseenterFunc函数的主体如下所示:

function mouseenterFunc() {
  for (let i = 0; i < links.length; i++) {
    if (links[i].parentNode.classList.contains("active")) {
      links[i].parentNode.classList.remove("active");
    }
    links[i].style.opacity = "0.25";
  }
  
  this.parentNode.classList.add("active");
  this.style.opacity = "1";
  
  const width = this.getBoundingClientRect().width;
  const height = this.getBoundingClientRect().height;
  const left = this.getBoundingClientRect().left;
  const top = this.getBoundingClientRect().top;
  const color = colors[Math.floor(Math.random() * colors.length)];

  target.style.width = `${width}px`;
  target.style.height = `${height}px`;
  target.style.left = `${left}px`;
  target.style.top = `${top}px`;
  target.style.borderColor = color;
  target.style.transform = "none";
}

在此函数内,我们执行以下操作:

  1. active类添加到目标链接的直接父级( li )。
  2. 减少所有菜单链接的opacity ,除了“活动”的链接。
  3. 使用getBoundingClientRect方法检索关联链接的大小及其相对于视口的位置。
  4. 从上述数组中获取随机颜色,并将其作为值传递给span元素的border-color属性。 请记住,其初始属性值设置为transparent
  5. 将从getBoundingClientRect方法提取的值分配给span元素的相应属性。 换句话说, span标签继承了被悬停的链接的大小和位置。
  6. 重置应用于span元素的默认变换。 仅当我们第一次将鼠标悬停在链接上时,此行为才重要。 在这种情况下,元素的转换从transform: translateX(-60px)transform: none 。 这给了我们很好的滑入效果。

如果活跃

重要的是要注意,上面的代码每次我们将鼠标悬停在链接上时都会执行。 因此,当我们将鼠标悬停在“活动”链接上时,它也会运行。 为了防止这种行为,我们将上面的代码包装在if语句中:

function mouseenterFunc() {
  if (!this.parentNode.classList.contains("active")) {
    // code here
  }
}

到目前为止,我们的演示如下:

差不多,但不是很

所以,一切似乎都按预期进行,对吧? 嗯,这不是真的,因为如果我们滚动浏览页面或调整视口的大小,然后尝试选择链接,事情就会变得混乱。 特别是, span元素的位置变得不正确。

播放整页演示 (确保您添加了足够的虚拟内容)以了解我的意思。

为了解决这个问题,我们必须计算从窗口顶部滚动了多远,然后将此值添加到目标元素的当前top值。 以同样的方式,我们应该计算出文档被水平滚动了多少(以防万一)。 将结果值添加到目标元素的当前left值。

这是我们更新的两行代码:

const left = this.getBoundingClientRect().left + window.pageXOffset;
const top = this.getBoundingClientRect().top + window.pageYOffset;

请记住,以上所有代码在浏览器处理DOM并找到相关脚本后就立即执行。 同样,对于您自己的实现和设计,您可能希望在页面加载时或类似的时候运行此代码。 在这种情况下,您必须将其嵌入事件处理程序(例如, load事件处理程序)中。

视口

我们要做的最后一件事是确保在调整浏览器窗口大小时该效果仍然有效。 为此,我们监听resize事件并注册resizeFunc事件处理程序。

window.addEventListener("resize", resizeFunc);

这是此处理程序的主体:

function resizeFunc() {
  const active = document.querySelector(".mynav li.active");
  
  if (active) {
    const left = active.getBoundingClientRect().left + window.pageXOffset;
    const top = active.getBoundingClientRect().top + window.pageYOffset;

    target.style.left = `${left}px`;
    target.style.top = `${top}px`;
  }
}

在上面的函数中,我们执行以下操作:

  1. 检查是否有一个菜单列表项,其类别为active 。 如果这样的元素,即国家,我们已经鼠标悬停在某个链接。
  2. 获取“活动”项的新lefttop属性以及相关的窗口属性,并将它们分配给span元素。 请注意,我们仅检索在resize事件期间更改的属性的值。 这意味着,无需重新计算菜单链接的宽度和高度。

浏览器支持

该演示在所有最新的浏览器中都能正常运行。 如果您遇到任何问题,请在下面的评论中告诉我。 另外,您可能已经注意到,我们使用Babel将我们的ES6代码编译为ES5。

结论

在本教程中,我们经历了创建简单但有趣的菜单悬停效果的过程。

希望您喜欢我们在此处构建的内容,并从中得到启发,开发出更强大的菜单效果,例如(在撰写本文时) Stripe网站中出现的菜单效果。

您是否创建过类似的作品? 如果是这样,请务必与我们分享您面临的挑战。

翻译自: https://webdesign.tutsplus.com/tutorials/how-to-build-a-shifting-underline-hover-effect-with-css-and-javascript--cms-28510

css鼠标悬停下划线

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值