skip to main content

New Element Proposals: tablist, tab, and tabpanel

Introduction

“The details element is needed to provide an accessible way of reflecting a common application widget in HTML-based applications without requiring authors to use extensive scripting, ARIA, and platform-specific CSS to get the same effect.”

The same could be said about a tab list.

In this demo, I have used Web Components technology to define custom elements custom-tablist, custom-tab, and custom-tabpanel. The elements are given a set of semantics (ARIA attributes), behaviors (event listeners), and styles (CSS). If HTML authors currently want to use such a widget, they must define these features each and every time. The obvious disadvantage is that authors will not likely be consistent in implementation due to the uncountably many ways to do so. Furthermore, author implementation will vary with browser support: as of , only Google Chrome supports Web Components.

I have drafted specifications for proposed tablist, tab, and tabpanel elements below. If such elments made their way into the HTML Standard and were implemented by browsers, authors could simply write the HTML elements and expect them to behave as specified. (Just like <details>.)

Specifications

Warning: This is not a real specification. Draft requesting review by WHATWG.

The tablist element

Categories:
  • Flow Content
  • Sectioning Root
  • If the element’s children include at least one tab-panel pair: Interactive Content
  • If the element’s children include at least one tab-panel pair: Palpable Content
Contexts in which this element can be used:
Where Flow Content is expected.
Content Model:
Zero or more implicit pairs, each consisting of exactly one tab element followed by exactly one tabpanel element, optionally intermixed with script-supporting elements.
Tag omission in text/html:
Neither tag is omissible.
Content Attributes:
Global attributes
Allowed ARIA role attribute values:
tablist
Allowed ARIA state and property attributes:
Global aria-* attributes
Any aria-* attributes applicable to the allowed roles
DOM Interface:
interface CustomTablist : HTMLElement {};

A tablist element represents a tab list: a list of tab-panel pairs, wherein all tabs and at most one panel are exposed to the user. When the user selects a tab, its corresponding panel becomes exposed and all other panels become hidden.

Note: An empty tablist element is valid; in this case no tabs or panels are exposed.

User agents must add the tablist element’s focusable children to the tab sequence of a page, in a manner defined by the algorithm below:

  1. Let the page’s tab sequence be identified by P.
  2. Remove all focusable descendants of the tablist from P.
  3. Create a new empty tab sequence T.
  4. For each tab-panel pair in the tablist, perform the following subroutine:
    1. Add the tab element to T.
    2. If the tab’s corresponding tabpanel element is expanded, add all focusable elements within the panel to T in the standard order. Otherwise, do nothing.
  5. Inject T into P, between the last focusable element preceding the tablist and the first focusable element following the tablist.

This algorithm must be re-run each time a new tab element is selected.

The tab element

Categories:
None
Contexts in which this element can be used:
As a child of a tablist element: directly before a tabpanel element.
Content Model:
Either Phrasing Content, or exactly one element of Heading Content.
Tag omission in text/html:
A tab element’s end tag can be omitted if the element is immediately followed by a tabpanel element.
Content Attributes:
Global attributes
Allowed ARIA role attribute values:
tab
button
Allowed ARIA state and property attributes:
Global aria-* attributes
Any aria-* attributes applicable to the allowed roles
DOM Interface:
interface CustomTab : HTMLElement {};

A tab element represents a tab in a tab list. The corresponding panel of a tab element is the adjacent tabpanel sibling that follows it. The tab labels its corresponding panel.

All tabs in a tab list must always be exposed to the user.

When a tab is selected, its corresponding panel must be expanded, and when a tab is not selected, its corresponding panel must be collapsed. The user agent should allow the user to select a tab. No more than one tab may be selected at a time.

The tabpanel element

Categories:
None
Contexts in which this element can be used:
As a child of a tablist element: directly after a tab element.
Content Model:
Flow Content
Tag omission in text/html:
A tabpanel element’s end tag can be omitted if the element is immediately followed by a tab element, or if there is no more content in the parent element.
Content Attributes:
Global attributes
open - Whether the panel is exposed
Allowed ARIA role attribute values:
tabpanel
Any role that supports aria-expanded
Allowed ARIA state and property attributes:
Global aria-* attributes
Any aria-* attributes applicable to the allowed roles
DOM Interface:
  interface CustomTabpanel : HTMLElement {
    attribute boolean open;
  };

A tabpanel element represents a panel in a tab list. The corresponding tab of a panel element is the adjacent tab sibling that precedes it. The panel is labeled by its corresponding tab.

No more than one panel in a tablist should be exposed to the user.

The open content attribute is a boolean attribute whose presence indicates whether or not the content of the panel is to be exposed to the user. A panel is called expanded when its open attribute is present, and collapsed otherwise.

When the element is created, if the open attribute is absent, the information should be hidden; if the attribute is present, that information should be shown. Subsequently, if the attribute is removed, then the information should be hidden; if the attribute is added, the information should be shown.

