Accessible (I Think) Split-Cell Table Headers – Eric’s Archived Thoughts
My colleague Chris Griffith, with whom I collaborated to put The<br>Effects of Nuclear Weapons, Third Edition (1977) online, is<br>also a spaceflight<br>enthusiast (and an urban trails hiker: check out his new book!). He recently<br>asked me how I would mark up a table with a split diagonal header cell;<br>specifically, this one from the Apollo 16 documentation:
The top left corner of the page in question.
My immediate thought was to throw two spans in the header cell and<br>position or grid them within that cell, but the accessibility of that<br>seemed… questionable. It’s also what<br>Wikipedia already does, and we here at meyerweb are nothing if not<br>obsessed with finding new ways to do niche stuff. So I tried something<br>different. But is its accessibility any better?
If you want to see it as a live example, it’s over at<br>Codepen. Most of the text in the table is what macOS Preview OCRed<br>out of the original image, which I kept intact because I think it’s<br>funny. Anyway, here was the original markup of the table head, which you<br>should not use :
SCIENTIFIC DISCIPLINE<br>GEOLOGY<br>GEOPHYSICS<br>GEOCHEMISTRY
EXPERIMENT
So one row for the headers across the top of the table, including the<br>top-left label that goes with them, and then another row with the header<br>that relates to the row headers on the rows below. That is to say, the<br>row-scoped table header in each of the rows in the table’s bodies (it<br>has more than one), like this:
CONTINGENCY SAMPLE COLLECTION<br>[…]
The thing is, when I ran the idea past accessibility experts like Alice Boxhall and Adrian Roselli, they identified<br>problems. Not having a full row of cells, as is the case for the second<br>header row, fails WCAG<br>1.3.3. The suggested fix was to rowspan most of the cells in the<br>first row, like this:
SCIENTIFIC DISCIPLINE<br>GEOLOGY<br>GEOPHYSICS<br>GEOCHEMISTRY
EXPERIMENT
With that, table navigation wasn’t perfect, but it seemed decent, so<br>we could move forward.
In terms of presentation, to get the upper-left header cell to do the<br>split-diagonal thing, I relatively position the<br>and then absolutely position the second row<br>in the table head to sit over top of the first, pinned to the bottom<br>left corner.
thead {<br>position: relative;<br>thead tr:nth-child(2) th {<br>position: absolute;<br>bottom: 0;<br>left: 0;
I fiddled around for a bit with trying to use a grid instead, but it<br>didn’t really add anything that positioning didn’t already provide and<br>threw some other wrenches into the works, like having to convert the<br>entire table into a grid so the columns would stay aligned, so I decided<br>to just stick with the positioning.
Then I throw a linear gradient background into the first row’s first<br>cell to draw the diagonal, and everything’s thus more or less as<br>intended, visually speaking. (That diagonal could also be an SVG, in<br>fact probably should be in production, but I was seeing how an all-CSS<br>solution might work so a gradient is where things stand.)
There are some layout caveats with this approach, but they’re pretty<br>much the same as other solutions I saw: primarily, the two bits of text<br>that the diagonal visually separates can stick out of their respective<br>halves of the split cell, or even overlap each other. Also, you<br>might need to explicitly set a minimum height of the first header row,<br>in order to not exacerbate the overlap risk just described.
And then there’s a really big caveat: Safari, as of this writing,<br>doesn’t handle the layout at all well, because it doesn’t apply<br>relative positioning to (or<br>or , but at least<br>it does s). I went to file a bug and found there’s already<br>one open, so maybe this will be fixed in the near future. I figured<br>out a way to get at least close to the intended result while still<br>allowing line-wrapping in the column header cells, but it mangled the<br>layout in Firefox and Chrome. In the end, to work around the problem, I<br>delved into browser<br>strangeness (at the suggestion of Marius Gundersen) and settled on<br>the following:
/* this is gross and I hate it but it works<br>to fix Safari’s layout of the table’s top headers */<br>@supports (font: -apple-system-body) {<br>thead tr:nth-child(1) th {<br>white-space: nowrap;<br>thead tr:nth-child(2) th {<br>position: static;<br>display: block;<br>margin-block: -1.5lh 0;<br>padding-block: 0;<br>text-align: start;<br>transform: translateY(0.25lh);
Thanks, I hate it! But it works, and I try to be pragmatic.
Anyway, the point being, what I’ve done here feels more accessible<br>to me, and basic testing by both me and Adrian didn’t reveal any major<br>problems, but I still worry about the positioning dorking things up for<br>the users of screen readers I don’t have access to. So I throw it to the<br>audience, particularly the accessibility-technology-using part of the<br>audience: does this solution fall down for you, or is it good enough?<br>Please let me know!
Accessible (I Think) Split-Cell Table Headers was published on Thursday, May 28th, 2026.
It was assigned to the (X)HTML,...