Transform origin so animation don't jump - css

I have created an animated spinner, which is build using "slices of pizza" made of background gradient. The problem is I can't figure out what the origin should be. The animation keeps on jumping.
See the fiddle: http://jsfiddle.net/eqc05bkf/
How can I get rid of the jumping?
HTML:
<div class="slices bar">
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
</div>
CSS:
.slices {
width:100px;
height:100px;
position:relative;
transform-origin: right bottom;
-webkit-animation: spin 2.8s infinite steps(8);
-moz-animation: spin 2.8s infinite steps(8);
-ms-animation: spin 2.8s infinite steps(8);
-o-animation: spin 2.8s infinite steps(8);
animation: spin 2.8s infinite steps(8);
}
.slices.bar div {
width: 100%;
height: 100%;
position: absolute;
top: 35px;
left: 45px;
border-radius: 50%;
background: linear-gradient(45deg, #CDCDCD 50%, transparent 50%) 0 0;
background-repeat: no-repeat;
background-size: 50% 50%;
transform-origin: 56px 52px;
/* container height / 2 */
}
#-webkit-keyframes spin {
to {
transform: rotate(1turn);
}
}
#-moz-keyframes spin {
to {
transform: rotate(1turn);
}
}
#-ms-keyframes spin {
to {
transform: rotate(1turn);
}
}
#keyframes spin {
to {
transform: rotate(1turn);
}
}
.slices.bar div:nth-child(1) {
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
background: linear-gradient(45deg, red 50%, transparent 50%) 0 0;
background-repeat: no-repeat;
background-size: 50% 50%;
}
.slices.bar div:nth-child(2) {
-webkit-transform: rotate(45deg);
transform: rotate(45deg);
}
.slices.bar div:nth-child(3) {
-webkit-transform: rotate(90deg);
transform: rotate(90deg);
}
.slices.bar div:nth-child(4) {
-webkit-transform: rotate(135deg);
transform: rotate(135deg);
}
.slices.bar div:nth-child(5) {
-webkit-transform: rotate(180deg);
transform: rotate(180deg);
}
.slices.bar div:nth-child(6) {
-webkit-transform: rotate(225deg);
transform: rotate(225deg);
}
.slices.bar div:nth-child(7) {
-webkit-transform: rotate(270deg);
transform: rotate(270deg);
}
.slices.bar div:nth-child(8) {
-webkit-transform: rotate(315deg);
transform: rotate(315deg);
}

I modified your code a bit. Primarily, I added a container div and simply rotated that. fiddle
HTML:
<div id='hold'>
<div class="slices bar">
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
</div>
</div>
CSS:
.slices {
width:100px;
height:100px;
position:relative;
margin-top: -31px;
margin-left: -45px;
transform-origin: right bottom;
/*-webkit-animation: spin 2.8s infinite steps(8);
-moz-animation: spin 2.8s infinite steps(8);
-ms-animation: spin 2.8s infinite steps(8);
-o-animation: spin 2.8s infinite steps(8);
animation: spin 2.8s infinite steps(8);*/
}
#hold {
width: 112px;
height: 112px;
border-radius: 50%;
overflow: hidden;
-webkit-animation: spin 2.8s infinite steps(8);
-moz-animation: spin 2.8s infinite steps(8);
-ms-animation: spin 2.8s infinite steps(8);
-o-animation: spin 2.8s infinite steps(8);
animation: spin 2.8s infinite steps(8);
}
.slices.bar div {
width: 100%;
height: 100%;
position: absolute;
top: 35px;
left: 45px;
border-radius: 50%;
background: linear-gradient(45deg, #CDCDCD 50%, transparent 50%) 0 0;
background-repeat: no-repeat;
background-size: 50% 50%;
transform-origin: 56px 52px;
/* container height / 2 */
}
#-webkit-keyframes spin {
to {
transform: rotate(1turn);
}
}
#-moz-keyframes spin {
to {
transform: rotate(1turn);
}
}
#-ms-keyframes spin {
to {
transform: rotate(1turn);
}
}
#keyframes spin {
to {
transform: rotate(1turn);
}
}
.slices.bar div:nth-child(1) {
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
background: linear-gradient(45deg, red 50%, transparent 50%) 0 0;
background-repeat: no-repeat;
background-size: 50% 50%;
}
.slices.bar div:nth-child(2) {
-webkit-transform: rotate(45deg);
transform: rotate(45deg);
}
.slices.bar div:nth-child(3) {
-webkit-transform: rotate(90deg);
transform: rotate(90deg);
}
.slices.bar div:nth-child(4) {
-webkit-transform: rotate(135deg);
transform: rotate(135deg);
}
.slices.bar div:nth-child(5) {
-webkit-transform: rotate(180deg);
transform: rotate(180deg);
}
.slices.bar div:nth-child(6) {
-webkit-transform: rotate(225deg);
transform: rotate(225deg);
}
.slices.bar div:nth-child(7) {
-webkit-transform: rotate(270deg);
transform: rotate(270deg);
}
.slices.bar div:nth-child(8) {
-webkit-transform: rotate(315deg);
transform: rotate(315deg);
}

