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
/* 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:
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"
.cool{
background: linear-gradient(120deg, red, blue);
}
.text{
background: #fff;
color: #000;
mix-blend-mode: screen;
}
<span class="cool">
<span class="text">
Your gradient text <br>
goes here. That simple!
</span>
</span>
we can also make a dark mode example with it.
same logic: text is white and bg is black. I say "show only darks".
body{
background: #000
}
.cool{
background: linear-gradient(120deg, red, blue);
}
.text{
background: #000;
color: #fff;
mix-blend-mode: multiply;
}
<span class="cool">
<span class="text">
Your gradient text <br>
goes here. That simple!
</span>
</span>
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.