周末我注意到一个游戏中进度条的有趣设计。完成百分比以文本形式显示在条形中间,并且不会移动。但是,该文本与从左到右填充的条形的背景颜色相同。看起来一旦背景与文本重叠,文本就会变得不可见,但实际上,文本颜色在任何与背景重叠的地方都反转为白色。
我的第一想法是:我们如何复制这种设计模式,以及在此过程中我们可能会学到什么?
这是我想出的方法,但请确保在最新版本的 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
属性也是如此。因此,如果您决定使用这两个技巧中的任何一个,请务必提供回退方案。
好技巧。在动画循环中更改内容的想法也很巧妙。混合模式的东西也很好,只是浏览器支持有点可惜。
非常有信息量
不错的技巧,但像这样的文章 *确实* 需要包含支持信息。在不包含 IE 和除最新版本的 Android 之外的任何内容的(视觉上差异很大的)回退方案的情况下,这在现实世界中还不可行。 https://caniuse.cn/#feat=css-mixblendmode
100% 同意,并且这是一个简单的改进,在我看来。
我今天在手机上开始阅读这篇文章,被打断了,然后在笔记本电脑上继续阅读,结果发现演示不起作用(Chrome)。最初,我以为这是那些不太常用的但非常有用且支持良好的 CSS 属性之一。我错了,而且同时感到沮丧。
在前面说明浏览器支持,或者至少表明它不受广泛支持,将是非常棒的。
缺乏 *任何* 版本的 IE 支持对我来说几乎完全排除了它,我真不如不读!
对于移动/Electron 应用,也许它具有一定的价值。了解功能的存在固然很好,但当你发现它在现实世界中几乎无法使用时,就会感到非常沮丧。
精彩的信息……
我多年来一直期待着 CSS 中的
mix-blend-mode
功能。我所有的设计师都希望在其透明度和阴影效果上使用花哨的混合模式。可惜 IE 还不支持,Edge/IE 平台状态 也令人相当沮丧,如果他们甚至在版本 14 中添加了它,我会感到惊讶您也可以使用 CSS 剪辑来实现这种效果,像 https://github.com/salsita/jq-clipthru 这样的库可以为您做到这一点。
http://salsita.github.io/jq-clipthru/demo/
实际上,就在几个月前,它还无法通过 CSS 动画化 content 属性。太棒了!
作为 CSS 新手,我发现这个很有趣,偶然发现它在 Chrome v46.0.2490.7a m Win 7 64 的稳定版中无法工作,但在 Firefox、Chrome Canary (48.02540.0) 和 Chrome Android 中可以工作!
如果我理解 Scott 的链接,它应该在 Chrome 46 中工作,但对我来说不行。在“常规”模式下不行,在隐身模式或访客模式下也不行。
我也在使用 Chrome v46.0.2490.7a,对我来说也不行… :P
似乎自动百分比目前仅在 Chrome Canary 中有效。
首先,访问 caniuse.com。
检查 mix-blend-mode……嗯,即使在 IE11 中也没有支持。
忘记这篇文章吧。十年后再回来重读它。
似乎很多人说“没有浏览器支持 - 无法使用它”。
为什么不将其作为渐进增强来添加呢?创建一个使用 CSS 的基本版本 - 然后之后添加 mix-blend-mode,这样任何可以处理它的浏览器都能获得增强效果 - 无法处理的浏览器则获得一个可靠的基本版本。
问题在于它在 Safari 9 上某种程度上得到了支持,因为图形的颜色会发生变化以使其可读。但图形的值在 Safari 上永远不会改变 - 随着进度条的推移,它始终为 0%。在 Chrome 中,您可以看到值正确递增。
使用这样的东西意味着我需要测试很多情况,找出不支持的情况(如果存在部分支持,那么多少部分支持是可以接受的?),然后编写代码、测试和维护所有这些。或者,在这种情况下,我可以寻找一个可以在任何浏览器中使用 JS 的 JS 组件。
不要误会我的意思,我很喜欢了解这些东西,但在实际使用中,当支持不仅不确定,而且不是一个清晰的“有效/无效”界限时,这些东西就会有问题。
重要的不仅仅是浏览器支持,还有回退机制 - 如果不支持此属性会发生什么?通常它们会被忽略。
检查了这两个示例后,我发现丢失了一定程度的高级可视化效果,但网站的功能不受影响。
在将某些东西视为不可用之前,请在不支持它的浏览器中检查它,并查看如何使其优雅降级,你甚至可能会发现它会自动优雅降级(想想 IE7 中的 border-radius)。
我认为在前面提供一些关于支持的信息也会很有用。不是为了让我决定是否阅读这篇文章;我仍然会阅读它,因为它可能有助于了解我将来可能考虑的事情。
但在这种情况下,我需要支持信息,因为在没有可用的演示的情况下,这篇文章很难理解。作者向我们展示了一个演示,并说“很酷,对吧?”但我不知道我应该看到什么,或者演示应该向我展示什么。因此,我需要付出两倍的努力才能理解这篇文章。
如果在前面提供支持信息,我就可以启动正确的浏览器来查看文章,而无需尝试所有浏览器,或求助于 caniuse。
David,你完全正确。我已更新了帖子,其中包含有关浏览器支持的说明,并在演示之前也使其更加清晰。
嘿 - 我认为拥有一个没有任何混合模式的版本会很酷。
你怎么认为?
http://codepen.io/anon/pen/BoJwZR
这是一个非常巧妙的相同想法的实现。我喜欢它!
你好,
你能详细说明一下为什么 **mix-blend-mode** 的 **difference** 值会导致两个受影响的颜色某种程度上合并在一起变成 *255,255,255* 吗?
这里需要一些色彩理论的知识!
谢谢
我还分享了一张关于网页设计趋势的幻灯片。我讨论了大多数优质网站使用的一些基本主题。
呵呵,大约两周前,我使用了 difference 混合模式来为 扁平化 UI 按钮创建类似的悬停效果。它还显示了一个不错的回退(只是没有过渡)以及如何使用 @supports 来确保良好的回退。
你说“请确保使用最新版本的 Chrome 以确保演示正常工作”。
具有讽刺意味的是,它在 Firefox 中运行良好,但在 Chrome 46 中,我在 codepen 小部件中看到的只是一片黑色。
(跑题了,但“在 Chrome 中观看效果最佳”是我对当今网络的一个不满……就好像我们忘记了那些“在 Netscape 中观看效果最佳”和“在 IE 中观看效果最佳”按钮在过去教给我们的所有经验教训。)
这位仁兄说得对,我使用的是最新版本的 Chrome,并且看到的全是黑色,但在 Firefox 中运行良好,也许这篇文章发布得有点早了,因为大多数读者都看不到任何东西?
承接 @ludwig 上面的评论,这里有一个兼容 IE9 的版本,无需混合模式魔法
http://codepen.io/theprojectsomething/pen/pjadwY
我从电视字幕中得到了这个想法。现在 text-shadow 得到更广泛的支持,它是一种保持文本可读性的方法,并且您可以设置与设计相匹配的颜色。
我之前使用 svg 和蒙版创建了类似的效果。它与滑块和过渡以及旧版浏览器配合得很好。 http://documenta60.de