Created
December 4, 2012 16:50
-
-
Save desandro/4206095 to your computer and use it in GitHub Desktop.
Use CSS transitions to scroll to element
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
( 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