CSS linear gradient progress animation - css

I've put together an animation which indicates a countdown until a toast notification disappears:
.toastDiv {
animation: toastProgress 3s ease;
border: 1px solid rgba(0, 0, 0, .5);
border-radius: 5px;
box-shadow: 0 0 5px 0 rgba(0, 0, 0, .25);
margin: 0 0 1ex 0;
padding: 1ex 1em;
}
#keyframes toastProgress {
0% {
background: linear-gradient(to right, aliceblue 0%, aliceblue 0%, white 0%, white 100%);
}
10% {
background: linear-gradient(to right, aliceblue 0%, aliceblue 10%, white 10%, white 100%);
}
20% {
background: linear-gradient(to right, aliceblue 0%, aliceblue 20%, white 20%, white 100%);
}
30% {
background: linear-gradient(to right, aliceblue 0%, aliceblue 30%, white 30%, white 100%);
}
40% {
background: linear-gradient(to right, aliceblue 0%, aliceblue 40%, white 40%, white 100%);
}
50% {
background: linear-gradient(to right, aliceblue 0%, aliceblue 50%, white 50%, white 100%);
}
60% {
background: linear-gradient(to right, aliceblue 0%, aliceblue 60%, white 60%, white 100%);
}
70% {
background: linear-gradient(to right, aliceblue 0%, aliceblue 70%, white 70%, white 100%);
}
80% {
background: linear-gradient(to right, aliceblue 0%, aliceblue 80%, white 80%, white 100%);
}
90% {
background: linear-gradient(to right, aliceblue 0%, aliceblue 90%, white 90%, white 100%);
}
100% {
background: linear-gradient(to right, aliceblue 0%, aliceblue 100%, white 100%, white 100%);
}
}
<div class="toastDiv">hello</div>
However, it is very tedious to have to spell out the individual animation stages and at the granularity I chose, I am getting choppy results.
I tried using this:
#keyframes toastProgress {
from {
background: linear-gradient(to right, aliceblue 0%, aliceblue 0%, white 0%, white 100%);
}
to {
background: linear-gradient(to right, aliceblue 0%, aliceblue 100%, white 100%, white 100%);
}
}
But this transitions from one solid background to the next instead of animating the color stops from left to right.
Is there a way to make this progress-style gradient animation using only from and to and not percent-steps?

You can rely on background-size animation and steps() like below:
.toastDiv {
border: 1px solid rgba(0, 0, 0, .5);
border-radius: 5px;
box-shadow: 0 0 5px 0 rgba(0, 0, 0, .25);
margin: 0 0 1ex 0;
padding: 1ex 1em;
background:
linear-gradient(aliceblue,aliceblue) left no-repeat,
white;
animation: toastProgress 5s steps(10,start);
}
#keyframes toastProgress {
0% {
background-size:0% 100%;
}
100% {
background-size:100% 100%;
}
}
<div class="toastDiv">hello</div>
<div class="toastDiv" style="animation-timing-function:ease">without Steps</div>
Related to understand how steps() works: https://stackoverflow.com/a/51843473/8620333

Related

How can I code this menu icon with only CSS and one element?

