CSS: transition a transformation once, then reset it without transition - css

Basically I want to transition my element by adding a class .anim every 5 seconds but reset it ever 1 second w/o transitioning the property.
The effect I want is to spin the arrow around once every 5 seconds.
What's the best way to do this?
setInterval(function(){
var $el = $("a.inbox");
$el.addClass('anim');
setTimeout(function(){
$el.removeClass('anim');
}, 1000);
console.log($el);
}, 5000);
a.inbox:before {
content: '⇧';
display: inline-block;
position: relative;
-webkit-transform: rotate(180deg);
margin-left: 5px;
transition: -webkit-transform 1s;
}
a.inbox {
&.anim:before {
-webkit-transform: rotate(540deg);
}
}
Inbox

Only put the transition property inside the a.inbox.anim style. This will mean that the transition is only applied when changing to that class, but won't be applied when it is removed.

Related

CSS FadeIn and FadeOut trigerred by onclick with only css (100% pure) if not possible less resources as possible (no jquery, and no js to animation)

I was trying to make a 100% pure css animation, fadein and fadeout when i click on hamburguer menu to reveal the sidebar, (the backdrop should showing opacity like 500 miliseconds) (like jquery fadein) and when i click inside the sidebar to close the menu (the backdrop should hidde the opacity in 2 seconds) (like jquery fadeout)
You can see the version of jquery code here: https://cdpn.io/gilperon/fullpage/ZErBzvY
This is a very simple code, to open menu i put the event on hamburguer icon onclick=' $('#menu-backdrop').fadeIn(500);' and close to close, i put onclick=' $('#menu-backdrop').fadeout(2000);'
If it is not possible to make 100% css pure the animation, since it should be activated by onclick, maybe use just the javascript pure to onclick to add class, and the animation by done via css
I have a lot of ways using height:0 and key frames, but it was not possible to make the animation fadeout, fadein it works.
I make a code that workds to fadein, but to fadeout not working:
Another options are welcome, maybe using visibility, or other ways to show and hidden the animation, display:none usually not works with css animation
#menu-backdrop {
display: none;
animation:fadeOut 5s linear;
}
#menu-backdrop.exibir {
display: block;
animation:fadeIn 0.5s linear;
}
#keyframes fadeIn {
0% {
opacity:0
}
100% {
opacity:1;
}
}
#keyframes fadeOut {
0% {
opacity:1
}
100% {
opacity:0;
}
}
If anyone can post a work solution should be great, thank you very much guys.
Okay what you need is a transition, and you need to move away from your display property as it will break your animations and transitions since you cannot animate or transition that property in CSS.
A quick example:
const button = document.querySelector( 'button' );
const nav = document.querySelector( 'nav' );
button.addEventListener( 'click', event => {
event.preventDefault();
nav.classList.toggle( 'active' );
});
nav {
position: fixed;
right: 0;
top: 0;
width: 50%;
height: 100%;
background: red;
transition: opacity .4s;
/* This should be set to 0, but to make the point
* of pointer-events clear, I will set it to slightly
* higher so you can see there's no interaction
* with the nav. */
opacity: .1;
pointer-events: none;
}
nav:hover {
/* If you can interact with the navigation,
* you will see it change color. */
background: blue;
}
nav.active {
opacity: 1;
pointer-events: all;
}
nav + button:before {
content: 'Open ';
}
nav.active + button:before {
content: 'Close ';
}
<nav></nav>
<button>Nav</button>
The above shows you that by combining pointer-events: none with opacity you can effectively hide your menu. I added the :hover state for the <nav> to show that you cannot click the <nav> when it is open, and you should therefor consider this element invisible to the user.

How can I animate my less from "display: block" to "display: none"?

