CSS: aspect ratio animation

Inspired by https://twitter.com/ryanseddon/status/1026321377228349440

by Julien Roche

HTML

<h1>Natural ratio</h1>
<img class="ratio-image" src="https://images.pexels.com/photos/289225/pexels-photo-289225.jpeg?auto=compress&cs=tinysrgb&h=650&w=940" />

CSS

:root {
  --animation-duration: 2s;
  --ratio-width: 100vw;
  --ratio-height-16-9: calc(var(--ratio-width) * 9 / 16);
  --ratio-height-21-9: calc(var(--ratio-width) * 9 / 21);
  --ratio-height-4-3: calc(var(--ratio-width) * 3 / 4);
}

html,
body {
  border: none;
  margin: 0 0 0 0;
  padding: 0 0 0 0;
}

img {
  height: 539px;
  width: 940px;
  transition-delay: 0s;
  transition-duration: var(--animation-duration);
  transition-property: all;
  transition-timing-function: ease;
}

.ratio-image--none {
  height: 539px;
  width: 940px;
}

.ratio-image--21-9 {
  height: var(--ratio-height-21-9);
  width: var(--ratio-width);
}

.ratio-image--16-9 {
  height: var(--ratio-height-16-9);
  width: var(--ratio-width);
}

.ratio-image--4-3 {
  height: var(--ratio-height-4-3);
  width: var(--ratio-width);
}

Babel + JSX

const imageElement = document.querySelector('img');
const durationTime = 2000;
const ratios = [
	'ratio-image--none',
  'ratio-image--21-9',
  'ratio-image--16-9',
  'ratio-image--4-3'
];
let index = 1;

function debounce (fn, time) {
  let timeout;

  return function() {
    const functionCall = () => fn.apply(this, arguments);
    
    clearTimeout(timeout);
    timeout = setTimeout(functionCall, time);
  }
}

function changeImageRatio() {
	console.info('apply', ratios[index]);
  imageElement.classList.value = ratios[index];
  index++;
  
  if (index > ratios.length) {
  	index = 0;
  }
}

imageElement.addEventListener('transitionend', debounce(changeImageRatio, 150), false);
changeImageRatio();