Working alternative for {background-clip: text} to achieve transparent text with gradient background in browsers other than Chrome

huangapple go评论72阅读模式
英文:

Working alternative for {background-clip: text} to achieve transparent text with gradient background in browsers other than Chrome

问题

I need help with the background-clip property in Chrome vs other browsers.

I want to create a logo and header with an animated gradient background for my website. Because logo and header are two separate elements, I'd like to create one background animation for both elements (instead of one for each and positioning them so the gradient animation looks the same), and then make their content / font transparent, so the gradient creates the illusion of making up the font color.

The svg used for the logo has a transparent stroke, and I wanted to use the background-clip CSS-property for the transparent text. However, that didn't work, as setting the background of the logo-text to white (obviously) prevents displaying the gradient below the element.

In order to have this approach work, I then used {mix-blend-mode: screen}, with black font-color and white background. This works perfectly in Chrome, however, when testing with Safari or Firefox, the entire p element is transparent, instead of only the text.

What I don't understand: Setting -webkit-background-clip: text; -moz-background-clip: text; doesn't solve the issue, but instead breaks the display in Chrome as well, not changing anything in Safari or Firefox. Setting -webkit-text-fill-color: transparent; -moz-text-fill-color: transparent; then makes the font color white, with the background still transparent. I could use an SVG with SVG masking - but I'd prefer not to use that instead of html for the text. Why does the code behave like that?

Below is a mockup of my code. The difference can be seen by opening the code in Safari or Firefox as opposed to Chrome or Edge, where it works fine:

CodePen Link

/* mockup CSS */

a {
  font-size: 200%;
  text-decoration: none;
}

.logo {
  display: flex;
  flex-direction: row;
  align-items: center;
  width: fit-content;
  height: 2.7rem;
}

.logo-text {
  padding: 0 0.6rem;
  font-weight: 700;
  font-size: 124%;
}

/* gradient animation CSS */

.logo-img {
  height: 2rem;
  background: transparent;
  background-clip: content-box;
  outline: 0.4rem solid white;
}

.logo-text.rainbow {
  color: black; /* transparent with mix-blend-mode & background-color */
  background: white;
  background-clip: text;
  mix-blend-mode: screen;
  padding: 0.2rem 0.6rem;
}

