I saw this animation on codepen, and I don't know why it's written this way to have this effect, but I think it's going to have the effect of rotating 360deg clockwise, 360deg counterclockwise, instead of bouncing up and down or left and right
I'm particularly puzzled with these Keyframe animation
#keyframes move{
from {
transform: rotate(360deg) translateX(1.125em) rotate(-360deg);
}
to {
transform: rotate(-360deg) translateX(1.125em) rotate(360deg);
}
}
Results the following
https://i.stack.imgur.com/9oWnw.gif
From the specification we can see how the broswer should deal with interpolation between transform values. In this case we use this:
If from- and to-transform have the same number of transform functions,
each transform function pair has either the same name, or is a
derivative of the same primitive: Interpolate each transform function
pair as described in Interpolation of transform functions. The
computed value is the resulting transform function list.
So the browser will change the first rotate from 360deg to -360deg and the same for the last rotate while translateX will kept the same. We will then have the following steps:
transform: rotate(360deg) translateX(1.125em) rotate(-360deg);
transform: rotate(350deg) translateX(1.125em) rotate(-350deg);
transform: rotate(340deg) translateX(1.125em) rotate(-340deg);
....
transform: rotate(0) translateX(1.125em) rotate(0);
....
....
transform: rotate(-360deg) translateX(1.125em) rotate(360deg);
Now we need to understand how rotate(-adeg) translateX(b) rotate(adeg) works. First you may notice that the rotation won't have any visual effect on the element since we deal with a circle, it will simply affect how the translation will work and more precisely it's the first rotation that is important (the one in the left).
.container {
width: 50px;
height: 50px;
margin: 50px;
border:2px solid;
}
.box {
width: 50px;
height: 50px;
background: red;
border-radius: 50%;
animation: move 2s linear infinite;
}
.alt {
animation: move-alt 2s linear infinite;
}
#keyframes move {
from {
transform: rotate(360deg) translateX(1.125em) rotate(-360deg);
}
to {
transform: rotate(-360deg) translateX(1.125em) rotate(360deg);
}
}
#keyframes move-alt {
from {
transform: rotate(360deg) translateX(1.125em);
}
to {
transform: rotate(-360deg) translateX(1.125em);
}
}
<div class="container">
<div class="box">
</div>
</div>
<div class="container">
<div class="box alt">
</div>
</div>
As you can see both animation are equivalent visually.
Now the effect is as follow: each time we rotate the X-axis and then we translate our element consider the new rotated axis. It's like we rotate the coordinate system then we translate OR its like we do the translation once (since it's the same) then we keep rotating the coordinate system thus we have a rotation at the end.
Now if we consider the opposite transform nothing will happen visually:
.container {
width: 50px;
height: 50px;
margin: 50px;
border: 2px solid;
}
.box {
width: 50px;
height: 50px;
background: red;
border-radius: 50%;
animation: move 2s linear infinite;
}
#keyframes move {
from {
transform: translateX(1.125em) rotate(-360deg);
}
to {
transform: translateX(1.125em) rotate(360deg);
}
}
<div class="container">
<div class="box">
</div>
</div>
In this case we translate the coordinate system by the same translation then we rotate our circle. If we change it to a square we will see the effect
.container {
width: 50px;
height: 50px;
margin: 50px;
border: 2px solid;
}
.box {
width: 50px;
height: 50px;
background: red;
animation: move 2s linear infinite;
}
#keyframes move {
from {
transform: translateX(1.125em) rotate(-360deg);
}
to {
transform: translateX(1.125em) rotate(360deg);
}
}
<div class="container">
<div class="box">
</div>
</div>
And here is how your initial animation will look with a square:
.container {
width: 50px;
height: 50px;
margin: 50px;
border: 2px solid;
}
.box {
width: 50px;
height: 50px;
background: red;
animation: move 2s linear infinite;
}
#keyframes move {
from {
transform:rotate(360deg) translateX(1.125em) rotate(-360deg);
}
to {
transform:rotate(-360deg) translateX(1.125em) rotate(360deg);
}
}
<div class="container">
<div class="box">
</div>
</div>
We rotate the coordinate system, we translate our element then we rotate the element so it's like we rotate our the element inside a bigger one that is also rotating in the opposite direction.
If you change the timing function to something else than linear you will have the same rotation but it won't be linear, it will be slower/faster in some interval:
.container {
width: 50px;
height: 50px;
margin: 50px;
border: 2px solid;
}
.box {
width: 50px;
height: 50px;
background: red;
animation: move 2s ease-in-out infinite;
}
#keyframes move {
from {
transform:rotate(360deg) translateX(1.125em) rotate(-360deg);
}
to {
transform:rotate(-360deg) translateX(1.125em) rotate(360deg);
}
}
<div class="container">
<div class="box">
</div>
</div>
This is a simplified explanation, you may check this answer if you want more details about how we deal with multiple function inside transform and how the order is important: Simulating transform-origin using translate
Related
My intention is to make a parent square which contain four smaller child cubes. I would want an animation to have those four smaller cubes move around within the parent cube. I first make one cube and move it around like so:
.parent {
background-color: aliceblue;
height: 400px;
width: 400px;
margin: 25px;
padding: 25px;
}
.child{
background: black;
position: absolute;
height:100px;
width:100px;
animation: move_around 5s ease-in-out infinite backwards;
}
#keyframes move_around {
0% {
transform: translateX(0%);
}
25% {
transform:translateY(300%);
}
50% {
transform:translateY(300%) translateX(300%);
}
75% {
transform: translateX(300%);
}
}
<div class="parent">
<div class='child'></div>
</div>
However, my intention is to make four of those little cubes, and I want them to start at each corner. Of course I could manually add another cube by adding another child and adding a new custom animation to it, like so:
.parent {
background-color: aliceblue;
height: 400px;
width: 400px;
margin: 100px;
padding: 25px;
}
.child{
background: black;
position: absolute;
height:100px;
width:100px;
}
.top {
animation: move_around 5s ease-in-out infinite backwards
}
.bot {
animation: move_around_bot 5s ease-in-out infinite backwards
}
#keyframes move_around {
0% {
transform: translateX(0%);
}
25% {
transform:translateY(300%);
}
50% {
transform:translateY(300%) translateX(300%);
}
75% {
transform: translateX(300%);
}
}
#keyframes move_around_bot {
0% {
transform:translateY(300%) translateX(300%);
}
25% {
transform: translateY(0%) translateX(300%);
}
50% {
transform: translateY(0%) translateX(0%)
}
75% {
transform: translateX(0%) translateY(300%);
}
100% {
transform:translateY(300%) translateX(300%);
}
}
<div class="parent">
<div class='child top'></div>
<div class='child bot'></div>
</div>
However, this does not seem like the best way. Now I have two, with more then double the amount of lines. Would it need double again the amount of lines for four cubes? What if I want even more cubes? My approach does not seem very usable in this way.
I realized that the second cube here is identical to the first cube, except that its animation is basically 50% of the frames 'ahead'. Is there a way to add a 3rd, 4th or Nth cube that are 25%, 75% or X% of the frames 'ahead'?
You could use animation-delay: -1.25s for the second cube, -2.5s for the third and -3.75s for the last one.
You could make something like:
.parent img:nth-child(1){
animation-delay: 0s; /* change this to something else for each */
}
To change the animation-delay, change the seconds u start at, and to change the specific cube you want, change the parameter at the top to something like:
.parent img:nth-child(2){
Yes. animation-delay will work.
.parent {
background-color: aliceblue;
height: 400px;
width: 400px;
margin: 25px;
padding: 25px;
}
.parent .child:nth-child(1){
animation-delay: 0s;
}
.parent .child:nth-child(2){
animation-delay: -1.25s;
}
.parent .child:nth-child(3){
animation-delay: -2.5s;
}
.parent .child:nth-child(4){
animation-delay: -3.75s;
}
.child{
background: black;
position: absolute;
height:100px;
width:100px;
animation: move_around 5s ease-in-out infinite backwards;
}
#keyframes move_around {
0% {
transform: translateX(0%);
}
25% {
transform:translateY(300%);
}
50% {
transform:translateY(300%) translateX(300%);
}
75% {
transform: translateX(300%);
}
}
<div class="parent">
<div class='child'></div>
<div class='child'></div>
<div class='child'></div>
<div class='child'></div>
</div>
I have a little noobish CSS question If someone could share some free time to help. what I want to do is the div to stop and freeze at the position whenever I leave (hover off) my cursor, and not reset to his fixed starting position.
<script>
.rotatingDiv {
width: 50px;
height: 30px;
background-color: red;
margin: auto;
margin-top: 10rem;
cursor: pointer;
}
.rotatingDiv:hover {
animation: spin 4s linear infinite;
}
#keyframes spin {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
</script>
<body>
<div class="rotatingDiv"> </div>
</body>
as seen on the example the div keeps reseting to the starting position which is 0deg (default) on mouse-out, so what I want to achieve is for the div to freeze at the exact degree whenever I leave my cursor (mouse out/ hover off) from the div.
I think you wanted this thing it would be work
.rotatingDiv {
width: 50px;
height: 30px;
background-color: red;
margin: auto;
margin-top: 10rem;
cursor: pointer;
animation: spin 4s linear infinite;
animation-play-state: paused;
}
.rotatingDiv:hover {
animation: spin 4s linear infinite;
}
#keyframes spin {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
<body>
<div class="rotatingDiv"> </div>
</body>
I have a CSS animation, for example, like this:
#keyframes my-animation {
0% { opacity: 0; visibility: visible; transform: scale(0,0); }
50% { transform: scale(1.15, 1.15); }
100% { transform: none; }
}
And I want to apply it to a DIV that has an arbitrary rotation e.g. like this:
<div style="width:100px; height:100px; transform: rotate(45deg)"/>
When I apply the CSS animation, keyframes have another transform attribute that only sets scale. As a result, my DIV is rotated back to 0 during the animation and, at the end, it is restored back to 45 degree rotation.
But I want it to keep its arbitrary original rotation. So the question is: is there a way to specify in transform property of the keyframes that it should keep existing (arbitrary) rotation?
Something like transform: scale(1.15, 1.15) rotate(keep) ?
Use CSS variables
.x {
transform: rotate(var(--r,0deg));
height: 50px;
width: 50px;
display:inline-block;
background: green;
animation: my-animation 5s;
margin: 20px;
}
#keyframes my-animation {
0% {
opacity: 0;
transform: scale(0) rotate(var(--r,0deg));
}
50% {
transform: scale(1.15) rotate(var(--r,0deg));
}
}
<div class="x" style="--r:80deg"></div>
<div class="x" ></div>
<div class="x" style="--r:60deg"></div>
Or like below so you can append any transformation to the one defined in the keyframes
:root {
--r: rotate(0deg); /* Use any null transform (ex: translate(0), skew(0deg), etc)*/
}
.x {
transform: var(--r);
height: 50px;
width: 50px;
display:inline-block;
background: green;
animation: my-animation 5s;
margin: 20px;
}
#keyframes my-animation {
0% {
opacity: 0;
transform: scale(0) var(--r);
}
50% {
transform: scale(1.15) var(--r);
}
}
<div class="x" style="--r:rotate(80deg) skew(20deg)"></div>
<div class="x" ></div>
<div class="x" style="--r:rotate(60deg) translate(20px,20px)"></div>
Here's a simple solution without variables - I would just wrap your div and do the scaling on the wrapper, keeping the inner div rotated arbitrarily. Trivial, but does the trick I think.
.box {
height: 50px;
width: 50px;
background: green;
margin: 50px;
}
.scale-me {
animation: my-animation;
animation-duration: 10s;
}
#keyframes my-animation {
0% {
opacity: 0;
transform: scale(0);
}
50% {
transform: scale(1.15);
}
}
<div class="scale-me">
<div class="box" style="transform: rotate(45deg)"></div>
<div class="box" style="transform: rotate(60deg)"></div>
<div class="box" style="transform: rotate(120deg)"></div>
</div>
I have a circle logo, with text on the outside, and a small circle in the middle. I plan to make the logo spin using some CSS3. That's relatively easily.
The tricky bit is that I want to make the logo change to BLACK when it's over a pink div, and change to WHITE as it moves over the black part...
I think this is achieved with a mask or a filter, but I just cannot work out how to do it...
I've setup a codepen with a basic example:
https://codepen.io/anon/pen/JQYQdp
<div class="main-header">
<div class="spinning">
<img src="https://i.ibb.co/pKVwqhY/test-logo.png" alt="test-logo" border="0">
</div>
</div>
<div class="pink">
</div>
CSS:
.main-header {
width:100%;
background-color:black;
height:200px;
}
.pink {
width:100%;
background-color:pink;
height:200px;
}
.spinning {
position:absolute;
z-index:2000;
height:200px;
width:200px;
top:100px;
right:0;
-webkit-animation:spin 4s linear infinite;
-moz-animation:spin 4s linear infinite;
animation:spin 4s linear infinite;
}
#-moz-keyframes spin { 100% { -moz-transform: rotate(360deg); } }
#-webkit-keyframes spin { 100% { -webkit-transform: rotate(360deg); } }
#keyframes spin { 100% { -webkit-transform: rotate(360deg); transform:rotate(360deg); } }
As the text of the image spins over the PINK background, I want that part of the text to be black, whilst the top half is still white...
mix-blend-mode will get you most of the way.
The mix-blend-mode CSS property sets how an element's content should blend with the content of the element's parent and the element's background.
MDN
.main-header {
width: 100%;
background-color: black;
height: 200px;
}
.pink {
width: 100%;
background-color: pink;
height: 200px;
}
.spinning {
mix-blend-mode: difference;
position: absolute;
z-index: 2000;
height: 200px;
width: 200px;
top: 100px;
right: 10px;
-webkit-animation: spin 4s linear infinite;
-moz-animation: spin 4s linear infinite;
animation: spin 4s linear infinite;
}
#-moz-keyframes spin {
100% {
-moz-transform: rotate(360deg);
}
}
#-webkit-keyframes spin {
100% {
-webkit-transform: rotate(360deg);
}
}
#keyframes spin {
100% {
-webkit-transform: rotate(360deg);
transform: rotate(360deg);
}
}
<div class="main-header">
<div class="spinning">
<img src="https://i.ibb.co/pKVwqhY/test-logo.png" alt="test-logo" border="0">
</div>
</div>
<div class="pink">
</div>
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);
}