Chapter 4. Coding for the Leanback UI

Working with the Google Chrome Browser on a TV Display

Window Size and Overscan

How Overscan Impacts Design

As we’ve discussed previously, TV resolution on Google TV will be either 1080p or 720p. Content is broadcast expecting the legacy display characteristics of tube TVs, such as overscan, which in a tube TV represents the left and right side of a display where the image cannot be accurately displayed. Subsequently, content is clipped with the expectation that the left and right sides will not be displayed to the viewer. In digital displays, content is clipped by presenting less than the full number of pixels on the left and right side. Subsequently, to maintain the correct aspect ratio, the vertical resolution is also clipped.

When Google TV users initially adjust the display using the setup wizard, they’re identifying the actual number of pixels visible on their TV display. For most TVs, this will be less than the display’s ideal resolution and it also will vary based on models and brand.

Dealing with Ovescan

In designing pages for Google TV, taking overscan into account means that the resolution of the display, whether fundamentally 1080p or 720p, is never the same between TVs. There are two basic approaches a designer can take to accomodate overscan:

  • A fixed-size page design, using elements of fixed size always fit onto a page assuming a 10% empty space around the page to account for overscan variability

  • An adjustable page design (also known as a “fluid” layout”) with elements that adjust to the page size or float on the page, moving to accommodate its dimensions

Fixed Page Design

You’ll discover that a fixed page design may result in a large amount of empty space on the right and bottom edges of the screen for displays that are close to full resolution. You can mitigate this issue somewhat by detecting the real size of the window and moving the top-left corner down and to the right so that the empty space is even on all sides.

This design has a number of advantages: content can be a fixed, predictable size, and the visual appearance of the page will be predictable and conform to your original design intent. However, one disadvantage is that you may need two sets of designs for 1080p and 720p resolutions (unless the content and layout scales well; see Autozoom Considerations for more details).

Adjustable Page Design

An adjustable design usually allows for a single page to serve both 1080p and 720p resolutions, and all variations of overscan for those displays. Floating the components on the page allows for additional flexibility.

The primary disadvantage of this design is that it may require considerably more effort to have one design and one set of content adjust and float across many different displays. For floating designs, D-pad navigation becomes more difficult to make intuitive because the relative positions of elements on the page can change for different display sizes.

Webkit Extensions for HTML5

The Google Chrome browser in Google TV benefits from a number of webkit extensions for CSS3. Since websites built for Google TV can rely on these extensions being available for their site, you can use these extensions to create compelling, dedicated 10-foot user experiences.

These extensions provide enhancements to the visual appeal of a page, including drop shadows and rounded corners on boxes, as well as “cinematic” effects using transitions and animations of CSS properties like position, rotation, size, color, opacity, and so on.

We’ll touch on most of the relevant webkit extensions later in this chapter.

Google TV’s User Agent String

Google TV includes a specific user agent string that is sent in the browser’s request headers. This user agent string ideally should be used to serve the appropriate and relevant content to the Chrome browser on Google TV, including web apps created for Google TV or “TV-friendly” versions of your web app.

Here are the high-level steps to implement this behavior for Google TV users:

  1. Detect the Google TV user-agent string by looking for the sub-strings Large Screen and GoogleTV, instead of trying to match the entire string. Here’s an example of a recent user-agent string:

    Mozilla/5.0 (X11; U; Linux i686; en-US) AppleWebKit/533.4
    (KHTML, like Gecko) Chrome/5.0.375.127
    Large Screen Safari/533.4 GoogleTV/161242
  2. Perform one of two options depending on whether you’re using an adapted site or a web app catered for Google TV:

    • Display the TV-friendly version of your site (based on CSS and HTML changes)

    • Redirect (temporary 302) to your web app

Migrating an Existing Website

Websites designed to be accessed on browsers in desktop or laptop computers generally require a few essential changes to provide a decent user experience in a 10-foot environment.

Traditional page designs are built for a window in portrait dimensions, navigated with a mouse pointer, and rely on vertical scrolling provided by the browser window to reach additional content on the page. This type of design contrasts with the types of designs we covered in the previous chapter.

