div {
border-radius: 2rem;
width: 10rem;
height: 10rem;
background-color: #0dd;
background-image:
linear-gradient(
-45deg,
rgba( 0,0,0,0.125 ), transparent, rgba( 0,0,0,0.125 ), transparent
);
}
div {
animation-name: diagonal_move;
animation-duration: 6s;
animation-timing-function: linear;
animation-iteration-count: infinite;
}
#keyframes diagonal_move {
0% {
background-position: 0rem 0rem;
}
100% {
background-position: 10rem 10rem;
}
}
<html>
<head>
<style>
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
html, body {
height: 100%;
}
body {
display: flex;
justify-content: center;
align-items: center;
}
</style>
</head>
<body>
<div></div>
</body>
</html>
As the linear gradient above animates the edges of the gradient can clearly be seen - opposed to blending seamlessly with its surroundings.
A solution attempted to hide the edges was to overlay additional gradients on top:
div {
border-radius: 2rem;
width: 10rem;
height: 10rem;
background-color: #0dd;
background-image:
linear-gradient( #0dd, transparent, transparent, transparent, #0dd ),
linear-gradient( 90deg, #0dd, transparent, transparent, transparent, #0dd ),
linear-gradient(
-45deg,
rgba( 0,0,0,0.125 ), transparent, rgba( 0,0,0,0.125 ), transparent
);
}
div {
animation-name: diagonal_move;
animation-duration: 6s;
animation-timing-function: linear;
animation-iteration-count: infinite;
}
#keyframes diagonal_move {
0% {
background-position: 0rem 0rem;
}
100% {
background-position: 10rem 10rem;
}
}
<html>
<head>
<style>
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
html, body {
height: 100%;
}
body {
display: flex;
justify-content: center;
align-items: center;
}
</style>
</head>
<body>
<div></div>
</body>
</html>
The issue with this approach is it hides much of the original gradient along with the seams. It also creates bright lines where the seams would be.
So is there any way to flip or mirror gradients when they end to create a seamless pattern? Or perhaps the original gradient could be larger and zoomed out to give the illusion of a seamless pattern. How could this be implemented?
Your gradient consists of 3 parts (between 4 reference points/color definitions), which creates a kind of "asymmetrical" structure since there's a different color at the end than at the beginning. If you add another reference point / color (same as first one), the gradient has the same color at the beginning and end and also in the other two corners of the square, and therefore the animation works smooth:
div {
border-radius: 2rem;
width: 10rem;
height: 10rem;
background-color: #0dd;
background-image:
linear-gradient(
-45deg,
rgba( 0,0,0,0.125 ), transparent, rgba( 0,0,0,0.125 ), transparent, rgba( 0,0,0,0.125 )
);
}
div {
animation-name: diagonal_move;
animation-duration: 6s;
animation-timing-function: linear;
animation-iteration-count: infinite;
}
#keyframes diagonal_move {
0% {
background-position: 0rem 0rem;
}
100% {
background-position: 10rem 10rem;
}
}
<html>
<head>
<style>
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
html, body {
height: 100%;
}
body {
display: flex;
justify-content: center;
align-items: center;
}
</style>
</head>
<body>
<div></div>
</body>
</html>
In such case better consider a repeating gradient that is twice bigger than the element so you don't have to bother with specific values inside background-position:
.box {
border-radius: 2rem;
width: 10rem;
height: 10rem;
background-color:;
background:
repeating-linear-gradient(
-45deg,
rgba( 0,0,0,0.125 ), transparent, rgba( 0,0,0,0.125 ) 25%
) bottom right/200% 200%
#0dd;
animation: diagonal_move 6s linear infinite;
}
#keyframes diagonal_move {
100% {
background-position: top left;
}
}
body {
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
margin:0;
}
<div class="box"></div>
Related for more details around the values and the calculation: Using percentage values with background-position on a linear-gradient
Related
<style type="text/css">
* {
box-sizing: border-box;
}
.fancy {
position: relative;
max-width: 400px;
padding: 15px;
text-align: center;
}
.fancy::before, .fancy::after {
content: "";
position: absolute;
left: 0;
right: 0;
height: 1px;
}
.fancy::before {
top: 0;
background: linear-gradient(to right, #FFFFFF, #168DBF 70%);
animation: fancy-top 2s linear infinite;
}
.fancy::after {
bottom: 0;
background: linear-gradient(to left, #FFFFFF, #168DBF 70%);
animation: fancy-bottom 2s linear infinite;
}
#keyframes fancy-top {
0% { background-position: 0 0; }
100% { background-position: 400px 0; }
}
#keyframes fancy-bottom {
0% { background-position: 0 0; }
100% { background-position: -400px 0; }
}
</style>
<h1 class="fancy">Fancy Heading</h1>
I'm looking for a way to allow this to work independent of the width - I've tried a few different solutions I found from searches on similar things (including background-size, transform, widths, left/right positions), nothing seems to give me the same smooth repeating animation that this does.
Can anyone lend a hand?
How would I be able to improve this animated static noise effect using a css gradient?
CSS only, no javascript, no svg, no image, using only a gradient, and adjusting that.
A tv no signal noise effect is what I am looking for using a css gradient.
Does anyone know how this effect can be improved, made better?
Is there a better way it can be written?
I am looking for something that is more accurate to a tv noise effect.
I think the way this effect is written can be improved.
Are there any tweaks or adjustments that can be made to it to so that it better depicts a tv noise effect?
The gradient can be anything, as long as it is a gradient, it doesn't matter what kind.
This one uses radial gradient:
https://jsfiddle.net/xhdkza5w/
html,
body {
width: 100%;
height: 100%;
display: flex;
}
.tv-static {
width: 500px;
height: 300px;
margin: auto;
background-image: repeating-radial-gradient(circle at 17% 32%, white, black 0.00085px);
animation: back 5s linear infinite;
}
#keyframes back {
from {
background-size: 100% 100%;
}
to {
background-size: 200% 200%;
}
}
<div class="tv-static"></div>
This one uses a conic-gradient: https://jsfiddle.net/bkx50apm/
html,
body {
width: 100%;
height: 100%;
display: flex;
}
.tv-static {
width: 500px;
height: 300px;
margin: auto;
background-image: repeating-conic-gradient(white, black 0.00085%);
animation: back 25s linear infinite;
}
#keyframes back {
from {
background-size: 100% 100%;
}
to {
background-size: 200% 200%;
}
}
<div class="tv-static"></div>
Do you mean this effect?
html,
body {
width: 100%;
height: 100%;
display: flex;
}
.animation {
width: 240px;
height: 240px;
margin: auto;
background-image: repeating-radial-gradient(circle at 17% 32%, white, black 0.00085px);
animation: animation 5s linear infinite;
}
#keyframes animation {
from {
background-position: 0px 0px;
}
to {
background-position: 240px 240px;
}
}
<div class="animation"></div>
Or this effect?
html,
body {
width: 100%;
height: 100%;
display: flex;
}
.animation {
width: 240px;
height: 240px;
margin: auto;
background-image: repeating-radial-gradient(circle at 17% 32%, white, black 0.00085px);
background-position: center;
animation: back 5s linear infinite;
}
#keyframes back {
from {
background-size: 100% 100%;
}
to {
background-size: 200% 200%;
}
}
<div class="animation"></div>
Edit: Added background-position: center.
By overlaying 2 of those effect on top of each other and each div has a different animation, you can create interference between the two that removes the artifacts of only having 1 static noise made from a single div.
This might be improved as I'm not well versed in css but the proof of concept works
html,
body {
width: 100%;
height: 100%;
display: flex;
}
.container_row {
display: flex;
}
.layer1 {
width: 100%;
background-color: rgba(255, 255, 255, 0.5);
}
.layer2 {
width: 100%;
margin-left: -100%;
background-color: rgba(255, 255, 255, 0.5);
}
.tv-static {
width: 500px;
height: 300px;
margin: auto;
background-image: repeating-radial-gradient(circle at 17% 32%, white, black 0.00085px);
}
.animation1 {
animation: back1 1s linear infinite;
}
.animation2 {
animation: back2 0.1s linear infinite;
}
#keyframes back1 {
from {
background-size: 100% 100%;
}
to {
background-size: 99% 100%;
}
}
#keyframes back2 {
from {
background-size: 48.56% 50%;
}
to {
background-size: 43.9% 50.1%;
}
}
<div class="layer1">
<div class="tv-static animation1"></div>
</div>
<div class="layer2">
<div class="tv-static animation2"></div>
</div>
With smooth timing function, animations don't give that effect we need to use step timing function to give those sudden change effect.
Solution 1: I've changed animation. And tweaked your gradient a little bit. I think using gradient is not a reliable solution because browsers do calculations differently and fractions, rounding change output. You are using radial gradient it looks things are going outwards from center of the placement. You'll have to test his on every platform and browser to see if it looks same.
Solution 2: Used SVG instead of gradient. The feTurbulence filter gives the noise effect. You can use svg as background-image.
Solution 3: Used image instead of gradient with same animation. Advantage of using image is that it'll look same across all browsers and screens.
Solution 3: Simply used noise gif image. No animation is required. :)
View following in 'full page' mode:
body {
text-align: center;
}
.tv {
width: 400px;
height: 200px;
border: 6px solid black;
margin: 0 auto;
overflow: hidden;
position: relative;
border-radius: 50% / 10%;
}
.tv-static {
position: absolute;
top: -200px;
left: -200px;
margin: auto;
height: 800px;
width: 800px;
background-image: repeating-radial-gradient(circle at 17% 132%, white 0.0005px, black 0.00085px);
animation: anim 1s steps(2, jump-both) infinite both;
transform: translate3d(0, 0, 0);
}
/******************************/
.tv0 {
width: 400px;
height: 200px;
border: 6px solid black;
margin: 0 auto;
overflow: hidden;
position: relative;
border-radius: 50% / 10%;
isolation: isolate;
}
.tv-static0 {
position: absolute;
top: 0px;
left: 0px;
margin: auto;
height: 300%;
width: 300%;
animation: anim 1s steps(2, end) infinite both;
transform: translate3d(0, 0, 0);
filter: contrast(300%) brightness(50%);
}
.tv-static0 svg {
height: 200%;
width: 100%;
transform: scale(2.5);
}
/******************************/
.tv1 {
width: 400px;
height: 200px;
border: 6px solid black;
margin: 0 auto;
overflow: hidden;
position: relative;
border-radius: 50% / 10%;
}
.tv-static1 {
position: absolute;
top: -500px;
right: -500px;
bottom: -500px;
left: -500px;
margin: auto;
background-image: url(https://i.stack.imgur.com/uzEM4.png);
animation: anim 1s steps(2, end) infinite both;
transform: translate3d(0, 0, 0);
}
/******************************/
.tv2 {
width: 400px;
height: 200px;
border: 6px solid black;
margin: 0 auto;
overflow: hidden;
position: relative;
border-radius: 50% / 10%;
}
.tv-static2 {
position: absolute;
top: -500px;
right: -500px;
bottom: -500px;
left: -500px;
margin: auto;
background-image: url(https://i.stack.imgur.com/9Be02.gif);
transform: translate3d(0, 0, 0);
}
#keyframes anim {
0% {
transform: translateX(0px, 0px);
}
10% {
transform: translate(-100px, 100px);
}
20% {
transform: translate(150px, -100px);
}
30% {
transform: translate(-100px, 100px);
}
40% {
transform: translate(100px, -150px);
}
50% {
transform: translate(-100px, 200px);
}
60% {
transform: translate(-200px, -100px);
}
70% {
transform: translateY(50px, 100px);
}
80% {
transform: translate(100px, -150px);
}
90% {
transform: translate(0px, 200px);
}
100% {
transform: translate(-100px, 100px);
}
}
Your original code. modified. May not work on every browser.
<div class="tv">
<div class="tv-static"></div>
</div>
<br> Using SVG `feTurbulence` filter
<div class="tv0">
<div class="tv-static0">
<svg viewBox="0 0 200% 200%" xmlns='http://www.w3.org/2000/svg'>
<filter id='noiseFilter'>
<feTurbulence type='turbulence' result='noise' baseFrequency='0.7' numOctaves='6' seed='2'
stitchTiles='noStitch' />
</filter>
<rect width='100%' height='100%' filter='url(#noiseFilter)' />
</svg>
<div class="overlay"></div>
</div>
</div>
<br>
<br> Animating image. Color TV
<div class="tv1">
<div class="tv-static1"></div>
</div>
<br> Using gif. No animation.
<div class="tv2">
<div class="tv-static2"></div>
</div>
I'm trying to make a simple download bar, but it turns out only a solid color without transition animation.
In addition, the "repeating-linear-gradient" does not work and I cannot understand why.
I am hope for your help. Thank you!
.Download {
height: 80px;
width: 1000px;
border: 2px solid black;
border-radius: 100px;
/*background: repeating-linear-graient (90deg, blue, red, 100px);*/
background: linear-gradient(to left, blue, red);
animation-name: download;
animation-direction: 10s;
animation-timing-function: linear;
animation-direction: normal;
}
#keyframes download {
0% {
left: -100%;
}
100% {
left: 100%;
}
}
<div class="Download">
</div>
You can use pseudo code to achieve this.
.Download {
height: 80px;
width: 1000px;
border: 2px solid black;
border-radius: 100px;
position: relative;
overflow: hidden;
}
.Download:after {
content: "";
position: absolute;
background-image: linear-gradient(to left, blue, red);
width: 100%;
height: 100%;
top: 0;
left: -100%;
animation: download 5s;
}
#keyframes download {
0% {
left: -100%;
}
100% {
left: 0%;
}
}
<div class="Download">
</div>
You need to make half the linear gradient transparent (a bit list to prevent a hole in the end). Set the background position x to 100% to present only the transparent part. Then animation to 0:
.Download {
height: 80px;
width: 1000px;
border: 2px solid black;
border-radius: 100px;
background: linear-gradient(to right, red 0, blue 50.02%, transparent 50.02%) no-repeat;
animation: download 10s forwards;
background-position: 100% 0;
background-size: 200% 100%;
}
#keyframes download {
to {
background-position: 0 0;
}
}
<div class="Download">
</div>
I wanted to animate a the text fill with CSS. The Text should be filled with color from left to right.
this is my CSS:
.box-with-text {
background-image: -webkit-linear-gradient(right, crimson 50%, white 50%);
background-repeat: repeat;
background-position: 0 0;
background-size: 200% 100%;
-webkit-text-fill-color: transparent;
-webkit-background-clip: text;
-webkit-animation: stripes normal forwards ease-in-out;
animation: stripes 2s normal forwards ease-in-out;
}
Now only the first letter is color-filled.
here is the fiddle
you may also take a look at flex (for centering things) and mix-blend-mode, so it can be avalaible also for Firefox:
.box-with-text {
text-transform: uppercase;
font: bold 26vmax/.8 Open Sans, Impact;
background: black;
display: table;
color: white;
mix-blend-mode: multiply
}
#-webkit-keyframes stripes {
to {
background-size:100% 100%;
}
}
#keyframes stripes {
to {
background-size:100% 100%;
}
}
html {
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
-webkit-box-align:center;
-webkit-align-items:center;
-ms-flex-align:center;
align-items:center;
height: 100%;
background: black;
}
body {
margin: auto;
background: -webkit-linear-gradient( crimson , crimson) turquoise no-repeat 0 0;
background: linear-gradient( crimson , crimson) turquoise no-repeat 0 0;
background-size: 0 100%;
-webkit-animation: stripes 2s linear infinite;
animation: stripes 2s linear infinite;
}
<div class="box-with-text">
Text
</div>
http://codepen.io/gc-nomade/pen/XKNKzd
/* Main styles */
#import url(http://fonts.googleapis.com/css?family=Open+Sans:800);
.box-with-text {
background-image: -webkit-linear-gradient(left, crimson 50%, white 50%);
background-repeat: repeat;
background-position: 0 0;
background-size: 100% 200px;
-webkit-text-fill-color: transparent;
-webkit-background-clip: text;
-webkit-animation: stripes 2s linear infinite;
animation: stripes 2s linear infinite;
}
#-webkit-keyframes stripes {
100% {
background-position: 0 -50px;
}
}
#keyframes stripes {
100% {
background-position: 385px 0;
}
}
/* Other stuff */
body {
overflow: hidden;
background: #000;
color: #FFF;
}
.box-with-text {
position: absolute;
top: 50%;
left: 50%;
white-space: nowrap;
text-align: center;
text-transform: uppercase;
font: bold 26vmax/.8 Open Sans, Impact;
-webkit-transform: translateX(-50%) translateY(-50%);
-ms-transform: translateX(-50%) translateY(-50%);
transform: translateX(-50%) translateY(-50%);
}
<div class="box-with-text">
Text
</div>
In this case you should change
#keyframes stripes {
100% {
background-position: 385px 0;
}
}
position depends on text width;
Say you are trying to animate a tilable background like this:
.container {
width: 160px;
height: 91px;
}
.bg {
width: 100%;
height: 100%;
background: url(http://i60.tinypic.com/2j2fhjm.jpg) repeat-x left center;
background-size: contain;
-webkit-animation: displace 2s linear infinite;
animation: displace 2s linear infinite;
}
#-webkit-keyframes displace {
from {
background-position: 0 center;
}
to {
background-position: 160px center;
}
}
#keyframes displace {
from {
background-position: 0 center;
}
to {
background-position: 160px center;
}
}
<div class="container">
<textarea class="bg"></textarea>
</div>
As soon as you change the dimensions of the container, the looping animation breaks!
Is there any way to make this responsive without JS?
The problem is that, to make it responsive, you need to set the animated background-position using percentages.
But, when you set background-size as cover or contain, in some cases the width is adjusted to 100%. In this case, background-position using percentages is useless (won't move it).
The only way that I have found to manage this is moving the image to a pseudo element, and moving it. To keep the continuity, though, we will need two pseudo elements.
But that won't work on a textarea.
You didn't said anything about textarea being a requirement, so I am posting this. To show that it works on resize, hover it.
.container {
width: 160px;
height: 100px;
position: relative;
border: solid 1px black;
display: inline-block;
}
.container:nth-child(2) {
width: 220px;
}
.bg {
position: absolute;
width: 100%;
height: 100%;
overflow: hidden;
}
.bg:before, .bg:after {
content: "";
position: absolute;
width: 100%;
height: 100%;
background-image: url(http://i.stack.imgur.com/wBHey.png);
background-size: 100%;
animation: move 2s infinite linear;
}
.bg:before {
right: 100%;
}
#keyframes move {
from {transform: translateX( 0%);}
to {transform: translateX(100%);}
}
<div class="container">
<div class="bg"></div>
</div>
<div class="container">
<div class="bg"></div>
</div>
I was able to make it work by making the background twice as big.
I know this isn't the perfect solution, but maybe you can do a trick with the image size or something to make it look the way you wanted it to.
.container {width: 160px;height: 91px;}
.bg {
width: 100%;
height: 100%;
background: url(http://i60.tinypic.com/2j2fhjm.jpg) repeat-x left center;
background-size: 200%;
-webkit-animation: displace 2s linear infinite;
animation: displace 2s linear infinite;
}
#-webkit-keyframes displace {
from { background-position: left center;
} to { background-position: 200% center; }
}
#keyframes displace {
from { background-position: left center;
} to { background-position: 200% center; }
}
<div class="container"><textarea class="bg"></textarea></div>
The problem you have is with the height resizing and your different settings. To get it to work with your actual settings, the displace would have to be 2x the height of the image (since the image has a ration of 2:1). I don't think you can do only by css.
But you have different options. I'm not sure exactly which part of you display you want to keep, so here are three ways to get your translation working on resize. None have exactly your settings, because the ones you have make it hard (impossible?) to set the proper displacement. Since you're stretching the width depending on the height, it's hard to follow. Via JS it would be easy, but css has limited access to these values.
The solutions proposed keep the height constant so you can keep your displace value constant.
First one, the background-size is the size of the container in px.
Second solution, you resize textarea only on x axis.
Third you repeat on y axis and keep height and width fixed.
There are probably other workarounds that are maybe more suited to your specific needs.
.container {
width: 160px;
height: 80px;
margin: 10px;
}
.bg {
width: 100%;
height: 100%;
background: url(http://i60.tinypic.com/2j2fhjm.jpg) repeat-x left center;
background-size: 160px 80px;
padding: 0px;
-webkit-animation: displace 2s linear infinite;
animation: displace 2s linear infinite;
}
.bg2 {
width: 100%;
height: 100%;
background: url(http://i60.tinypic.com/2j2fhjm.jpg) repeat-x left center;
background-size: contain;
padding: 0px;
resize: horizontal;
-webkit-animation: displace 2s linear infinite;
animation: displace 2s linear infinite;
}
.bg3 {
width: 100%;
height: 100%;
background: url(http://i60.tinypic.com/2j2fhjm.jpg) repeat left center;
background-size: 160px 80px;
padding: 0px;
-webkit-animation: displace 2s linear infinite;
animation: displace 2s linear infinite;
}
#-webkit-keyframes displace {
from {
background-position: 0 center;
}
to {
background-position: 160px center;
}
}
#-keyframes displace {
from {
background-position: 0 center;
}
to {
background-position: 160px center;
}
}
<div class="container">
<textarea class="bg"></textarea>
</div>
<div class="container">
<textarea class="bg2"></textarea>
</div>
<div class="container">
<textarea class="bg3"></textarea>
</div>
This is similar to Ilpo's answer, except it doesn't resize the image (background-size: auto;). The animation is smooth throughout, regardless of container size.
The downside is that the width (200px) of the image needs to be known beforehand.
Since you said tilable, and since this image looks to be tilable in both directions, I also made it repeat in both dimensions. As a result, your textarea is filled with the tiled background image, animated to scroll horizontally. If you only want to tile in 1 direction, you can change repeat back to repeat-x and change the vertical position from top to whatever you need.
.container {width: 160px;height: 91px;}
.bg {
width: 100%;
height: 100%;
background: url(http://i60.tinypic.com/2j2fhjm.jpg) repeat left top;
background-size: auto;
-webkit-animation: displace 2s linear infinite;
animation: displace 2s linear infinite;
}
#-webkit-keyframes displace {
from { background-position: 0px top; }
to { background-position: 200px top; }
}
#keyframes displace {
from { background-position: 0px top; }
to { background-position: 200px top; }
}
<div class="container"><textarea class="bg"></textarea></div>
For each background-position: 200px bottom; you need to add 1second for example if you want add 2S, you add another 200px so you
make it background-position: 400px bottom; I think.
Here is the code:
.container {
width: 160px;
height: 91px;
}
.bg {
width: 100%;
height: 100%;
background: url(http://i60.tinypic.com/2j2fhjm.jpg) fixed;
-webkit-animation: displace 1s linear infinite;
animation: displace 1s linear infinite;
}
#-webkit-keyframes displace {
from { background-position: 0 bottom; }
to { background-position: 200px bottom; }
}
#keyframes displace {
from { background-position: 0 bottom; }
to { background-position: 200px bottom;}
}
<div class="container">
<textarea class="bg"></textarea>
</div>
I hope it works for your case, Let me know if you have any question.
.container {
border: 1px solid black;
display: inline-block;
background: url(http://i60.tinypic.com/2j2fhjm.jpg) repeat-x left center;
-webkit-animation: displace 2s linear infinite;
animation: displace 2s linear infinite;
background-size: 160px 100%;
}
.bg {
float: left;
border: 0;
margin: 10px;
width: 160px;
height: 91px;
background-color: rgba(255, 255, 255, .5);
}
#-webkit-keyframes displace {
from {
background-position: 0 center;
}
to {
background-position: 160px center;
}
}
#keyframes displace {
from {
background-position: 0 center;
}
to {
background-position: 160px center;
}
}
<div class="container">
<textarea class="bg"></textarea>
</div>