Using aria-sort in validated HTML5

Craig Francis picture Craig Francis · Jul 21, 2014 · Viewed 14.1k times · Source

Assuming a static HTML table, such as:

<table>
    <thead>
        <tr>
            <th scope="col" aria-sort="none"><a href="...">Name&#xA0;<span title="Sort">&#9650;</span></a></th>
            <th scope="col" aria-sort="ascending"><a href="...">Score&#xA0;<span title="Ascending">&#9650;</span></a></th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>C</td>
            <td>1</td>
        </tr>
        <tr>
            <td>A</td>
            <td>5</td>
        </tr>
        <tr>
            <td>B</td>
            <td>9</td>
        </tr>
    </tbody>
</table>

Would the use of aria-sort be appropriate (for when UA's that support it)?

http://www.w3.org/TR/wai-aria/states_and_properties#aria-sort

I believe this could be useful, but the W3C validator currently requires a role="columnheader" on the <th scope="col">, which is kind of redundant, as it already implies a th[scope="col"]:

http://www.w3.org/TR/wai-aria/roles#columnheader

And once you start specifying that, you also need to set a role for everything up to the <table role="grid">... which is fine if your not using appropriate tags.

Answer

Jukka K. Korpela picture Jukka K. Korpela · Jul 23, 2014

The validator is correct. This may sound odd, but the problem is in the specifications, not in the validator.

As @CraigFrancis comments, this issue has been raised in the validator’s mailing list, where a message refers to a bug report. The bug has been closed on the grounds that the validator’s behavior is correct, as per the specifications. This means that if you use aria-sort, you need to explicitly set role to columnheader or rowheader, even if you have the scope attribute.

As the question states, this means that additional role attributes are then needed higher up in the document tree , so that you minimally end up with the following:

<!doctype html>
<title>aria-sort issue</title>
<table role="grid">
    <thead>
        <tr role="row">
            <th scope="col" role="columnheader" aria-sort="none"><a href="...">Name&#xA0;<span title="Sort">&#9650;</span></a></th>
            <th scope="col" role="columnheader" aria-sort="ascending"><a href="...">Score&#xA0;<span title="Ascending">&#9650;</span></a></th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>C</td>
            <td>1</td>
        </tr>
        <tr>
            <td>A</td>
            <td>5</td>
        </tr>
        <tr>
            <td>B</td>
            <td>9</td>
        </tr>
    </tbody>
</table>

This looks rather redundant, especially since the definition of role=columnheader says that it is “the structural equivalent to an HTML th element with a column scope”. However, HTML5 LC definitions related to WAI-ARIA do not specify any implied ARIA semantics for th (or tr or table). This might reflect the use of tables for layout, which has been widespread, so that it is unrealistic to assume in general that a table element represents a grid (array, matrix) in the structural (or “semantic”) sense. Thus, when the “tabularity” of a table element is relevant to ARIA, it must be explicitly expressed with role attributes at different levels of nesting.

Note that the aria-sort attribute is purely informative, declarative. It describes that the items of a table (grid) are in ascending or descending (or other) order. It does not ask the browser to sort them or to create UI tools for sorting. In practice, it is meant to be used when the author has taken care of sorting the table, in page generationg server-side or with JavaScript client-side. User agents can make use of this information in various ways, e.g. by announcing the user about the order.

The ARIA specification adds that “For each table or grid, authors SHOULD apply aria-sort to only one header at a time”. The code example violates this recommendation. (No error message is issued, however, by the validator; this is SHOULD, not a SHALL.) In this case, aria-sort="none" should be removed. The aria-sort attribute, when set on a column header, specifies that the rows of the table are sorted according to that column, so for obvious reasons it should be set on one column only.