Adding Keyboard Navigation

Keyboard navigation is one of the most essential components of the user experience in a 10-foot interface. Although adding an event handler to handle key down events for arrow keys is essential for keyboard navigation, it is not the only element to consider.

Ideally, every actionable element on a page should be reachable using the D-pad arrow keys. These elements should be visually highlighted as the user navigates around them to make it clear where they are on the page. Once an element is highlighted, the user should be able to trigger it with the OK or ENTER keys.

If the page has logical groupings of controls, it’s helpful to group the navigation as well. That is, allowing the highlight to “jump” around to disparate parts of the page can be confusing. An implementation can control for this by grouping the elements that can be highlighted by the containers that hold them. A keypress, such as the TAB key, can then be used to jump between areas of the page that would otherwise contain the highlight movement.

Autozoom Considerations

The Chrome browser on Google TV includes an algorithm for automatically zooming into page content. This autozoom is used to provide a basic level of usability for sites that were not designed for Google TV. By zooming in or out, the size of fonts and images is increased to a minimum readable size.

A website that requires autozoom for basic usability does not present an optimal user experience. Sites that have been designed for Google TV can still make use of autozoom to improve the user experience while saving effort. Using autozoom this way may degrade website display performance (such as with animations and scrolling), but this may be offset by the work for your design (and development) for multiple resolutions and for different TV overscan dimensions.

If you want to design your site without having to compensate for autozoom, you can disable this feature with the following meta tag:

<meta name="gtv-autozoom" content="off" />

Scrolling and Paging Content

Traditional web pages use scroll bars automatically provided by the browser to scroll through content. These scroll bars might be on the main browser window or in individual elements (for example, DIVs with the CSS property overflow: scroll set).

The 10-foot user experience makes it difficult for users to select a relatively small scroll bar on the display and position it accurately. Given this limitation, it’s better to rely on D-pad arrow keys to scroll a page instead and navigate individual items. In short, you shouldn’t rely on scroll bars to access off-screen content, as this will likely punish your users with a relatively poor experience.

Content Sizing for Fonts and Images

Reading from a display at a 10-foot distance requires fonts that are significantly larger than traditional pages. As a general rule of thumb, fonts should be a minimum of 16pt for 720p displays and 20pt for 1080p displays.

Images should be scaled to have the same visual impact at 10 feet. Note that the scale factor is not linear with the size of the display and the viewer’s distance. In technical terms, this is because the angle of view that a pixel of a certain size covers does not vary linearly with the viewer’s distance from the screen.

Tip

Since bitmap image content does not scale up losslessly, if one set of images is used for both 1080p and 720p, the best approach is to choose 1080p images and scale them down to the appropriate size.

Although not necessarily recommended, a simple approach to scaling all content is to use the CSS zoom property to scale the page. This property can be applied to the <body> element to scale all of the child elements proportionately. The number used for this property should be fixed, not calculated, and selected to be a factor of 2 or 1/2 for scaling efficiency where possible.

Working with HTML5

Audio and Video

HTML5 provides native support for audio and video playback with the <audio> and <video> tags.

In most cases, playback will also mean providing media key support as well as D-pad navigable controls for play, pause, fast-forward, and rewind.

These media types have play and pause methods to control playback, and you can simulate fast-forward and rewind by changing the currentTime of the element in small increments up or down. The following code snipped shows a key handler that handles fast-forward, rewind, and play/pause keys to control video playback:

var video = createElement('video');
// ...
window.addEventListener('keydown', function(e) {
  switch e.keyCode {
    case 227:
      // fast forward 10 seconds
      video.currentTime += 10;
      break;
    case 228:
      // rewind 10 seconds
      video.currentTime -= 10;
      break;
    case 179:
      if (video.paused) {
        video.play();
      } else {
        video.pause();
      }
  }
});

CSS3 Flexible Box Model

