Use cases for CSS transitions and CSS animations - css

As far as I understand, there is no such thing we can implement using css transitions, but we can not to implement using css animations, but not vice versa.
That is, any transition has a css animation equivalent.
For example, this one
.ablock:hover {
position: relative;
-moz-transition-property: background-color, color;
-moz-transition-duration: 1s;
-webkit-transition-property: background-color, color;
-webkit-transition-duration: 1s;
color: red;
background-color:pink;
}
is an equivalent of following:
.ablock:hover {
-moz-animation-duration:1s;
-moz-animation-name:transition;
-webkit-animation-duration:1s;
-webkit-animation-name:transition;
}
#-moz-keyframes transition {
to {
color: red;
background-color: pink;
}
}
#-webkit-keyframes transition {
to {
color: red;
background-color: pink;
}
}
My question is - if we a talking about browser supporting both css transitions and animations, what are use cases for choosing one or another approach?
As for transitions, I can name only one - they have more succinct syntax, we don't have to copy paste huge chucks of code for #-moz-keyframes, #-webkit-keyframes and so on.
As for control from javascript, flexibility and complexity animations are much more appropriate tool (at least, at first glance). So, what are use cases?
UPD:
OK, let me try to list interesting info found in questions.
This one is contributed by Roman Komarov. Say, we have a div and child div. While parent div is hovered, we are transitioning the child element. Once we are taking away the mouse, transition is cancelled. Duration of this cancellation is exactly the time we've already spend for transitioning. Animation is cancelled "immediately". I don't know, nevertheless, how standard are those two behaviours.

Animations can be looped (and there can be keyframes, yeeah).
Transitions can be more flexible and you can easily make transitions to different values and in different circumstances.
While you can emulate some transitions by animations (like you mentioned in your post), the transitions are just more powerful:
You just tell which properties you must animate and in which conditions (using the different selectors)
You can trigger the transition in different ways:
Changing properties in CSS for pseudo-classed :hover, :active etc. (Creating pure CSS UI)
Changing properties in different classes for different purposes.
Changing properties in inline styles: in conjunction with JS it's just more powerful than animations.

With transitions you are able to transition between any value of the defined property, which you want to be transitioned. As an example, you want to transition the color of a link, when it's hovered and active:
a {
color: #000;
transition: color .4s ease;
}
a:hover {
color: #888;
}
a:active {
color: #faa;
}
You are independent, which color you choose.
Now if you want to use the animation style, you have to explicitly set the color value for the animation states. And you are not able to easily animate between the three states: normal, hover and active. You need more complex definitions. I'll try this one with animations:
a {
color: #000;
animation-duration: 0.4s;
animation-fill-mode: forwards;
animation-name: toDefault;
}
a:hover {
animation-duration: 0.4s;
animation-fill-mode: forwards;
animation-name: toHover;
}
a:active {
animation-duration: 0.4s;
animation-fill-mode: forwards;
animation-name: toActive;
}
#keyframes toDefault {
to {
color: #000;
}
}
#keyframes toHover {
to {
color: #888;
}
}
#keyframes toActive {
to {
color: #faa;
}
}
Now this does not include the animation back to the state before. I'm not sure if you can even fetch that.
So in short: with transitions you are able to animate an undefined set of properties and values, whilst keyframe animations are used for well defined animations and/or transitions.

Related

CSS: define animations inline without a separate `keyframes` class

Generally you would define a onHover animation of a square class like this:
.square:hover {
animation-duration: 0.5s;
animation-name: square_hover;
}
#keyframes square_hover {
to {background-color: yellow;}
}
Is there a way to define it like this:
.square:hover {
animation-duration: 0.5s;
animation: {
to { background-color: yellow; }
};
}
#keyframes square_hover
?
According to MDN the correct way of declaring an animation is using this syntax:
#keyframes <keyframes-name> {
<keyframe-block-list>
}
And then call it back using animation properties:
animation-duration: time;
animation-name: animation;
Where you will is a string that will identify the animation name. And is the sequence you will follow to create the animation.
So in short, CSS has a strict syntax you have to follow. But it seems like you're trying to find a simpler way to declare/create animation on hover.
You can simply get rid of the animation and directly add the properties you want to change on hover. For instance, if you want to change the background colour of the square class you will simply start with the initial state/base styles:
.square {
background-color: black;
}
And then apply the styles you want to change:
.square:hover {
background-color: yellow;
}
And if you want smooth out the transition simply add the transition property to the base styles. And the syntax looks something like
transition: property-to-transition time ease;
A working example:
.square {
background-color: black;
transition: background-color .5s ease;
}
References:
MDN Docs #keyframes: #keyframes
MDN Docs transitions: transitions
MDN Docs animations: animations

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()

Is there a way to granulary control the animation properties on a CSS element?

I have this code:
transition: all 0.35s;
transition-delay: 0.25s;
transition-timing-function: cubic-bezier(.79,0,.46,1);
But it turned out to be problematic if I add more properties that I wanna animate, so I'm looking to do something like:
transition: transform 0.35s/*duration*/ 0.25s /*delay*/ cubic-bezier(.79,0,.46,1),
opacity 0.25s/*duration*/ 1s /*delay*/ ease-in ;
I looked at the short-hand properties but can't quite find the right combo.
Yes, what you want is a css animation not a css transition. Transitions are for creating a smooth transition from one state to another while animations allow you to define more complex behavior by changing css properties.
It would look something like this:
element {
animation-name: yourAnimationName;
animation-timing-function: cubic-bezier(.79,0,.46,1);
animation-delay: 0.25s;
}
#keyframes yourAnimationName {
// here you define which css properties to animate
}
You can either define the keyframes using from and to:
#keyframes yourAnimationName {
from { background-color: red; }
to { background-color: yellow; }
}
or you can define multiple keyframes using percentages (at what percentage of the entire animation):
#keyframes example {
0% {background-color: red;}
25% {background-color: yellow;}
50% {background-color: blue;}
100% {background-color: green;}
}
You also probably wont need your cubic-bezier timing function if you use keyframes as percentages.
I recommend reading a bit about css animations HERE.

