It's hard to say without seeing the actual code, but check out this fiddle and see if it helps anything:
http://jsfiddle.net/fxyuzo6z/4/
Basically, I removed the impulse animation that you ran on each focus event to be biased until there is a significant delay between keystrokes. This provides more resources for other animations that the browser should render, hope you clear the stutter / jank you notice. Timeout delay can be adjusted to your needs.
CSS
.focused { -webkit-box-shadow: inset 0px 0px 0px 3px rgba(255,255,255,1); -moz-box-shadow: inset 0px 0px 0px 3px rgba(255,255,255,1); box-shadow: inset 0px 0px 0px 3px rgba(255,255,255,1); } .focused.animate { -webkit-animation: pulse 1.8s infinite ease-in-out; -moz-animation: pulse 1.8s infinite ease-in-out; animation: pulse 1.8s infinite ease-in-out; }
JS:
var pool = document.querySelectorAll('.item-row') , container = document.getElementById('item-container') , containerBox = container.getBoundingClientRect() , focused = pool[0] , focusIndex = 0 , KEYS = {up: 38, down: 40} , keypressTimer = null; window.addEventListener('keyup', function(e) { if (e.keyCode === KEYS.up && focusIndex !== 0) { focusIndex--; setFocus() } else if (e.keyCode === KEYS.down && focusIndex !== pool.length - 1) { focusIndex++; setFocus() } }); function setFocus() { clearTimeout(focused); focused.classList.remove('animate'); focused.classList.remove('focused'); focused = pool[focusIndex]; focused.classList.add('focused'); scroll(); keypressTimer = setTimeout(function() { focused.classList.add('animate'); }, 1000); } function scroll() { var focusedBox = focused.getBoundingClientRect(); if (focusedBox.bottom > containerBox.bottom || focusedBox.top < containerBox.top) { requestAnimationFrame(function() { var distance = focusedBox.height + 12; animate(distance, focusedBox.top < containerBox.top, 20); }); } } function animate(distance, up, speed) { if (distance >= speed) { container.scrollTop += (up ? -speed : speed); requestAnimationFrame(function() { animate(distance - speed, up, speed); }); } else { container.scrollTop += (up ? -distance : distance); } }
Hope this helps!
EDIT:
I did another (insecure) hyper-optimized (hopefully) test to improve performance by uploading small calculations that you perform each time you click on a web worker. Obviously, this is not a cross-browser solution, so you decide whether to test:
http://jsfiddle.net/fxyuzo6z/5/