The CSS3 Flexible Box model (also known simply as FlexBox) provides an easy way to fit content into a container <div>. Child elements of the container can be spaced out horizontally or vertically, stretched to fit the container, and given a relative size ratio to assist the browser in spacing the child elements. Instead of having to fiddle with floating elements or percentage sizes, each of which cause other complexities with design, you can use a flexible box container to handle all of this automatically with a few properties.

You can learn more about the Flexible Box Model at:

W3 Consortium’s Flexible Box Module: http://goo.gl/UXEzY

HTML5Rocks.com offers an introductory article on the Flexible Box Model: http://goo.gl/Xgoh

We won’t cover all of the details of the flexible box model, but instead will focus on the more relevant concepts and properties.

display: -webkit-box

This property enables the flexible box model in a container. Children of this container will be laid out according to their flexible box properties when they are added to an enabled parent.

-webkit-box-orient

This property, set on the container element, can be either horizontal or vertical. Child elements will be sized to fit in the axis specified.

-webkit-box-flex

This property, set on the child elements, specifies the fraction of space a child will occupy in its container relative to its siblings. For example, if a box has two elements and one specifies -webkit-box-flex: 1 and the other specifies -webkit-box-flex: 3, then the second element will occupy three times the space in the box as its sibling.

Relevant CSS3 Properties

Animations and Transitions

JavaScript libraries like jQuery provide abstractions for providing animations and transitions of elements on the page. These commonly allow the translation (movement of the element’s origin on the page) and transformation (change in the element’s dimensions) of elements on the page over time, along with a means for triggering an event when complete.

CSS3 provides its own means for animations and transitions of elements, as well as events triggered upon completion. Google Chrome generally supports these CSS3 features, but requires the -webkit- extension to signify a specific implementation of a still-evolving standard.

-webkit-transition

When this style is applied to an element, it signifies that style changes applied subsequently will transition from the initial state to the new state over time. This can be accomplished without any JavaScript code.

For example, the following page shows a green box that changes to a larger, red box when hovered over with the mouse:

<html>
  <head>
    <style>
      body {
        overflow: hidden;
      }
      .wkt-demo {
        -webkit-transition-property: background-color, width, height;
        -webkit-transition-duration: 1s, 2s, 4s;
        -webkit-transition-timing-function: ease-in-out;
        -webkit-transition-delay: .25s;
      }
      .test-div {
        width: 50px;
        height: 50px;
        background-color: #0e0;
      }
      .test-div:hover {
        width: 300px;
        height: 300px;
        background-color: #e00;
      }
    </style>
  </head>
  <body>
    <div>
      <p>
         The DIV below will change background color, top and left positions
         using a CSS3 transition when hovered over, but each will change at
         a different rate.
      </p>
      <div class="test-div wkt-demo"></div>
    </div>
  </body>
</html>
webkitTransitionEnd event

A page could trigger JavaScript code at the completion of a transition. This could be used for additional animations or for activity to happen on the page when the transition is over, or merely to know that the transition has completed so that new events can be processed.

The webkitTransitionEnd event will fire when a transition completes successfully. If multiple transitions are timed (as in the previous example), multiple end events will be fired. The name of the property whose transition has ended is in the event’s propertyName attribute.

The new <body> contains the code that will add the property name to the page each time its transition ends:

<body>
  <script type="text/javascript">
    window.addEventListener('load', function() {
      var testDiv = document.getElementById('test');
      testDiv.addEventListener('webkitTransitionEnd', function(e) {
        var complete = document.getElementById('complete');
          complete.innerHTML += ' ' + e.propertyName;
        });
      });
  </script>
  <div>
    <p>
       The DIV below will change background color, top and left positions
       using a CSS3 transition, but each will change at a different rate.
    </p>
    <div>
      <p>
        Completed: <span id="complete"></span>
      </p>
    </div>
    <div id="test" class="test-div wkt-demo"></div>
  </div>
</body>
-webkit-animation

CSS3 animations provide another way to apply timed transitions of CSS properties to elements. Animations have the same related attributes as transitions. For example, -webkit-animation-delay represents the delay, in seconds, before an animation should begin once triggered.

