JSFiddle - React, Tailwind, and code Playground

HTML

<div id="item-container">
    <div class="item-row focused">1</div>
    <div class="item-row">2</div>
    <div class="item-row">3</div>
    <div class="item-row">4</div>
    <div class="item-row">5</div>
    <div class="item-row">6</div>
    <div class="item-row">7</div>
    <div class="item-row">8</div>
</div>

CSS

#item-container {
    width: 410px;
    padding: 5px;
    height: 440px;
    background-color: rgba(0,0,255,.4);
    overflow: hidden;
    margin: 0 auto;
}

.item-row {
    background-color: rgba(0,255,0,.9);
    width: 400px;
    height: 100px;
    margin-bottom: 10px;
}

.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;
}

@-webkit-keyframes pulse {
  0%   { -webkit-box-shadow: inset 0px 0px 0px 2px rgba(255,255,255,1); }
  50%  { -webkit-box-shadow: inset 0px 0px 0px 2px rgba(255,255,255,.4); }
  100% { -webkit-box-shadow: inset 0px 0px 0px 2px rgba(255,255,255,1); }
}
@-moz-keyframes pulse {
  0%   { -moz-box-shadow-color: inset 0px 0px 0px 2px rgba(255,255,255,1); }
  50%  { -moz-box-shadow-color: inset 0px 0px 0px 2px rgba(255,255,255,.4); }
  100% { -moz-box-shadow-color: inset 0px 0px 0px 2px rgba(255,255,255,1); }
}
@keyframes pulse {
  0%   { box-shadow-color: inset 0px 0px 0px 2px rgba(255,255,255,1); }
  50%  { box-shadow-color: inset 0px 0px 0px 2px rgba(255,255,255,.4); }
  100% { box-shadow-color: inset 0px 0px 0px 2px rgba(255,255,255,1); }
}

JavaScript

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(keypressTimer);
    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);
    }
}