Strange animation with transition on transform matrix - css

I'm getting a weird behaviour in my animation when I'm using transition on transform:matrix(). I'm only changing one parameter, but in the transition it looks like it's handling multiple parameters.
Hard to explain, so here's an example:
div {
width: 200px;
height: 400px;
border: 1px solid black;
position: relative;
overflow: hidden;
}
span {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: red;
transform: matrix(1, -.5, 0, 1, 0, 0);
transform-origin: left bottom;
transition: transform .5s ease;
}
div:hover span {
transform: matrix(1, 0, 0, 1, 0, 0);
}
<div>
<span></span>
</div>
External jsbin link
As you can see, it's only supposed to animate the bottom right corner (the top left is animated too, but out of view), but it seems to be doing something strange in the upper left hand corner. Any ideas how to get around this? Is there some trick to transitioning between transform:matrix?

You can use transform: skewY(-28deg); rather than transform: matrix(1,-.5,0,1,0,0); and transform: skewY(0); rather than transform: matrix(1,0,0,1,0,0);
Like I say here
When animating or transitioning transforms, the transform function lists must be interpolated. Two transform functions with the same name and the same number of arguments are interpolated numerically without a former conversion. The calculated value will be of the same transform function type with the same number of arguments.
Special rules apply to rotate3d(), matrix(), matrix3d() and perspective(). The transform functions matrix(), matrix3d() and perspective() get converted into 4x4 matrices first and interpolated. If one of the matrices for interpolation is singular or non-invertible (iff its determinant is 0), the transformed element is not rendered and the used animation function must fall-back to a discrete animation according to the rules of the respective animation specification.
maybe at some point in the transition(you'll have to do the math) appears a singular matrix and the animation function must fall-back to a discrete animation
Here is the full information

What you can do is to increase the scaleX and scaleY then decrease the translateX:
transform: matrix(1.2, 0, 0, 1.2, -30, 0);
DEMO
Trick? I don't think so, but it behaves like using skew in a photo editor (e.g Photoshop).
If you skew an element and then skew it again to bring it back to its original state(by doing it slowly) you may see the same behaviour

Related

CSS Animations: Move elements in flow, if expandable is animated to open state

I am currently building a css transition for an expandable component.
Now I add a scale(Y) transform on the element when opening (scale 0 > 1) or reverse the animation on close:
/*
* Animation: Slide In from Top
*/
.u-slide-from-top-enter-active,
.u-slide-from-top-leave-active {
transition-duration: $s-animation-duration-default;
transition-property: transform, opacity;
transform-origin: top;
overflow: hidden;
}
.u-slide-from-top-enter,
.u-slide-from-top-leave-to {
transform: scaleY(0);
opacity: 0;
}
.u-slide-from-top-enter-to,
.u-slide-from-top-leave {
transform: scaleY(1);
opacity: 1;
}
This works all great, but Now the element below in the flow in the DOM jumps from one position to the other.
I first thought I could animate the height, but this does not work, then I thought I could animate the max-height, but this would not work with a value of max-height: auto.
So my question:
If I open the the expandable, can I somehow add some transition classes to the following elements in the DOM to transition their position (although I don't set a position property explicitely.
I find some help here:
https://css-tricks.com/using-css-transitions-auto-dimensions/
But I don't want to use Javascript. If you see the javascript example you see the wanted behaviour, but I want it to make with css.
Thanks for inputs on that.
Cheers

How "transition-timing-function:cubic-bezier();" property works

Can someone please explain how exactly "transition-timing-function:cubic-bezier();" works please?
Here is my code
.sample_box{
background-color: orange;
height: 70px;
width: 35%;
transition: width 2s;
transition-timing-function: cubic-bezier(0.1,0.1,0.8,3.0);
}
.sample_box:hover{
width: 100%;
}
I've tried to break up the 2 seconds into 4 parts as "cubic-bezier" value but my box went insane, it goes completely out of the screen when hover in both directions
You need a bit of math background to really understand in depth about the cubic-bezier function as this function defines the control points of a cubic-bezier curve. I am not a math expert and so can only clarify the CSS portion of it. If you really need details on how a cubic bezier curve is drawn then wait to see if you get a better answer here (or) try asking on one of the math SE sites whichever is better suited to the question.
A cubic-bezier curve is a curve that is drawn based on four points P0, P1, P2 and P3. Here the points P0 and P3 are the start and end points of the curve whereas P1 and P2 are the control points that go towards defining the curvature of curve.
The four input values that are supplied to the cubic-bezier timing function specify the coordinates of the control points P1 and P2 of the cubic bezier curve (for the curve used by CSS, the points P0 and P3 are always (0,0) and (1,1) respectively). Based on the curve that is drawn (using the input values), the UAs will determine the amount of progress the transition or the animation must have made at any given point in time.
As specified in the W3C Specs, the values for x (parameters 1 and 3) should always be between 0 -1 whereas the values for y (parameters 1 and 4) can exceed this range. Below is the extract:
Both x values must be in the range [0, 1] or the definition is invalid. The y values can exceed this range.
For a live demo of how the curve is drawn based on the input value and how that shows the progress at any given point in time, you can refer to this great page created by Lea Verou. It allows you to alter the values of the control points on the graph, see how the curve changes based on it and also allows you to see a demo of how that curve would work on an actual transition.
The curve that is drawn for cubic-bezier(0.1,0.1,0.8,3.0) would look like this and as you can see it is completely normal that with this curve, the width exceeds 100% before the transition is completed and then comes back down to 100% by the end (as that is the end value). For the hover out, it will be the reverse behavior and so it will go the other way before coming to the end value (for your example, you won't see it because width cannot be lower than 0% but you'll see it in the second one below.)
.sample_box {
background-color: orange;
height: 70px;
width: 35%;
transition: width 2s;
transition-timing-function: cubic-bezier(0.1, 0.1, 0.8, 3.0);
}
.sample_box:hover {
width: 100%;
}
/* just for demo */
div.container {
height: 200px;
width: 300px;
border: 1px solid;
margin: 0px auto;
}
.sample_box_2 {
background-color: tomato;
height: 70px;
width: 35%;
transform: translate(0%, 0%);
transition: transform 2s;
transition-timing-function: cubic-bezier(0.1, 0.1, 0.8, 3.0);
}
.container.second:hover .sample_box_2 {
transform: translate(100%, 100%);
}
<div class='container'>
<div class='sample_box'></div>
</div>
<div class='container second'>
<div class='sample_box_2'></div>
</div>

transform: rotateY() making element disappear

I am trying to apply a simple transform: rotateY(90deg) on an div but it's (the div) disappearing as a result, dev tools is not throwing any error on that line, any suggestions or anything I might be missing?
This happens because when you rotate something on the Y axis by 90 degrees it has spun so that it's essentially facing a different direction. In the below example I've added a transition to show how the element changes over time (hover over it):
figure {
background: red;
height: 100px;
transition: 1s;
width: 100px;
}
div:hover figure {
transform: rotateY(90deg);
}
<div>
<figure></figure>
</div>
As our viewport looks directly onto the element and features no depth, it appears that the element has disappeared altogether.
If we do add some depth, it's easier to visualise what's happening:
The cube on the left is our pre-transform cube and the cube on the right is our cube after it's had rotateY(90deg) applied to it. As we have no depth at all and we're looking at our element front on, we can't see anything when it gets rotated by 90 degrees.

CSS3 Transform only plays first item

I am trying to get my div to rotate 360deg every time I click it, using CSS3 transform rotate. However, I'm also using the CSS3 transform translate to vertically align my div.
On the first click, it applies all the required CSS but doesn't actually rotate, however will rotate all clicks after that. It stays vertically aligned the whole time.
Unsure how to solve this and any help is appreciated :)
My css:
#my-div {
height: 300px;
width: 300px;
transition: all 0.5s ease-in-out;
display: block;
margin: auto;
/*to vertically align*/
position: relative;
top: 50%;
-webkit-transform: translateY(-50%);
transform: translateY(-50%);
}
My javascript
var angle = 360
$('#my-div').click(function() {
$(this).css({
'-webkit-transform' : 'translateY(-50%) rotate('+angle+'deg) ',
'transform' : 'translateY(-50%) rotate('+angle+'deg)'
})
angle += 360
});
In fact the transition works properly only when the 2 ends are explicitly set, here intially the rotate transform is not set explicitly, after the first click, it's explicitly set to rotate(360deg) and hence the next clicks work. To solve this, you just need to apply rotate(0deg) for your div initially via the CSS code:
#my-div {
/*...*/
-webkit-transform: translateY(-50%) rotate(0deg);
transform: translateY(-50%) rotate(0deg);
}
Note that I emphasized on the properly word, in fact if you set the initial angle to some angle equal or smaller than 180deg, you'll see it transitions OK. I doubt that if you don't set the initial rotate transform explicitly, the behavior is determined by the browser, that is 360deg won't make any transition, otherwise the rotating transition may be clockwise (if the angle % 360 is less than or equal to 180deg) and counter-clockwise if the angle % 360 is greater than 180deg (note about the modulo operation between angle and 360).
Demo.

