I want to have an animated 'carousel' of thumbnails.
However, for small devices I want my thumbnails to move in a vertical direction; And for larger devices I want my thumbnails to move in a circle.
I am looking for a css-only solution.
It seems fairly easy to do this with just one item ... but once additional items are added, there must be some means of staggering either their start moment or start position. Also for linear, there must be a way to return items that have gone out of the container div to return to make additional passes.
please see my solution down below ...
The key is in the css animation parameter: animation-delay ... and by simply staggering those everything will work (be sure to see my working plunker) ...
However, a lot of hardcoding is required for this: a unique css declaration has to be created for every individual item in the 'carousel', so imagine if you have 50 jpgs in your 'carousel' ... too verbose! (for what it is worth, I actually used php to create those individual, item-specific css declarations in a typical <?php for( /* each item */ ){ /* write its declaration */ }; echo $the_long_css_declarations_string;?>, but I don't show the php here, because this solution can be done without it)
This example uses 3 items in the 'carousel' ... (I have left out vendor-specific rules for simplicity ... (see autoprefixer to get vendor-specific rules))
// css
#media (min-width: 100px )
{
.carousel_item
{ position : absolute ;
top : 5% ;
left : -10% ;
width : auto ;
height : 90% ;
}
.carousel_item[data-index='0']
{ animation: the_name 6s linear 0s infinite normal ;
}
.carousel_item[data-index='1']
{ animation: the_name 6s linear 2s infinite normal ;
}
.carousel_item[data-index='2']
{ animation: the_name 6s linear 4s infinite normal ;
}
#keyframes the_name
{ 0% { transform: translate( -0%) ; }
100%{ transform: translate( 5000%) ; }
}
}
#media (min-width: 500px )
{
.carousel_item
{
position: absolute;
top : 50%;
left : 50%;
width : auto;
height : 10%;
border : solid red 1px ;
}
.carousel_item[data-index='0']
{ animation: the_name 6s linear 0s infinite normal ;
}
.carousel_item[data-index='1']
{ animation: the_name 6s linear 2s infinite normal ;
}
.carousel_item[data-index='2']
{ animation: the_name 6s linear 4s infinite normal ;
}
#keyframes the_name
{ 0% { transform: rotate(0deg) translateX(450%) rotate(0deg) ; }
100%{ transform: rotate(360deg) translateX(450%) rotate(-360deg); }
}
}
// html
<span id = "carousel" >
<span data-index = "0"
class = "carousel_item" >
0
</span>
<span data-index = "1"
class = "carousel_item" >
1
</span>
<span data-index = "2"
class = "carousel_item" >
2
</span>
</span>
Related
I want to make random "blinking" effect when hovering over a doodle. For this i store animation name blink into a variable when user hovers over doodle container. For some reason animation applies only to the first element of the grid. Is there a way to apply the animation to all elements?
CodePen: https://codepen.io/entityinarray/pen/mdbRPRz
<html>
<script src="https://unpkg.com/css-doodle#0.7.2/css-doodle.min.js"></script>
<css-doodle>
:doodle {
#grid: 4/128px;
--h: ;
}
:doodle(:hover) {--h: blink;}
background: #200040;
animation-delay: rand(500ms);
animation: #var(--h) 1s infinite;
#keyframes blink {
0% {
background: #200040;
}
100% {
background: #8000c0;
}
}
</css-doodle>
</html>
The issue is that the use of #var(--h) is generating code like var(--h)-x which is invalid and only the first item is having the good value var(--h).
Instead of doing this you can simply consider the animation state like below. Note that rand() should be used with # and placed after the animation definition:
<html>
<script src="https://unpkg.com/css-doodle#0.7.2/css-doodle.min.js"></script>
<css-doodle>
:doodle {
#grid: 4/128px;
}
:doodle(:hover) {--h:running;}
background: #200040;
animation: blink 1s infinite;
animation-play-state:var(--h,paused);
animation-delay: #rand(500ms);
#keyframes blink {
0% {
background: #200040;
}
100% {
background: #8000c0;
}
}
</css-doodle>
</html>
I was wondering how I can calculate two animation delays (fade in and fade out) by using a for loop in Sass.
Came up with the following, but doesn't know how to calc the second animation delay.
#for $i from 1 through 2 {
.text:nth-child(#{$i}) {
animation-delay: ($i * 0.5s), 4s;
}
}
I would like to do the same for the fade in, so each text element will be slightly stagger.
Already tried something like this, but with no result.
#for $i from 1 through 2 {
.text:nth-child(#{$i, $a}) {
animation-delay: ($i * 0.5s), ($a * 0.5s);
}
}
And how can I use the last delay to start another delay of another animation?
I'm not sure exactly what you're trying to accomplish.
The easy version
That said, the basic idea is to do the "in" and "out" animations as percentages of the same animation function. In this case the build in = 25%, static = 50%, and build out = 25%.
Then your duration controls how long each part takes to complete. In this case 2 seconds.
Next, the delay (calculated as part of the loop) offsets the animation. You could also multiply the duration in the loop to completely stagger the animation.
$timeOffset: 0.5s;
$aniLength: 2s;
// 0.5s in, 1s solid, 0.5s out = 2sec
.item {
opacity:0;
animation-name: animation;
animation-duration: $aniLength;
animation-timing-function: ease-in-out;
}
#for $i from 1 through 20 {
.item:nth-child(#{$i}){
// units are in the variable so SCSS just does math
animation-delay: $i * $timeOffset;
}
}
#keyframes animation {
0% {
opacity: 0;
transform: translatex(100%);
}
25% {
opacity: 1;
transform: translatex(0);
}
75% {
opacity: 1;
transform: translatex(0);
}
100% {
opacity: 0;
transform: translatex(-100%);
}
}
Here's a Codepen example since SO doesn't parse SCSS in the code sandbox available here.
More complex version with multiple delays
Your second example didn't work because you were building an odd selector in your nth-child code while using an undefined variable.
Also, you can do pretty complex math for each iteration. Just remember concepts like Order of Operations.
The correct way to specify two different delay values is like this:
#for $i from 1 through 20 {
// the hash forces SCSS to create a string
.item:nth-child(#{$i}){
// you need to use $i for BOTH since its the only defined increment
animation-delay: $i * $timeOffset, $i * $timeOffset + $aniLength;
// delay #1 = iteration * 0.5s, delay #2 = iteration * 0.5s + 2s (run at end of animation plus the offset)
}
}
You can set #if, #for, #each and #while in SCSS file. Refer my jsfiddle for fade out animation base on for loops.
#for $i from 1 through 10 {
.div-wrapper {
div:nth-child(#{$i}) {
transition: all $i/3 +s;
transition-delay: $i/3 +s;
}
}
}
Example: https://jsfiddle.net/hardyrajput/nt6p9hs2/29/
Refernce: http://thesassway.com/intermediate/if-for-each-while
I'm trying to create some Christmas lights (in January) using the CSS -webkit-animation property.
For this, I'm using this image:
I've tried:
#-webkit-keyframes lights {
0% {
background-position:0px;
} 100% {
background-position:0 -69px;
}
}
#lights {
width:100%;
height:69px;
background:url(https://mysterybrand.net/assets/images/new-year/live-drop-gardland.png);
-webkit-animation: lights 1s infinite;
}
What I want to achieve: I want to constantly change the background position, so it looks like the lights are turning off and on.
For some reason, my code doesn't change the background position, and animated the image.
You can consider steps()1 to have the needed effect and adjust the positions like below. Pay attention to the initial value because 0 is not the same as 0 0:
#keyframes lights {
0% {
/*Two zeros, not one !!*/
/*[0] is equivalent to [0 50%] and will create a different animation */
background-position:0 0;
}
100% {
background-position:0 -138px;
}
}
#lights {
height:69px;
background:url(https://i.imgur.com/BdGY6tH.png);
animation: lights 1s infinite steps(2);
}
<div id="lights"></div>
Or do it like this:
#keyframes lights {
0%,50% {
background-position:0 0; /*Two zeros, not one !!*/
}
50.1%,100% {
background-position:0 -69px;
}
}
#lights {
height:69px;
background:url(https://i.imgur.com/BdGY6tH.png);
animation: lights 1s infinite;
}
<div id="lights"></div>
1 More details about how to use steps() : https://stackoverflow.com/a/51843473/8620333
I have images that I want to swap in and out (no slide effect). The first cycle, the images appear stacked on top of each other (since they have holes). All subsequent cycles, it works correctly (only one visible at a time).
Html
<div class="small xfade">
<span></span>
<span></span>
<span></span>
<span></span>
</div>
css
#keyframes xfade {
0% { opacity:1; }
17% { opacity:1; }
25% { opacity:0; }
92% { opacity:0; }
100% { opacity:1; }
}
.xfade span {
animation-name: xfade;
animation-timing-function: ease-in-out;
animation-iteration-count: infinite;
animation-duration: 8s;
height: 100%;
left: 0;
/* opacity: 0; */
position: absolute;
top: 0;
width: 100%;
}
All visible at once during first loop
Only one visible during first loop, but flash
An usual scene when doing animations is where you have the same animation for several elements, but you want them to be delayed, making a sort of full cycle.
Then you set a animation-duration of say 8 seconds, and if you have 4 elements, you set a delay of 0 for the first, a delay of 2s for the second, and 4s and 6s for the others.
The problem with this is that the second element only starts animating after 2 seconds. In the meantime, it has the initial properties, that can match, or not, (usually not) the properties of the animation.
The best way to solve that is to realize that, if the animation-duration is 8s, then setting the delay to 2s is the same than setting it to -6s. because if you count 8s starting in -6s, you will end at 2s. But, then the animation is running from the first moment, with the properties that should have.
So, the delays in your case should be 0s, -6s, -4s, -2s. Just subtract the transition-duration from the transition delay.
Whenever you set an animation, and discover than the first animation is wrong, but after that they are ok, the likely problem (and solution) is this.
If you want to make everything go faster, but everything else being the same, then you have to reduce both the animation duration and all the animation delays
Example setting
.xfade span {
animation-duration: 4s;
}
.xfade span:nth-of-type(1) {
animation-delay: -1s;
}
.xfade span:nth-of-type(2) {
animation-delay: -2s;
}
.xfade span:nth-of-type(3) {
animation-delay: -3s;
}
fiddle
Also, let's analyze how the tween time is computed. First of all, you are setting the animation for an element that shares the full time with another 3 elements. That means that every element has 1/4 of the time, that is 25%.
This time has to be divided between time of full display and time of tween. Inthe original example, tween time is 8%. If you want that reduced, let's say that tween time will be 6%. Then, full display time will be 25 - 6 = 19.
That gives us the first part of the keyframes:
#keyframes xfade {
0% { opacity:1; }
19% { opacity:1; }
25% { opacity:0; }
Now, for the final keyframes, we have to remember that the tween time is 6, and set that at the end. The keyframe mus be at 100 - 6 = 94. Remainig keyframes:
94% { opacity:0; }
100% { opacity:1; }
}
i would like to make a slider with css3, I dont want any buttons for it. just an infinite animation that slides 5 individual images, the problem is i want something like this:
load in the page, wait 30sec then show 2nd wait 30sec then show 3rd wait 30sec then show 4th wait 30 sec then show 5th wait 30 sec then show first
#overflow #banner {
height: 350px;
width: 500%;
background: #fff;
-webkit-animation:slide-animation 10s infinite;
}
#-webkit-keyframes slide-animation {
0% {margin-left: 0;}
20% {margin-left:-100%;}
40% {margin-left:-200%;}
60% {margin-left:-300%;}
80% {margin-left:-400%;}
100% {margin-left:0;}
}
how can i do that?
use the css property animation-delay (-webkit-animation-delay or -moz-animation-delay). Duplicate the animation and set these delays to 30s, 60s, 90s etc
I have done this another way myself here is my example:
-webkit-animation: baloon 10s ease-in-out 3s infinite normal;
#-webkit-keyframes baloon {
0% { -webkit-transform: translate(0px, 0px); }
50% { -webkit-transform: translate(50px, 75px); }
100% { -webkit-transform: translate(0px, 0px); }
}
The 3s in the first line will delay it by 3 seconds before it starts after the page loads.
To make the initial delay you add 30s after the 10s, that sets the initial delay.
To set up the recurring delays, you can use the setInterval function in javascript to change the animation state every time interval you want.
You can use this code as a springboard for the css:
animation-play-state: paused;
-moz-animation-play-state: paused; /* Firefox*/
-webkit-animation-play-state: running; /* Safari and Chrome */
-o-animation-play-state: running; /* Opera */
With javascript, this function should do the trick:
function changeAnimState() {
x = 0;
var banner = document.getElementById("banner");
if (x%2 == 0) {banner.style.animationPlayState="running";}
else {banner.style.animationPlayState="paused";};
x+ = x;
)
window.onload = setInterval(changeAnimState(), 30000);
This code is for the unprefixed animation play state, to added the prefixed versions, just add: WebkitAnimationPlayState or MozAnimationPlayState or OAnimationPlayState.