Related

CSS animation. Slide in for 10 seconds and then move up and down infinitely

I currently have an image "floating". So it moves up and down over 10 seconds. But what I'd really like it to do is to do is slide in right from off canvas over 10 seconds and then float infinitely.
The code I have now just makes it float up and down and I'm struggling to add the slide in part. I'm new to CSS animation so I'd appreciate any help.
This is what I have so far.
.shake-vertical {
-webkit-animation: shake-vertical 15s cubic-bezier(0.455, 0.030, 0.515, 0.955) infinite both;
animation: shake-vertical 15s cubic-bezier(0.455, 0.030, 0.515, 0.955) infinite both;
}
#-webkit-keyframes shake-vertical {
0%,
100% {
-webkit-transform: translateY(0);
transform: translateY(0);
}
10%,
30%,
50%,
70% {
-webkit-transform: translateY(-8px);
transform: translateY(-8px);
}
20%,
40%,
60% {
-webkit-transform: translateY(8px);
transform: translateY(8px);
}
80% {
-webkit-transform: translateY(6.4px);
transform: translateY(6.4px);
}
90% {
-webkit-transform: translateY(-6.4px);
transform: translateY(-6.4px);
}
}
#keyframes shake-vertical {
0%,
100% {
-webkit-transform: translateY(0);
transform: translateY(0);
}
10%,
30%,
50%,
70% {
-webkit-transform: translateY(-8px);
transform: translateY(-8px);
}
20%,
40%,
60% {
-webkit-transform: translateY(8px);
transform: translateY(8px);
}
80% {
-webkit-transform: translateY(6.4px);
transform: translateY(6.4px);
}
90% {
-webkit-transform: translateY(-6.4px);
transform: translateY(-6.4px);
}
}
Considering your image has a class of ball. You can add this CSS to your Existing CSS:
#keyframes slide-in {
from{
margin-right: -100px;
}
to{
margin-right: 0;
}
}
.ball{
width: 100px;
height: 100px;
border-radius: 50%;
background-color: red;
float: right;
animation: slide-in 10s forwards,/*forwards keeps the ball at final position*/
shake-vertical 15s infinite 10s both;
/*
* Two animations applied
* comma separated
* shake-vertical has a 10 second delay specified by '10s'
* the delay should be same as the duration of first animation
*/
}
I have added comments for explanation but if you need more, feel free to comment.
You can set the object with a slidein animation for 10 seconds and on the animationend event change its class to your shake animation.
Add CSS something like this:
#keyframes slidein {
0% {
transform: translateX(100vw);
}
100% {
transform: translateX(50vw);
}
}
.slidein {
animation-name:slidein;
animation-duration:10s;
animation-fill-mode: follow;
}
.shake {
animation-name: shake-vertical;
animation-duration: 10s;
animation-iteration-count: infinite;
}
}
and JavaScript something like this
obj.addEventListener("animationend", function () {
obj.classList.remove('slidein');
obj.classList.add('shake');
});
Example with a simple sliding square in the Snippet.
<!DOCTYPE html>
<html>
<head>
<style>
#keyframes slidein {
0% {
transform: translateX(100vw);
}
100% {
transform: translateX(50vw);
}
}
#keyframes shake-vertical {
0%,
100% {
-webkit-transform: translateY(0);
transform: translateY(0);
}
10%,
30%,
50%,
70% {
-webkit-transform: translateY(-8px);
transform: translateY(-8px);
}
20%,
40%,
60% {
-webkit-transform: translateY(8px);
transform: translateY(8px);
}
80% {
-webkit-transform: translateY(6.4px);
transform: translateY(6.4px);
}
90% {
-webkit-transform: translateY(-6.4px);
transform: translateY(-6.4px);
}
}
#obj {
position: relative;
width: 50px;
height: 50px;
top: 50px;
background-color:magenta;
animation-delay:0s;
}
.slidein {
animation-name:slidein;
animation-duration:10s;
}
.shake {
left: 50vw;
animation-name:shake-vertical;
animation-duration: 10s;
animation-iteration-count: infinite;
}
</style>
</head>
<div id="obj" class="slidein"></div>
<script>
var obj = document.getElementById('obj');
obj.addEventListener("animationend", function () {
obj.classList.remove('slidein');
obj.classList.add('shake');
});
</script>
</html>

