Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to smoothen transition of width and height?

I have created this animation but it is not smooth. When you hover over the blue circle, a multicolored circle opens up but the opening is shaky, not 100% smooth. Can the animation be smoothened and how?

#container {
  border: 1px solid black;
  width: 600px;
  height: 600px;
  position: relative;
}
#circle {
  margin: 0;
  padding: 0;
  border: 1px solid black;
  width: 50px;
  height: 50px;
  border-radius: 50%;
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  overflow: hidden;
  transition: width 0.2s, height 0.2s;
}
#circle a {
  margin: 0;
  display: block;
  padding: 0;
  width: 250px;
  height: 220px;
  position: absolute;
  top: 50%;
  left: 50%;
  transform-origin: 0 0;
}
#circle a:hover {
  opacity: 0.5;
  cursor: pointer;
}
#trap1 {
  background-color: green;
  transform: rotate(0deg) skewX(30deg);
}
#trap2 {
  background-color: yellow;
  transform: rotate(60deg) skewX(30deg);
}
#trap3 {
  background-color: red;
  transform: rotate(120deg) skewX(30deg);
}
#trap4 {
  background-color: blue;
  transform: rotate(180deg) skewX(30deg);
}
#trap5 {
  background-color: orange;
  transform: rotate(240deg) skewX(30deg);
}
#trap6 {
  background-color: purple;
  transform: rotate(300deg) skewX(30deg);
}
#hide {
  position: absolute;
  top: 50%;
  left: 50%;
  z-index: 1;
  transform: translate(-50%, -50%);
  width: 50px;
  height: 50px;
  border-radius: 50%;
  background-color: cyan;
}
#circle:hover {
  width: 500px;
  height: 500px;
}
<div id="container">
  <div id="circle">
    <div id="hide"></div>
    <a id="trap1"></a>
    <a id="trap2"></a>
    <a id="trap3"></a>
    <a id="trap4"></a>
    <a id="trap5"></a>
    <a id="trap6"></a>
  </div>
</div>
like image 686
Dhruv Chadha Avatar asked Jun 03 '16 17:06

Dhruv Chadha


People also ask

How do I make transitions smoother in CSS?

With CSS3 we can specify how an element changes by just describing its current and target states. CSS3 will create a smooth transition between these states by applying a cubic Bézier curve and gradually change the element appearance.

How do you add height transitions?

For animate the "height" of element with CSS Transitions you need use "max-height". If use the "height: auto", the effect not works. Is necessary some value for the CSS create a CSS animate, and you can use "max-height" with a great value for emulate this effect.

Can you animate width in CSS?

The default width and height CSS properties are (along with most other properties) not suitable for animation. They impact render performance too much because updating them triggers the browser to re-evaluate related element positions and sizes.


1 Answers

Reason: (no links/source to back-up, it is just an educated guess)

I've run into similar a case in the past and what I've managed to find out is that the shake happens due to (I believe) a sub-pixel rendering issue.

When height and width are transitioned, the updates to the element seem to happen pixel by pixel. For example, in the below snippet there are two div elements whose height and width are being transitioned (first one increases by 3px over 5s while second increases by 5px). The key thing to note here is that for the first div there are three visible steps while there are five steps for the second one (meaning they increase pixel by pixel).

div{
  display: inline-block;
  height: 100px;
  width: 100px;
  background: red;
  border: 1px solid;
  margin: 10px;
  transition: all 5s linear;
}
div:nth-child(1):hover{
  height: 103px;
  width: 103px;
}
div:nth-child(2):hover{
  height: 105px;
  width: 105px;
}
<div></div>
<div></div>

Now you would ask me how does this have any connection with the shake. The connection is that the height and width increase pixel by pixel but the translate(-50%, -50%) means that the no. of px by which to translate the element is sometimes in fractions and it seems like some corrections happen during the actual transition to overcome these fractional values.


Solution: (or a work-around)

Instead of using translate(-50%, -50%) trick for horizontal + vertical centering, if we directly position the element by providing the top and left in pixels, you'd see that there is no shake. Based on my understanding, this is because browsers transition all 4 properties (height, width, top and left) pixel by pixel and hence there are no fractional values that cause the correction.

(Tested on the latest Chrome + Windows 10.)

#container {
  border: 1px solid black;
  width: 600px;
  height: 600px;
  position: relative;
}
#circle {
  margin: 0;
  padding: 0;
  border: 1px solid black;
  width: 50px;
  height: 50px;
  border-radius: 50%;
  position: absolute;
  top: 275px;
  left: 275px;
  overflow: hidden;
  transition: all 0.2s;
}
#circle a {
  margin: 0;
  display: block;
  padding: 0;
  width: 250px;
  height: 220px;
  position: absolute;
  top: 50%;
  left: 50%;
  transform-origin: 0 0;
}
#circle a:hover {
  opacity: 0.5;
  cursor: pointer;
}
#trap1 {
  background-color: green;
  transform: rotate(0deg) skewX(30deg);
}
#trap2 {
  background-color: yellow;
  transform: rotate(60deg) skewX(30deg);
}
#trap3 {
  background-color: red;
  transform: rotate(120deg) skewX(30deg);
}
#trap4 {
  background-color: blue;
  transform: rotate(180deg) skewX(30deg);
}
#trap5 {
  background-color: orange;
  transform: rotate(240deg) skewX(30deg);
}
#trap6 {
  background-color: purple;
  transform: rotate(300deg) skewX(30deg);
}
#hide {
  position: absolute;
  top: 50%;
  left: 50%;
  z-index: 1;
  transform: translate(-50%, -50%);
  width: 50px;
  height: 50px;
  border-radius: 50%;
  background-color: cyan;
}
#circle:hover {
  width: 500px;
  height: 500px;
  left: 50px;
  top: 50px;
}
<div id="container">
  <div id="circle">
    <div id="hide"></div>
    <a id="trap1"></a>
    <a id="trap2"></a>
    <a id="trap3"></a>
    <a id="trap4"></a>
    <a id="trap5"></a>
    <a id="trap6"></a>
  </div>
</div>
like image 170
Harry Avatar answered Sep 23 '22 14:09

Harry