CSS3 diaporama, how to make the change gradual? - html

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.

Related

Hide & show 3 images on a loop using CSS

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.

Is there a way to fade two div elements into one another in CSS?

If I have two div elements that contain some text and I want them into one another such that as one disappears the other appears and it then repeats how do i go about doing this? I'm not sure where to where to start.
<div id="body">
<div>My great adventure</div>
<div>Travel, adventure, leisure</div>
</div>
Using CSS animations we can achieve this pretty simply.
We will create 2 animations. One that causes the text to fade in initially, and one to cause the text to fade out initially. We will set these animations to loop forever.
You can fine tune the timings and opacity levels to your needs.
.fade {
position: absolute;
}
#start {
opacity: 1;
animation-name: fadeStart;
animation-duration: 4s;
animation-iteration-count: infinite;
}
#end {
opacity: 0;
animation-name: fadeEnd;
animation-duration: 4s;
animation-iteration-count: infinite;
}
#keyframes fadeStart {
0% {
opacity: 1;
}
50% {
opacity: 0;
}
100% {
opacity: 1;
}
}
#keyframes fadeEnd {
0% {
opacity: 0;
}
50% {
opacity: 1;
}
100% {
opacity: 0;
}
}
<div id="container">
<div class="fade" id="start">My great adventure</div>
<div class="fade" id="end">Travel, adventure, leisure</div>
</div>
If you are just talking about non-animated, static elements visually fading into one another, you can use a linear-gradient for the background of ::before and ::after pseudo-elements.
Below is a pure CSS example making use of CSS variables for consistent colors and sizing. The ::before and ::after pseudo-elements fade from the background color to transparent. You can increase the multiplier in margin on the #body > div to decrease the amount of overlap.
body {
--div-bg: orange;
--fade-height: 3rem;
background: white;
}
#body>div {
position: relative;
color: black;
background: var(--div-bg);
padding: 1rem;
margin: calc(var(--fade-height) * 1) 0 0;
}
#body>div::before,
#body>div::after {
content: "";
position: absolute;
left: 0;
right: 0;
height: var(--fade-height);
}
#body>div::after {
bottom: calc(var(--fade-height) * -1);
background: linear-gradient(to bottom, var(--div-bg), transparent);
}
#body>div::before {
top: calc(var(--fade-height) * -1);
background: linear-gradient(to top, var(--div-bg), transparent);
}
<div id="body">
<div>My great adventure</div>
<div style="--div-bg: #33F;">Travel, adventure, leisure</div>
</div>

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>

Remove/Hide div from DOM after animation completes using CSS?

