CSS 中基于背景颜色自动反转文本颜色

Avatar of Robin Rendle
Robin Rendle 发布

DigitalOcean 为您旅程的每个阶段提供云产品。立即开始使用 200 美元的免费额度!

周末我注意到一个游戏中进度条的有趣设计。完成百分比以文本形式显示在条形中间,并且不会移动。但是,该文本与从左到右填充的条形的背景颜色相同。看起来一旦背景与文本重叠,文本就会变得不可见,但实际上,文本颜色在任何与背景重叠的地方都反转为白色。

我的第一想法是:我们如何复制这种设计模式,以及在此过程中我们可能会学到什么?

这是我想出的方法,但请确保在最新版本的 Chrome 上查看此演示,以确保一切正常

查看 CodePen 上 Robin Rendle (@robinrendle) 编写的 纯 CSS 加载条

很酷,对吧?这可以通过 CSS 中 mix-blend-mode 的强大魔力实现。

让我们先看看标记

<div class="wrapper">
  <div class="bg">
    <div class="text"></div>
  </div>
</div>

.wrapper 将我们的元素保持在适当位置,.bg 将是我们的加载条,它会随着时间的推移而增加,而我们的 .text 元素将用作百分比信息。

让我们将整个过程都用 CSS 实现

Web 上的“真实”加载程序很可能由 JavaScript 提供支持,并以某种方式对实际数据做出反应。但是,既然我们在这里玩得开心,让我们让整个过程,甚至包括计数,都只在 CSS 中发生(使用 SCSS 来帮助循环)。

我们将设置我们的变量并设置 .bg 元素的样式

$loadingTime: 10s;
$color: rgb(255, 0, 0);

.bg {
  background-color: $color;
  animation: loading $loadingTime linear infinite;
}

使用 loading 动画,我们将更改元素的宽度,如下所示

@keyframes loading {
  0% {
    width: 0;
  } 100% {
    width: 100%;
  }
}

也许我们可以隐藏溢出并使用 transform 属性移动背景框(出于 性能原因),但在这个小演示中,我认为只 动画化 width 属性是可以的。

要使用正确的百分比值更新 .text 元素的内容,我们必须有点狡猾,并使用伪元素和动画的混合。首先,我们将保持 <div> 为空,在定义动画之前,将其 after 伪元素content 设置为 0%

.text {
  color: $color;
  width: 200px;
  border: 1px solid $color;

  &:after {
    padding-left: 20px;
    content: "0%";
    display: block;
    text-align: center;
    animation: percentage $loadingTime linear infinite;
  }
}

因此,我们希望对上面的 percentage 动画执行的操作是使用 1 到 100 中的每个值更新我们的 content 属性,如下所示

@keyframes percentage {
  0% {
    content: "0%";
  }
  1% {
    content: "1%"; 
  }
  /* ... */
  100% {
    content: "100%";
  }
}

但是,与其手动创建所有这些 @keyframe 选择器,不如让我们熟悉一下 Sass 中的 @for 循环语法

@keyframes percentage { 
  @for $i from 1 through 100 {
    $value: $i + "%";
    #{$value} {
      content: $value;
    }
  }
}

如果这看起来有点吓人,别担心!在第三行,我们添加当前循环中的任何数字(我们称之为 $i),并通过附加 % 将其转换为字符串并将其分配给变量。然后,我们可以使用 插值 使每个 @keyframe 选择器将 content 属性更新为正确的值。

颜色交换

最后,我们要做的就是设置伪元素的颜色和 mix-blend-mode,就是这样;一个纯 CSS 加载程序,其中背景颜色会影响前景色文本

.text:after {
    /* This value is the OPPOSITE color of our background */
    color: rgb(0, 255, 255); 
    mix-blend-mode: difference;
}

查看 CodePen 上 Robin Rendle (@robinrendle) 编写的 纯 CSS 加载条

使用 difference 混合模式,我们必须将文本元素的颜色值设置为背景的反色。因此,如果我们的背景是 rgb(0, 0, 0),我们需要将文本伪元素设置为 rgb(255, 255, 255)

我认为这个小演示帮助我们认识到 mix-blend-mode 属性有多么有用。将来会出现各种类似的情况,其中界面可以以我们以前从未想到的方式显示信息。

完全更改文本颜色

此技术的酷点在于,某些文本是一种颜色,而其他部分的文本是另一种颜色。反转仅仅基于覆盖和未覆盖的部分,即使它只是字母的一部分。

如果您正在寻找更多基于可访问性的“更改文本颜色以确保其具有足够的对比度”的功能,Sass 也可以帮助您实现这一点

另一个示例

XOXO 网站 广泛使用了 mix-blend-mode: darken; 来使背景、形状和文本以我们尚未在 Web 上广泛看到的方式进行微妙/有趣/美丽的交互。

浏览器支持

mix-blend-mode 属性 目前支持度并不高,可动画化的 content 属性也是如此。因此,如果您决定使用这两个技巧中的任何一个,请务必提供回退方案。