I'm trying to understand how the transform property works with order of operation and its relevance to the transform duration.
Say I have some html
<div class="container">
<ul>
<li id="obj-1">Item 1</li>
<li id="obj-2">Item 2</li>
</ul>
</div>
The relevant css for container would be:
transition: all 6s ease 0s;
Now if I wanted to transform #obj-1, id write something like this:
#obj-1 {
// some styling
}
#obj-1:hover {
transform: scale(10) scale(2) scale(0.05);
}
How would the browser interpret this css? My initial thought would be that it would allocate each "function" (3) an allocated amount of time (6s/3fun = 2 sec per fun). It doesn't work that way so I wanted to know if someone might point out what it is that determines how long each function would run or if they are somehow altered before execution.
Your allocated amount of time for the animation actually depends on the transition-timing-function. Here you have given ease as a transition-timing-function. ease does not distribute time equally.
If you want your time equally distributed, you have to use transition-timing-function: linear for that.
See the example below you will see the difference.
More help on Transition CSS
.main div {
width: 100px;
height: 100px;
background: red;
margin-bottom: 8px;
}
.main:hover div {
transform: translateX(200px);
}
.one {
transition: all 1s ease;
}
.two {
transition: all 1s linear;
}
.three {
transition: all 1s ease-in;
}
<div class="main">
<div class="one"></div>
<div class="two"></div>
<div class="three"></div>
</div>
And your answer to transform: scale(10) scale(2) scale(0.05);
It will take the highest scale value i.e. 10, So your element will take the scale(10) as the transform.
Note: If any scale contain 0 then scale(0) will take effect
But other than scale() all transform values translate, rotate works differently.
translateX(100px) translateX(100px) translateX(100px) will result translateX(300px)
rotate(45deg) rotate(45deg) will result rotate(90deg)
See the example below
div {
width: 100px;
height: 100px;
background: red;
margin: 0 auto 8px;
transition: all 1s linear;
}
div.one:hover {
transform: rotate(45deg) rotate(45deg);
}
div.two:hover {
transform: translateX(100px) translateX(100px);
}
div.three:hover {
transform: scale(2) scale(1);
}
div.four:hover {
transform: scale(0) scale(2);
}
<div class="one"></div>
<div class="two"></div>
<div class="three"></div>
<div class="four"></div>
And if you want to run these transfomm values in order I prefer to use
#keyframes CSS
Related
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
I have a working demo. just hover the img and there is the effect I want to have.
http://jsfiddle.net/jxgjhzer/1/
As you can see in css file, I don't use any css animation.
Just using CSS transform, I want my img to achieve same effect without hovering it. It should happen automatically.
So how to zoom-in and zoom-out automatically (without animation if possible)?
Code goes here:
.galleryImg{
height:150px;
width:100%;
transform-origin: 50% 50%;
transition: transform 30s linear;
}
.galleryImg:hover{
transform: scale(2) rotate(0.1deg);
}
that's very simple. you can see DEMO on this link on jsfiddle.net
<div class="cardcontainer">
<img class="galleryImg" src="https://www.google.com/logos/doodles/2014/2014-winter-olympics-5710368030588928-hp.jpg">
</div>
#keyframes zoominoutsinglefeatured {
0% {
transform: scale(1,1);
}
50% {
transform: scale(1.2,1.2);
}
100% {
transform: scale(1,1);
}
}
.cardcontainer img {
animation: zoominoutsinglefeatured 1s infinite ;
}
use animation
.galleryImg{
height:150px;
width:100%;
animation:move 3s infinite ease-in-out;
}
#keyframes move{
0%{
transform: scale(1) rotate(0deg);
}
100%{
transform: scale(2) rotate(0.1deg);
}
}
The below css code will help you out for zoom out effect on hover the particular image. Try this code its very useful to you
figure {
width: 300px;
height: 200px;
margin: 0;
padding: 0;
background: #fff;
overflow: hidden;
}
figure:hover+span {
bottom: -36px;
opacity: 1;
}
.hover04 figure img {
width: 400px;
height: auto;
-webkit-transition: .3s ease-in-out;
transition: .3s ease-in-out;
}
.hover04 figure:hover img {
width: 300px;
}
Refer the html code here.
<div class="hover04 column">
<div>
<figure><img src="1.jpeg" /></figure>
<span>Hover Text</span>
</div>
</div>
this is not right way to do i know that and it's not working anymore it's only done for understand my problem.
div
{
transform: rotate(0deg) translate(0);
transition:rotate 0.2s linear, translate 0.3s linear 0.2s;
}
div:hover
{
transform: rotate(60deg) translate(40);
}
As per css3 standards its not possible to achieve the same which you have mentioned. Instead you can make something like this.
<div class="outer">
<div class="inner">
</div>
</div>
.outer
{
height:30px;
width:30px;
transform:translateX(0);
transition:transform 2s linear;
}
.inner{
width: inherit; height: inherit;
transform: rotate(0deg);
transition:transform 2s linear;
background:blue
}
.outer:hover
{
transform: translateX(140px);
}
.outer:hover .inner
{
transform: rotate(160deg);
}
I'm new to css transitions and am experimenting with trying to animate the transition between two sub templates that I am including in my angularjs project using ng-include.
I am attempting to replicate the effect seen here (click on the flip option in the dropdown). However I can't seem to get the newly added template to animate its entrance correctly. The leaving template 'flips' out but the entering template just appears rather than 'flipping' in.
My page has the following basic structure:
<div class="content">
<div class="page flip" ng-include="something"></div>
</div>
I am using the following css:
.content {
-webkit-perspective: 600px;
perspective: 600px;
position:relative;
}
.page{
position:absolute;
background:red;
}
.content .page.flip {
-webkit-transform-style: preserve-3d;
transform-style: preserve-3d;
-webkit-backface-visibility: hidden;
backface-visibility: hidden;
-webkit-transition: all 1s ease-in-out;
transition: all 1s ease-in-out;
}
.content .page.flip.ng-enter {
-webkit-transform: rotateX(-180deg);
transform: rotateX(-180deg);
}
.content .page.flip.ng-enter-active {
-webkit-transform: rotateX(0deg);
transform: rotateX(0deg);
}
.content .page.flip.ng-leave {
-webkit-transform: rotateX(0deg);
transform: rotateX(0deg);
}
.content .page.flip.ng-leave-active {
-webkit-transform: rotateX(180deg);
transform: rotateX(180deg);
}
I've made a plunker by adapting the ng-include demo from angular website here to illustrate problem.
Can anyone point me to where I am going wrong?
I'm trying to create a 3d navbar using pure CSS with transforms, transitions and perspective.
Here is my code:
.navbar-fixed-bottom {
background: transparent;
}
.navbar-perspective {
width: 100%;
height: 100%;
position: relative;
-webkit-perspective: 1100px;
-moz-perspective: 1100px;
perspective: 1100px;
-webkit-perspective-origin: 50% 0;
-moz-perspective-origin: 50% 0;
perspective-origin: 50% 0;
}
.navbar-perspective > div {
margin: 0 auto;
position: relative;
text-align: justify;
-webkit-backface-visibility: hidden;
-moz-backface-visibility: hidden;
backface-visibility: hidden;
-webkit-transition: all 0.5s;
-moz-transition: all 0.5s;
transition: all 0.5s;
height: 50px;
font-size:20px;
}
.navbar-primary {
background-color: #cccccc;
z-index: 2;
-webkit-transform-origin: 0% 100%;
-moz-transform-origin: 0% 100%;
transform-origin: 0% 100%;
}
.navbar .navbar-secondary,
.navbar .navbar-tertiary {
background-color: #bfbfbf;
width: 100%;
-webkit-transform-origin: 0% 0%;
-moz-transform-origin: 0% 0%;
transform-origin: 0% 0%;
z-index: 1;
-webkit-transform: rotateX(-90deg);
-moz-transform: rotateX(-90deg);
transform: rotateX(-90deg);
-webkit-transition: top 0.5s;
-moz-transition: top 0.5s;
transition: top 0.5s;
position: absolute;
top: 0;
}
.navbar .navbar-tertiary {
background-color: #b3b3b3;
}
.navbar-rotate-primary {
height: 50px;
}
.navbar-rotate-primary .navbar-primary {
-webkit-transform: translateY(0%) rotateX(0deg);
-moz-transform: translateY(0%) rotateX(0deg);
transform: translateY(0%) rotateX(0deg);
}
.navbar-rotate-primary .navbar-secondary,
.navbar-rotate-primary .navbar-tertiary {
top: 100%;
-webkit-transition: -webkit-transform 0.5s;
-moz-transition: -moz-transform 0.5s;
transition: transform 0.5s;
-webkit-transform: rotateX(-90deg);
-moz-transform: rotateX(-90deg);
transform: rotateX(-90deg);
}
.navbar-rotate-secondary,
.navbar-rotate-tertiary {
height: 50px;
}
.navbar-rotate-secondary .navbar-primary,
.navbar-rotate-tertiary .navbar-primary {
-webkit-transform: translateY(-100%) rotateX(90deg);
-moz-transform: translateY(-100%) rotateX(90deg);
transform: translateY(-100%) rotateX(90deg);
}
.navbar-rotate-secondary .navbar-secondary,
.navbar-rotate-tertiary .navbar-secondary {
top: 100%;
-webkit-transition: -webkit-transform 0.5s;
-moz-transition: -moz-transform 0.5s;
transition: transform 0.5s;
-webkit-transform: rotateX(0deg) translateY(-100%);
-moz-transform: rotateX(0deg) translateY(-100%);
transform: rotateX(0deg) translateY(-100%);
}
.navbar-rotate-secondary-fallback .navbar-primary,
.navbar-rotate-tertiary-fallback .navbar-primary {
display: none;
}
.navbar-rotate-tertiary .navbar-secondary {
-webkit-transform: translateY(-100%) rotateX(90deg);
-moz-transform: translateY(-100%) rotateX(90deg);
transform: translateY(-100%) rotateX(90deg);
}
.navbar-rotate-tertiary .navbar-tertiary {
top: 100%;
-webkit-transition: -webkit-transform 0.5s;
-moz-transition: -moz-transform 0.5s;
transition: transform 0.5s;
-webkit-transform: rotateX(0deg) translateY(-100%);
-moz-transform: rotateX(0deg) translateY(-100%);
transform: rotateX(0deg) translateY(-100%);
}
<html>
<head>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
</head>
<body>
<nav id="navigation-bottom" class="navbar navbar-fixed-bottom">
<div class="navbar-perspective">
<div class="navbar-primary">
Rotate To Face 2
</div>
<div class="navbar-secondary">
Rotate To Face 3
</div>
<div class="navbar-tertiary">
Rotate Back To Face 1
</div>
</div>
</nav>
</body>
</html>
I've got the first two faces to rotate properly using a 3d effect, but the third face does not look right. You will notice as you rotate from second to third that the top does not rotate correctly and looks flat.
Any help is greatly appreciated.
Fiddle with a flipping box
This is vastly different from where you started, but let me post my CSS and show you the fiddle, and then I'll edit in a longer explanation of how and why this works:
HTML
<section class="container">
<nav id="nav-box" class="show-front">
<div class="front">
Show Bottom
</div>
<div class="bottom">
Show Back</div>
<div class="back">
Show Top</div>
<div class="top">
Show Front</div>
</nav>
</section>
CSS
.container {
position: relative;
perspective: 1000px;
transform: scale(0.95);
}
#nav-box {
width: 100%;
height: 50px;
position: absolute;
transform-origin: center center;
transform-style: preserve-3d;
transition: transform 0.5s;
}
#nav-box div {
width: 100%;
height: 50px;
display: block;
position: absolute;
transition: background-color 0.5s;
}
#nav-box .front { transform: rotateX( 0deg ) translateZ( 25px ); background-color: #ccc; }
#nav-box .back { transform: rotateX( 180deg ) translateZ( 25px ); background-color: #ccc; }
#nav-box .top { transform: rotateX( 90deg ) translateZ( 25px ); background-color: #ccc; }
#nav-box .bottom { transform: rotateX( -90deg ) translateZ( 25px ); background-color: #ccc; }
#nav-box.show-front { transform: rotateY( 0deg ); }
#nav-box.show-front .bottom { background-color: #a0a0a0; }
#nav-box.show-front .top { background-color: #e0e0e0; }
#nav-box.show-back { transform: rotateX( -180deg ); }
#nav-box.show-back .bottom { background-color: #e0e0e0; }
#nav-box.show-back .top { background-color: #a0a0a0; }
#nav-box.show-top { transform: rotateX( -90deg ); }
#nav-box.show-top .front { background-color: #a0a0a0; }
#nav-box.show-top .back { background-color: #e0e0e0; }
#nav-box.show-bottom { transform: rotateX( 90deg ); }
#nav-box.show-bottom .front { background-color: #e0e0e0; }
#nav-box.show-bottom .back { background-color: #a0a0a0; }
Explanation of the HTML/CSS
Setting up our box
You started thinking about this the wrong way, I hate to say. You approached this as "How can I treat these four sides like a box" rather than "How can I make a box in CSS?"
So let's learn how to make a box.
First, we establish a box container. Since this is a navigation box, let's call it nav-box. All the transforms we apply (save for the shading, which we'll get to later) will be done on our nav-box.
The rules on our nav-box will determine how it behaves as an object. Let's discuss two in particular: transform-origin and transform-style
transform-origin defaults to center center, but I wanted to call it out here. This is basically going to tell our box: Hey, we need you to pivot around your absolute center. If we set this up as transform-origin: center bottom' it would look like the box is spinning around its bottom edge. center top` and it would spin around its top edge. I don't think that's what you want, though.
transform-style needs to be set to preserve-3d. What this does is instruct the browser to not fuss with the elements with transform underneath it. Other options include flat which tells the browser to ignore rotates underneath it. The reason we want to set preserve-3d on our nav-box here is to ensure the transforms we applied to the box sides are preserved when we transform the parent. Neat stuff, huh?
Setting up our sides
We're setting our sides as children of our nav-box and just positioning them in the order that they should be in using rotateX:
0 rotation for the front
180deg for the back
-90deg for the bottom
90deg for the top
We could also set a left and right side right now with .left { transform: rotateY(-90deg); } .right { rotateY(90deg); }. Note that we used the Y axis for those two examples.
Secondly, we set a translateZ value of 25px. So what the hell is this doing? It's telling our boxes they need to move 25px from the center of the parent relative to their respective rotations. Why did we choose 25px? Because it's exactly half the height of each of our boxes. This means that it will flush up nicely with the sides at either edge.
And then the fun part:
We shade the boxes based on their position and what is facing the screen. The background colors are relative to what side of the box we're showing with show-front, show-back, etc. The side on the bottom gets darker, the side on the top gets lighter. I just liked that – totally not necessary to accomplish this task but makes it look a little more realistic.
Hope that helps!
Update for IE
Fiddle Example
So, there's not much pretty about this once we get through fixing it up for IE, but here it is. All preserve-3d is doing is applying the transforms for you when we rotate a container, instead of flattening them. If we can't use preserve-3d, we have to calculate based on the amount of total rotation.
This solution does that. I won't go as in-depth on this one, rather than to highlight how much more JavaScript this requires, and to highlight the .rewind class:
#nav-box.rewind div {
backface-visibility: hidden;
}
Because we have to manually rewind this solution, we'll have to prevent the z-index reordering to be applied at the wrong times. That's where backface-visibility comes in.
Example showing depth in IE
Another example without the need for the rewind class
Hope that solves IE for you.
First of all, thank you to all that commented and answered to this question, especially Josh!
Josh, your example works perfectly for browsers that support preserve-3d. The update you posted without preserve-3d appears flat on IE so it was still not perfected for all browsers.
After three days of headaches, I realized the problem. The origin of the sides was not being set correctly. The sides need to rotate around a point that is half way in on the Z axis.
Once I've updated the origin to :
transform-origin: 25px 25px -25px;
Once this was correct, all you really need to do is update the rotation of the object. No need to use any transformation of the X,Y,Z coordinates.
Here's the fiddle and the solution for a 3D Navigation bar that rotates and works for all browsers including IE10+.
http://jsfiddle.net/tx0emcxe/