How to animate a rolling rectangle

I'd like to animate a rectangle to roll from the left of the screen to the right of the screen. Please notice that the transform-origin point should not be in the center of the rectangle, but in the bottom-right corner, so that it doesn't overpass the "hr" line or bounce in any way.
This is what I have achieved untill now, but I'd like it to move continuously untill it gets to the right edge of the screen:
hr {
margin: 0;
}
div {
width: 135px;
height: 135px;
box-shadow: inset 0 0 10px #000000;
transform-origin: right bottom;
animation-name: move;
animation-duration: 2s;
animation-timing-function: linear;
animation-delay: 0;
animation-iteration-count: infinite;
animation-direction: alternate;
}
#keyframes move {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(90deg);
}
}
<div></div>
<hr>
You need to change the transform origin as you go :
hr {
margin: 0;
}
div {
width: 135px;
height: 135px;
box-shadow: inset 0 0 10px #000000;
transform-origin: right bottom;
animation-name: move;
animation-duration: 12s;
animation-timing-function: linear;
animation-delay: 0;
animation-iteration-count: infinite;
animation-direction: alternate;
margin-top: 20px;
}
#keyframes move {
0% {
transform: rotate(0deg);
transform-origin: right bottom;
}
25% {
transform: rotate(90deg);
transform-origin: right bottom;
}
25.1% {
transform: translate(100%, 100%) rotate(90deg);
transform-origin: top right;
}
50% {
transform: translate(100%, 100%) rotate(180deg);
transform-origin: top right;
}
50.1% {
transform: translate(300%, 100%) rotate(180deg);
transform-origin: left top;
}
75% {
transform: translate(300%, 100%) rotate(270deg);
transform-origin: left top;
}
75.1% {
transform: translate(400%, 0%) rotate(270deg);
transform-origin: left bottom;
}
100% {
transform: translate(400%, 0%) rotate(360deg);
transform-origin: left bottom;
}
}
<div>TEST</div>
<hr>
Interesting, I would consider adding a translation and the trick is to switch fastly between two states to be able to continue the move.
You are rotating your element with 90deg which is equivalent in your case to a translation by the width of the element if we only consider the final state so switching fastly between both situation won't be visible and thus you can rotate your element again and repeat the same trick until your reach the needed position.
hr {
margin: 0;
}
div {
width: 135px;
height: 135px;
box-shadow: inset 0 0 10px #000000;
transform-origin: right bottom;
animation-name: move;
animation-duration: 4s;
animation-timing-function: linear;
animation-delay: 0;
animation-iteration-count: infinite;
animation-direction: alternate;
}
#keyframes move {
0% {
transform: rotate(0deg);
}
25% {
transform: rotate(90deg);
}
25.01% {
transform: translateX(calc(1 * 135px)) rotate(0deg);
}
50% {
transform: translateX(calc(1 * 135px)) rotate(90deg);
}
50.01% {
transform: translateX(calc(2 * 135px)) rotate(0deg);
}
75% {
transform: translateX(calc(2 * 135px)) rotate(90deg);
}
75.01% {
transform: translateX(calc(3 * 135px)) rotate(0deg);
}
100% {
transform: translateX(calc(3 * 135px)) rotate(90deg);
}
}
<div></div>
<hr>