Convert transition to a transform for better performance

I'm in the process of implementing a 'drawer' type effect where the drawer opens from the bottom of the screen when a button is clicked. Example here: http://jsfiddle.net/jYcSF/
Im using CSS translate to do this:
.drawer {
position: absolute;
bottom: 0;
left: 0;
right: 0;
overflow: hidden;
background: #333;
height: 5px;
width: 100%;
-webkit-transition: height .25s linear;
-moz-transition: height .25s linear;
transition: height .25s linear;
}
Then I use jQuery to toggle a class on the drawer when the button is clicked:
$('.drawer-open').click(function(e){
$('.drawer').toggleClass('active');
});
$('.drawer-close').click(function(e){
$('.drawer').toggleClass('active');
});
This then allows the .active drawer CSS to take effect and animate the height of the drawer and make it open from the bottom of the screen:
.drawer.active {
height: 80%;
}
Is it possible to achieve the same effect using CSS transforms rather than transition? I'm trying to ensure the drawer opening is as smooth and jank free as possible.
Simple answer..
No
Its important to understand the reasons and differences behind these CS properties:
Transform
The CSS transform property lets you modify the coordinate space of the
CSS visual formatting model. Using it, elements can be translated,
rotated, scaled, and skewed according to the values set.
Transition
[...] It allows to define the transition between two states of an element.
In this instance, transform is not a suitable solution, because you are modifying a property (height) instead of the coordinate representation of the element in a 3d space. If you were to use transform the closest you could do would be scaleY and give it a rough value, you would also need to set the origin to a y value of 100% - however what you will notice is that though the element will grow, its contents will be stretched because you have transformed it on the 3d plane, not changed its underlying definitions from a property perspective.
Example Fiddle

Resources