I have an animation where a div slides out the view, however when the animation is completed, the div just returns to its origin position in the view. How do I totally remove the div or hide it after the animation ends using just CSS?
Here is the markup:
<div class="container">
<div class="slide-box" id="slide-box""></div>
</div>
and the css:
.slide-box {
position: relative;
width: 100px;
height: 100px;
background-image: url(../pics/red.png);
background-position: center;
background-size: cover;
background-repeat: no-repeat;
animation: slide 5s linear 1;
}
#keyframes slide {
0% {
left: 0;
}
20% {
left: 20%;
}
40% {
left: 40%;
}
60% {
left: 60%;
}
80% {
left: 80%;
}
100% {
left: 100%;
overflow: hidden;
visibility: hidden;
}
}
I don't want it to fade out over the duration of the animation, i just want it to disappear once it hits 100% in the keyframe. Thanks ahead of time!
Use the animation-fill-mode option. Set it to forwards and the animation ends at it's final state and stay like that.
Altered based upon comments Set opacity fade to just last 1% of animation... simplified keyframes. Added a jquery option to literally remove the div from the DOM. CSS alone won't alter the markup, where jQuery will.
Although you can't animate the display property. If you want the div totally gone, after the opacity fades to zero, you can then add the display property to remove the div. If you don't wait for opacity to end, the div will just vanish without any transition.
/*
This jquery is added to really remove
the div. But it'll essentially be
VISUALLY gone at the end of the
animation. You can not use, or
delete the jquery, and you really
won't see any difference unless
you inspect the DOM after the animation.
This function is bound to animation
and will fire when animation ends.
No need to "guess" at timeout settings.
This REMOVES the div opposed to merely
setting it's style to display: none;
*/
$('.slide-box').bind('animationend webkitAnimationEnd oAnimationEnd MSAnimationEnd', function(e) { $(this).remove(); });
.slide-box {
display: block;
position: relative;
left: 0%;
opacity: 1;
width: 100px;
height: 100px;
background: #a00;
animation: slide 1s 1 linear forwards;
/*
animation-name: slide;
animation-duration: 1s;
animation-iteration-count: 1;
animation-timing-function: linear;
animation-fill-mode: forwards;
*/
}
#keyframes slide {
0% {
left: 0%;
opacity: 1;
}
99% {
left: 99%;
opacity: 1;
}
100% {
left: 100%;
opacity: 0;
display: none;
}
}
#-webkit-keyframes slide {
0% {
left: 0%;
opacity: 1;
}
99% {
left: 99%;
opacity: 1;
}
100% {
left: 100%;
opacity: 0;
display: none;
}
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
<div class="slide-box" id="slide-box"></div>
</div>
animation: slide 5s linear forwards;
at 100%
opacity: 0;
display: none;
Try this.
Working fiddle: https://jsfiddle.net/jbtfdjyy/1/
UPDATE: JS mani
var slideBox = document.getElementById('slide-box');
setTimeout(function(){
slideBox.style.display = 'none';
}, 5000);
Try this. https://jsfiddle.net/jbtfdjyy/2/
Add something at 99% or so to your keyframes, and set opacity to 1 in that. If you have opacity: 1 at the start, then it will stay that way until 99%. Only at 100% will it change.
It's not technically fired at 100%. If you want that, I'd recommend using some JavaScript here, but this will at least give the illusion you want.
#keyframes slide {
0% {
left: 0;
}
20% {
left: 20%;
}
40% {
left: 40%;
}
60% {
left: 60%;
}
80% {
left: 80%;
}
99% {
opacity: 1;
}
100% {
left: 100%;
overflow: hidden;
opacity: 0;
display: none;
visibility: hidden;
}
}
UPDATE:
As per your request, here is a JavaScript version. Keep in mind, there are endless ways to accomplish such a task. I am using vanilla JS (no jQuery, etc.), and using ES6 syntax.
What we do here is set a timeout, and at the end of that timeout I broadcast an event animation_end. That event listener will handle the end of the animation (in this case, it adds a class which will handle the fading out). This is much more granular than you need it to be, you could simply do the adding of the class within the setTimeout, but I think it is slightly better this way as you can abstract you can do other things with events such as animation start, etc.
Here is the fiddle: https://jsfiddle.net/vmyzyd6p/
HTML:
<div class="container">
<div class="slide-box" id="slide-box""></div>
</div>
CSS:
.slide-box {
position: relative;
width: 100px;
height: 100px;
background-color: blue;
animation: slide 3s linear 1;
-webkit-transition: opacity 2s ease-in-out;
-moz-transition: opacity 2s ease-in-out;
transition: opacity 2s ease-in-out;
}
.animationEnd {
opacity: 0;
}
#keyframes slide {
0% {
left: 0;
}
20% {
left: 20%;
}
40% {
left: 40%;
}
60% {
left: 60%;
}
80% {
left: 80%;
}
100% {
left: 100%;
}
}
JavaScript:
// Create a function that handles the `animation_end` event
const animationEnd = () => {
// Grab the slidebox element
let slideBox = document.getElementById('slide-box');
// Get the class of the slidebox element
let slideClass = slideBox.getAttribute('class');
// Add the animation end class appended to the previous class
slideBox.setAttribute('class', slideClass + ' animationEnd');
};
// Create the animation end event
let animationEndEvent = new Event('animation_end');
// Cross browser implementation of adding the event listener
if (document.addEventListener) {
document.addEventListener('animation_end', animationEnd, false);
} else {
document.attachEvent('animation_end', animationEnd);
}
// Set the timeout with the same duration as the animation.
setTimeout(() => {
// Broadcast the animation end event
document.dispatchEvent(animationEndEvent);
}, 3000);

Animate div slider with CSS