CSS animation working everywhere but not in IE and edge?

All is in the title, I cannot figure out why my animation is working everywhere but not in IE and edge. Where am I missing something ?
Here are the keyframes of my animation and the JS fiddle associated
$(document).ready(function () {
$('#toggle').hide();
});
$('#toggler').click(function () {
$("#toggle").delay(800).velocity("slideDown", {
duration: 1200
});
$("#footer").delay(800).velocity("scroll", {
duration: 1200
});
});
body {
overflow-x:hidden;
overflow-y:scroll;
}
#content1 {
width:100%;
height:800px;
background-color:grey;
position:relative;
}
#toggler {
position: absolute;
left: 0;
right: 0;
bottom:10px;
margin-left: auto;
margin-right: auto;
width: 100px;
height:50px;
}
#footer {
background-color:black;
width:100%;
height:150px;
}
.slide-up {
display: block;
height: auto;
width:100%;
}
.animate {
animation: super-zgeger-mob 5s;
animation-timing-function: linear;
animation-iteration-count: 1;
transform-origin: 50% 50%;
z-index: 9999;
overflow: hidden;
-webkit-animation: super-zgeger-mob linear 5s;
-webkit-animation-iteration-count: 1;
-webkit-transform-origin: 50% 50%;
-webkit-animation-fill-mode: forwards;
-moz-animation: super-zgeger-mob linear 5s;
-moz-animation-iteration-count: 1;
-moz-transform-origin: 50% 50%;
-moz-animation-fill-mode: forwards;
-o-animation: super-zgeger-mob linear 5s;
-o-animation-iteration-count: 1;
-o-transform-origin: 50% 50%;
-o-animation-fill-mode: forwards;
-ms-animation: super-zgeger-mob linear 5s;
-ms-animation-iteration-count: 1;
-ms-transform-origin: 50% 50%;
-ms-animation-fill-mode: forwards;
}
#keyframes super-zgeger-mob {
0% {
transform: translate(-90%, 0%);
opacity: 0;
}
15% {
transform: translate(-90%, 0%);
opacity: 1;
}
50% {
transform: translate(0%, 0%);
}
75% {
transform: translate(-5%, 0%) rotate(10deg);
}
100% {
transform: translate(150%, 0%);
}
}
#-moz-keyframes super-zgeger-mob {
0% {
-moz-transform: translate(-90%, 0%);
opacity: 0;
}
15% {
-moz-transform: translate(-90%, 0%);
opacity: 1;
}
50% {
-moz-transform: translate(0%, 0%);
}
75% {
-moz-transform: translate(-5%, 0%) rotate(10deg);
}
100% {
-moz-transform: translate(150%, 0%);
}
}
#-webkit-keyframes super-zgeger-mob {
0% {
-webkit-transform: translate(-90%, 0%);
opacity: 0;
}
15% {
-webkit-transform: translate(-90%, 0%);
opacity: 1;
}
50% {
-webkit-transform: translate(0%, 0%);
}
75% {
-webkit-transform: translate(-5%, 0%) rotate(10deg);
}
100% {
-webkit-transform: translate(150%, 0%);
}
}
#-o-keyframes super-zgeger-mob {
0% {
-o-transform: translate(-90%, 0%);
opacity: 0;
}
15% {
-o-transform: translate(-90%, 0%);
opacity: 1;
}
50% {
-o-transform: translate(0%, 0%);
}
75% {
-o-transform: translate(-5%, 0%) rotate(10deg);
}
100% {
-o-transform: translate(150%, 0%);
}
}
#-ms-keyframes super-zgeger-mob {
0% {
-ms-transform: translate(-90%, 0%);
opacity: 0;
}
15% {
-ms-transform: translate(-90%, 0%);
opacity: 1;
}
50% {
-ms-transform: translate(0%, 0%);
}
75% {
-ms-transform: translate(-5%, 0%) rotate(10deg);
}
100% {
-ms-transform: translate(150%, 0%);
}
}
<div id=content1>
<button id="toggler">
push me
</button>
</div>
<div id="toggle">
<div id="animation" style="position: relative; left: 0; top: 0;">
<img src="http://image.gilawhost.com/16/11/09/jzjhk7o0.png" class="slide-up"/>
<img id="rolling" src="http://image.gilawhost.com/16/11/09/6d7tsk5k.png" class="slide-up animate" style="position: absolute; top: 0%; left: 0%; z-index: 99;" />
</div>
</div>
<div id=footer>
</div>
I guess, Using positioning on .animate (left:-90% to desired position) over translate() property will work for you.
translate partially supported by IE 11 only and in opera its also wont work properly.
http://caniuse.com/#feat=transforms2d.

