CSS animate radial gradient? [duplicate] - javascript
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 transformation 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?)
Using CSS variables and with the new #property we can easily animate radial-gradient (or any kind of gradient). The support cover only Chrome and Edge for now.
#property --x {
syntax: '<percentage>';
inherits: false;
initial-value: 0%;
}
#shine-div {
height: 30vh;
width: 60vw;
margin: auto;
border-radius: 10px;
background: radial-gradient(ellipse farthest-corner at var(--x) 0%, #FFFFFF 0%, #ffb3ff 8%, #ff33ff 25%, #800080 62.5%, #b300b3 100%);
animation: colorChange 5s infinite alternate;
}
#keyframes colorChange {
0% {
--x:0%;
}
50% {
--x:50%;
}
100% {
--x:100%;
}
}
<div id="shine-div"></div>
All we have to do is to define the position using a variable --x that will use percentage values and we animation that variable. As simple as that!
SVG solution
The author did not ask for a solution to his problem using SVG. But it will probably be useful to solve one issue in several ways.
Gradient attribute values were taken from the #Temani Afif response.
The SVG radial gradient formula for this question:
<radialGradient id="radGrad" fx="0%" fy="5%" r="200%">
<stop offset="0%" stop-color ="#FFFFFF" />
<stop offset="4%" stop-color ="#ffb3ff" />
<stop offset="12.25%" stop-color ="#ff33ff" />
<stop offset="31.25%" stop-color ="#800080" />
<stop offset="50%" stop-color ="#b300b3" />
</radialGradient>
To animate the gradient, you can use any attribute included in the formula.
The examples below will use the attributes fx andfy
Animation of horizontal gradient movement
Animation starts after clicking on a rectangle
svg {
width:50%;
height:50%;
}
.txt {
font-family:sans-serif;
font-size:28px;
font-weight:bold;
text-anchor:middle;
fill:#FFDD00;
}
<div id="shine-div">
<svg xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 400 100">
<defs>
<radialGradient id="radGrad" fx="0%" fy="0%" r="200%">
<stop offset="0%" stop-color ="#FFFFFF" />
<stop offset="4%" stop-color ="#ffb3ff" />
<stop offset="12.25%" stop-color ="#ff33ff" />
<stop offset="31.25%" stop-color ="#800080" />
<stop offset="50%" stop-color ="#b300b3" />
</radialGradient>
</defs>
<g id="gr1" >
<rect id="rect1" fill="url(#radGrad)" x="5%" y="5%" width="95%" height="95%" rx="10%"/>
<text class="txt" x="50%" y="60%"> Sun shine </text>
</g>
<animate xlink:href="#radGrad"
attributeName="fx"
dur="3s"begin="gr1.click"
values="0%;100%;0%"
repeatCount="1"
restart="whenNotActive" />
</svg>
</div>
An animation of the vertical gradient movement.
svg {
width:50%;
height:50%;
}
.txt {
font-family:sans-serif;
font-size:28px;
font-weight:bold;
text-anchor:middle;
fill:#FFDD00;
}
<div id="shine-div">
<svg xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 400 100">
<defs>
<radialGradient id="radGrad" fx="48%" fy="0%" r="200%">
<stop offset="0%" stop-color ="#FFFFFF" />
<stop offset="4%" stop-color ="#ffb3ff" />
<stop offset="12.25%" stop-color ="#ff33ff" />
<stop offset="31.25%" stop-color ="#800080" />
<stop offset="50%" stop-color ="#b300b3" />
</radialGradient>
</defs>
<g id="gr1" >
<rect id="rect1" fill="url(#radGrad)" x="5%" y="5%" width="95%" height="95%" rx="10%"/>
<text class="txt" x="50%" y="60%"> Sun shine </text>
</g>
<animate xlink:href="#radGrad"
attributeName="fy"
dur="2s"begin="gr1.click"
values="0%;50%;50%;100%;50%;50%;0%"
keyTimes="0;0.1;0.5;0.6;0.7;0.9;1"
repeatCount="1"
restart="whenNotActive" />
</svg>
</div>
Moving the gradient diagonally
Two attributes are simultaneously animated: fx andfy
svg {
width:50%;
height:50%;
}
.txt {
font-family:sans-serif;
font-size:28px;
font-weight:bold;
text-anchor:middle;
fill:#FFDD00;
}
<div id="shine-div">
<svg xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 400 100">
<defs>
<radialGradient id="radGrad" fx="0%" fy="0%" r="200%">
<stop offset="0%" stop-color ="#FFFFFF" />
<stop offset="4%" stop-color ="#ffb3ff" />
<stop offset="12.25%" stop-color ="#ff33ff" />
<stop offset="31.25%" stop-color ="#800080" />
<stop offset="50%" stop-color ="#b300b3" />
</radialGradient>
</defs>
<g id="gr1" >
<rect id="rect1" fill="url(#radGrad)" x="5%" y="5%" width="95%" height="95%" rx="10%"/>
<text class="txt" x="50%" y="60%"> Sun shine </text>
</g>
<animate xlink:href="#radGrad"
attributeName="fy"
dur="2s"begin="gr1.click"
values="0%;50%;50%;100%;0%"
keyTimes="0;0.1;0.5;0.9;1"
repeatCount="1"
restart="whenNotActive" />
<animate xlink:href="#radGrad"
attributeName="fx"
dur="2s"begin="gr1.click"
values="0%;50%;50%;100%;0%"
keyTimes="0;0.1;0.5;0.9;1"
repeatCount="1"
restart="whenNotActive" />
</svg>
</div>
Related
Prevent image from flipping during CSS animation
I'm working on a rock paper scissors game. When I click a button I have it where two images do a "shake" animation to simulate the hand motions done during a real game. This is all fine, however the image on the right flips horizontally during the animation but flips back at the end. I initially have it flipped so both hands face each other. I'm wondering if it's possible to prevent that second image from flipping during the animation. Images before the animation Images during the animation HTML <div class="img-container"> <div class="player-container"> <p class="player-1-text">Player Options: </p> <div class="player-img-container"> <button onclick="animation()"><img src="img/rock.jpg" alt="Rock Sign" width="100" height="100" class="img-space" id="player-img-main"></button> <button><img src="img/paper.jpg" alt="Rock Sign" width="100" height="100" class="img-space"></button> <button><img src="img/scissors.jpg" alt="Rock Sign" width="100" height="100" class="img-space"></button> </div> </div> <div class="computer-container"> <div class="computer-img-container"> <img src="img/rock.jpg" alt="Rock Sign" width="100" height="100" class="img-space" id="computer-img-main"> <img src="img/paper.jpg" alt="Rock Sign" width="100" height="100" class="img-space" id="computer-img"> <img src="img/scissors.jpg" alt="Rock Sign" width="100" height="100" class="img-space" id="computer-img"> </div> <p class="computer-text"> :Computer Options</p> </div> </div> Javascript function animation() { const element = document.getElementById('player-img-main'); const element2 = document.getElementById('computer-img-main'); element.classList.remove('shake'); // reset animation element2.classList.remove('shake'); // reset animation void element.offsetWidth; // trigger reflow void element2.offsetWidth; // trigger reflow element.classList.add('shake'); // start animation element2.classList.add('shake'); // start animation } CSS #computer-img-main { transform: scaleX(-1); /* Flip image horizontally */ } .shake { animation-name: shake; animation-iteration-count: 1; animation-duration: 2s; animation-fill-mode: both; } #keyframes shake { 3%, 21%, 39%, 57%, 74%, 92% { transform: translateY(5px) } 6%, 24%, 42%, 60%, 77%, 95% { transform: translateY(3px) } 9%, 27%, 45%, 63%, 80%, 98% { transform: translateY(-5px) } }
You can keep the HTML structure as it is, and share the keyframes, but you need to remember what the scaling is (the flipping of the hand image) and make sure that is in any transform that is done. You could use a CSS variable for this. e.g. here we set --s to 1 for the player side and to -1 for the computer side. And then in the transforms in the keyframes we add in scaleX(var(--s)). #player-img-main { --s: 1; } #computer-img-main { transform: scaleX(-1); --s: -1; /* Flip image horizontally */ } .shake { animation-name: shake; animation-iteration-count: 1; animation-duration: 2s; animation-fill-mode: both; } #keyframes shake { 3%, 21%, 39%, 57%, 74%, 92% { transform: scaleX(var(--s)) translateY(5px) } 6%, 24%, 42%, 60%, 77%, 95% { transform: scaleX(var(--s)) translateY(3px) } 9%, 27%, 45%, 63%, 80%, 98% { transform: scaleX(var(--s)) translateY(-5px) } }
Cut part of image CSS
Im tring to create a glitch image animation effect. I use layers with mix blend modes, and clip paths. but how can I cut part of the main image? Since I want to achieve the effect of displacing a piece of the picture. Main background can be image too, thats why I can't use background-color in layers. <div class="glitch-image"> <img class="glitch-image__image" src="https://clipart-db.ru/file_content/rastr/bmw_002.png" alt=""/> <div class="glitch-image__glitch" style="background-image: url(https://clipart-db.ru/file_content/rastr/bmw_002.png)" alt=""> </div> </div> CSS body display flex background-color #000 min-height 70vh box-sizing: border-box * box-sizing: border-box .glitch-image width 100% max-width 500px margin auto position relative &__image max-width 100% position relative z-index 1 display block vertical-align top filter: drop-shadow(0px 15px 15px #fff); &__glitch position absolute left 40px top 0 bottom 0 right 0 width 100% height 100% background-size 100% background-repeat no-repeat z-index 2 // animation: glitch-anim-1 2s infinite linear alternate; clip-path: polygon(0 20%, 100% 20%, 100% 40%, 0 40%); filter: sepia(1) hue-rotate(303deg) brightness(100%) saturate(200%) drop-shadow(5px 5px 25px red); #keyframes glitch-anim-1 { 0% { clip-path: polygon(0 0%, 100% 0%, 100% 5%, 0 5%); } 10% { clip-path: polygon(0 15%, 100% 15%, 100% 15%, 0 15%); } 20% { clip-path: polygon(0 10%, 100% 10%, 100% 20%, 0 20%); } 30% { clip-path: polygon(0 1%, 100% 1%, 100% 2%, 0 2%); } 40% { clip-path: polygon(0 35%, 100% 35%, 100% 35%, 0 35%); } 50% { clip-path: polygon(0 45%, 100% 45%, 100% 46%, 0 46%); } 60% { clip-path: polygon(0 50%, 100% 50%, 100% 70%, 0 70%); } 70% { clip-path: polygon(0 70%, 100% 70%, 100% 70%, 0 70%); } 80% { clip-path: polygon(0 80%, 100% 80%, 100% 80%, 0 80%); } 90% { clip-path: polygon(0 50%, 100% 50%, 100% 55%, 0 55%); } 100% { clip-path: polygon(0 60%, 100% 60%, 100% 70%, 0 70%); } } function random_polygon() { } See code pen
If you are intrested in a different idea here is another one without JS and only few line of CSS and with transparency: .box { width:400px; height:200px; margin:auto; background-image:url(https://clipart-db.ru/file_content/rastr/bmw_002.png); background-size:0 0; position:relative; display:grid; } .box::before, .box::after { content:""; grid-area:1/1; background-image:inherit; background-size:contain; background-position:center; background-repeat:no-repeat; -webkit-mask-image: linear-gradient(#000 0 0), linear-gradient(#000 0 0); -webkit-mask-size: 100% 20px,100% 100%; -webkit-mask-repeat: no-repeat; -webkit-mask-composite: destination-out; mask-composite: exclude; animation: glitch 1s infinite; } .box::after { -webkit-mask-image: linear-gradient(#000 0 0); animation: glitch 1s infinite, m .2s infinite cubic-bezier(0.5,200,0.5,-200); } #keyframes glitch{ 0% {-webkit-mask-position:0 20px,0 0} 20% {-webkit-mask-position:0 50% ,0 0} 40% {-webkit-mask-position:0 100%,0 0} 60% {-webkit-mask-position:0 3px ,0 0} 80% {-webkit-mask-position:0 70%,0 0} 100% {-webkit-mask-position:0 0 ,0 0} } #keyframes m{ 100% {transform:translate(0.1px)} } body { background:linear-gradient(90deg,yellow,lightblue); } <div class="box"> </div>
Im tring to create a glitch image animation effect. Consider using SVG filters: feTurbulence and feDisplacementMap By changing the attributeName = "baseFrequency" values, you can get the desired effect. .container { width:60%; height:60%; } <div class="container"> <svg xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 500 350" > <defs> <filter id="myFilter" > <feTurbulence type="turbulence" baseFrequency="0.0001" numOctaves="1" result="turbulence" > <animate attributeName="baseFrequency" dur="30s" values="0.0001;0.02;0.0001;0.02;0.0001" /> </feTurbulence> <feDisplacementMap xChannelSelector="R" yChannelSelector="G" scale="25" in="SourceGraphic" in2="turbulence" /> </filter> </defs> <image id="img1" x="-12" xlink:href="https://i.stack.imgur.com/Y6Rh9.jpg" width="100%" height="100%" filter="url(#myFilter)" /> </svg> </div> Same effect hover begin="img1.mouseover" end="img1.mouseout" .container { width:60%; height:60%; cursor:pointer; } <div class="container"> <svg xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 500 350"> <defs> <filter id="myFilter" > <feTurbulence type="turbulence" baseFrequency="0.0001" numOctaves="1" result="turbulence" > <animate attributeName="baseFrequency" dur="18s" values="0.0001;0.02;0.0001;0.02;0.0001" begin="img1.mouseover" end="img1.mouseout" /> </feTurbulence> <feDisplacementMap xChannelSelector="R" yChannelSelector="G" scale="25" in="SourceGraphic" in2="turbulence" /> </filter> </defs> <image id="img1" x="-12" xlink:href="https://i.stack.imgur.com/Y6Rh9.jpg" width="100%" height="100%" filter="url(#myFilter)" /> </svg> </div> Update If you play with the values of the attributes baseFrequency and scale = "15", you can get other interesting effects: .container { width:60%; height:60%; } <div class="container"> <svg xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 500 350" > <defs> <filter id="myFilter" > <feTurbulence type="turbulence" baseFrequency="0.0001" numOctaves="1" result="turbulence" > <animate attributeName="baseFrequency" dur="30s" values="0.0001;0.25;0.25;0.0001;0.25;0.0001;0.0001" /> </feTurbulence> <feDisplacementMap xChannelSelector="R" yChannelSelector="G" scale="15" in="SourceGraphic" in2="turbulence" /> </filter> </defs> <image id="img1" x="-12" xlink:href="https://i.stack.imgur.com/Y6Rh9.jpg" width="100%" height="100%" filter="url(#myFilter)" style="overflow:hidden1;" /> </svg> </div>
How to create an image with gradient where top has opacity 100% and bottom with opacity 0%?
So I have an image (Link to image=> https://i.imgur.com/TRTg8Cu.jpg) that has a gradient below it (background of the body). Currently, the image has a fade to black gradient, but I want the image to fade to the given gradient. Basically, a way to have the image go from opacity 100% on top and opacity 0% on the bottom. // HTML <div className="h-screen w-full gradient-bg hero-image z-10> <Image src={event.name_image.url} alt={event.Name} layout="fill" className="bg-top bg-cover object-cover" /> </div> // CSS .gradient-bg div { position: relative; display: inline-block; } .gradient-bg div:after { content: ''; position: absolute; left: 0; top: 0; width: 100%; height: 100%; display: inline-block; background: linear-gradient( to bottom, rgba(0, 0, 0, 0) 0%, rgba(0, 0, 0, 0) 50%, rgba(0, 0, 0, 1) 100% ); } If there is some other way to achieve the same so the image fades to the background, that can also work. If there is a JS/React library which can help me achieve this, that may also work. PS. background in my project is dynamic (gradient colors change every few seconds)
This is the purpose of mask: .gradient-bg { background: linear-gradient(to right, red, blue); display:inline-block; } .gradient-bg img { -webkit-mask: linear-gradient(white 50%, transparent); display:block; } <div class="gradient-bg"> <img src="https://picsum.photos/id/1/400/300"> </div>
CSS Shimmer effect with blocking JavaScript
I have a shimmer React component with the following CSS background: #ebebeb; background-image: linear-gradient(to right, #ebebeb 0%, #c5c5c5 20%, #ebebeb 40%, #ebebeb 100%); and the animation keyframe I apply to it is as follows: { 0%: { background-position: -468px 0 }; 100%: { background-position: 468px 0 }; } My home page is quite heavy on mount. So the animation freezes for about a second or so. I read that animating transition is done off-thread https://www.phpied.com/css-animations-off-the-ui-thread/ Can anyone help me do my shimmer effect in a similar off-thread manner?
Use transform as suggested in the link. Here is an idea with pseudo element: .box { background-image: linear-gradient(to right, #ebebeb calc(50% - 100px), #c5c5c5 50%, #ebebeb calc(50% + 100px)); background-size:0; height: 200px; position:relative; overflow:hidden; } .box::before { content:""; position:absolute; top:0; right:0; width:calc(200% + 200px); bottom:0; background-image:inherit; animation:move 2s linear infinite; } #keyframes move{ to { transform:translateX(calc(50% + 100px)); } } <div class="box"> </div>
Css Div 2 background colors
I am attempting to make a div with 2 background colors, and I am aware that you can do the 50/50 gradient, but when you go more extreme, say, 20/80, the colors start to blend. I have looked at this link 50%/50% hard gradient but, again, when I attempt to change the values to higher and lower, it starts to blend. Any suggestions? Thanks. Here is where I am trying to implement it: http://codepen.io/jettc/pen/zrOKqJ percent = Math.floor((time/timerTotal)*100); remainPercent = 100-percent; console.log(percent, remainPercent); $("#circle").css("background-image","-webkit-linear-gradient(top, #222222 "+percent+"%, grey "+remainPercent+"%)");
The gradient is just rendering how it is supposed to, you just need to change your CSS to make it how you want. To render to solid colors, both percentages must be the same. Here is some different examples of this: div{ width:200px; height:200px; background:linear-gradient( red 50%, blue 50%); } 50/50 <div></div> div{ width:200px; height:200px; background:linear-gradient( red 80%, blue 80%); } 80/20 <div></div> div{ width:200px; height:200px; background:linear-gradient( red 30%, blue 30%); } 30/70 <div></div> div{ width:200px; height:200px; background:linear-gradient( red 40%, blue 40%); } 40/60 <div></div> Updated codepen As you can see from the above examples, the key is to set both of the percentages to the same, so there is no space to blend the two colors. See these two images for an example:
"-webkit-linear-gradient(top, #222222 "+percent+"%, grey "+percent+"%)" You have to use the same percentages: background-image: linear-gradient(bottom, #FFD51A 20%, #FAC815 20%); or background-image: linear-gradient(bottom, #FFD51A 80%, #FAC815 80%); ... the percentages are defining the color-stops position. More about gradients here: http://www.w3schools.com/css/css3_gradients.asp and here https://developer.mozilla.org/en-US/docs/Web/CSS/linear-gradient