Motion/Emotion

Follow along at bit.ly/motion-preso

Use ← → keys to advance

About me, David DeSandro

Undulate demo

Attaining delightenment

CSS3 transforms and transitions

Presentation items

This presentation site uses transforms and transitions to reveal next item

Use JS to toggle on and off .hidden

.preso-item {
  -webkit-transition: -webkit-transform 0.4s, opacity 0.4s;
     -moz-transition:    -moz-transform 0.4s, opacity 0.4s;
       -o-transition:      -o-transform 0.4s, opacity 0.4s;
          transition:         transform 0.4s, opacity 0.4s;
  -webkit-transform-origin: left top;
     -moz-transform-origin: left top;
       -o-transform-origin: left top;
          transform-origin: left top;
}

.preso-item.hidden {
  opacity: 0;
  pointer-events: none;
  -webkit-transform: scale(2);
     -moz-transform: scale(2);
       -o-transform: scale(2);
          transform: scale(2);
}

(See dropshado.ws: CSS formatting for more details on code styles)

Transitioning background color

Use JS to change class on body every 5 seconds: color0, color1, color2

var colorT = 0;

function changeColor() {
  document.body.className = 'color' + colorT % 18;
  colorT++;
  setTimeout( changeColor, 5000 )
}

changeColor();

Add background color CSS

body.color0  { background-color: hsl(    0, 40%, 35% ); }
body.color1  { background-color: hsl(  100, 40%, 35% ); }
body.color2  { background-color: hsl(  200, 40%, 35% ); }
body.color3  { background-color: hsl(  300, 40%, 35% ); }
body.color4  { background-color: hsl(  400, 40%, 35% ); }
...

Linear transition gives the appearance that color is smoothly changing

body {
  -webkit-transition: background-color 5s linear;
     -moz-transition: background-color 5s linear;
       -o-transition: background-color 5s linear;
          transition: background-color 5s linear;
}

See this effect in action on metafizzy.co

Advantages

WebKit hardware acceleration

Thinking big - Isotope

Fallback progression

Layout effects

Hardware accelerated CSS transforms

.hide {
  transform: translate3d( 10px, 20px, 0 ) scale3d( 0.01, 0.01, 0);
  opacity: 0;
}

CSS transforms

.hide {
  transform: translate( 10px, 20px ) scale( 0.01 );
  opacity: 0;
}

Absolute positioning

.hide {
  left: 10px;
  top: 20px;
  opacity: 0;
}

Animation

How will the changing styles be applied

  1. CSS transitions - Firefox 4.0+, Safari, Chrome, Opera 11+
  2. jQuery animation Firefox 3.6-, IE9
  3. No animation - IE6, IE7

Demo

$(function() {

      // i.e. WebkitTransform or MozTransform
  var transformProperty = Modernizr.prefixed('transform'),
      getPosition;
  
  if ( Modernizr.csstransforms3d ) {
    // returns i.e. { WebkitTransform: translate3d( 10px, 20px, 0 ) }
    getPosition = function( x, y ) {
      var style = {};
      style[ transformProperty ] = 'translate3d(' + x + 'px, ' + y + 'px, 0)';
      return style;
    }
  }
  else if ( Modernizr.csstransforms ) {
    // returns i.e. { WebkitTransform: translate( 10px, 20px ) }
    getPosition = function( x, y ) {
      var style = {};
      style[ transformProperty ] = 'translate(' + x + 'px, ' + y + 'px)';
      return style;
    }
  }
  else {
    // returns i.e. { left: 10, top: 20 }
    getPosition = function( x, y ) {
      var style = {
        left: x,
        top: y
      };
      return style;
    }
  }

  var $dot = $('#dot'),
      // use jQuery animation only if no transitions or transforms
      applyStyle = Modernizr.csstransitions && Modernizr.csstransforms  ? 'css' : 'animate';

  $(document).click( function(event) {
    var position = getPosition( event.pageX-15, event.pageY-15 );
    $dot[ applyStyle ]( position );
  });

});

Value of animation

If you didn’t have the animation it would not be easy to see which items had risen and which fallen. You would have to compare your memory of the order before the change with what you’re looking at. This is cognitively very difficult.

JonnieCache on Hacker News, in response to Isotope

More than just icing

