I have two transform operations (rotate and translate) and I want to make transition for translate only (rotate have to be instant).
Some suggestions? I prefer pure css.
Use keyframes to reach your desired effect, in addition to animation-fill-mode to keep the computed styles when the animation is finished.
.object {
width: 50px;
height: 50px;
background-color: #F00;
animation-fill-mode: forwards;
}
.object:hover {
animation: move 1s;
animation-fill-mode: forwards;
}
#keyframes move {
0% {
transform: translateY(0px) rotate(0deg);
}
1% {
transform: rotate(45deg);
}
100% {
transform: translateY(25px) rotate(45deg);
}
}
<div class="object"></div>
Related
For this example, I'll use a simple box that, as an animation, pops into view using opacity and transform: translate().
I can do this in two ways:
Set the box's initial CSS to opacity: 0 and transform: translate(10px), then write a keyframes that just sets the to property. Then, persist the end state of the animation using animation-fill-mode: forwards (specified in the shorthand).
.animation {
width: 100px;
height: 100px;
background: green;
animation: slide-in .5s ease-in-out forwards;
opacity: 0;
transform: translateY(10px);
}
#keyframes slide-in {
to {
opacity: 1;
transform: translateY(0);
}
}
<div class="animation"></div>
The second way to do this is to specify the initial state in the keyframes instead, and not on the element itself. I specify a from and a to state, and leave everything to the animation.
.animation {
width: 100px;
height: 100px;
background: green;
animation: slide-in .5s ease-in-out;
}
#keyframes slide-in {
from {
opacity: 0;
transform: translateY(10px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
<div class="animation"></div>
Both ways seem to work well and so my question is:
Is one of these options better than the other?
I don't see any advantages/disadvantages that aren't based on opinion, so I'm looking for factual advantages (performance?, accessibility?)
If a user has disabled transitions and/or animations, using the first approach the element would be not visible at all because you defined opacity: 0 as a property of the element and not inside the keyframes.
So, the second approach at least ensures that the element is always visible, even when the animation can't run because of user's settings.
Note that this is not strictly related to the animation-fill-mode property, since you could still use it by slightly changing the CSS of the first snippet:
.animation {
width: 100px;
height: 100px;
background: green;
animation: slide-in .5s ease-in-out forwards;
}
#keyframes slide-in {
from {
opacity: 0;
transform: translateY(10px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
<div class="animation"></div>
I'm trying to make a css rotation animation that has different speeds at different degree points.
Here is the animation I'm trying to make:
Here is a Pen of what I currently have and below is the code:
img {
width: 125px;
}
body {
text-align: center;
}
#loading {
-webkit-animation: slow 1.5s linear 1.5s, fast 1s linear 1s, slow2 1s linear 1s;
-webkit-animation-iteration-count: infinite;
}
#-webkit-keyframes slow {
from {
-webkit-transform: rotate(0deg)
}
to {
-webkit-transform: rotate(90deg)
}
}
#-webkit-keyframes fast {
from {
-webkit-transform: rotate(91deg)
}
to {
-webkit-transform: rotate(270deg)
}
}
#-webkit-keyframes slow2 {
from {
-webkit-transform: rotate(271deg)
}
to {
-webkit-transform: rotate(359deg)
}
}
<img id="loading" src="https://i.imgur.com/VpLRlbZ.png">
So, in the example you provided, the effect is only done by modifying the animation-timing-function css property.
Then you'll have only one animation
div {
width:100px;
height:100px;
background:red;
animation:rotate 3s infinite;
animation-timing-function: cubic-bezier(1,0,.5,1);
}
#-webkit-keyframes rotate {
from { -webkit-transform: rotate(0deg) }
to { -webkit-transform: rotate(360deg) }
}
<div></div>
You can find more informations here : https://callmenick.com/dev/level-up-animations-cubic-bezier/
But the point is, use only one animation and modify speed at different angles value modifying this animation-timing-function.
EDIT Added a closer cubic bezier timing function thanks to #SirExotic comment.
You can just divide the animation keyframes into several ones, and adjust the percentages of each to set the relative speeds:
The natural percentage for 90deg would be 25% . Any value higher than that will make this part slower
img {
width: 125px;
}
body {
text-align: center;
}
#loading {
animation: rotate 4s linear infinite;
}
#keyframes rotate {
0% {
transform: rotate(0deg)
}
40% {
transform: rotate(90deg)
}
60% {
transform: rotate(270deg)
}
100% {
transform: rotate(360deg)
}
}
<img id="loading" src="https://i.imgur.com/VpLRlbZ.png">
Is there a way to pulsate opacity from 0 to 1 (repeat) slowly with a CSS3 keyframes transformation, infinitely? Or does this require jQuery or Javascript with a transition opacity inside a class that is toggled on an interval?
I'm trying to work it into my orbit transformations (below). (I'm working on a live wallpaper background effect with multiple opaque images floating in a sidebar image on an installer application I'm building in Objective C.)
.orbit1
{
animation: myOrbit 200s linear infinite;
}
.orbit2
{
animation: myOrbit2 200s linear infinite;
}
#keyframes myOrbit1
{
from { transform: rotate(0deg) translateX(150px) rotate(0deg) }
to { transform: rotate(360deg) translateX(150px) rotate(-360deg) }
}
#keyframes myOrbit2
{
from { transform: rotate(360deg) translateX(250px) rotate(-360deg) }
to { transform: rotate(0deg) translateX(250px) rotate(0deg) }
}
You can do it by adding multiple animations to the element, for example:
.orbit1
{
/* added for example reasons */
position :absolute;
top: 50%;
left: 50%;
margin-top: -100px;
margin-left: -100px;
width: 200px;
height: 200px;
background: red;
/* ---------- */
animation: myOrbit1 20s linear infinite, Pulsate 4s linear infinite;
}
#keyframes myOrbit1
{
from { transform: rotate(0deg) translateX(150px) rotate(0deg) }
to { transform: rotate(360deg) translateX(150px) rotate(-360deg) }
}
#keyframes Pulsate {
from { opacity: 1; }
50% { opacity: 0; }
to { opacity: 1; }
}
<div class="orbit1"></div>
I'ved modified some of your parameters (like the speed of the animation and the opacity minimum) and added some spoof styling for the element for the purpose of the example.
Edit
I had originally thought that the multiple rotate() declarations were in error, but #vals informed me why it was there (to create a counter rotation on the object). I've updated the answer, and learned something new.
I'm coding a CSS3 effect fired on mouseover; this effect simply animate an inner div scaling it endlessly.
All works great, but when I move the mouse away the div suddenly return to its original size. I would like to add a smooth effect to scale the div back.
I already checked the suggestion of this post:
Make CSS Hover state remain after "unhovering"
Unfortunately the code posted doesn't work :(
In my opinion my issue could be related with the "infinite" loop of the scale effect.
THe goal I would like to gain is the on mouse-out the image could return to its original size smoothly.
Here's the code: https://jsfiddle.net/9dtqpsLa/1/
CSS
#keyframes imageZoom{
0% { transform: scale(1); }
50% { transform: scale(1.24); }
100% { transform: scale(1);}
}
#-moz-keyframes imageZoom{
0% { -moz-transform: scale(1);}
50% { -moz-transform: scale(1.24); }
100% { -moz-transform: scale(1); }
}
#-webkit-keyframes imageZoom{
0% { -webkit-transform: scale(1); }
50% {-webkit-transform: scale(1.24); }
100% { -webkit-transform: scale(1); }
}
#-ms-keyframes imageZoom{
0% { -ms-transform: scale(1); }
50% { -ms-transform: scale(1.24); }
100% { -ms-transform: scale(1); }
}
.article:hover .imageWrapper {
animation: imageZoom linear 10s;
animation-iteration-count: infinite;
-webkit-animation: imageZoom linear 10s;
-webkit-animation-iteration-count: infinite;
-moz-animation: imageZoom linear 10s;
-moz-animation-iteration-count: infinite;
-ms-animation: imageZoom linear 10s;
-ms-animation-iteration-count: infinite;
transform-origin: 50% 80%;
}
.article {
background-color: #e6e6e6;
overflow: hidden;
width: 300px;
height: 300px;
}
.imageWrapper {
background-image: url('http://www.astutegraphics.com/images/blog/tutorials/widthscribe_patterns_18_mar_2013/floral-seamless-pattern.png');
width: 300px;
height: 300px;
}
HTML
<div class="article">
<div class="imageWrapper">
</div>
</div>
Please, could you help me?
Thanks so much
GOALS:
1. Have the image animate expansion and contraction on hover
2. Have the image animate to original state on mouseleave
PROBLEMS:
With CSS, I don't know how to use both an animation and a transition. The animation is the pulsing on hover. The transition is the return to default animation. The only way I could envision doing it is with JS. See each section for notes
https://jsfiddle.net/Bushwazi/9dtqpsLa/5/
HTML:
notes: same as example provided
<div class="article">
<div class="imageWrapper"></div>
</div>
CSS:
notes:
1. animation removed.
2. The scale is only fired with the existence of [data-dir='expand'].
3. transform-origin and transition moved into the default state of .imageWrapper
4. need to add prefixes
.article[data-dir='expand'] .imageWrapper {
transform:scale(1.24)
}
.article {
background-color: #e6e6e6;
overflow: hidden;
width: 300px;
height: 300px;
}
.imageWrapper {
background-image: url('http://www.astutegraphics.com/images/blog/tutorials/widthscribe_patterns_18_mar_2013/floral-seamless-pattern.png');
width: 300px;
height: 300px;
transform-origin: 50% 80%;
transition:all 10.0s linear 0.0s;
}
JAVASCRIPT:
notes:
1. all new
/*
1. on hover aka 'mouseenter' start the animation
2. 10 seconds in, change direction of the animation based on the `isHovering` variable
3. on exit aka 'mouseleave', return to default
*/
var thisArticle = document.querySelector('.article'),
thisTimer = '',
isHovering = false;
thisArticle.addEventListener('mouseenter', function(){
console.log('mouseenter');
thisArticle.setAttribute('data-dir', 'expand');
thisTimer = setInterval(fireAnimation, 10000);
isHovering = true
}, false);
thisArticle.addEventListener('mouseleave', function(){
console.log('mouseleave');
thisArticle.removeAttribute('data-dir');
isHovering = false;
clearInterval(thisTimer);
}, false);
var fireAnimation = function(){
if(isHovering){
if(thisArticle.getAttribute('data-dir') === 'expand'){
thisArticle.removeAttribute('data-dir');
} else {
thisArticle.setAttribute('data-dir', 'expand');
}
} else {
clearInterval(thisTimer);
}
alert('change direction');
}
MORE IDEAS
1. I used a data attribute, but I would prefer to use classList. Wasn't sure how to incorporate that into the fiddle in 30 seconds, so skipped it.
2. The return to default animation has no awareness of the scale when you leave, so it takes 10 seconds no matter what. I'm sure there is a way to make this better.
Once you the mouse is moved away from the element, the styles in the :hover pseudo class gets removed from your element, effectively putting it back where it started.
What you want to do is start and pause the animation:
Here is your fiddle, I edited it a bit and exploded the short-hand and removed -webkit, -ms, etc:
https://jsfiddle.net/9dtqpsLa/4/
#keyframes imageZoom {
100% {
transform: scale(4);
}
}
.article:hover .imageWrapper {
animation-play-state: running;
}
.article {
background-color: #e6e6e6;
overflow: hidden;
width: 300px;
height: 300px;
}
.imageWrapper {
background-image: url('http://www.astutegraphics.com/images/blog/tutorials/widthscribe_patterns_18_mar_2013/floral-seamless-pattern.png');
width: 300px;
height: 300px;
transform-origin: 50% 80%;
animation-name: imageZoom;
animation-duration: 2s;
animation-delay: 0s;
animation-iteration-count: 1;
animation-direction: both;
animation-timing-function: ease-in;
animation-fill-mode: forwards;
animation-play-state: paused;
}
Notice that all the animation logic has moved to the base class, and the :hover only kicks off the animation.
I'd like to spin an image and I came across this video https://www.youtube.com/watch?v=nD8xqlh6Esk which gave a very simple way to spin a div on a click. I thought this would be a great method to spin an image on a page load with minimal css so tried using a :after as opposed to a :click (with 720 deg) but that didn't work. Has anyone got this approach to work on a page load rather than on a click? I've seen other methods but they need quite a bit more css.
Detail provided
[Apparently my youtube link is to a football match although for me it's to a LevelUp Tuts CSS Experiments #1 - Card Flipping Effect video.]
Basically, he flips a card through a simple transform on a hover as follows:
<div class="card"></div>
.card {
background: blue;
width: 200px;
height: 200px;
}
.card:hover {
transform: rotateY (90deg);
}
So you can spin the div with a single line, a transform, on a hover. There's no need for keyframes.
Try this:
div {
width: 100px;
height: 100px;
background: red;
animation: spin 2s infinite;
-webkit-animation: spin 2s infinite;
}
#keyframes spin{
to{
transform: rotate(360deg);
}
}
#-webkit-keyframes spin{
to{
transform: rotate(360deg);
}
<div id="d"></div>
EDIT: is this more like what you wanted?
div {
width: 100px;
height: 100px;
background: red;
animation: spin 2s forwards;
-webkit-animation: spin 2s forwards;
}
#keyframes spin{
to{
transform: rotateY(90deg);
}
}
#-webkit-keyframes spin{
to{
transform: rotateY(90deg);
}
}
<div id="d"><img src="http://img4.wikia.nocookie.net/__cb20120208185721/logopedia/images/5/54/Barclays_Premier_League_logo_(shield).gif" width="100px" height="100px"></div>
You need animation as well, not just transition:
http://jsfiddle.net/rudiedirkx/AB277/95/
The magic:
.card {
animation: spinn 5s linear infinite;
/* you don't need transition at all */
}
#keyframes spinn {
0% { transform: rotateY(0deg); }
100% { transform: rotateY(720deg); }
}
For some reason, Chrome still needs prefixes.
More info on css-tricks.
this animates the object as soon as the css and the html load:
(http://jsfiddle.net/oemtt7cr/)
#-webkit-keyframes spin {
from {
-webkit-transform: rotateY(0deg);
}
to {
-webkit-transform: rotateY(720deg);
}
}
#keyframes spin {
from {
transform: rotateY(0deg);
}
to {
transform: rotateY(720deg);
}
}
.container {
-webkit-perspective: 2000px;
}
.card {
margin: 20px;
background: #990;
width: 200px;
height: 200px;
animation: spin 5s ease;
-webkit-animation: spin 5s ease;
}
<div class="container">
<div class="card">flipy</div>
</div>
Use .card:hover instead of .card:after if you like the animation start when user move in with cursor.
http://jsfiddle.net/AB277/90/
.card {margin 20px;
background: blue;
width: 200px;
height:200px;
transition: all 5s;
}
.card:hover {
transform: rotateY(720deg);
}
Or if you like the animation at page load, use the following script.
http://jsfiddle.net/AB277/93/
<div id="card"
</div>
var elm = document.getElementById('card');
elm.classList.add('cardMove');
#card {margin 20px;
background: blue;
width: 200px;
height:200px;
transition: all 5s;
}
.cardMove {
transform: rotateY(720deg);
}