Related
I am a tad stumped on this following CSS shenannigan.
I have a text input element and its background is red, and I want to animate a whitewash effect when it becomes focused, and the reverse red-wash effect when it is unfocused.
#keyframes reveal-search {
0% {
background: maroon;
}
20% {
background: linear-gradient(to left, maroon 0%, whitesmoke 40%, whitesmoke 60%, maroon 100%);
}
40% {
background: linear-gradient(to left, maroon 0%, white 30%, whitesmoke 70%, maroon 100%);
}
60% {
background: linear-gradient(to left, maroon 0%, whitesmoke 20%, whitesmoke 80%, maroon 100%);
}
80% {
background: linear-gradient(to left, maroon 0%, whitesmoke 10%, whitesmoke 90%, maroon 100%);
}
100% {
background: whitesmoke;
}
}
input {
border: none;
background: maroon;
}
input:focus {
outline: none;
background: whitesmoke;
animation: reveal-search 0.1s both;
}
<input type="text" />
I have tried playing around with moving animation outside of &:focus, setting setting a separate animation property with backwards in the input, and removing the background colors as I thought they were colliding with the animation.
As it stands, the when this input is focused the is a nice white reveal animation happening from the center. But when it is unfocused, it just goes back to red. I would like the animation to play in reverse, instead.
You don't need JS for this.
You can run the same animation in reverse for the input when it is not in focus.
However, there's a slight hitch as once an animation has been run CSS doesn't run it again - so using the same animation-name it just thinks it's done it.
This snippet copies the animation keyframes reveal but calls it unreveal and gets it run in reverse when the input is not in focus:
#keyframes reveal-search {
0% {
background: maroon;
}
20% {
background: linear-gradient(to left, maroon 0%, whitesmoke 40%, whitesmoke 60%, maroon 100%);
}
40% {
background: linear-gradient(to left, maroon 0%, white 30%, whitesmoke 70%, maroon 100%);
}
60% {
background: linear-gradient(to left, maroon 0%, whitesmoke 20%, whitesmoke 80%, maroon 100%);
}
80% {
background: linear-gradient(to left, maroon 0%, whitesmoke 10%, whitesmoke 90%, maroon 100%);
}
100% {
background: whitesmoke;
}
}
#keyframes unreveal-search {
0% {
background: maroon;
}
20% {
background: linear-gradient(to left, maroon 0%, whitesmoke 40%, whitesmoke 60%, maroon 100%);
}
40% {
background: linear-gradient(to left, maroon 0%, white 30%, whitesmoke 70%, maroon 100%);
}
60% {
background: linear-gradient(to left, maroon 0%, whitesmoke 20%, whitesmoke 80%, maroon 100%);
}
80% {
background: linear-gradient(to left, maroon 0%, whitesmoke 10%, whitesmoke 90%, maroon 100%);
}
100% {
background: whitesmoke;
}
}
input {
border: none;
background: maroon;
animation: unreveal-search 0.1s both;
animation-direction: reverse;
animation-fill-mode: forwards;
}
input:focus {
outline: none;
background: whitesmoke;
animation: reveal-search 0.1s both;
}
<input type="text" />
I need to present some data. Each block of data needs a country flag. I would like to display the country flag, using a nice little hanging banner, like this:
This image is edited in paint, and the example I've used, comes from this page
This link right here, shows how to display flags of Europe++ in pure CSS. In my system, I only need Nordic flags, which are all represented by a cross.
From the codepen example:
#function cross($back, $main, $detail: $back){
#return linear-gradient(90deg, transparent 28%, $main 28%, $main 34%, transparent 34%),
linear-gradient(transparent 42%, $detail 42%, $detail 46%, $main 46%, $main 58%, $detail 58%, $detail 62%, transparent 62%),
linear-gradient(90deg, $back 25%, $detail 25%, $detail 28%, $main 28%, $main 34%, $detail 34%, $detail 37%, $back 37%);
}
If I derive this (and rotate it 90deg to fit my preferred orientation, I can get something like this:
HTML:
<div class="norway"></div>
CSS:
.norway{
background: linear-gradient(180deg, transparent 28%, blue 28%, blue 34%, transparent 34%),
linear-gradient(90deg, transparent 42%, white 42%, white 46%, blue 46%,
blue 58%, white 58%, white 62%, transparent 62%),
linear-gradient(180deg, red 25%, white 25%, white 28%, blue 28%, blue 34%,
white 34%, white 37%, red 37%);
height: 600px;
width: 400px;
}
The hanging banner example however, is not really displaying the element itself, merely its border. I like the split in the bottom, So I would like to be able to set the linear gradients on the different border sides individually, or somehow otherwise solve the problem. I have tried a few approaches, but I can't seem to make the gradients work on individual border sides.
Does anyone know how I can display my flags as split end ribbons, using only CSS?
By the way, the Czech Republic is easy...
UPDATE:
I was able to render a Norwegian version, but I had to make two elements. One displaying the flag in the background of an element, and another element over it, displaying only the bottom border, in the same color as the block background. It seems like a pretty fragile solution, though...
https://jsfiddle.net/azjctc1y/
Note: After looking at Joseph's answer, I'd suggest you to go with that but this is another way.
Instead of using border to create the flag, we can use background with linear-gradient images like in the below snippet.
/* Latest compiled and minified CSS included as External Resource*/
html {
margin: 20px;
}
/* Optional theme */
#import url('//netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap-theme.min.css');
body {
margin: 10px;
}
.test-container {
background-color: lightgrey;
border: 1px solid black;
position: relative;
padding: 10px;
margin: 10px;
min-height: 100px;
}
.close-ribbon {
position: absolute;
top: 0;
right: 1em;
z-index: 1;
color: #eee;
font-size: 2em;
}
.close-ribbon:before {
content: "";
font-size: 0.5em;
position: absolute;
border-style: solid;
border-color: transparent transparent #B71C1C transparent;
top: -1em;
right: 3em;
border-width: 0 0 1em 0.7em;
z-index: -1;
}
.close-ribbon:after {
position: absolute;
content: "";
top: -1em;
right: 0;
height: 5em;
width: 3em;
background: linear-gradient(to bottom right, transparent 48%, lightgrey 52%), linear-gradient(to bottom left, transparent 48%, lightgrey 52%), linear-gradient(180deg, transparent 38%, blue 38%, blue 44%, transparent 44%), linear-gradient(90deg, transparent 40%, white 40%, white 46%, blue 46%, blue 56%, white 55%, white 62%, transparent 62%), linear-gradient(180deg, red 35%, white 35%, white 38%, blue 38%, blue 44%, white 44%, white 47%, red 47%), linear-gradient(to bottom right, red 50%, lightgrey 55%), linear-gradient(to top right, lightgrey 45%, red 50%);
background-size: 1.6em 1.4em, 1.45em 1.4em, 3em 4em, 3em 4em, 3em 4em, 1.2em 1.1em, 1.2em 1.1em;
background-position: 0% 100%, 100% 100%, 0% 0%, 0% 0%, 0% 0%, 0% 100%, 100% 100%;
background-repeat: no-repeat;
font-size: 0.5em;
z-index: -1;
-webkit-transition: height 0.5s;
transition: height 0.5s;
}
<div class="container">
<div class="row">
<div class="col-lg-3 col-md-4 col-sm-6 col-xs-12">
<div class="test-container">
<a class="close-ribbon"></a>
Czech Republic is easy...
</div>
</div>
</div>
</div>
Original Answer:
It is not 100% like the image provided in question or the ouput of your fiddle because the blue cross doesn't have the small triangular cut because I was trying create a cut that was transparent (so that you can use it on top of an element with any background). But if it is always going to be a grey background then that can also be done.
The below is the code that I have added:
.close-ribbon:after {
position: absolute;
content: "";
top: -1em;
right: 0;
height: 5em;
width: 3em;
background: linear-gradient(180deg, transparent 28%, blue 28%, blue 34%, transparent 34%), linear-gradient(90deg, transparent 40%, white 40%, white 46%, blue 46%, blue 58%, white 58%, white 62%, transparent 62%), linear-gradient(180deg, red 25%, white 25%, white 28%, blue 28%, blue 34%, white 34%, white 37%, red 37%), linear-gradient(to bottom right, red 50%, transparent 55%), linear-gradient(to top right, transparent 45%, red 50%);
background-size: 3em 4em, 3em 4em, 3em 4em, 1.25em 1em, 1.2em 1em;
background-position: 0% 0%, 0% 0%, 0% 0%, 0% 100%, 100% 100%;
background-repeat: no-repeat;
/* other styles */
}
/* Latest compiled and minified CSS included as External Resource*/
/* Optional theme */
#import url('//netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap-theme.min.css');
body {
margin: 10px;
}
.test-container {
background-color: lightgrey;
border: 1px solid black;
position: relative;
padding: 10px;
margin: 10px;
min-height: 100px;
}
.close-ribbon {
position: absolute;
top: 0;
right: 1em;
z-index: 1;
color: #eee;
font-size: 2em;
}
.close-ribbon:before {
content: "";
font-size: 0.5em;
position: absolute;
border-style: solid;
border-color: transparent transparent #B71C1C transparent;
top: -1em;
right: 3em;
border-width: 0 0 1em 0.7em;
z-index: -1;
}
.close-ribbon:after {
position: absolute;
content: "";
top: -1em;
right: 0;
height: 5em;
width: 3em;
background: linear-gradient(180deg, transparent 28%, blue 28%, blue 34%, transparent 34%), linear-gradient(90deg, transparent 40%, white 40%, white 46%, blue 46%, blue 58%, white 58%, white 62%, transparent 62%), linear-gradient(180deg, red 25%, white 25%, white 28%, blue 28%, blue 34%, white 34%, white 37%, red 37%), linear-gradient(to bottom right, red 50%, transparent 55%), linear-gradient(to top right, transparent 45%, red 50%);
background-size: 3em 4em, 3em 4em, 3em 4em, 1.2em 1em, 1.2em 1em;
background-position: 0% 0%, 0% 0%, 0% 0%, 0% 100%, 100% 100%;
background-repeat: no-repeat;
font-size: 0.5em;
z-index: -1;
-webkit-transition: height 0.5s;
transition: height 0.5s;
}
<div class="container">
<div class="row">
<div class="col-lg-3 col-md-4 col-sm-6 col-xs-12">
<div class="test-container">
<a class="close-ribbon"></a>
Czech Republic is easy...
</div>
</div>
</div>
</div>
You have a great base to go on. It just needs a few tweaks here and there. (Making individual styles for flags is going to be a colossal pain though). There's just a few places you could improve it. In most cases when using absolute positioning, you may want to have whatever you are positioning align with some edge of the parent element. For that you can use negative values like left: -1em or whatever, but a lot of times, it's more robust to leave left auto and set the right attribute to 100%. You also set the bottom border to right:0. In throwing it in this answer I discovered that the font size difference caused it to be aligned incorrectly. One way you can fix that is to give it a left:50% with a negative margin equal to the left border. In this case it's 1.5em. A few changes, but it's all about understanding and leveraging top, right, bottom, and left to their fullest potential, which includes percent based values.
Hope it helps!
body {
padding: 2em;
}
/* Latest compiled and minified CSS included as External Resource*/
/* Optional theme */
#import url('//netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap-theme.min.css');
body {
margin: 10px;
}
.test-container{
background-color: lightgrey;
border: 1px solid black;
position: relative;
padding: 10px;
margin: 10px;
min-height: 100px;
}
.ribbon {
position: absolute;
top: 0;
right: 1em;
z-index: 1;
color: #eee;
font-size: 2em;
}
.norway {
position: absolute;
top: -0.5em;
right: 1em;
z-index: 1;
font-size: 2em;
height: 70px;
width: 42px;
background: linear-gradient(180deg, transparent 28%, blue 28%, blue 34%, transparent 34%),
linear-gradient(90deg, transparent 40%, white 40%, white 46%, blue 46%, blue 54%, white 54%, white 60%, transparent 60%),
linear-gradient(180deg, red 25%, white 25%, white 28%, blue 28%, blue 34%, white 34%, white 37%, red 37%);
}
.ribbon:before {
content: "";
font-size: 0.5em;
position: absolute;
border-style: solid;
border-color: transparent transparent #B71C1C transparent;
top: 0;
right: 100%;
border-width: 0 0 1em 0.7em;
z-index: -1;
}
.ribbon:after {
content: "";
font-size: 0.5em;
position: absolute;
height: 5em;
border: 1.5em solid #F44336;
z-index: -1;
bottom: 0;
border-top-width: 1.5em;
border-bottom-color: lightgrey;
border-right-color: transparent;
border-left-color: transparent;
border-top-color: transparent;
left: 50%;
margin-left: -1.5em;
-webkit-transition: height 0.5s;
transition: height 0.5s;
}
<div class="container">
<div class="row">
<div class="col-lg-3 col-md-4 col-sm-6 col-xs-12">
<div class="test-container">
<a class="norway ribbon"></a>
Norway
</div>
</div>
</div>
</div>
Inserted a div into the anchor tag and styled a before and after content to display the blue cross. Used a + symbol to display the white underneath cross.
jsfiddle.net/8g1w5va9/4
EDIT
Just saw your fiddle. Looks good! Was just going to suggest something like that but decided to at least build somewhat of a working model.
I want to create the same linear gradient for each border.
The border gradient with 5 colors starts from
transparent to white to black to white to transparent
That way I have transparent corners.
How can I do this for all 4 borders?
Is it possible to assign a linear-gradient to a border?
Sidenote: It should run without too much effort on IE9+ else IE10+ :P
How about using a radial gradient? Although this is just a mock up, you can see the basic effect.
.outer {
vertical-align:top;
display:inline-block;
height: 100px;
width: 100px;
position: relative;
background: -moz-radial-gradient(center, ellipse cover, rgba(0,0,0,1) 1%, rgba(0,0,0,1) 50%, rgba(0,0,0,0) 90%, rgba(0,0,0,0) 99%, rgba(0,0,0,0) 100%); /* FF3.6+ */
background: -webkit-gradient(radial, center center, 0px, center center, 100%, color-stop(1%,rgba(0,0,0,1)), color-stop(50%,rgba(0,0,0,1)), color-stop(90%,rgba(0,0,0,0)), color-stop(99%,rgba(0,0,0,0)), color-stop(100%,rgba(0,0,0,0))); /* Chrome,Safari4+ */
background: -webkit-radial-gradient(center, ellipse cover, rgba(0,0,0,1) 1%,rgba(0,0,0,1) 50%,rgba(0,0,0,0) 90%,rgba(0,0,0,0) 99%,rgba(0,0,0,0) 100%); /* Chrome10+,Safari5.1+ */
background: -o-radial-gradient(center, ellipse cover, rgba(0,0,0,1) 1%,rgba(0,0,0,1) 50%,rgba(0,0,0,0) 90%,rgba(0,0,0,0) 99%,rgba(0,0,0,0) 100%); /* Opera 12+ */
background: -ms-radial-gradient(center, ellipse cover, rgba(0,0,0,1) 1%,rgba(0,0,0,1) 50%,rgba(0,0,0,0) 90%,rgba(0,0,0,0) 99%,rgba(0,0,0,0) 100%); /* IE10+ */
background: radial-gradient(ellipse at center, rgba(0,0,0,1) 1%,rgba(0,0,0,1) 50%,rgba(0,0,0,0) 90%,rgba(0,0,0,0) 99%,rgba(0,0,0,0) 100%); /* W3C */
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#000000', endColorstr='#00000000',GradientType=1 ); /* IE6-9 fallback on horizontal gradient */
}
.inner {
height: 90%;
width: 90%;
position: absolute;
left: 5%;
top: 5%;
background: white;
}
<div class="outer">
<div class="inner">
text
</div>
</div>
<div class="outer" style="height:100px; width:200px">
<div class="inner">
text
</div>
</div>
Resources
1 * gradient generator
Note
Not suitable for projects for <=IE9
You could also do this with multiple linear-gradients as backgrounds and position them as required like in the below snippet.
To change the size/width of the border, modify the 20px value in the background-size. (Note: Depending on the desired output, you may have to change the linear-gradient percentages also when you change the size. But that should be reasonably straight-forward to do.)
background-size: 100% 20px, 100% 20px, 20px 100%, 20px 100%;
Gradients on the whole have no support in IE 9 but should work in IE 10+. Border-image on the other hand works only from IE 11 upwards.
.border-image {
height: 200px;
width: 200px;
background: -webkit-linear-gradient(0deg, transparent 10%, white 10%, black 50%, white 90%, transparent 90%), -webkit-linear-gradient(0deg, transparent 10%, white 10%, black 50%, white 90%, transparent 90%), -webkit-linear-gradient(90deg, transparent 10%, white 10%, black 50%, white 90%, transparent 90%), -webkit-linear-gradient(90deg, transparent 10%, white 10%, black 50%, white 90%, transparent 90%);
background: -moz-linear-gradient(0deg, transparent 10%, white 10%, black 50%, white 90%, transparent 90%), -moz-linear-gradient(0deg, transparent 10%, white 10%, black 50%, white 90%, transparent 90%), -moz-linear-gradient(90deg, transparent 10%, white 10%, black 50%, white 90%, transparent 90%), -moz-linear-gradient(90deg, transparent 10%, white 10%, black 50%, white 90%, transparent 90%);
background: linear-gradient(90deg, transparent 10%, white 10%, black 50%, white 90%, transparent 90%), linear-gradient(90deg, transparent 10%, white 10%, black 50%, white 90%, transparent 90%), linear-gradient(0deg, transparent 10%, white 10%, black 50%, white 90%, transparent 90%), linear-gradient(0deg, transparent 10%, white 10%, black 50%, white 90%, transparent 90%);
background-repeat: no-repeat, no-repeat, no-repeat, no-repeat;
background-size: 100% 20px, 100% 20px, 20px 100%, 20px 100%;
background-position: 0px 0px, 0px 100%, 0px 0px, 100% 0px;
padding: 20px;
}
<div class="border-image">Some Test Content</div>
I want this effect
http://antonioleiva.com/wp-content/uploads/2014/03/SwipeRefreshLayout.gif
At the moment I have this one http://codepen.io/anon/pen/czulD
Can someone code it like native android swipetorefresh layout?
See code below (same as CodePen example)
HTML
<html>
<body>
<div class="preloader"></div>
</body>
</html>
CSS
.preloader {
height: 5px;
width: 100%;
}
.preloader {
background-size: 100px 100px;
background-image: -moz-linear-gradient(135deg, #fecf23 25%, transparent 25%,transparent 50%, #fecf23 50%, #fecf23 75%,transparent 75%, transparent);
background-image: -webkit-gradient(135deg, #fecf23 25%, transparent 25%,transparent 50%, #fecf23 50%, #fecf23 75%,transparent 75%, transparent);
background-image: -webkit-linear-gradient(135deg, #fecf23 25%, transparent 25%,transparent 50%, #fecf23 50%, #fecf23 75%,transparent 75%, transparent);
background-image: -o-linear-gradient(135deg, #fecf23 25%, transparent 25%,transparent 50%, #fecf23 50%, #fecf23 75%,transparent 75%, transparent);
background-image: -ms-linear-gradient(135deg, #fecf23 25%, transparent 25%,transparent 50%, #fecf23 50%, #fecf23 75%,transparent 75%, transparent);
background-image: linear-gradient(135deg, #fecf23 25%, transparent 25%,transparent 50%, #fecf23 50%, #fecf23 75%,transparent 75%, transparent);
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#fecf23', endColorstr='#34c2e3',GradientType=1 );
background-color: #34c2e3;
-ms-animation: animate-stripes 1.2s linear infinite;
-o-animation: animate-stripes 1.2s linear infinite;
-moz-animation: animate-stripes 1.2s linear infinite;
animation: animate-stripes 1.2s linear infinite;
-webkit-animation: animate-stripes 1.2s linear infinite;
transition: width .4s ease-in-out;
-ms-transition: width .4s ease-in-out;
-o-transition: width .4s ease-in-out;
-webkit-transition: width .4s ease-in-out;
-moz-transition: width .4s ease-in-out;
}
#-ms-keyframes animate-stripes {
0% {
background-position: 0 0;
}
100% {
background-position: 200px 0;
}
}
#-o-keyframes animate-stripes {
0% {
background-position: 0 0;
}
100% {
background-position: 200px 0;
}
}
#-moz-keyframes animate-stripes {
0% {
background-position: 0 0;
}
100% {
background-position: 200px 0;
}
}
#-webkit-keyframes animate-stripes {
0% {
background-position: 0 0;
}
100% {
background-position: 200px 0;
}
}
#keyframes animate-stripes {
0% {
background-position: 0 0;
}
100% {
background-position: 200px 0;
}
}
Since linear-gradients are, in fact, rendered images, they are not animatable (yet).
You can get the effect thinking about it in that way.
The way I use to animate gradients is to interpolate opacity between multiple elements with different gradients. Like this:
http://jsfiddle.net/L9p4swzx/
.container{
position:relative;
width:300px;
height:300px;
border:1px solid black;
}
.container h1{
display:block;
position:relative;
z-index:2;
}
.animated {
z-index:1;
position:absolute;
width:100%;
height:100%;
background: -webkit-gradient(linear, left top, right bottom, color-stop(0%, #ff670f), color-stop(21%, #ff670f), color-stop(56%, #ffffff), color-stop(88%, #0eea57));
background: -webkit-linear-gradient(-45deg, #ff670f 0%, #ff670f 21%, #ffffff 56%, #0eea57 88%);
background: linear-gradient(135deg, #ff670f 0%, #ff670f 21%, #ffffff 56%, #0eea57 88%);
animation:gra1 5s infinite;
animation-direction:alternate;
-webkit-animation:gra1 5s infinite;
-webkit-animation-direction:alternate;
animation-timing-function:linear;
-webkit-animation-timing-function:linear;
}
.animated2 {
content: ' ';
z-index:1;
position:absolute;
width:100%;
height:100%;
border:1px solid black;
background: -webkit-gradient(linear, left top, right bottom, color-stop(0%, #ff670f), color-stop(10%, #ff670f), color-stop(40%, #ffffff), color-stop(60%, #0eea57));
background: -webkit-linear-gradient(-45deg, #ff670f 0%, #ff670f 10%, #ffffff 40%, #0eea57 60%);
background: linear-gradient(135deg, #ff670f 0%, #ff670f 10%, #ffffff 40%, #0eea57 60%);
animation-direction:alternate;
-webkit-animation:gra2 5s infinite;
-webkit-animation-direction:alternate;
animation-timing-function:linear;
-webkit-animation-timing-function:linear;
}
.animated3 {
content: ' ';
z-index:1;
position:absolute;
width:100%;
height:100%;
border:1px solid black;
background: -webkit-gradient(linear, left top, right bottom, color-stop(0%, #ff670f), color-stop(5%, #ff670f), color-stop(10%, #ffffff), color-stop(40%, #0eea57));
background: -webkit-linear-gradient(-45deg, #ff670f 0%, #ff670f 5%, #ffffff 10%, #0eea57 40%);
background: linear-gradient(135deg, #ff670f 0%, #ff670f 5%, #ffffff 10%, #0eea57 40%);
animation-direction:alternate;
-webkit-animation:gra3 5s infinite;
-webkit-animation-direction:alternate;
animation-timing-function:linear;
-webkit-animation-timing-function:linear;
}
#-webkit-keyframes gra {
33% {
opacity: 1;
}
80% {
opacity: 0;
}
100% {
opacity:0;
}
}
#-webkit-keyframes gra2 {
33% {
opacity: 0;
}
66% {
opacity: 1;
}
100% {
opacity:0;
}
}
#-webkit-keyframes gra3 {
33% {
opacity: 0;
}
66% {
opacity: 0;
}
100% {
opacity:1;
}
}
With a little bit more of tweaking you can get decent animation.
But for your case, there's a better solution, which is animate the background position, since the gradient changes are similar.
http://jsfiddle.net/3L6tybd5/1/
.container{
position:relative;
width:300px;
height:300px;
border:1px solid black;
}
.container h1{
display:block;
position:relative;
z-index:2;
}
.animated {
z-index:1;
position:absolute;
width:100%;
height:100%;
background: -webkit-gradient(linear, left top, right bottom, color-stop(0%, #ff670f), color-stop(5%, #ff670f), color-stop(20%, #ffffff), color-stop(44%, #0eea57));
background: -webkit-linear-gradient(-45deg, #ff670f 0%, #ff670f 5%, #ffffff 20%, #0eea57 44%);
background: linear-gradient(135deg, #ff670f 0%, #ff670f 5%, #ffffff 20%, #0eea57 44%);
background-size:200%;
background-position:0px 0px;
animation:gra1 5s infinite;
animation-direction:alternate;
-webkit-animation:gra1 5s infinite;
-webkit-animation-direction:alternate;
animation-timing-function:linear;
-webkit-animation-timing-function:linear;
}
#-webkit-keyframes gra1 {
33% {
background-position:0px 0px;
}
66% {
background-position:-50px -50px;
}
100% {
background-position:-150px -150px;
}
}
Notice that I changed some values of the animation and the gradient so it renderer bigger than the container.
Hope it helps
I want to move my gradient that has multiple colors smoothly but the problem is that the animation is not smooth. It just changes its position at every step.
<style>
.animated {
width: 300px;
height: 300px;
border: 1px solid black;
animation: gra 5s infinite;
animation-direction: reverse;
-webkit-animation: gra 5s infinite;
-webkit-animation-direction: reverse;
animation-timing-function: linear;
-webkit-animation-timing-function: linear;
}
#keyframes gra {
0% {
background: -webkit-gradient(linear, left top, right bottom, color-stop(0%, #ff670f), color-stop(21%, #ff670f), color-stop(56%, #ffffff), color-stop(88%, #0eea57));
background: -webkit-linear-gradient(-45deg, #ff670f 0%, #ff670f 21%, #ffffff 56%, #0eea57 88%);
background: linear-gradient(135deg, #ff670f 0%, #ff670f 21%, #ffffff 56%, #0eea57 88%);
}
50% {
background: -webkit-gradient(linear, left top, right bottom, color-stop(0%, #ff670f), color-stop(10%, #ff670f), color-stop(40%, #ffffff), color-stop(60%, #0eea57));
background: -webkit-linear-gradient(-45deg, #ff670f 0%, #ff670f 10%, #ffffff 40%, #0eea57 60%);
background: linear-gradient(135deg, #ff670f 0%, #ff670f 10%, #ffffff 40%, #0eea57 60%);
}
100% {
background: -webkit-gradient(linear, left top, right bottom, color-stop(0%, #ff670f), color-stop(5%, #ff670f), color-stop(10%, #ffffff), color-stop(40%, #0eea57));
background: -webkit-linear-gradient(-45deg, #ff670f 0%, #ff670f 5%, #ffffff 10%, #0eea57 40%);
background: linear-gradient(135deg, #ff670f 0%, #ff670f 5%, #ffffff 10%, #0eea57 40%);
}
}
</style>
<div class="animated">
<h1>Hello</h1>
</div>
Is it possible to accomplish without using jQuery?
My jsfiddle link is https://jsfiddle.net/bAUK6
Please try this code:
#gradient
{
height:300px;
width:300px;
border:1px solid black;
font-size:30px;
background: linear-gradient(130deg, #ff7e00, #ffffff, #5cff00);
background-size: 200% 200%;
-webkit-animation: Animation 5s ease infinite;
-moz-animation: Animation 5s ease infinite;
animation: Animation 5s ease infinite;
}
#-webkit-keyframes Animation {
0%{background-position:10% 0%}
50%{background-position:91% 100%}
100%{background-position:10% 0%}
}
#-moz-keyframes Animation {
0%{background-position:10% 0%}
50%{background-position:91% 100%}
100%{background-position:10% 0%}
}
#keyframes Animation {
0%{background-position:10% 0%}
50%{background-position:91% 100%}
100%{background-position:10% 0%}
}
<html>
<div id="gradient">
Hello
</div>
</html>
Dynamic implementation of Dave's answer:
:root{
--overlay-color-1: #ff0000;
--overlay-color-2: #0000ff;
--anim-duration: 2s;
}
#gradient {
opacity: 0.8;
background: none;
}
#gradient:after,
#gradient:before {
content: '';
display: block;
position: absolute;
top: 0; bottom: 0; left: 0; right: 0;
}
#gradient:before {
background: linear-gradient(135deg, var(--overlay-color-2) 0%, var(--overlay-color-1) 100%);
animation: OpacityAnim var(--anim-duration) ease-in-out 0s infinite alternate;
}
#gradient:after {
background: linear-gradient(135deg, var(--overlay-color-1) 0%, var(--overlay-color-2) 100%);
animation: OpacityAnim var(--anim-duration) ease-in-out calc(-1 * var(--anim-duration)) infinite alternate;
}
#keyframes OpacityAnim {
0%{opacity: 1.0}
100%{opacity: 0.0}
}
<div id="gradient"></div>
Using CSS variables it's now a trivial task.
Here is a basic example (hover to see the result)
#property --a{
syntax: '<angle>';
inherits: false;
initial-value: 90deg;
}
#property --l{
syntax: '<percentage>';
inherits: false;
initial-value: 10%;
}
#property --c{
syntax: '<color>';
inherits: false;
initial-value: red;
}
.box {
/* needed for firefox to have a valid output */
--a:80deg;
--l:10%;
--c:red;
/**/
cursor:pointer;
height:200px;
transition:--a 0.5s 0.1s,--l 0.5s,--c 0.8s;
background:linear-gradient(var(--a), var(--c) var(--l),blue,var(--c) calc(100% - var(--l)));
}
.box:hover {
--a:360deg;
--l:40%;
--c:green;
}
<div class="box"></div>
More details here: https://dev.to/afif/we-can-finally-animate-css-gradient-kdk
How about this:
Set the body margin and padding to 0. Set an html rule to 100% height (higher than 100% may be required).
Set the body to the end state for the gradient.
Create an empty div with a background which is the start state for the gradient. Give the empty div 100% height.
Give both the body and the empty div a background-attachment: fixed;
Create a wrapper for your body content.
Set the empty div to position: fixed;
Set the wrapper to position: relative;
Give both a z-index, the wrapper being higher.
Create an animation that will change the opacity of the empty div from 1 to 0 over the desired time. Add animation-fill-mode:forwards; to the div rule so the animation stays where it ends.
It's not as sexy as a real animated gradient shift, but it's as simple as you can get with CSS only and keyframes, I think.
Here is another way. The following has the static gradient containing all phases of the animation, which is then moved inside the outer element. This allows to perform animation smoothly (as the topic suggests), because the only animation here is the element position.
Please note that for the sake of performance the gradient element left unchanged. Although the question was to animate the gradient, moving the background does practically the same thing, while the performance wins!
.animated {
width: 300px;
height: 300px;
overflow: hidden;
position: relative;
border: 1px solid black;
}
.innerGradient {
z-index: -1;
width: 300%;
height: 300%;
position: absolute;
animation: gra 5s infinite;
-webkit-animation: gra 5s infinite;
background: linear-gradient(135deg, #ff670f 0%, #ff670f 20%, #ffffff 50%, #0eea57 80%, #0eea57 100%);
background: -webkit-linear-gradient(135deg, #ff670f 0%, #ff670f 20%, #ffffff 50%, #0eea57 80%, #0eea57 100%);
}
#keyframes gra {
0% { left: -200%; top: -200%; }
50% { left: 0%; top: 0%; }
100% { left: -200%; top: -200%; }
}
<div class="animated">
<h1>Hello</h1>
<div class="innerGradient"></div>
</div>