How it was done

window.addEventListener( 'load', function() {
  var box = document.getElementById('box'),
      docHeight = document.documentElement.offsetHeight;
  
  window.addEventListener( 'scroll', function() {
        // normalize scroll position as percentage
    var scrolled = window.scrollY / ( docHeight - window.innerHeight ),
        transformValue = 'scale(' + (1-scrolled) + ')';

    box.style.WebkitTransform = transformValue;
    box.style.MozTransform = transformValue;
    box.style.OTransform = transformValue;
    box.style.transform = transformValue;
    
  }, false);
  
}, false);

More technical details in 2011.beercamp.com/colophon and ZUI Site Riot

More complexity

Transitions

document.getElementById('nav').addEventListener( 'click', function(event) {
  var level = parseInt( event.target.getAttribute('href').slice(1), 10 ),
      // normalize scroll position
      scrollY = ( level / 4 ) * ( docHeight - window.innerHeight );
  // enable transitions
  box.className = 'transitions-enabled';
  // change scroll position
  window.scrollTo( 0, scrollY );
}, false);

function transitionEnded(event) {
  // disable transition
  box.className = '';
}

box.addEventListener( 'webkitTransitionEnd', transitionEnded, false);
box.addEventListener( 'transitionend', transitionEnded, false);
box.addEventListener( 'oTransitionEnd', transitionEnded, false);

More details in ZUI Site Riot - transitions

Pitfalls and issues

Poor font rendering

CSS transforms trigger poor anti-aliasing in Opera. See dropshado.ws: Opera Transform Issues

Hardware acceleration in WebKit messes with font anti-aliasing. See dropshado.ws: Resolving anti-aliasing on WebKit hardware-accelerated elements

Hardware accelerated, no background:

with opaque background

Adding a background:

with opaque background

CSS transforms break Flash content

Safari and Firefox don’t properly render Flash content inside elements with CSS transforms. See dropshado.ws: CSS transforms breaking flash

Ugly keyframes

@-webkit-keyframes open-1 {
  from { opacity:0; -webkit-transform:translate3d( 210px, -145px, 0); }
  25%  { opacity:1; -webkit-transform:translate3d( -15.6px, 4.1px, 0); }
  30%  { opacity:1; -webkit-transform:translate3d( -10.3px, 2.7px, 0); }
  35%  { opacity:1; -webkit-transform:translate3d( 0, 0, 0); }
  40%  { opacity:1; -webkit-transform:translate3d( 4.5px, -1.2px, 0); }
  45%  { opacity:1; -webkit-transform:translate3d( 2.9px, -0.8px, 0); }
  50%  { opacity:1; -webkit-transform:translate3d( 0, 0, 0); }
  55%  { opacity:1; -webkit-transform:translate3d( -1.3px, 0.3px, 0); }
  60%  { opacity:1; -webkit-transform:translate3d( -0.8px, 0.2px, 0); }
  65%  { opacity:1; -webkit-transform:translate3d( 0, 0, 0); }
  70%  { opacity:1; -webkit-transform:translate3d( 0.4px, -0.1px, 0); }
  75%  { opacity:1; -webkit-transform:translate3d( 0.2px, -0.1px, 0); }
  80%  { opacity:1; -webkit-transform:translate3d( 0, 0, 0); }
  85%  { opacity:1; -webkit-transform:translate3d( -0.1px, 0, 0); }
  90%  { opacity:1; -webkit-transform:translate3d( -0.1px, 0, 0); }
  to   { opacity:1; -webkit-transform:translate3d( 0, 0, 0); }
}

There are even better animations on the Mac subsection, all springy and bouncy and whatnot.

While it’s pleasing to the eye and fun to use, implementing this is less fun:

— Thomas Fuchs, CSS animation transition-timing-functions and why they are not enough

Avoid Rube Goldberg contraptions

Motion/Emotion

We’re still learning how to use motion to say something

But that’s exactly what we’re doing with CSS3 and JavaScript: we’re moving elements, not animating them. We’re constantly specifying beginning and end states and allowing the technology to interpolate between the two. And yet, it’s the nuances within those middle frames that create the sense of life we’re looking for.

— Dan Mall, Real Animation Using JavaScript, CSS3, and HTML5 Video

Thank you!