Hide & show 3 images on a loop using CSS - html

Trying to loop through 3 images with only showing one at time for 7 seconds, which then disappears and then show the next one in the sequence, then the next image. The loop needs to be infinite without a "transition / fade" delay.
The images are animating GIFs, so trying to line up the timing with the transitions is so far failing to work.
Currently using this:
.images {
margin: auto;
}
.images img {
position: absolute;
-webkit-animation: fade 21s infinite;
animation: fade 21s infinite;
}
#keyframes fade {
0% {
opacity: 1;
}
15% {
opacity: 1;
}
25% {
opacity: 0;
}
90% {
opacity: 0;
}
100% {
opacity: 1;
}
}
-webkit-#keyframes fade {
0% {
opacity: 1;
}
15% {
opacity: 1;
}
25% {
opacity: 0;
}
90% {
opacity: 0;
}
100% {
opacity: 1;
}
}
#img1 {
-webkit-animation-delay: 0s;
animation-delay: 0s;
}
#img2 {
-webkit-animation-delay: -7s;
animation-delay: -7s;
}
#img3 {
-webkit-animation-delay: -14s;
animation-delay: -14s;
}
<div class="images">
<img id="img1" src="https://example.com/gif-1.gif">
<img id="img2" src="https://example.com/gif-2.gif">
<img id="img3" src="https://example.com/gif-3.gif">
</div>
Any help would be greatly appriciated

Here you can define the duration in a variable to control the appearance time of a single image.
I'm using a single set of keyframes, changing the opacity of every image to 1 for ⅓ of the animation-duration (and to 0 for the remaining time).
Unfortunately calc can't be used to define percentages into keyframes, so if you change the number of images you also need to manually change those percentages, as described in the comments inside the code.
Grid display is used as an alternative of position: relative and position: absolute. fetchpriority was used for the first image to increase its priority (since it's the first image of the animation and it has to be loaded soon).
.loop {
--time: 7s;
display: grid;
}
/* show animation only if user hasn't set a preference,
otherwise just show stacked images */
#media (prefers-reduced-motion: no-preference) {
.loop img {
grid-area: 1/1;
animation: rotate calc(var(--time) * 3) linear 0s infinite;
}
.loop img:nth-child(2) { animation-delay: calc(var(--time) * -2); }
.loop img:nth-child(3) { animation-delay: calc(var(--time) * -1); }
}
#keyframes rotate {
/* 33.33% is (100% / number of images) */
0%, 33.33% { opacity: 1; }
/* 33.34% is (100% / number of images) + 0.01 */
33.34%, 100% { opacity: 0; }
}
<div class="loop">
<img src="https://picsum.photos/id/237/300/200/" fetchpriority="high" />
<img src="https://picsum.photos/id/238/300/200/" />
<img src="https://picsum.photos/id/239/300/200/" />
</div>
As a side note, for a matter of accessibility, you should give the user the capability to stop every animation longer than 5 seconds since it can potentially provoke seizures. In any case don't rotate images faster than 3 per second.

Related

How do I make this animation play, then stop, then play again after a set amount of time? (css)

I'm making a text animation for my friend's website and I'm trying to make a flicker effect, it works, however, it plays once, and I want it to play, then stop, then start again. THe make I've tried only messes it up. Does anyone know a solution?
(my animation code)
.neon span {
animation: flicker 900ms linear 2;
}
.neon .delay1 {
animation-delay: 1.4s;
}
.neon .delay2 {
animation-delay: 2.0s;
}
#keyframes flicker
{
0% { opacity: 0; }
10% { opacity: 1; }
20% { opacity: 0; }
40% { opacity: 1; }
50% { opacity: 0; }
60% { opacity: 1; }
80% { opacity: 0; }
100% { opacity: 1; }
}
In the animation: flicker 900ms linear 2; line of code I've tried putting infinte but when I do that it flickers supers fast with no break. I want it to flicker kinda slow then stop, then flicker again.
animation-delay only specifies the delay time before the animation first starts.
animation-iteration-count which (for example) you might specify in your animation shorthand as infinite doesn't include that in between interations.
So, you have to 'fake' it by manually building that into your #keyframes.
.neon span {
animation: flicker 900ms linear 1.4s infinite;
}
#keyframes flicker {
0% { opacity: 0; }
10% { opacity: 1; }
20% { opacity: 0; }
40% { opacity: 1; }
50% { opacity: 0; }
60% { opacity: 1; } /* 'fake' delay */
80% { opacity: 1; } /* 'fake' delay */
100% { opacity: 1; } /* 'fake' delay */
}
In the example above, it will wait 1.4 seconds upon initial page load, then start to flicker between opacity: 0 and opacity: 1 for 60% of your 900ms duration, then stay opacity: 1 for the other 40%.
How fast it flickers will depend on your animation-duration (e.g. 900ms) divided by the number of selectors (steps) over the course of your #keyframes.
So, if you increase/decrease the duration, or decrease/increase the number of keyframe selectors (e.g. 0%, 1%, 2%, 3% ... 100%) it will flicker slower/faster.
Then it will restart immediately after and repeat infinitely.
Discussed here:
CSS animation delay in repeating
CSS animation delay between iterations

