最新版Safari浏览器中的linear-gradient到透明色的bug?

28

我正在应用一个基本的线性渐变,就像这样:

background-image:  linear-gradient(to top, red, rgba(0,0,0,0));

这个代码在除了 Safari 之外的其他地方都表现正常,但在 Safari 中透明的部分被渲染成黑灰色:

这是 Chrome 中的效果(应该是这样的):

在这里输入图片描述

而这是 Safari 中的效果:

在这里输入图片描述

我已经尝试用 -webkit- 前缀来修饰它,将 rgba 改为 rgba(0,0,0,0.001),但它从未变成实心透明。 这是一个 bug 吗?有没有办法解决这个问题?

这里有一个示例:https://jsfiddle.net/2Lrp3sv1/2/


3
设置rgba(255,0,0,0)是否更好?(适用于所有浏览器?) - vals
@vals 在我的 CSS 中呈现为红色,这很奇怪...在 JSFiddle 上可以正常工作。我尝试了 rgba(255,255,255,0),但它仍然从灰色变成白色 :) 不完全透明。 - valerio0999
首先,决定您想要在中心点使用哪种纯色。然后,我们可以计算出最终的颜色... - vals
6个回答

51
没有浏览器将 transparent 渲染为 rgba(255, 255, 255, 0),那完全是错误的。 根据CSS Color 3 规范transparent 始终是 rgba(0,0,0,0)。然而,几年前我们改变了颜色渐变的插值方式,并指定 应该在预乘 RGBA 空间中进行,正是为了解决这个问题并使对于 transparent 的插值效果如预期一样。看起来其他浏览器已经实现了这个变化,但 Safari 还没有。如果你想让 Safari 中的渐变效果相同,你需要使用颜色停止点,利用你正在进行插值的颜色的透明版本(如果这些颜色不同,则有时需要在同一位置使用两个颜色停止点),在这种情况下,使用 linear-gradient(to top, red, rgba(255,0,0,0))。或者就等着 Safari 跟上潮流吧! :)

2
也许“渲染”这个词不太合适。无论如何,会有一些人在听到检查规范时就感到头晕眼花。有没有更简单易懂的说法呢?如果有的话,我会点赞的。 - AJFarkas
1
我本来准备写Safari实际上确实执行了正确的颜色插值,因为从255,0,00,0,0的线性过渡实际上是从红色黑色,但后来我读了规格和关于预乘sRGBA空间的内容,现在完全有道理了。链接中的规格有EXAMPLE 23,它演示了在非预乘空间中计算红色到透明的不正确转换为黑色的情况!非常好而且信息量大的答案,+1。 - Christos Lytras
直到今天,这种行为仍然存在。Safari绝对是新的IE,人们应该停止使用它。 - Parziphal

47

这与浏览器渲染 transparent 的方式有关。

对于大多数浏览器,

transparent === rgba(255,255,255,0)

但 Safari 将其呈现为

transparent === rgba(0,0,0,0)

因此,如果你有一个从 transparentwhite(或 rgba(255,255,255,1))的渐变,对于大多数浏览器,你只是在梯度上改变透明度从0到1。

但对于Safari,你将透明度从0到1和颜色从2550进行了更改,因此你会得到一系列灰色的渐变色。

这让我疯狂了一段时间。


14
您不知道。那是苹果的创新。 - Nirmal
15
这个说法完全错误,我希望人们在传播错误信息之前能够查看规格或至少 MDN。没有任何浏览器将transparent视为rgba(255, 255, 255, 0),它总是rgba(0,0,0,0),是不同浏览器插值方式产生了 OP 所问的差异。有关更多细节,请查看我的答案。 - Lea Verou
2
很高兴你对学习如此热情。是否可以建议你和我更好地互动? 我完全愿意接受这不是一个正确的技术答案,甚至一个不同的口语化的答案会更好,但这个描述当时所看到的非常准确,帮助理解了解决方案。 如果您希望,我肯定可以提出一个不太正确的答案。 - AJFarkas
1
2021年更新:请查看Lea Verou的答案,以获得更清晰的了解实际情况。 - tenni

35
根据@AJFarkas所写,只需将transparent替换为rgba(255, 255, 255, 0),在Safari上就可以正常工作!在我的情况下,它是从白色渐变到透明再到白色的线性渐变。
background-image: linear-gradient(to right, #fff 10%, rgba(255, 255, 255, 0) 25%, rgba(255, 255, 255, 0) 75%, #fff 90%);

8
终于有一个提供实际解决方案的答案了。 - lenooh
这真是疯狂的变化,不过它确实有效! - Matt Lo

4

对于我的情况,看起来需要更改为

background-image: linear-gradient(rgba(243, 243, 251, 1), transparent);

to:

background: linear-gradient(rgba(243, 243, 251, 1), rgba(255, 255, 255, 0));

在Safari上完美运行。


1
我也在Safari中看到了这个问题。对我来说,它会变成浅红色,即使我使用的颜色都与红色无关。
我使用“transparent”作为值来解决这个问题。一旦我停止使用rgba,它就像预期的那样显示。

1
一旦我停止使用透明,改用rgba,它看起来就像预期的那样。这里发生了什么:D - Dejan Munjiza
1
也许你有不同的期望! - Mr Lister

1
我遇到了这样的情况,即渐变中的颜色是由CMS动态应用的,因此在Safari中需要考虑这个问题的Javascript修复方法。
假设您正在使用伪类来实现此目的,您可以使用js返回元素,创建一个新的样式标签并将其插入文档的头部。
<script>
    var col = document.querySelector('.my_div').style.color;
    var style = document.createElement('style');

    // Replace RGB with RGBA (we need the opacity)
    col = col.replace(/rgb/i, "rgba");
    col = col.replace(/\)/i,', 0)');

    //Create our new styles based on the returned colours
    style.innerHTML =
      '.my_div::before {' 
    + 'background-image: linear-gradient(to left, currentColor 0%, '
    + col 
    + ' 15%);'
    +'}';

    var ref = document.querySelector('script');
    // Insert our new styles before the first script tag
    ref.parentNode.insertBefore(style, ref);
</script>

这里是这个棒棒的技巧的源代码


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接