Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

css, reverse transition on different class

When the width of the element grows I want my animation to start off by shrinking and stopping instantly when it's big. When it's big I want to start instantly and shrink a little further than the end state. When the element enters the page however, the element starts below the page until it's in the center.

I started with cubic-bezier(0.4, -0.5, 1,1); as timing function to have to grow effect. However I'm failing to meet the conditions I stated above.

jsfiddle

let big = document.getElementById('big')
let cube  = document.getElementById('cube')

big.addEventListener("click", t)

function t (){
 let isBig = cube.classList.contains('big')
 if(isBig){
  cube.classList.remove("big")
  cube.classList.add("small")
	big.innerText =  "Make big" 
 }
 else{
 		cube.classList.remove("small")
  	cube.classList.add("big")
		big.innerText =  "Make small" 
 }
}
.ctnr{
  width: 100%;
  height: 100vh;
  display: flex;
  justify-content: center;
  align-items: center;
  overflow:hidden;
}
.cube{
  height: 10rem;
  margin-bottom: 0;
  transition: width 1s;
  transition-timing-function: cubic-bezier(0.4, -0.5, 1,1); 
  animation-name: incomming;
  animation-duration: 0.7s;
}

.big{
  width: 20rem;
  background:orange;
}
.small{
  width: 10rem;
  background:deeppink;

}

@keyframes incomming {
  0%{
    margin-bottom:-100%;
  }
  100%{
    margin-bottom: 0;
  }
}
<button id="big">
Make big
</button>
<div class="ctnr">
  <div id="cube" class="cube small">

  </div>
</div>
like image 669
Ced Avatar asked May 19 '26 03:05

Ced


1 Answers

Your animation description is a bit unclear (at least for me) but from what I understand it should be either:

.cube{
  transition-timing-function: cubic-bezier(.84,0,.63,1.42);
}
.big.cube {
  transition-timing-function: cubic-bezier(.35,-.35,.48,.84);  
}

let big = document.getElementById('big')
let cube  = document.getElementById('cube')

big.addEventListener("click", t)

function t (){
 let isBig = cube.classList.contains('big')
 if(isBig){
  cube.classList.remove("big")
  cube.classList.add("small")
	big.innerText =  "Make big" 
 }
 else{
 		cube.classList.remove("small")
  	cube.classList.add("big")
		big.innerText =  "Make small" 
 }
}
.ctnr{
  width: 100%;
  height: 100vh;
  display: flex;
  justify-content: center;
  align-items: center;
  overflow:hidden;
}
.cube{
  height: 10rem;
  margin-bottom: 0;
  transition: width 1s;
  transition-timing-function: cubic-bezier(.84,0,.63,1.42);
  animation-name: incomming;
  animation-duration: 2s;
}

.big{
  width: 20rem;
  background:orange;
}
.big.cube {
  transition-timing-function: cubic-bezier(.35,-.35,.48,.84);  
}
.small{
  width: 10rem;
  background:deeppink;
}

@keyframes incomming {
  0%{
    margin-bottom:-100%;
  }
  100%{
    margin-bottom: 0;
  }
}
<button id="big">
Make big
</button>
<div class="ctnr">
  <div id="cube" class="cube small">

  </div>
</div>

... or:

.cube{
  transition-timing-function: cubic-bezier(.84,0,.63,1.42);
}
.big.cube {
  transition-timing-function: cubic-bezier(.35,-.35,.84,.48);  
}

let big = document.getElementById('big')
let cube  = document.getElementById('cube')

big.addEventListener("click", t)

function t (){
 let isBig = cube.classList.contains('big')
 if(isBig){
  cube.classList.remove("big")
  cube.classList.add("small")
	big.innerText =  "Make big" 
 }
 else{
 		cube.classList.remove("small")
  	cube.classList.add("big")
		big.innerText =  "Make small" 
 }
}
.ctnr{
  width: 100%;
  height: 100vh;
  display: flex;
  justify-content: center;
  align-items: center;
  overflow:hidden;
}
.cube{
  height: 10rem;
  margin-bottom: 0;
  transition: width 1s;
  transition-timing-function: cubic-bezier(0.84, 0, 0.63, 1.42);
  animation-name: incomming;
  animation-duration: 2s;
}

.big{
  width: 20rem;
  background:orange;
}
.big.cube {
  transition-timing-function: cubic-bezier(.35,-.35,.84,.48);  
}
.small{
  width: 10rem;
  background:deeppink;
}

@keyframes incomming {
  0%{
    margin-bottom:-100%;
  }
  100%{
    margin-bottom: 0;
  }
}
<button id="big">
Make big
</button>
<div class="ctnr">
  <div id="cube" class="cube small">

  </div>
</div>

Let me know if I got it right or if you want it modified. If none is correct, perhaps you could use some of these terms so I could understand it better:

  • ease-in: gradual acceleration
  • ease-out: gradual deceleration
  • ease-in-out (a.k.a. easy ease): both of the above (slow start and end with fast middle)
  • spring (a.k.a. anticipation/overlap) to go over the value in an elastic way in order to start in opposite direction (anticipation) or to stop from the opposite direction (overlap)

Note: Probably going through the 12 animation principles defined by Disney might help you better describe the effect you are after.

Tooling: I needed to make sense of cubic-bezier() when there were no proper tools for it, at least from my perspective and compared to now. That drastically changed when Chrome added a real time visualization tool to their developer console. Open the console on any element in Chrome and click the tiny square symbol next to the cubic-bezier() set on that element. And drag the dot segments around to change the bezier function.
Congratulations! You're now officially a cubic-bezier() expert.

like image 108
tao Avatar answered May 20 '26 19:05

tao