What makes -webkit-animation different is that, where -webkit-transform continues to act on style changes to an element as long as it is present, -webkit-animation provides the ability to define a more complex movement using keyframes. Each keyframe is expressed as a percent of the total animation completion time, and every keyframe definition has a from and to frame that defines the start and end state for the element in the animation.

You can also loop animations a specific number of times or infinitely.

<html>
  <head>
    <style>
      body {
        overflow: hidden;
      }
      @-webkit-keyframes test-anim {
        from {
          width: 50px;
          height: 50px;
          background-color: #0e0;
        }
        50% {
          width: 600px;
          height: 600px;
          background-color: #00e;
   }
        to {
          width: 300px;
          height: 300px;
          background-color: #e00;
         }
      }
      .wkt-demo {
         -webkit-animation-name: test-anim;
         -webkit-animation-duration: 4s;
         -webkit-animation-timing-function: ease-in-out;
         -webkit-animation-iteration-count: infinite;
       }
       .test-div {
       }
     </style>
  </head>
  <body>
    <div>
      <p>
         The DIV below will change background color,
         width, and height using a CSS3 animation.
         At the start, the DIV is small and green;
         halfway through it is large and blue;
         at the end it is medium and red.
      </p>
      <div id="test" class="test-div wkt-demo"></div>
    </div>
  </body>
</html>
webkitAnimationEnd event

This is similar to the webkitTransitionEnd event. You can listen for this event when using -webkit-animation- on your page.

-webkit-transform

The webkit-transform CSS3 style opens up a range of possibilities for cinematic effects on a Google TV web app when combined with transitions or animations. The webkit-transform style compounds a number of possible transforms into one attribute. Transforms available include rotate (X, Y, Z), translate (X, Y, Z), and scale (X, Y).

This animation rotates an element in all three dimensions, while scaling up the size of the element:

  @-webkit-keyframes test-anim {
    from {
      -webkit-transform: rotate(0deg) rotateY(0deg) rotateZ(0deg);
    }
    to {
      -webkit-transform: rotateX(90deg) rotateY(270deg) rotateZ(45deg) scaleX(4) 
      scaleY(8);
    }
  }

Presentation Enhancements

-webkit-box-shadow

The box-shadow style allows a variety of shadow and outline effects around elements on a page. In its most basic form, the property takes just a horizontal and vertical offset from the element being styled:

  -webkit-box-shadow: 5px, 5px;     

The shadow can also be given a color, in this case green:

  -webkit-box-shadow: 5px, 5px, #0e0;     

Additional variants allow a blur distance and shadow spread, which can be used to give the drop shadow a softer edge or larger shadow:

  -webkit-box-shadow: 5px, 5px, 3px, 4px #0e0;     

An inset shadow draws the shadow inside the padding box of the element:

  -webkit-box-shadow: inset 5px, 5px, 3px, 4px #0e0;     
border-radius

The border-radius property is a popular CSS3 addition that provides rounded border corners. The corner is described in terms of the horizontal and vertical radii of a quarter eclipse. The easiest way to use the property is to have these be the same for all four corners:

  border-radius: 10px;     

However, it is possible to supply different radii for the horizontal and vertical portion of the corner:

  border-radius: 10px / 5px;      

Finally, if desired, each corner can have its own radius:

  border-radius: 10px 7px 10px 7px;
  border-radius: 10px 7px 10px 7px / 5px 2px 5px 2px;       

Thus far, we’ve covered some of the core technical elements, including CSS3, that you should consider using for your web app. Obviously, if you are building your web app in Flash, you’ll need to adapt some of the aforementioned logic and you won’t rely on CSS3 transformations. Regardless of which development approach you take, the key is to understand that your web app needs to accomodate overscan and compensate for the issues that this may cause for elements in your UI. At the same time, designing a modern UI for your web app can be accomplished with fewer lines of code and a lesser reliance on images, if you utilize relevant CSS3 properties.

We’ll take a deeper dive into the technical discussion around navigation, controls, and interactivity in the next chapter.

Get Building Web Apps for Google TV now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.