# Remote-control navigation for TV web apps | WebKoding

On a TV there is no pointer. Every element is reached with four arrow keys, and the question “where does focus go when I press right?” has to have an…

Source: https://webkodingtheme.com/blog/tv-app-remote-control-navigation/

---

Applications sold as source

# Remote-control navigation for TV web apps

AÖ Arif Özelci , developer of Vela · Published 31 Oct 2026 · 8 min read
On a TV there is no pointer. Every element is reached with four arrow keys, and the question “where does focus go when I press right?” has to have an answer the viewer can predict. Get it wrong and the app feels broken even when every screen renders perfectly. Here is the model that works, the key codes for webOS and Tizen, and a few traps that only show up on a TV.
Focus has to be obvious from across the room: a clear outline, a slight scale, nothing subtle.

## Nearest-element versus rows and columns

There are two families of spatial navigation. Geometric navigation measures every focusable element on screen and picks the nearest one in the pressed direction. It needs no markup, and it surprises people: in a row of posters of different heights, “down” can land on a card two columns over, because it happened to be closer.
Grid navigation treats the screen as rows, each with items. Left and right move within the row; up and down move to the neighbouring row and keep the column, clamped to that row’s length. It needs a small amount of markup — a row container and focusable children — and it never surprises anyone. For content apps, where nearly every screen is rows of things, the grid model is the one viewers already know from every streaming app on their TV. <nav data-nav-row>
<button data-focusable>Home</button>
<button data-focusable>Live TV</button>
</nav>
<div class="row-track" data-nav-row>
<button class="card" data-focusable>…</button>
<button class="card" data-focusable>…</button>
</div>

## Key codes on webOS and Tizen

Remotes deliver keyCode values; desktop browsers deliver e.key. Handle both, so the app is testable on a laptop and correct on a TV.

Key LG webOS Samsung Tizen Keyboard
Arrows 37–40 37–40 Arrow keys
OK 13 13 Enter
Back 461 10009 Backspace / Esc
Play 415 415 —
Pause 19 19 —
Play/Pause — 10252 Space
Rewind / Fast-forward 412 / 417 412 / 417 —
On Tizen, media keys are not delivered at all until the app registers them with tizen.tvinputdevice.registerKey(&#x27;MediaPlayPause&#x27;) and friends, and the manifest needs the tv.inputdevice privilege. An app that works with arrows and silently ignores the play button has usually skipped this step.

## Scroll the row, not the page

When focus moves past the edge of the screen, slide the row with a CSS transform rather than scrolling the document. It is smoother on TV hardware and keeps vertical scrolling for moving between rows. Only slide when the focused card would leave the visible area; a row that jumps on every keypress is tiring to watch.
Vertically, keep the focused row at a steady height on screen, around 40% from the top, and animate scrollTop yourself with requestAnimationFrame. Native smooth scrolling is missing or unreliable on older TV engines; writing scrollTop works everywhere.

## The trap: lazy-loaded posters that never load

Putting loading="lazy" on poster images is the obvious optimisation, and inside rows moved by transforms it can leave posters blank: the browser’s visibility check does not see the card enter the viewport, so the image is never requested. We hit this building Vela — the first screen looked fine, every row further down was empty frames. Use decoding="async" instead, and keep posters small enough that loading a row’s worth is cheap.

## Make focus impossible to miss

- A thick outline in a colour that contrasts with every poster, not a subtle shadow.
- A small scale-up on the focused card, so focus is visible even in peripheral vision.
- Never let focus land on nothing: when a screen renders, focus its first sensible element.
- When a row is shorter than the column you came from, clamp to its last item rather than skipping the row.

Vela uses exactly this model $ 199 once. Vela’s navigation engine is the row/column grid described here, with webOS and Tizen key codes, media-key registration, row sliding and steady vertical scrolling. It is part of a complete streaming app you can rebrand and ship. Open the demo →

AÖ
Arif Özelci Builds the WebKoding plugins. Answers support himself.
Share on X LinkedIn Copy link
In this article Nearest-element versus rows and columns Key codes on webOS and Tizen Scroll the row, not the page The trap: lazy-loaded posters that never load Make focus impossible to miss
Related How to build an LG webOS TV app with web technologies Playing HLS on Samsung Tizen and LG webOS
The product this is about: Vela , $ 199 . Live demo, no signup.