I have a less file that hide and display an element like the following:
.cmp-accordion__panel {
&--hidden {
display: none;
}
&--expanded {
display: block;
-webkit-animation: slide-down 0.5s ease-out;
-moz-animation: slide-down 0.5s ease-out;
}
}
#-webkit-keyframes slide-down {
0% {
opacity: 0;
-webkit-transform: translateY(-5%);
}
100% {
opacity: 1;
-webkit-transform: translateY(0);
}
}
#-moz-keyframes slide-down {
0% {
opacity: 0;
-moz-transform: translateY(-5%);
}
100% {
opacity: 1;
-moz-transform: translateY(0);
}
}
In my JavaScript, I toggle the class name of the element between "cmp-accordion__panel--hidden" and "cmp-accordion__panel--expanded" if the event is triggered. I use keyframe and opacity to animate the transition from "display:none" to "display:block".
However, when I go from "display:block" to "display:none" to hide the element, the effect happens INSTANTLY. What should I add to animate the hiding?
As already said, is not possible animate or transition from display:block; to display: none; but this could be simulated in another way and is not necessary to use CSS animations, simply CSS transitions (in addition, is not necessary anymore to use vendor-prefixes to declare transitions or animations).
Please, look at this working example:
HTML (I inserted a fake content to create an element with a relative big height)
<div class="cmp-accordion__panel--expanded">
b<br>b<br>b<br>b<br>b<br>b<br>b<br>b<br>b<br>b<br>b<br>b<br>b<br>b<br>b<br>b<br>b<br>b<br>b<br>b
</div>
LESS
[class*="cmp-accordion__panel"] {
border:solid 1px red;
overflow:hidden;
transition:opacity 0.3s ease-out, max-height 0.8s ease-out;
}
.cmp-accordion__panel {
&--hidden {
max-height:0;
opacity:0;
}
&--expanded {
opacity:1;
max-height:1000px;
}
}
Please note that, thanks to attribute partial value selector I added also some rules that apply to both *--hidden and *--expanded classes (I personally prefer a general class and an addition of a second one in some cases, instead of switching between two, but I did not want to change too much your approach).
The key rule is switching between two values of max-height property, from a 0 value to another "enough big" one. If you effectively know final height of the element you can simply use also height property, but in case of dynamic content, max-height did the trick.
Please note also the presence of overflow:hidden; applied to both classes, to simulate height changes.
Finally, animation effect relies only on a CSS transition applied to opacity and max-height properties, with different timings to enhance effect.
You cannot animate or transition from display: block; to display: none;, so you will need to remove this if you wish to animate it.
To ensure it fades and is removed you should animate the visibilty and opacity attributes.
Alternatively if you are using jQuery you can use the .fadeOut() function.
MDN - CSS Visibility
jQuery - fadeOut()

ui-view: Slide animation without position: absolute

I am trying to implement a slide in/out animation when transitioning between ui-views.
Here's a plunker. (Navigate from Home > About > Home)
When a new view appears, the old view jumps down below it. The intention is for the old view to seamlessly slide off left with no vertical movement, like a carousel.
I am aware of the position: absolute solution to this; but doing this rather messes up other elements of my layout; I'd like to keep the elements in the page flow. I have tried all manner of combinations of display, position etc.
.slide-left {
position: relative;
transition: all 1s ease-in-out;
margin: 1em;
}
.slide-left.ng-enter {
transform: translateX(110%);
opacity: 0;
}
.slide-left.ng-enter-active {
transform: translateX(0);
opacity: 1;
}
.slide-left.ng-leave {
transform: translateX(0);
opacity: 1;
}
.slide-left.ng-leave-active {
transform: translateX(-110%);
opacity: 0;
}
Are there any other solutions? How do carousels work? (Off to check their source code...)
Edit:
Having checked Bootstrap's source code, they use position: absolute when the slide animation is in progress (.next and .prev classes). I'm concluding that the use of absolute is unavoidable for this effect to work; at least it only has to apply during the effect.

Combine multiple animations

