The theme_table() function doesn't include semantic table headings in Core. For WCAG validation it is important to add semantic information to data tables.
This has been added in the Views module #864006: Improve table semantics by adding scope or headers/id attributes which is great, but it should also be built into theme_table() so that programmatically.
Previous patches here have used scope="col"
since it was easier to implement, but the Views solution for table data already in Core uses the header/id approach so it would be good to be consistent.
There are advantages to both, but for this application it would probably be best to be consistent.
Taking from the WebAim description (see the link below):
"The purpose of data tables is to present information in a grid, or matrix, and to have column or rows that show the meaning of the information in the grid. When screen readers read straight through data tables—especially large ones—it's easy for users to get lost.
In order for a data table to be accessible, it must have the proper markup in the HTML. When the proper HTML markup is in place, users of screen readers can navigate through data tables one cell at a time, and they will hear the column and row headers spoken to them."
---
From the A11ySprint discussion we postponed this issue #1096124: Accessibility: Compose tips tables need better use of id's & summary elements because theme table needs to be able to support the scope and header relationship attributes. Also discussed the need for a scope attribute in #1413670: Document 'show row weights' mode
http://api.drupal.org/api/drupal/includes!theme.inc/function/theme_table/7
More information about this is described here:
http://tink.co.uk/2010/08/screen-reader-support-for-html-tables/
http://webaim.org/techniques/tables/data
Comment | File | Size | Author |
---|---|---|---|
#27 | semantic-tables-1645308-27.patch | 3.74 KB | mgifford |
#22 | semantic-tables-1645308-22.patch | 3.51 KB | mgifford |
#22 | th-scope-col-row.png | 211.75 KB | mgifford |
#20 | semantic-tables-1645308-20.patch | 2.61 KB | mgifford |
#18 | semantic-tables-1645308-17.patch | 928 bytes | mgifford |
Comments
Comment #1
mgiffordAdding
scope="col"
has got to be redundant when looking at a TD that's nicely wrapped in a THEAD.Can we reliably add
scope="row"
to the first column of all of the TBODY rows? Not sure that is adding much either. Although it is used in the example - http://www.access-board.gov/sec508/guide/1194.22.htmARIA added as per:
http://www.w3.org/WAI/PF/aria/roles#columnheader
Not sure that the complex tables described in the Webaim article can be done without a customized theme_table().
I thought we'd discussed tying the TBODY cell to a header id but can't see a requirement for that now.
Comment #3
BarisW CreditAttribution: BarisW commentedWould be nice if can tell theme_table which column is the one to be used for the row attribute (which is the key column).
See this example: http://www.w3.org/TR/WCAG20-TECHS/H63#H63-examples
So I took the following approach. When setting the $header for the table, you can also define which header is the primary identifier. I'm not sure if this is the best way to it, or if we want to introduce a new attribute which holds the primary column name.
If you define the table like this:
This will result in the following output:
If you don't define a primary column, the first column will get the scope attribute.
Comment #5
BarisW CreditAttribution: BarisW commentedWhat's wrong?
Comment #6
BarisW CreditAttribution: BarisW commented#3: semantic-tables-1645308-3.patch queued for re-testing.
Comment #8
mgiffordI noticed the patch in #1 wasn't included.
Like the changes you made for rows, tried to apply it to my local git repo and it failed. So I re-rolled it (with #1 included).
To add the following to the output:
I also added the ARIA role "rowheader" - https://wiki.mozilla.org/Accessibility/TableHeaders & http://www.w3.org/TR/wai-aria/roles
Comment #10
BarisW CreditAttribution: BarisW commentedAs far as I understand the ARIA roles, they only make sense when you don't use the semantic elements themselves. The examples they give apply roles to div's, not to td's. So I'm not sure if need all the extra HTML?
Comment #11
mgiffordGood question.. Less is almost always better, but I'll try to get some feedback on this.
Comment #12
mgiffordI asked Paul Jackson and got the following:
"Are you looking for feedback on the use of WAI-ARIA on tables? If so, I agree with BarisW that we should avoid using ARIA to enforce existing semantics as it doesn't add anything and would make file sizes bigger (to the detriment of mobile). I only use WAI-ARIA to override the defaults for a semantic element or to add semantics where it doesn't already exist. In the case of a regulat table, I wouldn't use table WAI-ARIA but would if I'm trying to emulate a table using divs and CSS."
This approach makes sense to me. I'll re-roll the patch.
Comment #13
mgiffordComment #15
mgifford#13: semantic-tables-1645308-13.patch queued for re-testing.
Comment #17
mgiffordThere's been a lot of discussion in Views about table attributes #864006: Improve table semantics by adding scope or headers/id attributes.
In the end though I don't see how we can do much more than add the
scope="col"
attribute to the table element.For validation for accessibility guidelines this is very useful.
The scope attribute is only valid for the TH attribute, so I've adjusted the HTML accordingly. I don't see any way to add
<th scope="row">
in D7 or D8. You'd need to have some way of specifying which column includes header information as far as I see it.Feedback on this simpler patch would be appreciated (and the Views table issue).
Comment #18
mgiffordwoops. forgot to attach the patch.
Comment #20
mgiffordHopefully this patch does it.
There's still a discussions about how to address the rows to add the scope. Paul Jackson suggested:
"Maybe a reasonable solution would be to have an option to make the first cell in each secondary row into a TH. It would be set at the table level to save the user time (so don't have to manually add for each row)."
However, I think that might be best to take on as a separate issue.
Comment #22
mgiffordOk, I got Paul's suggestion working, but it does look kinda silly. The TH is formatted like a header when most of the time we wouldn't want it to be.
I guess there could be some work arounds for this via css... Also digging into the table code I can see that you can really make more complicated tables here. However, not sure how many are used in core. Most in core are pretty simple, with the most complicated thing being some colspans here/there.
Comment #24
mgiffordThis will help meet Section 508 guidelines as well as WCAG 2.0AA.
Also, wanted to change the name to indicate that there are two recommended ways to associate the data cells with the appropriate headers as per http://webaim.org/techniques/tables/data/#id
Comment #25
BarisW CreditAttribution: BarisW commentedRe #17:
See http://www.w3.org/TR/html4/struct/tables.html#course-ex
It's perfectly valid to add a scope attribute to a
<td>
, and it can be used to define which cell in that row defines the scope. My patch from #3 combined with your patch from #22 would make a table like showed in the URL given above.Comment #26
mgiffordIt got depreciated in HTML5. The thread in Views got interesting about here:
https://drupal.org/node/864006#comment-6457058
With D7 one could still add a TD based scope attribute, but that's not an option for D8. At least not at this point.
Comment #27
mgiffordRe-rolling the patch to keep up with Core.
Comment #29
mgiffordI'm coming to conclude that something in simpletest doesn't like scope="col" being added to a header:
I went here:
Looked at the results locally. Adjusted the number of columns based on the test from 3 to 4. This is still giving me grief.
What's the best way to count the headers if xpath is failing me?
Comment #30
mgiffordMarking this as a duplicate of #864006: Improve table semantics by adding scope or headers/id attributes
Comment #30.0
mgiffordadding relationship to another issue.
Comment #31
mgiffordThat issue ultimately was tied to just Views tables, so... Reopening this one looking at theme_table().
Comment #32
mgiffordWhat happened to the function theme_table()? There are certainly still references in the comments.
Closest I could find was function template_preprocess_table().
This should follow the same approach as what we implemented in Views, so using Headers & ID's.
Comment #33
mgiffordAnother good one to sprint on over the weekend.
Comment #34
mgiffordWrong name...
Comment #35
mgiffordComment #36
BarisW CreditAttribution: BarisW commentedCan someone update the issue description? What exactly is the requested output?
Comment #37
mgiffordStarting the update, but it still needs more work. Having to step away though.
Comment #38
mgiffordComment #39
mgiffordComment #40
mgiffordtheme_table() no longer exists in D8 so I am going to close this issue.