如何使用CSS为径向渐变设置动画? [英] How to animate a radial-gradient using CSS?

查看:74
本文介绍了如何使用CSS为径向渐变设置动画?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试为div框创建放射状渐变光泽效果,但我不确定这样做的最佳方法是什么.我没有发现实现我想要实现的目标的资源;只是光泽会影响看起来像叠加的效果.

我发现的大多数示例都是这样的 http://jsfiddle.net/nqQc7/512/.

下面,我显示了我要创建的内容.

 #shine-div {
  height: 30vh;
  width: 60vw;
  margin-right: auto;
  margin-left: auto;
  border-radius: 10px;
  /*background: radial-gradient(ellipse farthest-corner at right top, #FFFFFF 0%, #ffb3ff 8%, #ff33ff 25%, #800080 62.5%, #b300b3 100%);*/
  display: flex;
  justify-content: center;
  align-items: center;
  color: white;
  font-weight: bold;
  animation: colorChange 5s infinite;
}

@keyframes colorChange {
  0% {
    background: radial-gradient(ellipse farthest-corner at left top, #FFFFFF 0%, #ffb3ff 8%, #ff33ff 25%, #800080 62.5%, #b300b3 100%)
  }
  50% {
    background: radial-gradient(ellipse farthest-corner at top, #FFFFFF 0%, #ffb3ff 8%, #ff33ff 25%, #800080 62.5%, #b300b3 100%)
  }
  100% {
    background: radial-gradient(ellipse farthest-corner at right top, #FFFFFF 0%, #ffb3ff 8%, #ff33ff 25%, #800080 62.5%, #b300b3 100%)
  }
} 

 <div id="shine-div">
  Shine
</div> 

是否可以这样做?我还想使白色的光晕从顶部向左平滑过渡吗?我的尝试是否在正确的轨道上?

解决方案

您可以不同地进行渐变并为位置设置动画.诀窍是将渐变的大小加倍,并使色标的值停止为实际值的一半,以便保持相同的视觉渐变,然后可以从左到右对其进行动画处理.

由于计算了最远的角,它看上去与动画中定义的渐变完全不一样.

 #shine-div {
  height: 30vh;
  width: 60vw;
  margin-right: auto;
  margin-left: auto;
  border-radius: 10px;
  background: radial-gradient(farthest-corner at top, #FFFFFF 0%, #ffb3ff 4%, #ff33ff 12.25%, #800080 31.25%, #b300b3 50%) top right/200% 200%;
  display: flex;
  justify-content: center;
  align-items: center;
  color: white;
  font-weight: bold;
  animation: colorChange 5s infinite alternate;
}

@keyframes colorChange {
  to {
    background-position:top left;
  }
 } 

 <div id="shine-div">
  Shine
</div> 


要更接近渐变,您还必须为background-size 设置动画(有关计算的详细信息,请参见下文)

 #shine-div {
  height: 30vh;
  width: 60vw;
  margin-right: auto;
  margin-left: auto;
  border-radius: 10px;
  background: radial-gradient(farthest-corner at top, #FFFFFF 0%, #ffb3ff 8%, #ff33ff 24.5%, #800080 62.5%, #b300b3 100%);
  display: flex;
  justify-content: center;
  align-items: center;
  color: white;
  font-weight: bold;
  animation: colorChange 5s infinite alternate linear;
}

@keyframes colorChange {
  from { /* radial-gradient(farthest-corner at top right, ..) */
    background-position:left top;
    background-size:200% 100%;
  
  }
  49.9% {
    background-position:left top;  
  }
  50% { /* radial-gradient(farthest-corner at top center, ..) */
    background-size:100% 100%;
  }
  50.1% {
    background-position:right top; 
  }
  to { /* radial-gradient(farthest-corner at top left, ..) */
    background-position:right top;
    background-size:200% 100%;
  }
 } 

 <div id="shine-div">
  Shine
</div> 

您还可以在考虑伪元素的情况下制作相同的动画,并进行变换以使其具有更好的性能:

 #shine-div {
  height: 30vh;
  width: 60vw;
  margin-right: auto;
  margin-left: auto;
  border-radius: 10px;
  display: flex;
  justify-content: center;
  align-items: center;
  color: white;
  font-weight: bold;
  overflow:hidden;
  position:relative;
  z-index:0;
}
#shine-div:before {
  content:"";
  position:absolute;
  z-index:-1;
  top:0;
  left:0;
  width:400%;
  height:200%;
  background: radial-gradient(farthest-corner at top, #FFFFFF 0%, #ffb3ff 4%, #ff33ff 12.25%, #800080 31.25%, #b300b3 50%);
  animation: colorChange 5s infinite alternate linear;
}

@keyframes colorChange {
  from {
    transform:translateX(-50%);
  }
  50% {
    transform:scaleX(0.75) translateX(-50%)
  }
  to {
    transform:translateX(-25%);
  }
 } 

 <div id="shine-div">
  Shine
</div> 



更深入

为了使答案更通用,我将详细说明如何从两个不同的位置为任何种类的渐变设置动画.主要技巧是以不同的方式编写渐变以使其定义为常数(radial-gradient(<constant_definition>)并为background-position(在某些情况下为background-size)设置动画

让我们认为渐变为background:radial-gradient(Rh Rv at X Y, color1 p1, color2 p2),其中RhRy分别是椭圆的水平半径和垂直半径(如果两者相等或仅使用一个值,则为圆).

首先,我们将渐变大小加倍.此技巧将使我们能够轻松地使用百分比值来调整渐变的位置(在此处说明:在线性位置上将百分比值与背景位置一起使用渐变)

如果半径是用像素值定义的,那么我们会保留它,但如果半径是用百分比值定义的,则将它除以2,因为它是相对于他已增大的大小而言的.如果两个半径均以百分比表示,我们既可以将它们都除以2,也可以保留它们,然后将色标除以2.

第二,我们删除at X Y,它将使渐变出现在中心,因此我们需要使用background-position校正位置.显然,如果渐变位于0 0,则需要使用background-position:100% 100%

绿色框是我们背景的两倍,是元素(黑色框)的两倍,红色圆圈是我们的渐变.通过调整背景位置,我们可以将渐变直观地定位在0 0.

对于任何XY值,我们在逻辑上将具有background-position:calc(100% - X) calc(100% - Y)

如果X,Y是像素值,我们也可以使用background-position: right -X bottom -Y(请注意,它是-X而不是- X,我们使用负值)

示例:

具有像素值

 .box {
  height:150px;
  width:150px;
  border:1px solid;
  display:inline-block;
} 

 <div class="box" style="background:radial-gradient(20% 100px at 20px 30px,red 30%,blue 60%);"></div>
<div class="box" style="background:radial-gradient(10% 100px,red 30%,blue 60%) right -20px bottom -30px/200% 200%;"></div>
<br>
<div class="box" style="background:radial-gradient(40% 40% at 40px 50px,yellow 30%,blue);"></div>
<div class="box" style="background:radial-gradient(40% 40%,yellow 15%,blue 50%) right -40px bottom -50px/200% 200%;"></div>
<div class="box" style="background:radial-gradient(20% 20%,yellow 30%,blue) right -40px bottom -50px/200% 200%;"></div> 

带有百分比值

 .box {
  height:150px;
  width:150px;
  border:1px solid;
  display:inline-block;
} 

 <div class="box" style="background:radial-gradient(20% 100px at 50% 10%,red 30%,blue 60%);"></div>
<div class="box" style="background:radial-gradient(10% 100px,red 30%,blue 60%) calc(100% - 50%) calc(100% - 10%)/200% 200%;"></div>
<br>
<div class="box" style="background:radial-gradient(40% 40% at 30% 70%,yellow 30%,blue);"></div>
<div class="box" style="background:radial-gradient(40% 40%,yellow 15%,blue 50%) calc(100% - 30%) calc(100% - 70%)/200% 200%;"></div>
<div class="box" style="background:radial-gradient(20% 20%,yellow 30%,blue) calc(100% - 30%) calc(100% - 70%)/200% 200%;"></div> 

因此,如果我们要从以下设备制作动画:

radial-gradient(Rh Rv at X Y, color1 p1, color2 p2)

radial-gradient(Rh Rv at X1 Y2, color1 p1, color2 p2)

我们用不同的方式编写它,并为background-position设置动画:

 .box {
  height:150px;
  width:150px;
  border:1px solid;
  display:inline-block;
}
.first {
  background:radial-gradient(10% 100px,red 30%,blue 60%) calc(100% - 50%) calc(100% - 10%)/200% 200%;
  animation:change1 2s linear infinite alternate;
}
.second {
  background:radial-gradient(20% 20%,yellow 30%,blue)right -50px bottom 0/200% 200%;
  animation:change2 2s linear infinite alternate;
}

@keyframes change1 {
  to {
    background-position:calc(100% + 10%) calc(100% - 80%);
  }
}

@keyframes change2 {
  to {
    background-position:right -100px bottom -100px;
  }
} 

 <div class="box first" ></div>
<div class="box second"></div> 


现在,让我们考虑更棘手的情况,例如我们的初始示例,使用farthest-side来定义大小.我们将执行相同的逻辑并进行转换

radial-gradient(farthest-side at X Y, color1 p1, color2 p2);

radial-gradient(farthest-side, color1 p1, color2 p2) Px Py/Sx Sy no-repeat;

我将为一个轴(X)进行解释,而对另一根轴进行解释

farthest-side将半径定义为从渐变中心到渐变框最远侧的距离(默认情况下,渐变框是元素本身,因为我们没有定义任何大小).如果X是百分比值,则半径是X100% - X之间的最大值,并且在变换的渐变中,半径将是50%,因为我们位于中心.因此,我们需要将第一个半径与50%*Sx

匹配

如果X50%,则Sx应该是100%,如果X0100%,则Sx应该是200%.

公式为Sx = max(X,100% - X)*2

在这种情况下,由于形状应接触一侧的渐变的性质,位置更容易

  • 如果[0 50%[ Px中的X应该是100%(right)
  • 如果X50%,则Px的任何值都将生效,因为Sx=100%
  • 如果]50% 100%] Px中的X应该是0%(left)

相关问题:将百分比值与线性梯度的背景位置一起使用

示例:

 .box {
  height:150px;
  width:150px;
  border:1px solid;
  display:inline-block;
} 

 <div class="box" style="background:radial-gradient(farthest-side at 20% 60%, red 20%, blue 100%, yellow 100%)" ></div>
<div class="box" style="background:radial-gradient(farthest-side, red 20%, blue 100%, yellow 50%) 100% 0/calc(80%*2) calc(60%*2)"></div>
<br>
<div class="box" style='background:radial-gradient(farthest-side at 22% 100%,red 40%, blue 100%,yellow 100%)'></div>
<div class="box" style="background:radial-gradient(farthest-side,red 40%, blue 100%,yellow 100%) 100% 0/calc(78%*2) calc(100%*2)"></div> 

对于farthest-corner,我们执行完全相同的操作:

 .box {
  height:150px;
  width:150px;
  border:1px solid;
  display:inline-block;
} 

 <div class="box" style="background:radial-gradient(farthest-corner at 20% 60%, red 20%, blue 50%, yellow 60%)" ></div>
<div class="box" style="background:radial-gradient(farthest-corner, red 20%, blue 50%, yellow 60%) 100% 0%/calc(80%*2) calc(60%*2)"></div>
<br>
<div class="box" style="background:radial-gradient(farthest-corner at 40% 100%, red 20%, blue 50%, yellow 60%)" ></div>
<div class="box" style="background:radial-gradient(farthest-corner, red 20%, blue 50%, yellow 60%) 100% 0%/calc(60%*2) calc(100%*2)"></div> 

我们也可以将farthest-side(或farthest-corner)转换为Rh Rv并进行先前的计算,但是它对动画没有用,因为我们将有两个半径不同的渐变,而我们需要相同的渐变

 .box {
  height:150px;
  width:150px;
  border:1px solid;
  display:inline-block;
} 

 <div class="box" style="background:radial-gradient(farthest-side at 20% 60%, red 20%, blue 100%, yellow 100%)" ></div>
<div class="box" style="background:radial-gradient(80% 60% at 20% 60%, red 20%, blue 100%, yellow 100%)" ></div>
<div class="box" style="background:radial-gradient(80% 60%, red 10%, blue 50%, yellow 50%) 80% 40%/200% 200%"></div> 

如果X是像素值,则有两种情况:

  • 该元素具有固定的宽度:在这种情况下,我们可以简单地将X的像素值转换为宽度的百分比,并执行与上述相同的逻辑.
  • 该元素的宽度可变:在这种情况下,转换渐变非常困难(可能是不可能的),因为形状会根据宽度而变化.当width-X > X时,我们将具有变量半径;当width-X < X时,我们将具有固定半径.我认为我们无法使用background-sizebackground-position来表达这一点.示例:

 body {
  margin:0;
  height:100vh;
  background:radial-gradient(farthest-side at 400px 200px,blue 40%,yellow 50%);
} 

考虑到Sx=min(X,100% - X)*2closest-side将执行相同的逻辑,但我们应添加no-repeatbackground-color等于渐变中的最后一种颜色,因为尺寸小于100%

 .box {
  height:150px;
  width:150px;
  border:1px solid;
  display:inline-block;
} 

 <div class="box" style="background:radial-gradient(closest-side at 20% 60%, red 20%, blue 100%, yellow 100%)" ></div>
<div class="box" style="background:radial-gradient(closest-side, red 20%, blue 100%, yellow 100%) 0 100%/calc(20%*2) calc(40%*2)"></div>
<div class="box" style="background:radial-gradient(closest-side, red 20%, blue 100%, yellow 100%) 0 100%/calc(20%*2) calc(40%*2) no-repeat,yellow"></div>
<br>
<div class="box" style='background:radial-gradient(closest-side at 22% 10%,red 40%, blue 100%,yellow 100%)'></div>
<div class="box" style="background:radial-gradient(closest-side,red 40%, blue 100%,yellow 100%) 0 0/calc(22%*2) calc(10%*2)"></div>
<div class="box" style="background:radial-gradient(closest-side,red 40%, blue 100%,yellow 100%) 0 0/calc(22%*2) calc(10%*2) no-repeat,yellow"></div> 

我们可以对closest-corner做同样的事情,但是由于渐变会使渐变框溢出,因此我们会遇到一些问题.

 .box {
  height:150px;
  width:150px;
  border:1px solid;
  display:inline-block;
} 

 <div class="box" style="background:radial-gradient(closest-corner at 20% 60%, red 20%, blue 100%, yellow 100%)" ></div>
<div class="box" style="background:radial-gradient(closest-corner, red 20%, blue 100%, yellow 100%) 0 100%/calc(20%*2) calc(40%*2)"></div>
<div class="box" style="background:radial-gradient(closest-corner, red 20%, blue 100%, yellow 100%) 0 100%/calc(20%*2) calc(40%*2) no-repeat,yellow"></div> 

要纠正此问题,我们可以将色标除以2,以确保将整个渐变保留在内部.然后我们将尺寸增大两倍,并调整位置

 .box {
  height:150px;
  width:150px;
  border:1px solid;
  display:inline-block;
} 

 <div class="box" style="background:radial-gradient(closest-corner at 20% 60%, red 20%, blue 100%, yellow 100%)" ></div>
<div class="box" style="background:radial-gradient(closest-corner, red 10%, blue 50%, yellow 50%) -100% 33%/calc(20%*4) calc(40%*4)"></div>
<div class="box" style="background:radial-gradient(closest-corner, red 10%, blue 50%, yellow 50%) -100% 33%/calc(20%*4) calc(40%*4) no-repeat,yellow"></div>
<br>
<div class="box" style='background:radial-gradient(closest-corner at 22% 10%,red 40%, blue 100%,yellow 100%)'></div>
<div class="box" style="background:radial-gradient(closest-corner,red 20%, blue 50%,yellow 50%) -100% 0%/calc(22%*4) calc(10%*4)"></div>
<div class="box" style="background:radial-gradient(closest-corner,red 20%, blue 50%,yellow 50%) -164% -18%/calc(22%*4) calc(10%*4) no-repeat,yellow"></div> 


即使没有动画,也更支持没有at X Y的渐变语法.某些类似Safari的浏览器不支持at(如何使径向渐变在Safari中起作用?)

I am trying to create a radial-gradient shine affect to a div box and I am unsure whats the best way of doing so. I Have found no resources of achieving what I want to achieve; just shine affects which look like overlay.

Most of the examples I have found looks like this http://jsfiddle.net/nqQc7/512/.

Below I have displayed what I am trying to create.

#shine-div {
  height: 30vh;
  width: 60vw;
  margin-right: auto;
  margin-left: auto;
  border-radius: 10px;
  /*background: radial-gradient(ellipse farthest-corner at right top, #FFFFFF 0%, #ffb3ff 8%, #ff33ff 25%, #800080 62.5%, #b300b3 100%);*/
  display: flex;
  justify-content: center;
  align-items: center;
  color: white;
  font-weight: bold;
  animation: colorChange 5s infinite;
}

@keyframes colorChange {
  0% {
    background: radial-gradient(ellipse farthest-corner at left top, #FFFFFF 0%, #ffb3ff 8%, #ff33ff 25%, #800080 62.5%, #b300b3 100%)
  }
  50% {
    background: radial-gradient(ellipse farthest-corner at top, #FFFFFF 0%, #ffb3ff 8%, #ff33ff 25%, #800080 62.5%, #b300b3 100%)
  }
  100% {
    background: radial-gradient(ellipse farthest-corner at right top, #FFFFFF 0%, #ffb3ff 8%, #ff33ff 25%, #800080 62.5%, #b300b3 100%)
  }
}

<div id="shine-div">
  Shine
</div>

Is it possible to do this? I'd also like to make the white shine on top to go from left to right smoothly? Am I even on the right track with my attempt?

解决方案

You can do the gradient differently and animate the position. The trick is to double the size of the gradient and make the value of color stop half of their actual values so you keep the same visual gradient then you can animate it from left to right.

It won't look exactly the same as the gradient you defined in the animation due to the calculation of farthest-corner.

#shine-div {
  height: 30vh;
  width: 60vw;
  margin-right: auto;
  margin-left: auto;
  border-radius: 10px;
  background: radial-gradient(farthest-corner at top, #FFFFFF 0%, #ffb3ff 4%, #ff33ff 12.25%, #800080 31.25%, #b300b3 50%) top right/200% 200%;
  display: flex;
  justify-content: center;
  align-items: center;
  color: white;
  font-weight: bold;
  animation: colorChange 5s infinite alternate;
}

@keyframes colorChange {
  to {
    background-position:top left;
  }
 }

<div id="shine-div">
  Shine
</div>


To get more closer to your gradients you have to also animate the background-size (see below for calculation details)

#shine-div {
  height: 30vh;
  width: 60vw;
  margin-right: auto;
  margin-left: auto;
  border-radius: 10px;
  background: radial-gradient(farthest-corner at top, #FFFFFF 0%, #ffb3ff 8%, #ff33ff 24.5%, #800080 62.5%, #b300b3 100%);
  display: flex;
  justify-content: center;
  align-items: center;
  color: white;
  font-weight: bold;
  animation: colorChange 5s infinite alternate linear;
}

@keyframes colorChange {
  from { /* radial-gradient(farthest-corner at top right, ..) */
    background-position:left top;
    background-size:200% 100%;
  
  }
  49.9% {
    background-position:left top;  
  }
  50% { /* radial-gradient(farthest-corner at top center, ..) */
    background-size:100% 100%;
  }
  50.1% {
    background-position:right top; 
  }
  to { /* radial-gradient(farthest-corner at top left, ..) */
    background-position:right top;
    background-size:200% 100%;
  }
 }

<div id="shine-div">
  Shine
</div>

You can also do the same animation considering pseudo element and transform to have better performance:

#shine-div {
  height: 30vh;
  width: 60vw;
  margin-right: auto;
  margin-left: auto;
  border-radius: 10px;
  display: flex;
  justify-content: center;
  align-items: center;
  color: white;
  font-weight: bold;
  overflow:hidden;
  position:relative;
  z-index:0;
}
#shine-div:before {
  content:"";
  position:absolute;
  z-index:-1;
  top:0;
  left:0;
  width:400%;
  height:200%;
  background: radial-gradient(farthest-corner at top, #FFFFFF 0%, #ffb3ff 4%, #ff33ff 12.25%, #800080 31.25%, #b300b3 50%);
  animation: colorChange 5s infinite alternate linear;
}

@keyframes colorChange {
  from {
    transform:translateX(-50%);
  }
  50% {
    transform:scaleX(0.75) translateX(-50%)
  }
  to {
    transform:translateX(-25%);
  }
 }

<div id="shine-div">
  Shine
</div>



More in-depth

To make the answer more generic, I am going to detail how you can animate any kind of gradient from two different position. The main trick is to write the gradient differently to have its definition a constant ( radial-gradient(<constant_definition>) ) and animate the background-position (and the background-size in some cases)

Let's consider our gradient to be background:radial-gradient(Rh Rv at X Y, color1 p1, color2 p2) where Rh and Ry are respectively the horizontal radius and vertical radius of our ellipse (if both are equal or only one value is used then it's a circle).

First, we double the size of the gradient. This trick will allow us to easily adjust the position of the gradient using percentage value (explained here: Using percentage values with background-position on a linear gradient)

If the radius is defined with pixel values we keep it but if it's defined with percentage value we divide it by 2 since it's relative to the size that he have increased. If both radius are in percentage we can either divide both by 2 or keep them and divide the color stops by 2.

Second, we remove the at X Y which will bring the gradient in the center thus we need to rectify the position using background-position. It's clear that if the gradient was at 0 0 we need to use background-position:100% 100%

The green box is our background twice bigger than the element (the black box) and the red circle is our gradient. By adjusting the background position we visually position the gradient at 0 0.

For any X, Y values we will logically have background-position:calc(100% - X) calc(100% - Y)

If X,Y are pixel values we can also use background-position: right -X bottom -Y (note that it' -X and not - X, we use the negative value)

Examples:

With pixel values

.box {
  height:150px;
  width:150px;
  border:1px solid;
  display:inline-block;
}

<div class="box" style="background:radial-gradient(20% 100px at 20px 30px,red 30%,blue 60%);"></div>
<div class="box" style="background:radial-gradient(10% 100px,red 30%,blue 60%) right -20px bottom -30px/200% 200%;"></div>
<br>
<div class="box" style="background:radial-gradient(40% 40% at 40px 50px,yellow 30%,blue);"></div>
<div class="box" style="background:radial-gradient(40% 40%,yellow 15%,blue 50%) right -40px bottom -50px/200% 200%;"></div>
<div class="box" style="background:radial-gradient(20% 20%,yellow 30%,blue) right -40px bottom -50px/200% 200%;"></div>

With percentage values

.box {
  height:150px;
  width:150px;
  border:1px solid;
  display:inline-block;
}

<div class="box" style="background:radial-gradient(20% 100px at 50% 10%,red 30%,blue 60%);"></div>
<div class="box" style="background:radial-gradient(10% 100px,red 30%,blue 60%) calc(100% - 50%) calc(100% - 10%)/200% 200%;"></div>
<br>
<div class="box" style="background:radial-gradient(40% 40% at 30% 70%,yellow 30%,blue);"></div>
<div class="box" style="background:radial-gradient(40% 40%,yellow 15%,blue 50%) calc(100% - 30%) calc(100% - 70%)/200% 200%;"></div>
<div class="box" style="background:radial-gradient(20% 20%,yellow 30%,blue) calc(100% - 30%) calc(100% - 70%)/200% 200%;"></div>

So if we want to animate a gadient from:

radial-gradient(Rh Rv at X Y, color1 p1, color2 p2)

to

radial-gradient(Rh Rv at X1 Y2, color1 p1, color2 p2)

we write it differently and we animate the background-position:

.box {
  height:150px;
  width:150px;
  border:1px solid;
  display:inline-block;
}
.first {
  background:radial-gradient(10% 100px,red 30%,blue 60%) calc(100% - 50%) calc(100% - 10%)/200% 200%;
  animation:change1 2s linear infinite alternate;
}
.second {
  background:radial-gradient(20% 20%,yellow 30%,blue)right -50px bottom 0/200% 200%;
  animation:change2 2s linear infinite alternate;
}

@keyframes change1 {
  to {
    background-position:calc(100% + 10%) calc(100% - 80%);
  }
}

@keyframes change2 {
  to {
    background-position:right -100px bottom -100px;
  }
}

<div class="box first" ></div>
<div class="box second"></div>


Now let's consider more tricky cases, like our initial example, using farthest-side in order to define the size. We will do the same logic and convert

radial-gradient(farthest-side at X Y, color1 p1, color2 p2);

to

radial-gradient(farthest-side, color1 p1, color2 p2) Px Py/Sx Sy no-repeat;

I will explain for one axis (X) and the same apply to the other

farthest-side define the radius to be the distance from the gradient center to the farthest side of the gradient box (the gradient box is by default the element itself since we didn't define any size). If X is a percentage value then the radius is the max between X and 100% - X and in the transformed gradient the radius will be 50% since we are at the center. So we need to match the first radius with 50%*Sx

If X is 50% then Sx should be 100% and if X is 0 or 100% then Sx should be 200%.

The formula is Sx = max(X,100% - X)*2

The position is easier in this case due to the nature of the gradient where the shape should touch one side

  • If X within [0 50%[ Px should be 100% (right)
  • If X is 50% any value for Px will work since Sx=100%
  • If X within ]50% 100%] Px shoudd be 0% (left)

Related question: Using percentage values with background-position on a linear gradient

Examples:

.box {
  height:150px;
  width:150px;
  border:1px solid;
  display:inline-block;
}

<div class="box" style="background:radial-gradient(farthest-side at 20% 60%, red 20%, blue 100%, yellow 100%)" ></div>
<div class="box" style="background:radial-gradient(farthest-side, red 20%, blue 100%, yellow 50%) 100% 0/calc(80%*2) calc(60%*2)"></div>
<br>
<div class="box" style='background:radial-gradient(farthest-side at 22% 100%,red 40%, blue 100%,yellow 100%)'></div>
<div class="box" style="background:radial-gradient(farthest-side,red 40%, blue 100%,yellow 100%) 100% 0/calc(78%*2) calc(100%*2)"></div>

For the farthest-corner we do exactly the same:

.box {
  height:150px;
  width:150px;
  border:1px solid;
  display:inline-block;
}

<div class="box" style="background:radial-gradient(farthest-corner at 20% 60%, red 20%, blue 50%, yellow 60%)" ></div>
<div class="box" style="background:radial-gradient(farthest-corner, red 20%, blue 50%, yellow 60%) 100% 0%/calc(80%*2) calc(60%*2)"></div>
<br>
<div class="box" style="background:radial-gradient(farthest-corner at 40% 100%, red 20%, blue 50%, yellow 60%)" ></div>
<div class="box" style="background:radial-gradient(farthest-corner, red 20%, blue 50%, yellow 60%) 100% 0%/calc(60%*2) calc(100%*2)"></div>

We can also transform farthest-side (or farthest-corner) to Rh Rv and do the previous calculation but it won't be useful for the animation since we will have two gradient with different radius whereas we need the same gradient.

.box {
  height:150px;
  width:150px;
  border:1px solid;
  display:inline-block;
}

<div class="box" style="background:radial-gradient(farthest-side at 20% 60%, red 20%, blue 100%, yellow 100%)" ></div>
<div class="box" style="background:radial-gradient(80% 60% at 20% 60%, red 20%, blue 100%, yellow 100%)" ></div>
<div class="box" style="background:radial-gradient(80% 60%, red 10%, blue 50%, yellow 50%) 80% 40%/200% 200%"></div>

If X is a pixel value we have two cases:

  • The element has a fixed width: In this case we can simply convert the pixel value of X as a percentage of the width and we do the same logic as above.
  • The element has a variable width: In this case it would be tricky to convert the gradient (probably impossible) because the shape will change based on the width. When width-X > X we will have a variable radius and when width-X < X we will have a fixed radius. I don't think we can express this using background-size and background-position. Example:

body {
  margin:0;
  height:100vh;
  background:radial-gradient(farthest-side at 400px 200px,blue 40%,yellow 50%);
}

For the closest-side will do the same logic considering Sx=min(X,100% - X)*2 BUT we should add no-repeat and a background-color equal to the last color in the gradient since the size is less than 100%

.box {
  height:150px;
  width:150px;
  border:1px solid;
  display:inline-block;
}

<div class="box" style="background:radial-gradient(closest-side at 20% 60%, red 20%, blue 100%, yellow 100%)" ></div>
<div class="box" style="background:radial-gradient(closest-side, red 20%, blue 100%, yellow 100%) 0 100%/calc(20%*2) calc(40%*2)"></div>
<div class="box" style="background:radial-gradient(closest-side, red 20%, blue 100%, yellow 100%) 0 100%/calc(20%*2) calc(40%*2) no-repeat,yellow"></div>
<br>
<div class="box" style='background:radial-gradient(closest-side at 22% 10%,red 40%, blue 100%,yellow 100%)'></div>
<div class="box" style="background:radial-gradient(closest-side,red 40%, blue 100%,yellow 100%) 0 0/calc(22%*2) calc(10%*2)"></div>
<div class="box" style="background:radial-gradient(closest-side,red 40%, blue 100%,yellow 100%) 0 0/calc(22%*2) calc(10%*2) no-repeat,yellow"></div>

We can do the same for closest-corner but we will have some issue due the fact that the gradient can overflow the gradient box.

.box {
  height:150px;
  width:150px;
  border:1px solid;
  display:inline-block;
}

<div class="box" style="background:radial-gradient(closest-corner at 20% 60%, red 20%, blue 100%, yellow 100%)" ></div>
<div class="box" style="background:radial-gradient(closest-corner, red 20%, blue 100%, yellow 100%) 0 100%/calc(20%*2) calc(40%*2)"></div>
<div class="box" style="background:radial-gradient(closest-corner, red 20%, blue 100%, yellow 100%) 0 100%/calc(20%*2) calc(40%*2) no-repeat,yellow"></div>

To rectify this we can divide the color stop by 2 to make sure we keep the whole gradient inside. Then we make the size twice bigger and we rectify the position

.box {
  height:150px;
  width:150px;
  border:1px solid;
  display:inline-block;
}

<div class="box" style="background:radial-gradient(closest-corner at 20% 60%, red 20%, blue 100%, yellow 100%)" ></div>
<div class="box" style="background:radial-gradient(closest-corner, red 10%, blue 50%, yellow 50%) -100% 33%/calc(20%*4) calc(40%*4)"></div>
<div class="box" style="background:radial-gradient(closest-corner, red 10%, blue 50%, yellow 50%) -100% 33%/calc(20%*4) calc(40%*4) no-repeat,yellow"></div>
<br>
<div class="box" style='background:radial-gradient(closest-corner at 22% 10%,red 40%, blue 100%,yellow 100%)'></div>
<div class="box" style="background:radial-gradient(closest-corner,red 20%, blue 50%,yellow 50%) -100% 0%/calc(22%*4) calc(10%*4)"></div>
<div class="box" style="background:radial-gradient(closest-corner,red 20%, blue 50%,yellow 50%) -164% -18%/calc(22%*4) calc(10%*4) no-repeat,yellow"></div>


Even without animation, the syntax of the gradient without the at X Y is more supported. Some browser like Safari doesn't support the at (How to make radial gradients work in Safari?)

这篇关于如何使用CSS为径向渐变设置动画?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