How to reset the opacity of an image after pressing?

I have an image on my page representing an up arrow and, which is used to jump to the top of the page thanks to a link). This image has an opacity of "0.2", and "1" when hovering over it with the mouse.
From a smartphone or tablet, when you press on this image, the opacity remains at "1".
I would like this opacity to return to "0.2" after pressing this one.
How to do please?
My HTML code :
<img src="./img/up.png" alt="up" title="up">
My CSS code :
a > img {
width: 60%;
height: 60%;
opacity: 0.2;
}
a > img:hover {
opacity: 1;
}
Thanks
A solution with Javascript/Jquery
I modified an answer of mine of few days ago
$('#clickMe').click(function () {
$(this).addClass('tothetop');
$(this).on("animationend", function(event) {
$(this).removeClass('tothetop')
});
});
img {
opacity:0.2;
}
.tothetop {
animation-fill-mode: forwards;
animation-name: test;
animation-duration: 2s;
}
#keyframes test {
50% {opacity:1;}
100% {opacity:0.2;}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<img id="clickMe" src="https://picsum.photos/200">
A solution using only CSS
#keyframes move {
50% {
opacity: 1;
}
100% {
opacity: 0.2;
}
}
img {
animation-fill-mode: forwards;
opacity:0.2;
}
img:hover {
animation: move 2s;
}
<img src="https://picsum.photos/200">
A Pure CSS Solution without JavaScript
The problem lies with how best to implement :hover on interfaces where the user is not using a cursor controlled by a mouse or trackpad or a keyboard.
There isn't (yet) a perfect way to do this.
It doesn't exist, but we could imagine that the touchscreen counterpart to:
my-div:hover
might be:
my-div:touch
where the :hover behaviour is displayed for a second or two and then no longer displayed.
In the absence of a hypothetical :touch pseudo-class however, we can nevertheless implement one - and in CSS alone, without using JavaScript.
We can do this by introducing an animation for touchscreens - something like this:
#keyframes hoverForTouchScreens {
0%, 50% {
opacity: 1;
}
}
We can also ensure that this animation only fires on touchscreens with a #media query:
#media screen and (hover: none) and (pointer: coarse) {
a > img:hover {
opacity: 0.2;
animation: hoverForTouchScreens 2s ease-out;
}
}
Working Example
Putting it all together:
a > img {
opacity: 0.2;
}
a > img:hover {
opacity: 1;
}
a > img.touchscreen-simulation:hover {
opacity: 0.2;
animation: hoverForTouchScreens 2s ease-out;
}
#keyframes hoverForTouchScreens {
0%, 50% {
opacity: 1;
}
}
#media screen and (hover: none) and (pointer: coarse) {
a > img:hover {
opacity: 0.2;
animation: hoverForTouchScreens 2s ease-out;
}
}
<a href="#top">
<img src="https://picsum.photos/120/120" alt="up" title="up">
<img class="touchscreen-simulation" src="https://picsum.photos/120/120" alt="up" title="up">
</a>
<p>The <code>#media query</code> won't be active on non-touch screens, so the <strong>image on the right</strong> is set up to simulate what <em>would</em> happen on a touchscreen in this setup.</p>
Working Example:

Modifying the jm spinner dot to make it same size without the bounce

I'm using the jm spinner plugin on my site, but I want to change the bouncing dots from changing size (bouncing) when they show. They display as a 'bounce' that makes them look like they are growing in size. I just want them to stay the same size, but I've been playing with the .css file and the debugger and I can't figure out to make any changes!
Here is a code pen
On the site it says I can modify/style the spinner like
.spinner {
}
but I'm not sure what to put here.
It seems like I don't want the 'sk-bouncedelay' but not sure
Something like this? If so, you can forget about the plugin.
.spinner>div {
width: 13px;
height: 13px;
background-color: blue;
border-radius: 50%;
display: inline-block;
opacity: 0;
animation: showhide 1.4s infinite;
}
.spinner .dot1 {
animation-delay: -0.32s;
}
.spinner .dot2 {
animation-delay: -0.16s;
}
#keyframes showhide {
0%,
100% {
opacity: 0;
}
80% {
opacity: 1;
}
}
<div class="spinner">
<div class="dot1"></div>
<div class="dot2"></div>
<div class="dot3"></div>
</div>