The user agent should allow the user to request that the panel’s contents be shown or hidden. To honor a request for the contents to be shown, the user agent must set the open attribute on the element to the empty string. To honor a request for the information to be hidden, the user agent must remove the open attribute from the element.

A tablist element must have no more than one child tabpanel element with its open attribute set. If no child tabpanel elements have the open attribute present, the user agent should set that attribute on the first tabpanel element child, with the empty string as its value. Any time the user agent sets the open attribute on a tabpanel child of tablist, it must remove the open attribute from all other sibling tabpanel elements.

The open IDL attribute must reflect the open content attribute.

Suggested User Interaction

Skip to summary.

As stated above, the user agent should allow the user to request that a panel’s contents be shown or hidden, and it should show at most one panel in a tab list at all times. This section describes possible implementations of these axioms.

At any time, the user may select a tab by clicking or tapping it.

The tabindex attribute of all tab elements should be set to 0, so that keyboard users can access them. The Tab key may move the focus to these elements in the standard tab sequence order, and Shift + Tab may move the focus in reverse order.

When a selected tab has focus, subsequent keystrokes of the Tab key should move the focus to within the expanded panel, to any focusable elements such as any links or form controls. When the focus has reached the end of the panel, it should then proceed to the next tab in the tab list, or if there is none, out of the tab list.

When an unselected tab has focus, its corresponding panel is not exposed to the user. Thus the Tab key should move the focus not to any elements within the collapsed panel, but rather to subsequent tabs in the tab list, or if there are none, out of the tab list.

When any tab (selected or not) has focus, the user may press the Space key (the spacebar) to select it. The spacebar is probably a better choice than Enter, as the latter typically activates links and leads the user away from the page. To activate a focused tab, it is best to use the same key that activates form controls.

When any tab (selected or not) has focus, the user may press any arrow keys (Up, Down, Left, Right) to select another tab and give it focus. When Down or Right is pressed, the next tab in the tab list should be selected and receive focus, and when Up or Left is pressed, the previous tab should be selected and receive focus. These keybindings allow for both vertical and horizontal layouts of tabs. If the user reaches the end or the beginning of the list of tabs, the selection should wrap around to the other side of the list.

Note: The user agent should set directional key bindings based on writing mode and direction, and whether or not the tab list is styled accordingly. For example, in a right-to-left direction (dir="rtl"), the user agent should switch the behavior of the Left and Right keys, but only if the tabs were also displayed from right to left. If, however, the dir="rtl" attribute were specified, but the tabs were still displayed from left to right, the directional keys should retain their original functionality.

Lastly, the user agent should allow the user to use the Home and End keys to move the focus to the first tab and last tab, respectively, and select it.

This table summarizes the effects of keyboard keys on a tab element with focus.
Key Function
Tab Respects the tab sequence of the page. See tablist tab sequence for details. When the tab key brings focus to a tab element, it does not necessarily select it.
Space Selects the tab.
Down / Right
  • If the tab is not the last tab: Moves focus to the next tab and selects it.
  • If the tab is the last tab: Moves focus to the first tab and selects it.
Up / Left
  • If the tab is not the first tab: Moves focus to the previous tab and selects it.
  • If the tab is the first tab: Moves focus to the last tab and selects it.
Home Moves focus to the first tab and selects it.
End Moves focus to the last tab and selects it.

Suggested Presentation

This section provides suggestions for default styling of the tablist element and its children.

The selected tab in a tab list should be styled differently from unselected tabs in the same tab list. This meets Level AAA of §2.4.8 (Location) of WCAG 2.0: Information about the user’s location within a set of Web pages is available.

Within a tablist element, user agents should display all the tab children together in a single track, with the expanded tabpanel element on a separate track. Three popular layouts are described below, but user agents are not limited to these.

Horizontal Tabs

Tabs may be laid out in a single row. If this is the case, tabs should be laid out in the inline direction (from left to right, or, if the text direction is rtl, right to left instead). The expanded panel may appear either below or above the tab row, and the tab widths could be evenly divided into the panel width.

Vertical Tabs

Tabs may be laid out in a single column, preferrably in the block direction (top to bottom in most writing modes). The expanded panel may appear either to the left or to the right of the tab column, and the panel height could be set to the total sum of the heights of the tabs.

Mobile Devices

Small screens might not have enough real estate to be able to display one track of tabs with another track for the panel. Therefore, it is advantageous to lay out the tabs and panel together into one track, similarly to an accordion component (the difference being that in an accordion it is possible to expand more than one panel at a time). Rather than grouping the tabs separately from the panel, the user agent could display the expanded panel directly after its corresponding tab.

Demonstration

A demonstration and sample implementation of the elements specified above.

See the Pen Proposal: tablist element by Chris Harvey (@chharvey) on CodePen.

jump to top