I am designing an HTML+CSS slider with automatic transition between slides and infinite duration. I have
this slider on different pages with different content (and number of divs), so I need
to write the same code for everything.
<div class="slide-container">
<div class="slide">div 1 goes here!</div>
<div class="slide">div 2 goes here!</div>
<div class="slide">div 3 goes here!</div>
</div>
I have started with this CSS code and tried with different animations, but I don't know how to do this
.slide-container {
-webkit-animation: transition 2s infinite linear;
-moz-animation: transition 2s infinite linear;
-o-animation: transition 2s infinite linear;
}
EDIT: This is the last transition I used to solve my issue:
#-webkit-keyframes animation {
20%,30% {-webkit-transform: translate(100%);}
70%,100% {-webkit-transform: translate(-100%);}
}
I want to get a div in screen for 5-10 seconds and a transition between divs of 2 seconds (in brackets div that must be on screen at these moment, width=100%, height=50px):
(-start-DIV1 5s)--2s-->(DIV2 5s)--2s-->...-->(DIVN 5s)--2s-->(DIV1 5s)-->...
The reason I do slider with CSS is because I'm trying to avoid JavaScript and JQuery functions.
Below where 12s is defined is the total slide time. This divided by the amount of slides (which in this demo is 3) gives us 4s a slide in this example. This is one method where you can toggle slide time. But like the other poster mentioned you'll still have to customize a bit. My method demonstrates a horizontal slide approach with a smooth transition and fast load time. In any case pure CSS3 is what your after.
JS Poodle.
CSS3 power:
body {
padding: 1em;
background: #999
}
.scrollable {
width: 333px;
margin: 0 auto;
padding: 0;
border:10px solid #fff;
background: #000;
position: relative;
overflow: hidden;
text-align: center;
}
img {
max-width: 333px;
margin: 0;
float:left;
}
.items {
width:999px;
-webkit-animation: hscroll 12s infinite;
-moz-animation: hscroll 12s infinite;
-ms-animation: hscroll 12s infinite;
}
#-webkit-keyframes hscroll {
0% { margin-left: 0; }
27.33% { margin-left: 0 }
33.33% { margin-left: -333px; }
60.66% { margin-left: -333px; }
66.66% { margin-left: -666px; }
94.99% { margin-left: -666px; }
100% { margin-left: 0 }
}
#-moz-keyframes hscroll {
0% { margin-left: 0; }
27.33% { margin-left: 0 }
33.33% { margin-left: -333px; }
60.66% { margin-left: -333px; }
66.66% { margin-left: -666px; }
94.99% { margin-left: -666px; }
100% { margin-left: 0 }
}
#-ms-keyframes hscroll {
0% { margin-left: 0; }
27.33% { margin-left: 0 }
33.33% { margin-left: -333px; }
60.66% { margin-left: -333px; }
66.66% { margin-left: -666px; }
94.99% { margin-left: -666px; }
100% { margin-left: 0 }
}
<div class="scrollable">
<div class="items">
<img src="http://placehold.it/333x500/E8117F/FFFFFF&text=Horizontal"/>
<img src="http://placehold.it/333x500/FFFFFF/E8117F&text=css3"/>
<img src="http://placehold.it/333x500/3D668F/FFFFFF&text=slide show"/>
</div>
</div>
Here is a quick demo that demonstrates some of the techniques you'll need to use. I've used the same HTML markup you provided. This is not a ready-to-go "copy and paste" solution -- you'll need to take some time to understand the code and apply the concept to your particular use-case.
The technique basically involved lining up all the slides side-by-side, then shift the entire row of them every few seconds. The edges will be cropped so that only one slide is shown at a time.
To start with, you'll need to define the size of your "viewing area", by applying a width and height to the .slide-container element. Then apply overflow: hidden to the container, so that slides which aren't in the "viewing area" aren't shown.
Each slide should fill the "viewing area", so apply a width and height of 100% to each .slide element. You'll also need make them display as inline-block elements, so that they are aligned side-by-side, but still fill their container.
Finally, the hard part: defining the animation. Keyframe animations are percentage-based. Basically, since there are three slides, we want to switch after 33% of the animation has elapsed, again after 66%, and return to the beginning after 100%. We want a smooth "slide", so we'll make the actual transition last 5% in total -- so the first one actually starts at 28% and ends at 33%. The keyframes code looks like this:
#keyframes slide {
/* modify percentages to match how many items you have */
0% { margin-left: 0; } /* initial position */
/* (stays in first position ) */
28.333% { margin-left: 0; } /* start sliding */
33.333% { margin-left: -100%; } /* done sliding */
/* (stays in second position ) */
61.667% { margin-left: -100%; } /* start sliding */
66.667% { margin-left: -200%; } /* done sliding */
/* (stays in third position ) */
95% { margin-left: -200%; } /* start sliding */
100% { margin-left: 0; } /* done sliding - back to initial position */
}
And it can be applied to the first slide like this (adjust transition time as desired):
.slide:first-of-type {
animation: slide 10s ease;
animation-iteration-count: infinite;
}
After you've done this, you'll just need to adjust to your preferences. Experiment with slide durations and transition types. Perhaps change how the animation repeats at the end. You can even use the animation-play-state property to pause the animation when you hover over the "viewing window". I've included a full demo below that includes the hover-to-pause feature. If you're not 100% clear about how it works, try removing the overflow: hidden property from the .slide-container element.
#keyframes slide {
0% { margin-left: 0; }
28.333% { margin-left: 0; }
33.333% { margin-left: -100%; }
61.667% { margin-left: -100%; }
66.667% { margin-left: -200%; }
95% { margin-left: -200%; }
100% { margin-left: 0; }
}
.slide-container {
overflow: hidden; /* try commenting this line out! */
width: 150px;
height: 100px;
border: 1px solid #000000;
}
.slide {
display: inline-block;
width: 100%;
height: 100%;
}
.slide:first-of-type {
animation: slide 10s ease;
animation-iteration-count: infinite;
}
.slide-container:hover .slide:first-of-type {
animation-play-state: paused;
}
<div class="slide-container">
<div class="slide" style="background: #ff0000">div 1 goes here!</div><div class="slide" style="background: #00ff00">div 2 goes here!</div><div class="slide" style="background: #0000ff">div 3 goes here!</div>
</div>
Here is the same demo on jsFiddle.