CSS3 diaporama, how to make the change gradual?

I'm making a diaporama in pure css, and so far so good, however each pic changes to the other abruptly and i'm trying to make the change gradual (one pic disapearing slowly while the other appears).
I've tried with all timing functions (except cubic-bezier since i'm not too sure how to use it yet) and it hasn't worked.
How to make the changes gradual? I've seen someone doing it with only css3 but I haven't been able to reproduce it.
Here is the css and the html
.diapo {
width: 350px;
height: 150px;
border: 3px solid #544B4D;
background-image: url("http://via.placeholder.com/350x150/F00");
background-size: 350px 150px;
animation-name: diapo1;
animation-duration: 9s;
animation-timing-function: linear;
animation-iteration-count: infinite;
animation-direction: normal;
}
#keyframes diapo1 {
0% {
background-image: url("http://via.placeholder.com/350x150/F00");
}
33% {
background-image: url("http://via.placeholder.com/350x150/0F0");
}
66% {
background-image: url("http://via.placeholder.com/350x150/00F");
}
}
<body>
<div class="diapo">
</div>
</body>
Thanks for any answer!
IMO, the best solution is to use multiple img in the DOM combined with some opacity animations:
.container {
position: relative;
/* Define size on the container: (best if aligned with images size) */
width: 350px;
height: 150px;
box-sizing: content-box;
/* fancy stuff, not required */
border: 1px solid #000;
border-radius: 5px;
overflow: hidden;
}
.container > img {
height: inherit;
width: inherit;
/* images are stacked on top of each other */
position: absolute;
top: 0;
left: 0;
opacity: 0;
/* 10s is total time (time for a complete cycle) */
animation: fadeInOut 10s infinite;
}
.container > img:nth-child(2) {
animation-delay: 3.33s; /* totalTime * 1/3 */
}
.container > img:nth-child(3) {
animation-delay: 6.66s; /* totalTime * 2/3 */
}
/* choose a % of anim time allocated to transition,
let's call it transTime. Here it's 10%. */
#keyframes fadeInOut {
0% {
opacity: 0;
}
/* transTime */
10% {
opacity: 1;
}
/* transTime + (100% / image count) */
43% {
opacity: 1;
}
/* previous + transTime */
53% {
opacity: 0;
}
}
<div class="container">
<img src="http://via.placeholder.com/350x150/F00"/>
<img src="http://via.placeholder.com/350x150/0F0"/>
<img src="http://via.placeholder.com/350x150/00F"/>
</div>
I strongly advise you to use a preprocessor that allow variables and loops (maybe SCSS or Less) to generate the nth-child section and even the animation block
I don't know that most browser can interprete a change in background-image gradually... How can they interprete that change ? Should it mean the picture slides from the top, should it mean a fade out/fade in, should it mean a fade in of the new picture above the old one ?
I think you'd need to animate a fade out/in (The code below might not work as is, it is just to give you an idea) :
#keyframes diapo1 {
0% {
background-image: url("pics-about-us/a-u1.jpeg");
}
30% { opacity:1;}
33% {
background-image: url("pics-about-us/a-u3.jpeg");
opacity:0;
}
36% {opacity:1}
//etc...
If you want to do it with a gradual change over the whole animation, I would use on <div> child per background image and animate each individually.

CSS Animation Delay and Keyframe