I'm trying to combine several parts of animation together by clicking a button. Here's an example:
.element {
background-color: black;
display: block;
width: 160px;
height: 160px;
border-radius: 80%;
}
.one {
animation: one 1.5s ease 1 forwards;
}
.two {
animation: two 1s forwards;
}
#keyframes one {
from {
transform: scale(0.25);
opacity: 0;
}
25% {
opacity: 0.5;
}
to {
transform: scale(1);
opacity: 0.5;
}
}
#keyframes two {
from {
opacity: 0.5;
}
to {
opacity: 0;
}
}
I'm trying to combine these two animation: one and two. My way of doing this was to use JS: classList.add('.two') when I clicked the button. But the problem was: at the moment I added the class, the element changed to its default opacity which was 1.
To solve this, I added a new class contained styles which were actually clones of final styles of the first animation. And after the second part was finished, I had to remove the class list to prepared for the first animation to be played.
So my question is, is there a better way of doing this?
Here is a CodePen Demo
I just realised a problem with this: If I start the second animation before the first one was finished, there would be a discontinuity (the circle would just turns to a larger one all of a sudden).
The demo can be found from the above link, thanks!
Can I combine these two animations?
I assume by combine you mean producing forward (on click of add animation) and reverse (on click of remove animation) animations using the same keyframe rules. It's possible to achieve but for that both the forward and reverse animations should be exactly the same (but in opposite directions). When it is same, we can use animation-direction: reverse to achieve reverse effect with same keyframes.
Here, the forward animation has a transform change whereas the reverse doesn't and hence adding animation-direction: reverse would not produce the same effect as the original snippet. Moreover, coding it is not as easy as just adding a property also, a lot of work is needed like mentioned here.
What is the reason for the other two issues?
The reason for both the issues (that is, the element getting opacity: 1 immediately when the remove button is clicked and element getting full size when remove button is clicked while forward animation is still happening) are the same. When you remove the animation on an element (by removing the class) it immediately snaps to the size specified outside of the animation.
For the first case, the size is the one that is mentioned under .element (as .one is removed) and its opacity is default 1 because there is no opacity setting in it. For the second case, when the .one is removed and .two is added, the animation is removed and so the element's size is as specified in .element and the opacity is as specified in .two (because that is later in CSS file).
So what else is the alternate?
When both forward and reverse effects are required and the animation doesn't have any intermediate states (that is, there is only a start state and an end state) then it is better to use transitions instead of animations. The reason is because transitions automatically produce the reverse effect on removal of the class (unlike animations where the reverse animation needs to be written as a separate keyframe and added to the element).
Below is a sample snippet showing how you can achieve a similar effect using just one class without the need for writing keyframes.
var theBut = document.getElementById('butt');
var theBut2 = document.getElementById('butt2');
theBut.addEventListener('click', function a() {
document.querySelector('.element').classList.add('one');
});
theBut2.addEventListener('click', function b() {
document.querySelector('.element').classList.remove('one');
});
.element {
background-color: #d91e57;
display: block;
width: 160px;
height: 160px;
border-radius: 90%;
transform: scale(0.25);
opacity: 0;
transition: opacity 2s, transform .1s 2s;
}
.one {
transform: scale(1);
opacity: 0.5;
transition: all 2s;
}
<div class="element">
</div>
<button id="butt">add animation</button>
<button id='butt2'>remove animation</button>

CSS Animation, State change finish animation

We are implementing a wishlist functionality on a site we are developing, and when the user clicks on an icon to add the current item to a wishlist, it fires an ajax request.
Now while that ajax request is doing it's business, we add a loading class to the icon, so it scales bigger and smaller slightly. My issue, is once the ajax request has finished loading, we then remove that class, but the animation abruptly stops rather than scaling back down to it's initial size.
How can we make the animation finish, rather than just suddenly stopping?
Below is my CSS:
/**
* Keyframes
*/
#keyframes breathe {
50% {
transform: scale(1.2);
}
100% {
transform: scale(1);
}
}
/**
* Icon
*/
.wishlist-icn {
transition: all .3s ease;
}
.wishlist-icn--isAdded {
fill: #4B3814;
}
.wishlist-icn--isLoading {
animation: breathe 2s ease-in-out 0s infinite normal both;
}
tl;dr: Try applying animation-fill-mode: forwards
The normal behavior after CSS animation is done is that it resets the styles to the initial state. The way I see the process here is that when you remove the --isLoading class the animation stops and reverts the styles to the original state. Only after then the transitions starts to work and has nothing to do since the styles already are reset. animation-fill-mode: forwards in .wishlist-icn would prevent the animation from resetting, thus the transition would be able to operate gradually. To be sure you can add transform: scale(1) to .wishlist-icn or to :not(.wishlist-icn--isLoading) so that the transition knew what to head for. Not that I have tested it in this particular case, but it's worth trying ;P
$('.start-animation').on('click', function() {
$('.wishlist-icn').addClass('wishlist-icn--isLoading');
});
$('.stop-animation').on('click', function() {
$(".wishlist-icn").bind("mozAnimationIteration animationiteration webkitAnimationIteration", function() {
$(this).removeClass("wishlist-icn--isLoading");
});
});
/**
* Keyframes
*/
#keyframes breathe {
50% {
transform: scale(1.2);
}
100% {
transform: scale(1);
}
}
/**
* Icon
*/
.wishlist-icn {
position: relative;
display: inline;
transition: all 2s ease;
font-size: 5em;
}
.wishlist-icn--isAdded {
fill: #4B3814;
}
.wishlist-icn--isLoading {
animation: breathe 2s ease-in-out 0s infinite normal both;
animation-fill-mode: forward;
}
.wishlist-icn--isLoaded {
transform: scale(1);
}
}
<link href="http://code.ionicframework.com/ionicons/2.0.1/css/ionicons.min.css" rel="stylesheet" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="wishlist-icn"> <i class="ion-heart"></i>
</div>
<button class="start-animation">start animation</button>
<button class="stop-animation">stop animation</button>
you would probably have to use javascript to listen for the animation iteration to end then remove the class.
$(".wishlist-icn").bind( "mozAnimationIteration animationiteration webkitAnimationIteration" , function() {
$(this).removeClass("wishlist-icn--isLoading");
});

Resources