Reputation: 83
How do I make this the transition between classes smooth instead of the shaking effect that you see here: http://codepen.io/Cogarius/pen/tfhgx
The box shakes severely because of the differences in widths and heights along with changes to the border size which the classes are transitioning.
HTML:
<div class="outer">
<div class="original"></div>
</div>
CSS:
.original {
float: left;
height: 0;
width: 0;
background: #ffffff;
border: 150px solid #000000;
margin: 0px;
}
.changed {
float: left;
height: 296px;
width: 296px;
border: 2px solid #ff3333;
background: #ffffff;
margin: 0px;
}
jQuery
$(document).ready(function(){
$('.original').on('click', function(){
$(this).toggleClass( "changed", 500, "easeOutQuad" );
});
});
Upvotes: 3
Views: 235
Reputation: 66218
There are several ways you can approach this problem (and the good news is, they are all jitter free :D )
One trick is to use box shadows to your advantage. For the rest state, you ensure that the box shadow (inset) fills up the entire dimension of your box. For the toggled state, you collapse the box shadow by reducing its spread radius, and also by changing its colour. CodePen Demo
.original {
height: 300px;
width: 300px;
background: #fff;
box-shadow: inset 0 0 0 150px #000000;
position: relative;
transition: all .5s ease-in-out;
}
.changed {
box-shadow: inset 0 0 0 2px #ff3333;
}
One caveat: You need to specify the spread radius (fourth number) in pixel values... so if you are using a responsive element, this might be an issue.
Another issue I can foresee is that since the spread radius has to be in pixel values, it might still show jittering as slow transition speeds. For a entirely jitter-free transition, I can only recommend taking advantage of CSS3 2D transforms, which we will need to use pseudo-elements (see next solution).
This trick is to use a pseudo-element, e.g. ::before
, on the container and then scale it when the classes are toggled. Under all states, the container has a black background with a 2px black border. The pseudo-element is absolutely positioned in the center and fills the width and height of its parents, but at rest state it is scaled to 0 (i.e. no size). At the toggled state we de-scale it back to its original dimensions. CodePen Demo
.original {
box-sizing: border-box;
height: 300px;
width: 300px;
background:#000;
border: 2px solid #000;
position: relative;
transition: all .5s ease-in-out;
&::before {
background-color: #fff;
content: '';
position: absolute;
width: 100%;
height: 100%;
transition: all .5s ease-in-out;
transform: scale(0);
}
}
.changed {
background-color: #ff3333;
border-color: #ff3333;
&::before {
background-color: #fff;
transform: scale(1);
}
}
Note that I have used:
box-sizing
property, so the width declared is the final dimensionsUpvotes: 2
Reputation: 157
Changing the width
and height
values cause this situation. If you want a smooth transition, then you need to use a hardware accelerated css transform, like scale
, translateX
, translateY
etc.
Here is a more descriptive article about that.
Upvotes: 0
Reputation: 128796
You can replace your current transition with CSS. Simply add a transition
property to your .changed
selector:
.changed {
...
transition: 0.5s; /* Equal to 500ms */
}
The shakiness is still there, but it's less prominent than it was when handled through jQuery.
Upvotes: 1