CSS3 animation: Not loading in Safari

the following animation doesn't even load in Safari browser (but works nicely in Chrome, Mozilla, IE, Opera)
http://codepen.io/anon/pen/utdIK
Any idea how to fix it? This problem looks similar, but it didn't fit to my problem.
CSS3 animation not working in safari
HTML:
<div id="spinner-2">
<div class="slices bar">
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
</div>
</div>
<div class="maskWheel"></div>
</div>
CSS:
#spinner-2 {
width: 45px;
height: 45px;
-webkit-border-radius: 100px;
-moz-border-radius: 50%;
border-radius: 50%;
overflow: hidden;
margin: 0 auto;
-webkit-animation: spin .8s infinite steps(8);
-moz-animation: spin .8s infinite steps(8);
-ms-animation: spin .8s infinite steps(8);
-o-animation: spin .8s infinite steps(8);
animation: spin .8s infinite steps(8);
}
.slices {
width: 45px;
height: 45px;
position: relative;
transform-origin: right bottom;
}
.slices.bar div {
width: 100%;
height: 100%;
position: absolute;
-webkit-border-radius: 100px;
-moz-border-radius: 50%;
border-radius: 50%;
background: -webkit-linear-gradient(45deg, #cdcdcd 43%, transparent 43%) 0 0;
background: -moz-linear-gradient(45deg, #cdcdcd 43%, transparent 43%) 0 0;
background: -o-linear-gradient(45deg, #cdcdcd 43%, transparent 43%) 0 0;
background: linear-gradient(45deg, #cdcdcd 43%, transparent 43%) 0 0;
background-repeat: no-repeat;
background-size: 50% 50%}
#-webkit-keyframes spin {
to {
transform: rotate(1turn);
}
}#-moz-keyframes spin {
to {
transform: rotate(1turn);
}
}#-ms-keyframes spin {
to {
transform: rotate(1turn);
}
}#keyframes spin {
to {
transform: rotate(1turn);
}
}.slices.bar div:nth-child(1) {
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
}
.slices.bar div:nth-child(2) {
-webkit-transform: rotate(45deg);
transform: rotate(45deg);
}
.slices.bar div:nth-child(3) {
-webkit-transform: rotate(90deg);
transform: rotate(90deg);
}
.slices.bar div:nth-child(4) {
-webkit-transform: rotate(135deg);
transform: rotate(135deg);
}
.slices.bar div:nth-child(5) {
-webkit-transform: rotate(180deg);
transform: rotate(180deg);
}
.slices.bar div:nth-child(6) {
-webkit-transform: rotate(225deg);
transform: rotate(225deg);
}
.slices.bar div:nth-child(7) {
-webkit-transform: rotate(270deg);
transform: rotate(270deg);
}
.slices.bar div:nth-child(8) {
-webkit-transform: rotate(315deg);
transform: rotate(315deg);
}
.slices.bar div:nth-child(3) {
background: linear-gradient(45deg, #ed3000 43%, transparent 43%) 0 0;
background-repeat: no-repeat;
background-size: 50% 50%}
As Dan stated in his answer, the -webkit- prefix was missing.
One issue for Safari 5 is that shortend properties will not be interpreted by the browser.
You need to specify each single animation property in full.
-webkit-animation-name: spin;
-webkit-animation-duration: 8s;
-webkit-animation-iteration-count: infinite;
-webkit-animation-timing-function: steps(8);
-moz-animation-name: spin;
-moz-animation-duration: 8s;
-moz-animation-iteration-count: infinite;
-moz-animation-timing-function: steps(8);
-ms-animation-name: spin;
-ms-animation-duration: 8s;
-ms-animation-iteration-count: infinite;
-ms-animation-timing-function: steps(8);
-o-animation-name: spin;
-o-animation-duration: 8s;
-o-animation-iteration-count: infinite;
-o-animation-timing-function: steps(8);
animation-name: spin;
animation-duration: 8s;
animation-iteration-count: infinite;
animation-timing-function: steps(8);
If still does not work you can try to remove the to and add the percentage and change the 1turn unit and add the default one in degrees.
#-webkit-keyframes spin {
100% {
transform: rotate(360deg);
}
}#-moz-keyframes spin {
100% {
transform: rotate(360deg);
}
}#-ms-keyframes spin {
100% {
transform: rotate(360deg);
}
}#keyframes spin {
100% {
transform: rotate(360deg);
}
DEMO http://jsfiddle.net/a_incarnati/q0v1wgc8/2/ with no 'to' and '1turn'
DEMO http://jsfiddle.net/a_incarnati/q0v1wgc8/3/
Let me know if it works in Safari 5.0.5
The -webkit- prefix was missing from your webkit specific keyframe.
#-webkit-keyframes spin {
to {
-webkit-transform: rotate(1turn);
}
Here's an updated Codepen
Tested in Safari 7.
I would just like to add that the element should be display:block type in Safari (display: inline works in chrome only ...)

