JSFiddle - React, Tailwind, and code Playground
HTML
<div id="root"></div>
CSS
#root {
position: absolute;
top: 5px;
bottom: 25px;
left: 5px;
right: 25px;
}
.item {
background: #000;
}
.item.active {
background: #00F;
}
JavaScript
var navigation =
{
"active": 0,
"root": document.getElementById("root"),
"items": root.getElementsByClassName("item")
};
navigation.move = function (x, y, currentidx, items)
{
var x0 = items[currentidx].getBoundingClientRect().left;
var y0 = items[currentidx].getBoundingClientRect().top;
var best = 0;
var bestidx = currentidx;
for (var i = 0; i < items.length; i++)
{
var score = (items[i].getBoundingClientRect().left - x0) * x + (items[i].getBoundingClientRect().top - y0) * y;
if (score > 0 && (score < best || best === 0))
{
best = score;
bestidx = i;
}
}
return bestidx;
}
document.onkeydown = function (evt)
{
var x = 0, y = 0;
switch (evt.keyCode)
{
case 37: x = -1; break;
case 38: y = -1; break;
case 39: x = 1; break;
case 40: y = 1; break;
default:
return;
}
navigation.items[navigation.active].classList.remove("active");
navigation.active = navigation.move(x, y, navigation.active, navigation.items);
navigation.items[navigation.active].classList.add("active");
};
for (var i = 0; i < 10; i++)
{
var e = document.createElement("div");
e.classList.add("item");
e.style.left = Math.round(Math.random() * 10) * 10 + "%";
e.style.top = Math.round(Math.random() * 10) * 10 + "%";
e.style.width = "20px";
e.style.height = "20px";
e.style.position = "absolute";
navigation.root.appendChild(e);
if (i == navigation.active)
{
e.classList.add("active");
}
}