I have tried so far.
body {
margin:0;
padding:20px;
background-color: #000;
}
.mobil-menu__icon {
height: 50px;
width: 50px;
background:
linear-gradient(to bottom, #fff 0%, #fff 20%, transparent 20%, transparent 100%),
linear-gradient(to bottom, transparent 0%, transparent 40%, #fff 40%, #fff 60%, transparent 60%, transparent 100%),
linear-gradient(to bottom, transparent 0%, transparent 80%, #fff 80%, #fff 100%);
}
<div class="mobil-menu__icon"></div>
Use only solid color in gradient and rely on background-size:
.mobil-menu__icon {
height: 50px;
width: 50px;
background:
/* position / width height */
linear-gradient(#fff,#fff) top left / 100% 20%,
linear-gradient(#fff,#fff) center left / 80% 20%,
linear-gradient(#fff,#fff) bottom left / 60% 20%,
red;
border:10px solid red;
background-repeat:no-repeat; /* Never forget this! */
}
<div class="mobil-menu__icon"></div>
With hover animation:
.mobil-menu__icon {
height: 50px;
width: 50px;
background:
linear-gradient(#fff,#fff) top left,
linear-gradient(#fff,#fff) center left,
linear-gradient(#fff,#fff) bottom left,
red;
background-size:
100% 20%,
80% 20%,
60% 20%;
border:10px solid red;
background-repeat:no-repeat;
transition:0.3s all;
}
.mobil-menu__icon:hover {
background-size:100% 20%;
}
<div class="mobil-menu__icon"></div>
And if you want with transparency:
.mobil-menu__icon {
height: 50px;
width: 50px;
background:
linear-gradient(red,red) 0 calc(1*100%/4) / 100% 20%,
linear-gradient(red,red) 0 calc(3*100%/4) / 100% 20%,
linear-gradient(red,red) 100% calc(2*100%/4) / 20% 20%,
linear-gradient(red,red) 100% calc(4*100%/4) / 40% 20%;
border:10px solid red;
background-repeat:no-repeat;
}
body {
background:repeating-linear-gradient(to right,white 0 5px,grey 10px);
}
<div class="mobil-menu__icon"></div>
You were also almost good with your code but you were missing the size and the repeat:
body {
margin: 0;
padding: 20px;
background-color: #000;
}
.mobil-menu__icon {
height: 50px;
width: 50px;
background:
linear-gradient(to bottom, #fff 0%, #fff 20%, transparent 20%, transparent 100%),
linear-gradient(to bottom, transparent 0%, transparent 40%, #fff 40%, #fff 60%, transparent 60%, transparent 100%),
linear-gradient(to bottom, transparent 0%, transparent 80%, #fff 80%, #fff 100%);
background-size:100% 100%,80% 100%, 60% 100%;
background-repeat:no-repeat;
}
<div class="mobil-menu__icon"></div>
Related question to get more details about the different values:
Using percentage values with background-position on a linear gradient

Blend diagonal linear gradients

I have created this pattern, consisting of blue and red lines. But I can't find a way to blend the red and the blue lines (to something like dark purple if I'm correct) where they cross each-other (see third case). Any ideas? Using transparency doesn't help as I only want it where they cross.
div{
width:50px; height:100px;
border: solid 2px black;
float:left;
margin:10px;
font-size:30px;
font-weight:bold;
}
.caro-pattern1 {
background-color:#2ECC40;
background-image: linear-gradient(-45deg, blue 5%, transparent 5%, transparent 45%, blue 45%, blue 55%, transparent 55%, transparent 95%, blue 95% );
background-size:50px 50px;
}
.caro-pattern2 {
background-color:#2ECC40;
background-image:
linear-gradient(45deg, red 5%, transparent 5%, transparent 45%, red 45%, red 55%, transparent 55%, transparent 95%, red 95% );
background-size:50px 50px;
}
.caro-pattern3 {
background-color:#2ECC40;
background-image:
linear-gradient(45deg, red 5%, transparent 5%, transparent 45%, red 45%, red 55%, transparent 55%, transparent 95%, red 95% ),
linear-gradient(-45deg, blue 5%, transparent 5%, transparent 45%, blue 45%, blue 55%, transparent 55%, transparent 95%, blue 95% );
background-size:50px 50px;
}
<div class="caro-pattern1">1</div>
<div class="caro-pattern2">2</div>
<div class="caro-pattern3">3</div>
You have one posibility, without changing much your current approach.
Just set the red stripes twice, the first without transparency. On top, set the blue stripes, and on top set againg the red ones, now with alpha:
div {
width: 50px;
height: 100px;
border: solid 2px black;
float: left;
margin: 10px;
font-size: 30px;
font-weight: bold;
}
.caro-pattern3 {
background-color: #2ECC40;
background-image:
linear-gradient(45deg, rgba(255, 0, 0, .5) 5%, transparent 5%, transparent 45%, rgba(255, 0, 0, .5) 45%, rgba(255, 0, 0, .5) 55%, transparent 55%, transparent 95%, rgba(255, 0, 0, .5) 95%),
linear-gradient(-45deg, blue 5%, transparent 5%, transparent 45%, blue 45%, blue 55%, transparent 55%, transparent 95%, blue 95%),
linear-gradient(45deg, red 5%, transparent 5%, transparent 45%, red 45%, red 55%, transparent 55%, transparent 95%, red 95%);
background-size: 50px 50px;
}
<div class="caro-pattern3">3</div>
Another posibility, as posted by Abhitalks, is to use blend mode (with limited browser support). But you need to set it on a pseudo element to avoid blending it with the solid background:
div {
width: 50px;
height: 100px;
border: solid 2px black;
float: left;
margin: 10px;
font-size: 30px;
font-weight: bold;
}
.caro-pattern3 {
background-color: #2ECC40;
position: relative;
}
.caro-pattern3:after {
content: "";
position: absolute;
left: 0;
top: 0;
right: 0;
bottom: 0;
background-image:
linear-gradient(-45deg, blue 5%, transparent 5%, transparent 45%, blue 45%, blue 55%, transparent 55%, transparent 95%, blue 95%),
linear-gradient(45deg, red 5%, transparent 5%, transparent 45%, red 45%, red 55%, transparent 55%, transparent 95%, red 95%);
background-size: 50px 50px;
background-blend-mode: screen;
}
<div class="caro-pattern3">3</div>
You can experiment with the new background-blend-mode, which is currently in editor's draft for Compositing and blending Level 1.
References: background-blend-mode and mix-blend-mode.
Be advised though, that this is currently not supported by IE, Edge and Opera, with partial support in Safari. That leaves only Chrome and Firefox :(
Example Snippet:
div {
width: 50px; height: 100px;
border: solid 2px black;
margin: 10px;
}
.caro-pattern3 {
background-color: #2ECC40;
background-image:
linear-gradient(45deg, red 5%, transparent 5%, transparent 45%, red 45%, red 55%, transparent 55%, transparent 95%, red 95% ),
linear-gradient(-45deg, blue 5%, transparent 5%, transparent 45%, blue 45%, blue 55%, transparent 55%, transparent 95%, blue 95% );
background-size: 50px 50px;
background-blend-mode: color, hard-light;
}
<div class="caro-pattern3">3</div>

Split a div in 3 section

I have to do a soccer team shield with css, the idea is do a circle with the team colors and I have done the circles for shields with 1 or 2 colors but I am having troubles with 3 color shields
I'm using this for 2 colors shields
.equipo{
border-radius: 50%;
vertical-align: middle;
border: 1px solid #333333;
box-sizing: border-box;
width: 25px;
height: 25px;
background-image: linear-gradient(to right, #01135B 50%, #FFFFFF 50%);
background-image: -o-linear-gradient(left, #01135B 50%, #FFFFFF 50%);
background-image: -moz-linear-gradient(left, #01135B 50%, #FFFFFF 50%);
background-image: -webkit-linear-gradient(left, #01135B 50%, #FFFFFF 50%);
background-image: -ms-linear-gradient(left, #01135B 50%, #FFFFFF 50%);
display: inline-block;
}
<div class="equipo"></div>
but I want that it have 3 color and I try this, but it doesn't work
.equipo{
border-radius: 50%;
vertical-align: middle;
border: 1px solid #333333;
box-sizing: border-box;
width: 25px;
height: 25px;
background-image: linear-gradient(to right, #01135B 20%, #FFFFFF 50%, #DF0408 30%);
background-image: -o-linear-gradient(left, #01135B 20%, #FFFFFF 50%, #DF0408 30%);
background-image: -moz-linear-gradient(left, #01135B 20%, #FFFFFF 50%, #DF0408 30%);
background-image: -webkit-linear-gradient(left, #01135B 20%, #FFFFFF 50%, #DF0408 30%);
background-image: -ms-linear-gradient(left, #01135B 20%, #FFFFFF 50%, #DF0408 30%);
display: inline-block;
}
<div class="equipo"></div>
What I have to do, I want 3 or more colors?
It is the nature of CSS gradients to behave, well, like gradients. The trick for having discrete colors, which do not blend, is to make the blend area have no width. This is done by putting two colors at the same point on the gradient, as shown below.
.equipo {
border-radius: 50%;
vertical-align: middle;
border: 1px solid #333333;
box-sizing: border-box;
width: 25px;
height: 25px;
background-image: linear-gradient(left, #01135B 33%, #FFFFFF 33%, #FFFFFF 67%, #DF0408 67%);
background-image: -o-linear-gradient(left, #01135B 33%, #FFFFFF 33%, #FFFFFF 67%, #DF0408 67%);
background-image: -moz-linear-gradient(left, #01135B 33%, #FFFFFF 33%, #FFFFFF 67%, #DF0408 67%);
background-image: -webkit-linear-gradient(left, #01135B 33%, #FFFFFF 33%, #FFFFFF 67%, #DF0408 67%);
background-image: -ms-linear-gradient(left, #01135B 33%, #FFFFFF 33%, #FFFFFF 67%, #DF0408 67%);
display: inline-block;
}
<div class="equipo"></div>
Add the same color again, if one ends at 30%, the next one should start at 30%,
As so: -moz-linear-gradient(left center , #01135b 30%, #ffffff 30%, #ffffff 65%, #df0408 30%)
This will essentially make a hard edge/stop on the previous color
.equipo {
border-radius: 50%;
vertical-align: middle;
border: 1px solid #333333;
box-sizing: border-box;
width: 25px;
height: 25px;
display: inline-block;
background: -moz-linear-gradient(left center , #01135b 32%, #ffffff 32%, #ffffff 66%, #df0408 66%);
}
<div class="equipo"></div>
Apply the same principal to the rest.
Try this just added new linear gradients which is overriding your styling if this is what you were looking for you can remove the upper gradients. Also added one alternate with many colors.
.equipo{
border-radius: 50%;
vertical-align: middle;
border: 1px solid #333333;
box-sizing: border-box;
width: 25px;
height: 25px;
background-image: linear-gradient(to right, #01135B 20%, #FFFFFF 50%, #DF0408 30%);
background-image: -o-linear-gradient(left, #01135B 20%, #FFFFFF 50%, #DF0408 30%);
background-image: -moz-linear-gradient(left, #01135B 20%, #FFFFFF 50%, #DF0408 30%);
background-image: -webkit-linear-gradient(left, #01135B 20%, #FFFFFF 50%, #DF0408 30%);
background-image: -ms-linear-gradient(left, #01135B 20%, #FFFFFF 50%, #DF0408 30%);
display: inline-block;
background-image: -o-linear-gradient(top, #a8e9ff 0%, #052afc 25%,#ff8d00 100%);
background-image: -ms-linear-gradient(top, #a8e9ff 0%, #052afc 25%,#ff8d00 100%);
background-image: -webkit-gradient(linear, right top, right bottom, color-stop(15%,#a8e9ff), color-stop(32%,#052afc),color-stop(90%,#ff8d00));
}
.grad {
background-image: -moz-linear-gradient( to right, red, #f06d06, rgb(255, 255, 0), green, blue, gray, purple );
background-image: -webkit-linear-gradient( to right, red, #f06d06, rgb(255, 255, 0), green, blue, gray, purple );
background-image: linear-gradient( to right, red, #f06d06, rgb(255, 255, 0), green, blue, gray, purple );
}
<div class="equipo"></div>
<div class="equipo grad"></div>
here i worked for a flag, this is same as your requirement, try this
.flag-sample {
border-radius: 50%;
border: 1px solid #333333;
width: 100px;
height: 100px;
display: block;
background: -moz-linear-gradient(left center , #01135b 33%, #ffffff 33%, #ffffff 66%, #df0408 66%);
}
<div class="flag-sample"></div>

Apply linear gradient on <hr>

I want an hr that contains 50% of the page.
hr {
background-color: #E0DFDF;
background-image: -moz-linear-gradient(left, white 0%, #E0DFDF 50%, white 100%);
background-image: -webkit-linear-gradient(left, white 0%, #E0DFDF 50%, white 100%);
background-image: -o-linear-gradient(left, white 0%, #E0DFDF 50%, white 100%);
background-image: linear-gradient(left, white 0%, #E0DFDF 50%, white 100%);
border: none;
margin: 1.5em auto;
height: 1px;
width: 50%;
}
background-color: #border; is invalid CSS. I guess you are porting some code from preprocessor (e.g. SASS), please fix it.
Your syntax is wrong:
/* incorrect */
-webkit-linear-gradient: (left, white 0%, #E0DFDF 50%, white 100%);
^^
/* correct */
-webkit-linear-gradient(left, white 0%, #E0DFDF 50%, white 100%);
Here's a demo:
hr {
background-image: -moz-linear-gradient(left, white 0%, #E0DFDF 50%, white 100%);
background-image: -webkit-linear-gradient(left, white 0%, #E0DFDF 50%, white 100%);
background-image: -o-linear-gradient(left, white 0%, #E0DFDF 50%, white 100%);
background-image: linear-gradient(left, white 0%, #E0DFDF 50%, white 100%);
border: none;
margin: 1.5em auto;
height: 1px;
width: 50%;
}
<hr>
Your syntax is incorrect. linear-gradient: (...) should be ---> linear-gradient(...), without the semi-colon(:).
hr {
background: -webkit-linear-gradient(to right, white 0%, #E0DFDF 50%, white 100%);
background: -moz-linear-gradient(to right, white 0%, #E0DFDF 50%, white 100%);
background: -o-linear-gradient(to right, white 0%, #E0DFDF 50%, white 100%);
background: linear-gradient(to right, white 0%, #E0DFDF 50%, white 100%);
border: 0;
margin: 1.5em auto;
height: 1px;
width: 50%;
}
<hr />

Radial gradient background pattern

I'm trying to achieve the effect below with pure CSS3. I think that repeating-radial-gradient is the right path to take, but I can't figure out how to get the radial gradient to go "from big to small" horizontally. Any advice?
This is the closest I've gotten jsfiddle. It's close, but it doesn't go "from big to small" horizontally.
.dotted {
padding: 2.25em 1.6875em;
background-color: #ffb55d;
background-image: -webkit-repeating-radial-gradient(center center, #ff9d4b, #ff9d4b 2px, transparent 2px, transparent 100%);
background-image: -moz-repeating-radial-gradient(center center, #ff9d4b, #ff9d4b 2px, transparent 2px, transparent 100%);
background-image: -ms-repeating-radial-gradient(center center, #ff9d4b, #ff9d4b 2px, transparent 2px, transparent 100%);
background-image: repeating-radial-gradient(center center, #ff9d4b, #ff9d4b 2px, transparent 2px, transparent 100%);
-webkit-background-size: 5px 5px;
-moz-background-size: 3px 3px;
background-size: 5px 5px;
}
Much Closer to what you are looking for:
.dotted {
height:100px;
width:100%;
background: radial-gradient(orange 15%, transparent 16%) 1px 1px,
radial-gradient(orange 15%, transparent 16%) 8px 8px,
radial-gradient(rgba(255,255,255,.1) 15%, transparent 20%) 0 1px,
radial-gradient(rgba(255,255,255,.1) 15%, transparent 20%) 8px 9px;
background-color:#ffb55d;
background-size:16px 16px;
}
Modified jbutler483's find on codepen (just for fun) (with Chrome):
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div style="background: rgba(0,0,0,1);">
<div class='halftone' height='100px'></div>
<div class='halftone2' height='100px'></div>
</div>
<style>
* {
margin: 0;
padding: 0;
position: relative;
box-sizing: border-box;
}
html,
body {
height: 100%;
}
div {
height: 100%;
background-color: 0;
}
.halftone {
/*
size progressively decreasing
*/
background-image: radial-gradient(circle, dodgerblue 85%, transparent 0), radial-gradient(circle, dodgerblue 80%, transparent 0), radial-gradient(circle, dodgerblue 75%, transparent 0), radial-gradient(circle, dodgerblue 70%, transparent 0), radial-gradient(circle, dodgerblue 65%, transparent 0), radial-gradient(circle, dodgerblue 60%, transparent 0), radial-gradient(circle, dodgerblue 55%, transparent 0), radial-gradient(circle, dodgerblue 50%, transparent 0), radial-gradient(circle, dodgerblue 45%, transparent 0), radial-gradient(circle, dodgerblue 40%, transparent 0), radial-gradient(circle, dodgerblue 35%, transparent 0), radial-gradient(circle, dodgerblue 30%, transparent 0), radial-gradient(circle, dodgerblue 25%, transparent 0), radial-gradient(circle, dodgerblue 20%, transparent 0);
/*
change all other values when changing this.
I suppose this'd be easier to do in Sass.
*/
background-size: 1em 1em;
/*
If you want a vertical pattern change to repeat-x, also remember to switch the background-positions' values. Eg. "2em 0" becomes "0 2em".
*/
background-repeat: repeat-y;
/*
based on background-size value
*/
background-position: 0 0, 1em 0, 2em 0, 3em 0, 4em 0, 5em 0, 6em 0, 7em 0, 8em 0, 9em 0, 10em 0, 11em 0, 12em 0, 13em 0;
}
.halftone2 {
/*
size progressively increasing
*/
background-image: radial-gradient(circle, dodgerblue 20%, transparent 0), radial-gradient(circle, dodgerblue 25%, transparent 0), radial-gradient(circle, dodgerblue 30%, transparent 0), radial-gradient(circle, dodgerblue 35%, transparent 0), radial-gradient(circle, dodgerblue 40%, transparent 0), radial-gradient(circle, dodgerblue 45%, transparent 0), radial-gradient(circle, dodgerblue 50%, transparent 0), radial-gradient(circle, dodgerblue 55%, transparent 0), radial-gradient(circle, dodgerblue 60%, transparent 0), radial-gradient(circle, dodgerblue 65%, transparent 0), radial-gradient(circle, dodgerblue 70%, transparent 0), radial-gradient(circle, dodgerblue 75%, transparent 0), radial-gradient(circle, dodgerblue 80%, transparent 0), radial-gradient(circle, dodgerblue 85%, transparent 0);
/*
change all other values when changing this.
I suppose this'd be easier to do in Sass.
*/
background-size: 1em .8em;
/*
If you want a vertical pattern change to repeat-x, also remember to switch the background-positions' values. Eg. "2em 0" becomes "0 2em".
*/
background-repeat: repeat-y;
/*
based on background-size value
*/
background-position: 0 0, 1em 0, 2em 0, 3em 0, 4em 0, 5em 0, 6em 0, 7em 0, 8em 0, 9em 0, 10em 0, 11em 0, 12em 0, 13em 0;
}
.halftone {
animation: rt 4s infinite;
animation-direction: alternate;
}
.halftone2 {
animation: rt2 4s infinite;
animation-direction: alternate;
}
#keyframes rt {
0% {
opacity: 0;
transform: rotateY(0deg);
}
25% {
opacity: 1
}
50% {
opacity: 0;
transform: rotateY(180deg);
}
75% {
opacity: 1
}
100% {
opacity: 0;
transform: rotateY(360deg);
}
}
#keyframes rt2 {
0% {
opacity: 1;
transform: rotateY(0deg) translateY(-405px);
}
25% {
opacity: 0
}
50% {
opacity: 1;
transform: rotateY(180deg) translateY(-405px);
}
75% {
opacity: 0
}
100% {
opacity: 1;
transform: rotateY(360deg) translateY(-405px);
}
}
</style>
Okay, looks like this isn't possible via CSS3. I did make it work with an image though, so I guess that's the best answer.

Resources