.logo {
  background: repeating-linear-gradient(to right, #ff0018, #ffa52c, #ffff41, #008018, #0000f9, #86007d, #ff0018);
  background-repeat: repeat-x;
  background-size: 400% 100%;
  animation: rainbow_animation 6s linear infinite;
}

@keyframes rainbow_animation {
  0% {
      background-position:100% 50%
  }
  100% {
      background-position:-33% 50%
  }
}
<div class="logo" id="home-redirect">
  <img src="https://www.dropbox.com/s/jvgikg1zez1c7kg/logo-test.svg?raw=1" class="logo-img" alt="Logo">
  <p class="logo-text rainbow"><a href="index.html">Logo</a></p>
</div>

How it should look vs. how it looks in Webkit / Gecko:

Working alternative for {background-clip: text} to achieve transparent text with gradient background in browsers other than Chrome

Working alternative for {background-clip: text} to achieve transparent text with gradient background in browsers other than Chrome

英文:

I need help with the background-clip property in Chrome vs other browsers.

I want to create a logo and header with an animated gradient background for my website. Because logo and header are two separate elements, I'd like to create one background animation for both elements (instead of one for each and positioning them so the gradient animation looks the same), and then make their content / font transparent, so the gradient creates the illusion of making up the font color.

The svg used for the logo has a transparent stroke, and I wanted to use the background-clip CSS-property for the transparent text. However, that didn't work, as setting the background of the logo-text to white (obviously) prevents displaying the gradient below the element.

In order to have this approach work, I then used {mix-blend-mode: screen}, with black font-color and white background. This works perfectly in Chrome, however, when testing with Safari or Firefox, the entire p element is transparent, instead of only the text.

What I don't understand: Setting -webkit-background-clip: text; -moz-background-clip: text; doesn't solve the issue, but instead breaks the display in Chrome as well, not changing anything in Safari or Firefox. Setting -webkit-text-fill-color: transparent; -moz-text-fill-color: transparent; then makes the font color white, with the background still transparent. I could use an SVG with SVG masking - but I'd prefer not to use that instead of html for the text. Why does the code behave like that?

Below is a mockup of my code. The difference can be seen by opening the code in Safari or Firefox as opposed to Chrome or Edge, where it works fine:

https://codepen.io/alessandrov/pen/gOQYwoy

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-css -->

/* mockup CSS */

a {
  font-size: 200%;
  text-decoration: none;
}

.logo {
  display: flex;
  flex-direction: row;
  align-items: center;
  width: fit-content;
  height: 2.7rem;
}

.logo-text {
  padding: 0 0.6rem;
  font-weight: 700;
  font-size: 124%;
}

/* gradient animation CSS */

.logo-img {
  height: 2rem;
  background: transparent;
  background-clip: content-box;
  outline: 0.4rem solid white;
}

.logo-text.rainbow {
  color: black; /* transparent with mix-blend-mode &amp; background-color */
  background: white;
  background-clip: text;
  mix-blend-mode: screen;
  padding: 0.2rem 0.6rem;
}

.logo {
  background: repeating-linear-gradient(to right, #ff0018, #ffa52c, #ffff41, #008018, #0000f9, #86007d, #ff0018);
  background-repeat: repeat-x;
  background-size: 400% 100%;
  animation: rainbow_animation 6s linear infinite;
}

@keyframes rainbow_animation {
  0% {
      background-position:100% 50%
  }
  100% {
      background-position:-33% 50%
  }
}

<!-- language: lang-html -->

&lt;div class=&quot;logo&quot; id=&quot;home-redirect&quot;&gt;
        &lt;img src=&quot;https://www.dropbox.com/s/jvgikg1zez1c7kg/logo-test.svg?raw=1&quot; class=&quot;logo-img&quot; alt=&quot;Logo&quot;&gt;
        &lt;p class=&quot;logo-text rainbow&quot;&gt;&lt;a href=&quot;index.html&quot;&gt;Logo&lt;/a&gt;&lt;/p&gt;
      &lt;/div&gt;

<!-- end snippet -->

How it should look vs. how it looks in Webkit / Gecko:

Working alternative for {background-clip: text} to achieve transparent text with gradient background in browsers other than Chrome

Working alternative for {background-clip: text} to achieve transparent text with gradient background in browsers other than Chrome

答案1

得分: 1

我可以使用混合模式来“填充”没有文字的部分。因此,我会有一个纯色蒙版放在渐变上面。

简单来说:文字是黑色,背景是白色。我说“只显示白色”。

我们还可以用它来创建深色模式的示例。
同样的逻辑:文字是白色,背景是黑色。我说“只显示深色”。

一个使用screen,另一个使用multiply混合模式。

背景中有一个渐变,透明文字透过它显示出来。

英文:

I can use blend modes to "fill" the part without text. So I would have a solid color mask to put on a gradient.

Simply: text is black and bg is white. I say "show only whites"

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-css -->

.cool{
  background: linear-gradient(120deg, red, blue);
}

.text{
  background: #fff;
  color: #000;
  mix-blend-mode: screen;
}

<!-- language: lang-html -->

&lt;span class=&quot;cool&quot;&gt;
  &lt;span class=&quot;text&quot;&gt;
    Your gradient text &lt;br&gt;
    goes here. That simple!
  &lt;/span&gt;
&lt;/span&gt;

<!-- end snippet -->

we can also make a dark mode example with it.
same logic: text is white and bg is black. I say "show only darks".

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-css -->

body{
  background: #000
}

.cool{
  background: linear-gradient(120deg, red, blue);
}

.text{
  background: #000;
  color: #fff;
  mix-blend-mode: multiply;
}

<!-- language: lang-html -->

&lt;span class=&quot;cool&quot;&gt;
  &lt;span class=&quot;text&quot;&gt;
    Your gradient text &lt;br&gt;
    goes here. That simple!
  &lt;/span&gt;
&lt;/span&gt;

<!-- end snippet -->

One uses screen the other uses multiply blend modes

there's a gradient in the back which shows up through the transparent text in both.

huangapple
  • 本文由 发表于 2023年6月5日 07:35:09
  • 转载请务必保留本文链接:https://go.coder-hub.com/76402823.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定