I have a problem with animation delay on CSS Animation. I have 3 images and I want to make it slideshow. The illustrations is, image 1 to image 2 takes 15 seconds to change and image 2 to image 3 takes 15 seconds to change and image 3 back to image 1 it takes 30 seconds, after the first loop, I want to make the slideshow end in image 3 so image 1 to image 2 still 15 seconds and image 2 to image 3 still 15 seconds and when image 3 load it no need to back to image 1. I tried this code but it gives me 15 seconds delay to all images. This is my code :
ul {
list-style: none;
margin: 0;
padding: 0;
position: relative;
}
li {
position: absolute;
opacity:0;
}
li {
animation: xfade 45s infinite;
}
li:nth-child(2) {
animation-delay:15s;
}
li:nth-child(3) {
animation-delay:30s;
}
#keyframes xfade{
3%{opacity:1}
33% {opacity:1;}
36%{opacity:0}
}
<ul>
<li><img width="500" height="500" src="http://lorempixel.com/500/500/sports" alt="pic1"></li>
<li><img width="500" height="500" src="http://lorempixel.com/500/500/people" alt="pic2"></li>
<li><img width="500" height="500" src="http://lorempixel.com/500/500/transport" alt="pic3"></li>
</ul>
I want to make delay in my animation according the illustrations above. Anyone could help me solve this problem ? Thank you before.
I am thinking that using GreenSock is better if you want animation with specific scenario like this.
Here is the closest I can get with HTML and CSS, I also need to duplicate the <li> to fit your scenario.
ul {
list-style: none;
margin: 0;
padding: 0;
position: relative;
}
li {
position: absolute;
opacity: 0;
}
li:nth-child(6) {
/*The last item always on the top, direction will goes from last to first*/
animation: xfade 15s;
}
li:nth-child(5) {
/*Put animation length double the delay (in this case delay is the actual animation length)*/
animation: xfade 30s 15s;
}
li:nth-child(4) {
animation: xfade 30s 15s;
}
li:nth-child(3) {
animation: xfade 30s 15s;
}
li:nth-child(2) {
animation: xfade 30s 15s;
}
li:nth-child(1) {
opacity: 1;
}
#keyframes xfade{
0%{opacity:0}
33% {opacity:1;}
100%{opacity:0}
}
<ul>
<li>1<img width="500" height="500" src="http://lorempixel.com/500/500/sports" alt="pic1"></li>
<li>2<img width="500" height="500" src="http://lorempixel.com/500/500/people" alt="pic2"></li>
<li>3<img width="500" height="500" src="http://lorempixel.com/500/500/transport" alt="pic3"></li>
<!-- Duplicate -->
<li>4<img width="500" height="500" src="http://lorempixel.com/500/500/sports" alt="pic1"></li>
<li>5<img width="500" height="500" src="http://lorempixel.com/500/500/people" alt="pic2"></li>
<li>6<img width="500" height="500" src="http://lorempixel.com/500/500/transport" alt="pic3"></li>
</ul>
Here's something that gave real food for thought :)
I had to apply 2 animations for opacity change: xfade-25pct and xfade-50pct. Both play only 2 times, fading out briefly after 25% and 50% of the animation. And an additional show animation to make the 3rd image stick after 2 animation loops, with the necessary rule animation-fill-mode: forwards;.
The trick to opacity is this: you have to split the animation in 4 quarters. If you want you can change the total animation duration from 60s to a multiple of 4, and adjust the delays. The 3rd animation delay is the double of the 2nd one.
----#----#----#----#----#----#----#----#----#----#
1st animation | 1st animation |
--------------------------------------------------
15s | 2nd animation | 2nd animation |
--------------------------------------------------
30s | 3rd animation | 3rd animation |
----#----#----#----#----#----#----#----#----#----#
Feel free to ask. Hope this helps you.
var s = 0,
c = 1;
/* Code for displaying timer */
window.setInterval(function() {
s++;
document.querySelector('DIV').innerHTML = s;
if (s == 15 && c <= 2 || s == 30) {
if (s == 30) {
c = 1;
} else {
c++;
}
s = 0;
}
}, 1000);
ul {
list-style: none;
margin: 0;
padding: 0;
position: relative;
}
li {
position: absolute;
opacity: 0;
}
li {
animation: xfade-25pct 60s 2;
}
li:nth-child(2) {
animation-delay: 15s;
}
li:nth-child(3) {
animation-delay: 30s, 120s;
animation-name: xfade-50pct, show;
animation-duration: 60s, 1s;
animation-iteration-count: 2, 1;
animation-fill-mode: forwards;
}
#keyframes xfade-25pct {
0% {
opacity: 0;
}
2%,
25% {
opacity: 1;
}
27% {
opacity: 0;
}
}
#keyframes xfade-50pct {
0% {
opacity: 0;
}
2%,
50% {
opacity: 1;
}
52% {
opacity: 0;
}
}
#keyframes show {
0%,
100% {
opacity: 1;
}
}
<DIV></DIV>
<ul>
<li><img width="500" height="500" src="https://www.noao.edu/image_gallery/images/d2/pelican_500.jpg" alt="pic1"></li>
<li><img width="500" height="500" src="http://whc.unesco.org/uploads/thumbs/news_920-500-500-20151015155516.jpg" alt="pic2"></li>
<li><img width="500" height="500" src="https://i.pinimg.com/736x/4c/17/65/4c176537aee906de294138c3bac5b8f5--merry-christmas-love-coffee-aroma.jpg" alt="pic3"></li>
</ul>