<div id="container">
  <div id="expo">
    <img src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/106114/zoom-15.jpg" />
    <div class="label">ExpoScaleEase</div>

  <div id="linear">
    <img src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/106114/zoom-15.jpg" />
    <div class="label">Linear easing</div>

<link href='//fonts.googleapis.com/css?family=Signika+Negative:300,400' rel='stylesheet' type='text/css'>
body {
  margin: 0;
  padding: 0;
  background-color: black;
#expo {
  /*display: none;*/
#container {
  display: flex;
  min-height: 100vh;
#expo, #linear {
  flex-grow: 1;
  overflow: hidden;
  position: relative;
  color: white;
  font-size: 3em;
#linear {
  border-left: 2px solid white;
img {
  position: absolute;
  top: 50%;
  left: 50%;
  min-width: 100%;
.label {
  position: relative;
  top: 0px;
  text-align: center;
  font-family: "Signika Negative", sans-serif;
  background-color: rgba(0,0,0,0.5);
TweenLite.set("img", {yPercent:-50, xPercent:-50, top:"50%", left:"50%", minWidth:"100%", position:"absolute"});

//linear easing doesn't APPEAR linear (visually).
TweenMax.fromTo("#linear img", 10, {scale:0.1}, {scale:8, ease:Linear.easeNone, repeat:-1});

//notice how we feed in the starting and ending [scale] values to ExpoScaleEase.config() so that it can adjust its curve accordingly so that scaling appears linear visually even though technically the scale values aren't animating linearly at all. 
TweenMax.fromTo("#expo img",   10, {scale:0.1}, {scale:8, ease:ExpoScaleEase.config(0.1, 8), repeat:-1});

//for a more complicated example that shows multi-step zooming 
//(swapping new images for better resolution as it progresses), 
//see https://codepen.io/GreenSock/pen/NyXBbV?editors=0010

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

  1. https://cdnjs.cloudflare.com/ajax/libs/gsap/1.20.4/TweenMax.min.js