What is the difference between applying CSS transition property in hover rather than in its normal state?

I'm learning CSS3. Now, what I've seen in w3schools website is that:
CSS
#ID {
transition: transform 3s;
}
#ID:hover {
transform: rotateX(20deg);
}
And what I did is this:
CSS:
#ID:hover {
transform: rotateX(20deg);
transition: transform 3s;
}
Both are working. So, the question is: Can I put both transition and any transformation property in same selector? Or is it not the right way?
SHORT ANSWER:
If you define your transition property in element:hover, it will only get applied in that state.
EXPLANATION:
Whichever CSS properties you define in element:hover will only be applied when the element is in the hover state, whereas whichever CSS properties you define in your element will be applied in both states.
Transition property declared in normal state:
See how the transition always runs when the element's state is changed. When you stop hovering the element it will still make the transition back to its normal state.
CODE SNIPPET:
#ID {
width: 100px;
height: 100px;
margin: 0 auto;
background-color: royalblue;
transition: transform 1s;
}
#ID:hover {
transform: rotateX(60deg);
}
<div id="ID"></div>
Transition property declared in hovered state:
See how the transition breaks when you stop hovering the element and it jumps to its normal state immediately.
CODE SNIPPET:
#ID {
width: 100px;
height: 100px;
margin: 0 auto;
background-color: royalblue;
}
#ID:hover {
transition: transform 1s;
transform: rotateX(60deg);
}
<div id="ID"></div>
The first example is generally correct, as the transition timing is stated on the unaffected state. But that's based on the majority of examples I've seen of how to generate transitions on hover actions.
1st case :
All your transition in the #ID will have a transition of 3s.
When you hover your #ID, your transformation is rotateX(20deg).
2nd case :
When you hover your #ID, you have a transition of 3s.
Overall :
All the transitions from the first css will have a duration of 3s. Then you can apply transitions on your #ID from different places. Whereas in your second case you separate them and if you want to have another transitions triggerd by something else than hover, you will have to specify the duration again.
Both are correct
When a transition is specified for the :hover state, the transition won’t work on mouse out.

CSS3 transition only when class is added, not when removed

I have the following CSS example:
.message{
background-color: red;
transition: background-color 5s;
-webkit-transition: background-color 5s; /* Safari */
transition-delay: 2s;
-webkit-transition-delay: 2s; /* Safari */
}
.unreadMessage{
background-color: blue;
}
Then, i have a DIV with .message class, and by pressing a Button, i add the class .unreadMessage, and by pressing another Button, i remove it.
With this example, every time i change background-color, by adding or removing .unreadMessage, it does the CSS transition.
What i want to do, is, if possible, to have an instant color change when i add .unreadMessage, and have the transition only when removing it.
The first thing that come in my mind, was to have a different class containing the CSS transition properties, and add it after adding .unreadMessage.
But it is possible to do it with only one class, or using a Javascript workaround?
If you want to only apply a transition when the .message element does not have the unreadMessage class, then put the transition properties in the .message:not(.unreadMessage) selector:
.message{
background-color: red;
}
.message:not(.unreadMessage) {
-webkit-transition: background-color 5s; /* Safari */
transition: background-color 5s;
-webkit-transition-delay: 2s; /* Safari */
transition-delay: 2s;
}
.unreadMessage{
background-color: blue;
}
Demo: http://jsfiddle.net/Hs8fa/
Documentation for :not()
There are two things to remember when using CSS transitions:
Transitions happen when an element's state is modified "using pseudo-classes like :hover or :active or dynamically set using JavaScript."
You have to have a starting point and an ending point or they won't work.
The biggest issue with OP's question isn't their CSS, it's their naming structure. A major pattern of CSS transitions is to modify an element's class (or in the MDN's language "dynamically set using Javascript"). In OP's example they're not modifying an element's class structure, they're changing classes. CSS transitions won't work when an element changes from one class to another, but they will work when a class is added or taken away.
The easiest example of this is going from .element to .element.active. If we put the transition on the base class, .element, and then add a modifying class, .active, the transitions applied to .element will transition from .element settings to .element.active. settings.
Here's a JSFiddle example of modifying a base class
Secondly, and this is one I forget all the time, the base class must have a starting style. I can't transition left in the modified state if I don't have left set in the base state.
This code snippet contains a div with transition: none;
On click, override transition property by adding a new class add-transition
On the second click, the same class is removed & no transition.
var elm = document.querySelector('.no-transition');
elm.onclick = () => (
elm.classList.toggle('add-transition')
);
.no-transition {
background-color: aliceblue;
transition: none;
}
.add-transition {
background-color: deepskyblue;
transition: background-color 3s;
}
/* Note: As like other any other CSS property
Specificity or CSS Order can make the difference.
Styles below are for code the snippet to look better. */
.wrapper {
padding: 20px;
margin: 20px;
text-align: center;
cursor: pointer;
border: 1px solid lightgray;
}
<div class="wrapper no-transition">
Run code snippet & click here !!!<hr/>
on load, No transition. <br/>
on click, transition added(bg color). <br/>
on second click, no transtion.
</div>
https://developer.mozilla.org/en-US/docs/Web/CSS/Specificity

Resources