仅当文本与 div 重叠时无法更改字体颜色

Unable to change font color only when the text is overlapping with a div

只有当选择器与文本重叠并且找不到解决方案时,我才尝试将字体颜色更改为白色。

想要的行为如下:

  1. 仅在选择器为 重叠。
  2. 将活动选项卡的字体大小增加到 18px
  3. 选择器应移动到活动选项卡。

我尝试了一些方法,none 似乎有效。

这是我现在拥有的:https://codepen.io/galanflorind/pen/gOpQKPP

var tabs = $('.tabs');
var selector = $('.tabs').find('a').length;
var activeItem = tabs.find('.active');
var activeWidth = activeItem.innerWidth();
$(".selector").css({
  "left": activeItem.position.left + "px", 
  "width": activeWidth + "px"
});

$(".tabs").on("click","a",function(e){
  e.preventDefault();
  $('.tabs a').removeClass("active");
  $(this).addClass('active');
  var activeWidth = $(this).innerWidth();
  var itemPos = $(this).position();
  $(".selector").css({
    "left":itemPos.left + "px", 
    "width": activeWidth + "px"
  });
  
// Temporary fix for resizing after the transition is done
// TODO: find another solution
  setTimeout(() => {
    var activeWidth = $(this).innerWidth();
    var itemPos = $(this).position();
    $(".selector").css({
    "left":itemPos.left + "px", 
    "width": activeWidth + "px"
  });
    }, 401)
});
@import url('https://fonts.googleapis.com/css?family=Nunito');

body{
  height:100vh;
  display:flex;
  flex-direction:column;
  justify-content:center;
  align-items:center;
}

.wrapper{
  text-align:center;
  margin:50px auto;
    font-family: 'Nunito', sans-serif;
}

.tabs{
  font-size:15px;
  padding:0px;
  list-style:none;
  display:inline-block;
  border-radius:50px;
  position:relative;
}

.tabs a{
  text-decoration:none;
  color: #2f3059;
  text-transform:uppercase;
  padding:6px 20px;
  display:inline-block;
  position:relative;
  z-index:1;
  transition-duration: 0.4s;
}

.tabs a.active{
  color:#fff;
  font-size: 18px;
}

.tabs .selector{
  height:100%;
  display:inline-block;
  position:absolute;
  background: #3e40db;
  left:0px;
  top:0px;
  z-index:1;
  border-radius: 16px;
  transition: width 1s, .6s;
  transition-timing-function: easeOutCirc;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="wrapper">
  <nav class="tabs">
    <div class="selector"></div>
    <a href="#" class="active">WHOLESALE SUPPLY</a>
    <a href="#">E-LEARNING</a>
    <a href="#">MEDICAL COMPLIANCE</a>
  </nav>
</div>

Stripe 网站上有类似的内容 - https://stripe.com/en-nl/sigma

您必须让每个字符都有自己的 html 元素才能改变其颜色。

没有 CSS 属性 只能更改按钮的某些字母的颜色。

如果您关心可访问性,请小心,这会毁掉屏幕阅读器。建议不要这样做。但是,如果是暂时的并且仅在动画期间发生,则可能没问题。

我看不出有什么简单的方法可以做到这一点。快速右键单击 -> 检查显示,即使您引用的站点实际上也使用 <canvas> 动画来绘制整个效果(即,它不是 CSS- 它只是一张图片)。这里有一些选项,但它们不是很完整,就是需要很长时间才能实现。

选项 1.) 获得类似效果的最快方法是添加 CSS 属性 mix-blend-mode: screen;到您的 links 并删除 color: #fff; 规则。但是,新颜色看起来会有些褪色:

.tabs a {
  position: relative;
  width: 200px;
  mix-blend-mode: screen;
}

选项 2.) 像引用的站点一样使用 <canvas> 创建动画,或者在用户单击选项卡区域时更改的动画 gif。这些过程中的任何一个都将花费很长时间,因为您必须创建图像或编写动画代码。

选项 3.) 将每个字母包裹在 <span> 中,并在 JavaScript 中使用 setTimeouts 设置何时根据动画的长度更改每个字母的颜色以及选择器前进的方向(如果您不介意它们褪色而不是立即改变颜色,则可以为每个动画设置 CSS 动画)。这里的一个问题是整个字母会立即改变颜色,而不是一次只改变一点。

选项 4.) 如果您可以完全控制导航元素的定位和大小,则可以通过编写大量 CSS 来重现效果(所以我不会试图找出整个事情都在这里,但我会解释如何去做)。这可能比它值得的工作更多。

为每个 link 创建一个副本,例如,在每个 hyperlink 中创建两个跨度,每个跨度中使用相同的文本。 将 span 直接放置在彼此之上,以便相应的文本重叠(即,您不应该能够看到底部的文本)。

将底层跨度文本颜色设置为白色,将顶部跨度设置为#3e40db。 CSS clip-path 属性 是可动画的,因此您可以使用 CSS 动画在选择器 div 移过它时隐藏顶部跨度层(因为您可以控制在元素大小、过渡时间和动画时间上,你应该能够在投入足够时间的情况下做到这一点)。基本上 clip-path 可以 "clip out" 一个元素中显示的矩形区域,所以如果你必须重叠 divs,然后用受控动画制作那个矩形区域 smaller/larger您可以准确控制何时隐藏顶部的水平矩形区域(即显示底部)。同样,主要问题是这将花费大量代码和很长时间 write/implement,因为您必须完善绝对定位、时间,并考虑选择器是否向左或向右移动一个div。但如果您愿意投入时间和精力,基本设置将如下所示:

@keyframes clip-animation-from-left {
    0% {
       clip-path: polygon(0px 0px, 0px 0px, 0px 300px, 0px 300px);
    }

    50% {
        clip-path: polygon(150px 0px, 300px 0px, 300px 300px, 150px 300px);
    }

    100% {
        clip-path: polygon(300px 0px, 300px 0px, 300px 300px, 300px 300px);
    }
}


/* You'll have to rewrite some JavaScript to add/remove classes determining which way the selector is coming */
.tabs a.active-from-left {
    animation-name: clip-animation-from-left;
    animation-duration: .4s;
}