Skip to content

Instantly share code, notes, and snippets.

@desandro
Created December 4, 2012 16:50
Show Gist options
  • Save desandro/4206095 to your computer and use it in GitHub Desktop.
Save desandro/4206095 to your computer and use it in GitHub Desktop.
Use CSS transitions to scroll to element
( function( window, undefined ) {
'use strict';
// helper function
function capitalize( str ) {
return str.charAt(0).toUpperCase() + str.slice(1);
}
// ========================= getStyleProperty by kangax ===============================
// http://perfectionkills.com/feature-testing-css-properties/
var prefixes = 'Moz Webkit O Ms'.split(' ');
function getStyleProperty( propName ) {
var style = document.documentElement.style,
prefixed;
// test standard property first
if ( typeof style[propName] === 'string' ) {
return propName;
}
// capitalize
propName = capitalize( propName );
// test vendor specific properties
for ( var i=0, len = prefixes.length; i < len; i++ ) {
prefixed = prefixes[i] + propName;
if ( typeof style[ prefixed ] === 'string' ) {
return prefixed;
}
}
}
var transformProp = getStyleProperty('transform');
var transitionProp = getStyleProperty('transition');
var cssTransformProp = {
WebkitTransform: '-webkit-transform',
MozTransform: '-moz-transform',
MsTransform: '-ms-transform',
OTransform: '-o-transform',
transform: 'transform'
}[ transformProp ];
var transitionEndEvent = {
WebkitTransition: 'webkitTransitionEnd',
MozTransition: 'transitionend',
OTransition: 'otransitionend',
transition: 'transitionend'
}[ transitionProp ];
// console.log( transformProp, transitionProp );
function transitionScrollTo( options ) {
var opts = {};
// get options from defaults
for ( var prop in transitionScrollTo.defaults ) {
opts[ prop ] = transitionScrollTo.defaults[ prop ];
}
// overwrite with argument options
for ( prop in options ) {
opts[ prop ] = options[ prop ];
}
var elem = opts.element;
// enable transition
elem.style[ transitionProp + 'Property' ] = cssTransformProp;
elem.style[ transitionProp + 'Duration' ] = opts.duration;
// no more than scrolling to the bottom
var targetX = Math.min( opts.x, elem.clientWidth - window.innerWidth );
var targetY = Math.min( opts.y, elem.clientHeight - window.innerHeight );
// no less than top left corner
targetX = Math.max( targetX, 0 );
targetY = Math.max( targetY, 0 );
// account for current scroll position
targetX -= window.scrollX;
targetY -= window.scrollY;
elem.style[ transformProp ] = 'translate( ' + -targetX + 'px, ' + -targetY + 'px)';
var onTransitionEnd = function( event ) {
// disregard transition end on child elements
if ( event.target !== elem ) {
return;
}
// clean up transform and transition styles
elem.style[ transformProp ] = null;
elem.style[ transitionProp + 'Duration' ] = null;
elem.style[ transitionProp + 'Property' ] = null;
// apply scroll to window
window.scrollTo( opts.x, opts.y );
// remove listener
elem.removeEventListener( transitionEndEvent, onTransitionEnd, false );
};
elem.addEventListener( transitionEndEvent, onTransitionEnd, false );
}
transitionScrollTo.defaults = {
element: document.body,
x: 0,
y: 0,
duration: '0.4s'
};
window.transitionScrollTo = transitionScrollTo;
})( window );
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment