Scrolling inner div on key down and up

By using tabIndex="-1" attribute on each of the children of a container, the browser will automatically scroll the container to have the child with the current focus in-view.

Demo (vanilla javascript):

var listElm = document.querySelector('ul')

// Mark first list item
listElm.firstElementChild.focus()

// Event listener
window.addEventListener('keydown', onKeyDown)

// Event callback
function onKeyDown(e){
  e.preventDefault()
  
  var selectedElm = document.activeElement,
      goToStart,
      // map actions to event's key
      action = {ArrowUp:"previous", Up:"previous", ArrowDown:"next", Down:"next"}

  selectedElm = selectedElm[action[e.key] + "ElementSibling"];

  // loop if top/bottom edges reached or "home"/"end" keys clicked
  if( !selectedElm || e.key == 'Home' || e.key == 'End' ){
    goToStart = action[e.key] == "next" || e.key == 'Home'
    selectedElm = listElm.children[goToStart ? 0 : listElm.children.length - 1]
  }
  
  selectedElm.focus()
}
ul{ 
  list-style: none; 
  border    : 1px solid silver; 
  max-height: 170px;
  padding   : 0;
  margin    : 0;
  scroll-behavior: smooth; /* nice smooth movement */
  overflow  : hidden;      /* set to hidden by OP's request */
}

li{ padding:.5em; margin:0; }
li:focus{ background:LIGHTSALMON; outline:none; }
<ul>
  <li tabIndex="-1">item 1</li>
  <li tabIndex="-1">item 2</li>
  <li tabIndex="-1">item 3</li>
  <li tabIndex="-1">item 4</li>
  <li tabIndex="-1">item 5</li>
  <li tabIndex="-1">item 6</li>
  <li tabIndex="-1">item 7</li>
  <li tabIndex="-1">item 8</li>
  <li tabIndex="-1">item 9</li>
  <li tabIndex="-1">item 10</li>
  <li tabIndex="-1">item 11</li>
  <li tabIndex="-1">item 12</li>
  <li tabIndex="-1">item 13</li>
  <li tabIndex="-1">item 14</li>
  <li tabIndex="-1">item 15</li>
</ul>

To make this list accessible (ARIA) read this


You can update your script to find the relative position of the selected element and scroll to it:

$(".someInput").on("keyup", function(e) {
   $(".wrapper").show(); 
    if (e.which == 40) {
        $('.element:not(:last-child).element-hover').removeClass('element-hover').next().addClass('element-hover');
    } else if (e.which == 38) {
        $('.element:not(:first-child).element-hover').removeClass('element-hover').prev().addClass('element-hover');    
    }
    //scroll to element:
    $(".wrapper .inner_div").scrollTop(0);//set to top
    $(".wrapper .inner_div").scrollTop($('.element-hover:first').offset().top-$(".wrapper .inner_div").height());//then set equal to the position of the selected element minus the height of scrolling div
});

http://jsfiddle.net/kMzR9/3/


There are several ways to implement it. and the exact solution for you need to consider your context.

Anyway, one possible solution is to use in the container div 'position: relative' and in the inner div (which hold the content) use 'position: absolute' and 'top: 0px'. When user press on the up/down arrows you changing the top property accordingly.

CSS:

.container {
    position: relative;
    height: 50px;
    width: 200px;
    overflow: hidden;
    border: 1px solid blue;
}

.content {
    position: absolute;
    top: 0px;
}

JavaScript:

function moveContent(px) {
    var top = $('.content').position().top;
    $(".content").css("top", top+px);
}

$(document).keydown(function(e){
    if (e.keyCode == 38) { 
       moveContent(-5);
    }
    if (e.keyCode == 40) { 
       moveContent(5);
    }
});

HTML:

<div class="container">
    <div class="content">
        hello 1<br/>
        hello 2<br/>
        hello 3<br/>
        hello 4<br/>
        hello 5<br/>
        hello 6<br/>
    </div>
</div>

See my example in: http://jsfiddle.net/Kq2Qq/3/