css3 keyframes hover animation firefox

I created some keyframes animation to animate div on mouse hover in pure css3.
It works great in every browsers (google chrome, safari, IE, opera) execpted in FIREFOX!
I really don't know why it didn't works only in firefox. The animation won't works on mouseover but works on load....
Here a css example of keyframe :
#-webkit-keyframes swing {
20%, 40%, 60%, 80%, 100% { -webkit-transform-origin: top center; }
20% { -webkit-transform: rotate(15deg); }
40% { -webkit-transform: rotate(-10deg); }
60% { -webkit-transform: rotate(5deg); }
80% { -webkit-transform: rotate(-5deg); }
100% { -webkit-transform: rotate(0deg); }
}
#-moz-keyframes swing {
20% { -moz-transform: rotate(15deg); }
40% { -moz-transform: rotate(-10deg); }
60% { -moz-transform: rotate(5deg); }
80% { -moz-transform: rotate(-5deg); }
100% { -moz-transform: rotate(0deg); }
}
#-o-keyframes swing {
20% { -o-transform: rotate(15deg); }
40% { -o-transform: rotate(-10deg); }
60% { -o-transform: rotate(5deg); }
80% { -o-transform: rotate(-5deg); }
100% { -o-transform: rotate(0deg); }
}
#keyframes swing {
20% { transform: rotate(15deg); }
40% { transform: rotate(-10deg); }
60% { transform: rotate(5deg); }
80% { transform: rotate(-5deg); }
100% { transform: rotate(0deg); }
}
.col:hover .swing {
-webkit-transform-origin: top center;
-moz-transform-origin: top center;
-o-transform-origin: top center;
transform-origin: top center;
-webkit-animation: swing 1s linear;
-moz-animation: swing 1s linear;
-o-animation: swing 1s linear;
animation: swing 1s linear;
}
.swing {
-webkit-transform-origin: top center;
-moz-transform-origin: top center;
-o-transform-origin: top center;
transform-origin: top center;
-webkit-animation: swing 1s linear 1s;
-moz-animation: swing 1s linear 1s;
-o-animation: swing 1s linear 1s;
animation: swing 1s linear 1s;
}
.col,
.th-icon {
position: relative;
margin: 40px 0 0 100px;
width: 200px;
height: 200px;
}
i.swing {
display: block;
width: 200px;
height: 200px;
background: grey;
}
And the fiddle: http://jsfiddle.net/ktxDp/1/
May be Firefox doesn't allow same animation twice.
It worked when I called the animation only once. Working Demo
.col:hover .swing {
-webkit-transform-origin: top center;
-moz-transform-origin: top center;
-o-transform-origin: top center;
transform-origin: top center;
-webkit-animation: swing 1s linear;
-moz-animation: swing 1s linear;
-o-animation: swing 1s linear;
animation: swing 1s linear;
}

Resources