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);
Related
I have created an animation for an element on my page and it always runs when the page is refreshed but i would like the animation to play when an element is clicked. How would i go about doing this?
CSS:
#login-or-signup-selection {
display: flex;
animation-name: test;
animation-duration: 5s;
position: relative;
height: 70%;
}
#keyframes test {
0% {top: 0px;}
50% {top:300px}
100% {top: 0;}
}
HTML:
<p id="clickMe">Element to click</p>
$('#clickMe').click(function () {
$(this).addClass('login-or-signup-selection');
$(this).on("animationend", function(event) {
$(this).removeClass('login-or-signup-selection')
});
});
.login-or-signup-selection {
display: flex;
animation-name: test;
animation-duration: 5s;
position: relative;
height: 70%;
}
#keyframes test {
0% {top: 0px;}
50% {top:300px}
100% {top: 0;}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<p id="clickMe">Element to click</p>
If you want only css and don't even care about js onclick events for now,
use the :active pseudo selector.
The only downside is that it only plays while (=during) e.g. the mouse button is down.
You would need some JavaScript for this.
First off, separate the CSS animation properties, and anything else related to your animation, and add them to their own class.
Next up, the JavaScript. You'll want to add an event listener to your element to add the animation class when clicked, and a timeout to remove the class afterwards so it will animate when clicked again.
const yourElement = document.getElementById('clickMe');
yourElement.addEventListener('click', _=> {
yourElement.classList.add('animation-class');
setTimeout(
_=> yourElement.classList.remove('animation-class'),
5000
)
});
#clickMe {
display: flex;
position: relative;
height: 70%;
}
.animation-class {
animation-name: test;
animation-duration: 5s;
}
#keyframes test {
0% { top: 0px; }
50% { top: 300px; }
100% { top: 0; }
}
<p id="clickMe">Element to click</p>
You need JavaScript for this.
If you add an event listener on the p element to listen for a click, this can then add the animation name to the selection div.
But you need to also listen for the end of the animation, otherwise subsequent clicks will have no effect. On animation end this snippet removes the animation name.
Note also that in order to be absolutely sure that the first (onload) animation end is trapped, the first animation name is not set until the event listeners have been set up.
function init() {
const clickMe = document.querySelector('#clickMe');
const selection = document.querySelector('#login-or-signup-selection');
clickMe.addEventListener('click', function() {
selection.style.animationName = 'test';
});
selection.addEventListener('animationend', function() {
selection.style.animationName = '';
});
selection.style.animationName = 'test';
}
window.onload = init;
#login-or-signup-selection {
display: flex;
animation-duration: 5s;
animation-iteration-count: 1;
position: relative;
height: 70%;
}
#keyframes test {
0% {
top: 0px;
}
50% {
top: 300px
}
100% {
top: 0;
}
}
<p id="clickMe">Element to click</p>
<div id="login-or-signup-selection">Login or signup selection</div>
I am wanting to animate an element so it cycles between "0% interest free credit" and "free delivery", I am trying to achieve this with no javascript, but I am only able to get the first element to fade away and not get the second to fade in.
.parent {
position: relative;
}
.parent p {
position: absolute;
top: 0;
left: 0;
}
.parent p:first-child {
animation: hide 2s ease-in
}
.parent p:last-child {
opacity: 0;
animation: show 2s ease-in animation-delay:2s;
}
#keyframes show {
to {
opacity: 1;
}
}
#keyframes hide {
to {
opacity: 0;
}
}
<div class="parent">
<p>0% interest free credit</p>
<p>free delivery</p>
</div>
What am I doing wrong I would like 1 fade out as the other fades in, and for it to loop endlessly.
First, you need to make sure your animation is set to loop. Use the keyword infinite as your animation-timing-function for that.
Second, we can restructure your animation to happen in one reusable keyframe sequence that shows and hides the element. By making the whole animation 4 seconds long and offsetting it by half of that (2 seconds) on one element, we achieve a seamless loop of the two elements fading in and out:
.parent {
position: relative;
}
.parent p {
animation: show 4s infinite;
position: absolute;
top: 0;
left: 0;
}
.parent p:last-child {
animation-delay: -2s;
}
#keyframes show {
0%, 50%, 100% {
opacity: 0;
}
10%, 40% {
opacity: 1;
}
}
<div class="parent">
<p>0% interest free credit</p>
<p>free delivery</p>
</div>
I have an angular component that has a button and the button triggers a sidePanel and the side panels slidesOut over the component that has the button triggering the side panel to come out. I have 2 issues I can solve. The side panel has a width of 350px;
1) When the component with the button is loaded you can see the sidePanel doing the animation to hide
2) The slideIn works fine but the slideOut moves really fast
HTML
<div class="credit-card-container {{toggleSideBarFlag ? 'showSideBar': 'hideSideBar'}} {{ submittingPayment ? 'payment-success-container' : ''}}">
<app-bulk-pay-credit-card [ccTotalDue]="totalDue" [pickupAvailabilityList]='selectedEquipment' (submittingPayment)="isSubmittingPayment(true)"
(toggleSideBar)="onToggleSideBar(false)" (close)="onCloseBulkPay(false)"></app-bulk-pay-credit-card>
</div>
CSS
.bulk-pay-storage-container {
.showSideBar {
width: 100%;
display: block;
position: absolute;
z-index: 9999;
animation: slideIn 1s;
}
.hideSideBar {
width: 100%;
display: block;
position: absolute;
right: -350px;
z-index: 9999;
animation: slideOut 1s forwards;
}
}
#keyframes slideIn {
0% {
transform: translateX(350px);
}
100% {
transform: translate(0);
}
}
#keyframes slideOut {
100% {
transform: translateX(350px);
}
}
I would use transitions rather than animations in your example.
You can basically toggle between having showSideBar class and not having it.
Sidebar's start position is hidden outside of the viewport (left: -350px) and its visible state is left: 0.
Set left and transition properties on your sidebar and remove the animation property.
.bulk-pay-storage-container {
/ ... /
left: -350px;
transition: left 2s;
}
.bulk-pay-storage-container.showSideBar {
left: 0
}
I'm doing an animation that gets triggered with adding a class to a element. Now on removal of the class I want the animation to go the other way, I figured out to how to reverse the animation, the problem is onload that it triggers it. What can I do to prevent it, what can I change, what am I missing?
the full html/css/js are in the fiddle
here are the good parts,
#keyframes expand {
20% {
opacity: 0;
width: 5rem;
}
70%, 100% {
opacity: 1;
transform: translate(0, 0);
width: 100%;
}
}
#keyframes contract {
0% {
transform: translate(0, 0);
width: 100%;
}
100% {
transform: translate(0, -6rem);
width: 5rem;
}
}
[data-am-button~="buy"] {
margin-bottom: .5rem;
transform: translate(0, -6rem);
width: 5rem;
animation: contract 500ms forwards;
span {
display: none;
}
.is-expanded & {
animation: expand 500ms forwards;
}
}
So instead of putting the animation on the button by default. Add the animation to a .is-contracted class.
Then toggle between these 2 classes when clicking the button. This means that nothing is animated on the page load. Only the button clicking.
CSS changes:
[data-am-button~="buy"] {
margin-bottom: .5rem;
transform: translate(0, -6rem);
width: 5rem;
//animation: contract 500ms forwards; <-- Removed this
span {
display: none;
}
.is-expanded & {
animation: expand 500ms forwards;
}
.is-contracted & {
animation: contract 500ms forwards;// <-- added it to this new class
}
JS changes:
$('.js-expander').on('click', function() {
var $this = $(this);
var $parent = $this.parents('.product-info');
if ( $parent.hasClass('is-expanded') ){
$parent.removeClass('is-expanded')
$parent.addClass('is-contracted')
} else {
$parent.addClass('is-expanded')
$parent.removeClass('is-contracted')
}
});
Here's a fiddle : https://jsfiddle.net/BradChelly/Lugnmmpe/7/
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.