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>
Related
I am new to animations in CSS and this is my code
#keyframes fadeOut{
0% {opacity: 1;}
100% {opacity: 0;}
}
I want the above code to take effect on #menu only no matter where it is called, For EG: It is called on a button click but only affects the #menu element. Somewhat like and doesn't do anything to the button
button:focus{animation-name: fadeOut;
animation-duration: 4s;}
#keyframes fadeOut{
#menu{0% {opacity: 1;}}
#menu{100% {opacity: 0;}}
}
But the above code is illegal in CSS and hence, I can't use it.
Is there any alternate way to do this.
Thanks in advance.
You can do that by using JavaScript:
Example 1
In this example, we add an event for each element, each event calls the animation function that styles the #menu element.
let menu = document.getElementById('menu');
let btn = document.querySelector('.btn');
let p = document.querySelector('.p');
let box = document.querySelector('.box');
function animateIt(){
menu.style.animation = 'fade 1s';
setTimeout(function(){
menu.style.animation = 'unset';
}, 1000);
}
btn.addEventListener('click', (e) => {
animateIt();
});
p.addEventListener('click', (e) => {
animateIt();
});
box.addEventListener('click', (e) => {
animateIt();
});
#menu {
width: 200px;
height: 200px;
background-color: red;
margin-bottom: 20px;
opacity: 0;
}
.box {
background-color: blue;
color: #fafafa;
width: 200px;
}
#keyframes fade{
from {
opacity: 0;
}
to {
opacity: 1;
}
}
<div id="menu"></div>
<button class="btn">Click</button>
<p class="p">Or Click Here</p>
<div class="box">Or Click Even Here</div>
Example 2
In this example, we simply add the elements that will have events that animates the #menu in an array of objects with the class name and the event listener for each one. Each element and it's event will basically call the animateIt() function that styles and animates the #menu.
All you have to do is to add a line for each element that will call the animation, including ONLY the class name, and the event that calls it.
// Get the #menu
let menu = document.getElementById('menu');
// Gather the elements in an array of objects including the class name and the event
let elements = [
{class: ".btn", evt: "click"},
{class: ".p", evt: "click"},
{class: ".box", evt: "mouseover"}
];
for(let i = 0; i < elements.length; i++){
// Get the element
let theTarget = document.querySelector(elements[i].class);
// Get the event
let targetEvt = elements[i].evt;
// Add event for each element to call the animation function
theTarget.addEventListener(targetEvt, (e) => {
animateIt();
});
}
// The animation function that styles (animate) the #menu
function animateIt(){
menu.style.animation = 'fade 1s';
setTimeout(function(){
menu.style.animation = 'unset';
}, 1000);
}
#menu {
width: 200px;
height: 200px;
background-color: red;
margin-bottom: 20px;
opacity: 0;
}
.box {
background-color: blue;
color: #fafafa;
width: 200px;
}
#keyframes fade{
from {
opacity: 0;
}
to {
opacity: 1;
}
}
<div id="menu"></div>
<button class="btn">Click Here</button>
<p class="p">Or Click Here</p>
<div class="box">Or Hover Here</div>
As i understood , you have to add the animation to your element Like :
/* The animation code */
#keyframes example {
from {background-color: red;}
to {background-color: yellow;}
}
/* The element to apply the animation to */
div {
width: 100px;
height: 100px;
background-color: red;
animation-name: example;
animation-duration: 4s;
}
In your case it will be :
#menu {
animation-name: fadeOut;
animation-duration: 4s;
}
You can change 4s to the duration you want.
I have two divs that appear like this:
The idea is that when you close the bottom div (click on the 'X'), it should disappear.
And when you close the top div, it should disappear, and also the bottom div should slide up and take its place.
I'm very new to jQuery, but this is my first attempt:
function initAnnouncements() {
$(document)
// Closes announcement modules
.on('click', 'annoucements-close', function () {
$('announcement-div').hide();
})
}
#keyframes slideInFromRight {
0% {
transform: translateX(100%);
}
.1%{
opacity: 1;
}
100% {
transform: translateX(0);
opacity: 1;
}
}
.announcements-container {
position: fixed;
top: 80px;
right: 20px;
z-index: 1001;
display: flex;
flex-direction: column;
width: 300px;
/* align-items: flex-end; */
}
.announcements-1 {
animation: slideInFromRight 0.4s ease;
opacity: 0;
animation-fill-mode: forwards;
}
.announcements-2 {
/* animation: 0.4s ease-out 0s 1 slideInFromRight; */
animation: slideInFromRight 0.4s ease;
opacity: 0;
animation-fill-mode: forwards;
animation-delay: .4s;
margin-top: 15px;
}
.annoucements-header {
background-color: #1481C3;
color: #ffffff;
font-family: "Proxima Nova Bold";
padding: 7px 10px;
}
.annoucements-close {
position: absolute;
right: 5px;
width: 24px;
height: 36px;
cursor: pointer;
opacity: .85;
}
.annoucements-close:hover {
opacity: 1;
}
.annoucements-close::before,
.annoucements-close::after {
content: '';
width: 24px;
height: 2px;
background: white;
position: absolute;
top: 7px;
left: 0;
}
.annoucements-close::before {
transform: rotate(-45deg);
}
.annoucements-close::after {
transform: rotate(45deg);
}
/*opened or closed*/
.announcement-div-opened {
display: none;
}
.announcement-div.opened .announcement-div-opened {
display: block;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<body>
<div class="announcements-container">
<div class="announcement-div announcements-1">
<div class="annoucements-header">
<span class="annoucement-type-quantity">2 School Announcements</span>
<i class="annoucements-close"></i>
</div>
</div>
<div class="announcement-div announcements-2">
<div class="annoucements-header">
<span class="annoucement-type-quantity">1 Admin Announcement</span>
<i class="annoucements-close"></i>
</div>
</div>
</div>
</body>
As you can see this isn't doing anything. I'm trying to toggle the class from 'open' (display:block) to 'closed' (display:none) when the annoucements-close <i> element is clicked on.
And ideally I would like for the second div to slide up when the top one is closed, but first I'd just like to get either one to disappear.
What's wrong with my code where that's not working as expected?
Link to JSFiddle
There are 2 issues with your code: the click() event is inside the function initAnnouncements that doesn't get called. You could move it outside of this function or call the function. Then you have issues with your selectors: It's
.on('click', '.annoucements-close', function () {
$('.announcement-div').hide();
})
instead of
.on('click', 'annoucements-close', function () {
$('announcement-div').hide();
})
for class selectors. Working Fiddle.
If you just want to hide the annoucement which was clicked upon, just change it to
.on('click', '.annoucements-close', function () {
$(this).closest('.announcement-div').hide();
})
I looked at your code and adjusted it a little to demonstrate:
Added your common class on the two announcements "announcement-div"
Attached the document click handler with the jQuery ready event
Used the delegated event selector to listen to clicks within the document that match that common selector
On click of one of the announcement-div's animate the height to 0 and then remove the element
Comments are included in the fiddle. Hope this is helpful!
// Fire this function when the document is ready
$(function() {
// Listen on the whole document for click events on the .announcement-div element
$(document).on('click', '.annoucements-close', function () {
// From the close button find the closest parent "announcement-div"
var annoucement = $(this).closest('.announcement-div');
// Function to run after animating the element (use .hide() to keep element but display:none)
function destroy() {
annoucement.remove();
}
// Animate the annoucement's height to 0 over 400ms and then call the destroy function
annoucement.animate({ height: "0px" }, 400, destroy);
});
});
Updated JS Fiddle
I am currently trying to replicate a website for practice, but have came to a halt due to a search box that I don't know how to create.
Now, I know how to create a normal search box, with the form and input method, however this specific search box has a slight animation.
I'll explain.
Search Box
Ok, so the search box only appears once you click the magnifying glass. Once you do this, the search box will sort of slide out from the left hand side of the magnifying glass.
How do I go about hiding the search box and only making it visible after being clicked on? And how do I make it "slide out" ?
My solution:
Use the following JavaScript code for appearing:
var button = document.getElementById("search");
var input = document.getElementById("search_input");
document.body.removeChild(input);
var permission = true;
button.addEventListener("click", appear);
function appear() {
if (permission == true) {
if(document.getElementById("search_input") == null || window.getComputedStyle(document.getElementById("search_input")).getPropertyValue("opacity") == 0) {
input.setAttribute("class", "static");
document.body.appendChild(input);
} else {
sliding();
}
}
}
function sliding() {
permission = false;
input.setAttribute("class", "sliding");
document.body.removeChild(input);
document.body.appendChild(input);
window.setTimeout(remove, 2900);
}
function remove() {
document.body.removeChild(input);
permission = true;
}
You only have to add "search" as id in the button tag or in the img tag and "search_input" as id in the input tag. And for sliding out you could use this CSS animation:
#keyframes slide {
from { left: 10%; opacity: 1;}
to { left: 90%; opacity: 0;}
}
#-webkit-keyframes slide {
from { left: 10%; opacity: 1;}
to { left: 90%; opacity: 0;}
}
#search_input {
position: absolute;
left: 10%;
}
.sliding {
animation-name: slide;
animation-duration: 3s;
-webkit-animation-name: slide;
-webkit-animation-duration: 3s;
}
Here's a simply jQuery solution.
$(document).ready(function() {
$('#trigger').click(function() {
$('#search-bar').toggleClass('search-bar-expanded');
});
});
#search-bar {
width: 0;
overflow: hidden;
display: inline-block;
transition:width 1s;
}
.search-bar-expanded {
width: 200px!important;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet"/>
<div id="search">
<button><i class="fa fa-search" id="trigger"></i></button>
<div id="search-bar">
<input type="text"/>
</div>
</div>
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);
Can I use properties such as position:absolute and display:none in CSS keyframe animation? I don't care if they are transitioned smoothly, I just want them to be applied as 25% of the animation such as this :
#-webkit-keyframes expanding {
25% {
width: 50%;
height: 50%;
position: absolute;
}
100% {
width: 100%;
height: 100%;
position: absolute;
}
}
or
#-webkit-keyframes hiding {
0% {
opacity: 1;
}
25% {
opacity: 0;
display: none;
}
}
It appears to ignore position and display in the keyframes and doesn't apply them when I want them applied.
You can get a animationEnd callback when one of the animatable properties finishes its cycle, then use that to set the non-animatable properties:
var anim = document.getElementById("anim");
anim.addEventListener("animationend", function () {
anim.style.display = "none";
}, false);
Unfortunately, there's no keyframe event, so you might need to set up another animation with slightly different timing, synchronised to the 25% moment. For example, it could finish when the main animation gets to 25% or whatever. You could also set up a timeout.