Convert transition to a transform for better performance - css

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

Related

How to show transitionDuration in css animation?

Fiddle A:
I have a gallery of images (there are 4 right now) as shown here in this JSFiddle (lets call as Fiddle A)
in which every single image fades out after 3s second and there is transition delay of 800ms.
I have used JS to make the animation work. In JS, I have used the following constants in my JS.
transitionDuration => is the delay (white flash which we see) which happens on moving from one image to another.
transitionDelay => is the presenation time of an image (meaning the time span for which the image stay at their place).
totalDelay => is only for one image.
Fiddle B:
I also have another gallery of images as shown in this JSFiddle (let's call as Fiddle B) in which a CSS animation is going on.
Presentation time of one image in the fiddle is 3 seconds, and then it moves to another images.
Problem Statement:
I am wondering what changes I need to make in Fiddle B so that it looks like Fiddle A. In Fiddle B there is no transitionDuration. Is there a way we can add a transitionDuration (white flash which we can
see on moving from one image to another)?
In Fiddle B, I have used the following CSS:
a:nth-of-type(4), .featured-block a:nth-of-type(5), .featured-block a:nth-of-type(6) {
position: absolute;
animation: 9s infinite ease-in-out cf4FadeInOut;
opacity: 0;
z-index:1;
}
Adjusting opacity in keyframes to achieve transition duration works, which you have implemented.
Remove opacity: 1 and opacity: 0 so that it becomes
.featured-block a { display: inline-block; }
a:nth-of-type(4), .featured-block a:nth-of-type(5), .featured-block a:nth-of-type(6) {
position: absolute;
animation: 3s infinite ease-in-out cf4FadeInOut;
z-index:1;
}

Can divs below a css transform move along with divs above?

I am using css transitions to lay out a bunch of divs on top of each other. At any point, one of the divs may collapse. And all of the divs below it are supposed to move up to fill its spot.
Here is a codepen that describes the situation.
The css I am using is the following:
div {
height: 100px;
width: 100px;
margin: 15px;
}
.top {
background-color: red;
transform-origin: top;
animation: move 2s infinite;
}
.bottom {
background-color: blue;
}
#keyframes move {
0% {
transform: rotateX(0deg);
}
50% {
transform: rotateX(90deg);
}
}
With this, the top div will expand and contract. I want the divs below it to move up as the top one collapses.
If I switch transform for height, like this:
#keyframes move {
0% {
height 0;
}
50% {
height: 100px;
}
}
The bottom divs do move, but this is not a good solution for me because in the actual application, each div has a dynamically calculated size.
How can the bottom divs move smoothly with the top div?
With transform you won't be able to do that, as when an element is transformed, the surrounding elements won't see any change in the DOM, as DOM-wise nothing have happened.
What you can do to optimize it all, is to prepare the browser that the height will change, with the property will-change: height
MDN: https://developer.mozilla.org/en-US/docs/Web/CSS/will-change
This new CSS property aim's to do what transform does, make smoother and more optimized animations.
Do note though:
will-change is intended to be used as a last resort, in
order to try to deal with existing performance problems. It should not
be used to anticipate performance problems.
Another possible solution (read hack), is to trick the browser to use GPU instead of CPU, shown in this answer (see its p.1):
CSS `will-change` - how to use it, how it works
Updated
In case of the height is auto, or similar, this will work with the max-height trick, and here is a couple of answers of mine, showing how-to:
CSS Animation on max-height change
Can't use the same animation in reverse for class toggle
CSS transition auto width
And the last resort, if none of the above is applicable, is to use a small script and either create a styles dynamically (links below), or set them inline.
Dynamically styling pseudo-elements using jQuery or Javascript
How to prevent css from getting converted to inline css

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

-webkit-appearance forcing transitions?

Given a basic HTML template and CSS style, I'm seeing two different elements react completely different.
setTimeout(function() {
document.body.id = 'animate';
}, 100);
#animate input[type="checkbox"]{
width: 100px;
height: 100px;
transition: 2s all;
-moz-appearance: none;
}
#animate div{
width: 100px;
height: 100px;
background:blue;
transition: 2s all;
}
<input type="checkbox"/>
<div></div>
If you open this in a browser, you see that, on load, the div already has its 100px height/width, yet the checkbox grows from 0px to 100px height/width over 2s.
Why does the input behave differently than the div? Is it because the input has default -webkit-appearance giving it something to transition between?
The div's default width/height is auto and as such it won't animate.
The input has a default width/height and as such will animate.
As a side note, the transition does work on the div, though only animate its color, as it is possible to animate a color from transparent to blue
You should also consider to not use all with transition, as it can give unpredictalbe result because of this fact that browsers does set some values on elements to a default value, where some can be animated, some can't.
So, in your case, if your intention is to animate width/height, set it up like this: transiton: width 2s ease, height 2s ease;
The answer is simple. The input's style has a pre-loaded values in the DOM, that's why just right after appearing in the document, smoothly changes his shape.
Quite contrary with the div element. The div hasn't any pre-loaded, default values in the DOM before setting them by the user. That's why it appears in the document with already set size.
Important note
If you want the transition to work, it has to have a set, starting, default value and ending value. The animation will occur between these two values. The input has already set the default value of the size, that's why the animation will occur.
You may ask, so why the background transition is working? It works, since the default value of background is transparent.
setTimeout(function() {
$('.xx').addClass('x');
}, 500);
* {
margin: 0;
padding: 0;
border: 0;
}
input[type="checkbox"] {} div {} .x {
width: 100px;
height: 100px;
transition: all 2s ease;
background: blue;
}
.container {
display: flex;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class='container'>
<input type='checkbox'>
<div class='xx'></div>
<input class='xx' type="checkbox">
</div>
Short answer without being to technical. CSS transition's will do it's job when there is a previous state to start animate from.
A default div doesn't have any styling by default.
An input element is always pre-styled in the browser itself.
Here is a fiddle that can be used to re-create the behaviour that the OP mentioned. It simulate external loading with a simply JS delay. https://jsfiddle.net/xvt359ju/1/
Nevermind, 2 other answers was faster than me.
Browsers have their own basic CSS styling of elements, the checkbox too have it. When you inspect the element you can see width and height to the checkbox applied by the browser, that will be overridden when your external stylesheets loads. And animating it as you have given transition to it.

Overlapping image caught behind next image

I'm sure this is a pretty simple one but can't find the specific answer I'm looking for elsewhere.
Basically, I have a series of side by side images set out in a responsive grid layout. As you hover over each image it zooms and scales the image bigger so it looks like it's coming out towards you.
However, the issues I have is that the later image always overlaps the prior image. I have tried setting all the divs containing the image to the same z-index but to no avail.
I have setup a js.fiddle which demonstrates the issue. I'm hoping to solve with purely CSS.
JSfiddle link http://jsfiddle.net/Aloha_Design_Co/46poxw9j/
Any ideas would be most appreciated.
Thanks,
Heath
Simply, give more z-index in .photo-content:hover.
.photo-content:hover {
background-size: 120%;
/* in conjuction with the transition below it zooms in on the background image - doesn't change box size in itself; */
-webkit-transition: all 0.5s linear;
-moz-transition: all 0.5s linear;
transition: all 0.5s linear;
transform: scale(1.2);
/* expands the box to look like it is 3D coming out of page */
/* Add z-index */
z-index: 10;
}
Jsfiddle

Resources