惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

K
Kaspersky official blog
小众软件
小众软件
Engineering at Meta
Engineering at Meta
博客园 - 三生石上(FineUI控件)
WordPress大学
WordPress大学
G
Google Developers Blog
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
V
V2EX
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
Google DeepMind News
Google DeepMind News
Security Archives - TechRepublic
Security Archives - TechRepublic
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
C
Check Point Blog
aimingoo的专栏
aimingoo的专栏
罗磊的独立博客
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
MongoDB | Blog
MongoDB | Blog
L
LINUX DO - 热门话题
酷 壳 – CoolShell
酷 壳 – CoolShell
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
H
Help Net Security
Martin Fowler
Martin Fowler
G
GRAHAM CLULEY
Simon Willison's Weblog
Simon Willison's Weblog
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
博客园 - Franky
V
Vulnerabilities – Threatpost
云风的 BLOG
云风的 BLOG
博客园_首页
C
Cybersecurity and Infrastructure Security Agency CISA
量子位
Stack Overflow Blog
Stack Overflow Blog
Recent Announcements
Recent Announcements
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
I
Intezer
Scott Helme
Scott Helme
A
About on SuperTechFans
博客园 - 司徒正美
Hacker News: Ask HN
Hacker News: Ask HN
The GitHub Blog
The GitHub Blog
Forbes - Security
Forbes - Security
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
博客园 - 聂微东
人人都是产品经理
人人都是产品经理
The Cloudflare Blog
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
Spread Privacy
Spread Privacy
T
Tailwind CSS Blog
S
Security Affairs
宝玉的分享
宝玉的分享

Tech – Thoughts From Eric

In situ Syntax Highlighting in macOS Applications Like Keynote Canvas-ing the Web Targeting by Reference in the Shadow DOM Custom Asidenotes Parenthetical Asidenotes Bookmarklet: Load All GitHub Comments (take 2) No, Google Did Not Unilaterally Decide to Kill XSLT To Infinity… But Not Beyond! Infinite Pixels Masonry, Item Flow, and… GULP? CSS Naked Day 2025 CSS Wish List 2025 Announcing BCD Watch Design for Real Life News!
Accessible (I Think) Split-Cell Table Headers
Eric Meyer · 2026-05-28 · via Tech – Thoughts From Eric

My colleague Chris Griffith, with whom I collaborated to put The Effects of Nuclear Weapons, Third Edition (1977) online, is also a spaceflight enthusiast (and an urban trails hiker: check out his new book!).  He recently asked me how I would mark up a table with a split diagonal header cell; 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 position or grid them within that cell, but the accessibility of that seemed… questionable.  It’s also what Wikipedia already does, and we here at meyerweb are nothing if not obsessed with finding new ways to do niche stuff.  So I tried something different.  But is its accessibility any better?

If you want to see it as a live example, it’s over at Codepen.  Most of the text in the table is what macOS Preview OCRed out of the original image, which I kept intact because I think it’s funny.  Anyway, here is the original markup I came up with for the table head, which you should not use:

<thead>
	<tr>
		<th scope="row">SCIENTIFIC DISCIPLINE</th>
		<th scope="col">GEOLOGY</th>
		<th scope="col">GEOPHYSICS</th>
		<th scope="col">GEOCHEMISTRY</th>
	</tr>
	<tr>
		<th scope="col">EXPERIMENT</th>
	</tr>
 </thead>

So one row for the headers across the top of the table, including the top-left label that goes with them, and then another row with the header that relates to the row headers for the rows below.  That is to say, the row-scoped table header in each of the rows in the table’s bodies (it has more than one), like this:

<tbody>
	<tr>
		<th scope="row">CONTINGENCY SAMPLE COLLECTION</th>
		[…]
	</tr>

The thing is, when I ran the idea past accessibility experts like Alice Boxhall and Adrian Roselli, they identified a problem: Not having a full row of cells, as is the case for the second header row, fails WCAG 1.3.3.  The suggested fix was to rowspan most of the cells in the first row, like this:

 <thead>
	<tr>
		<th scope="row">SCIENTIFIC DISCIPLINE</th>
		<th scope="col" rowspan="2">GEOLOGY</th>
		<th scope="col" rowspan="2">GEOPHYSICS</th>
		<th scope="col" rowspan="2">GEOCHEMISTRY</th>
	</tr>
	<tr>
		<th scope="col">EXPERIMENT</th>
	</tr>
 </thead>

With that, table navigation wasn’t perfect, but it seemed decent, so we could move forward.

In terms of presentation, to get the upper-left header cell to do the split-diagonal thing, I relatively position the <thead> and then absolutely position the second row in the table head to sit over top of the first, pinned to the bottom left corner.

thead {
	position: relative;
}
thead tr:nth-child(2) th {
	  position: absolute;
	  bottom: 0;
	  left: 0;
}

I fiddled around for a bit with trying to use a grid instead, but it didn’t really add anything that positioning didn’t already provide and threw some other wrenches into the works, like having to convert the entire table into a grid so the columns would stay aligned, so I decided to just stick with the positioning.

Then I throw a linear gradient background into the first row’s first cell to draw the diagonal, and everything’s thus more or less as intended, visually speaking.  (That diagonal could also be an SVG, in fact probably should be in production, but I was seeing how an all-CSS solution might work so a gradient is where things stand.)

There are some layout caveats with this approach, but they’re pretty much the same as other solutions I saw: primarily, the two bits of text that the diagonal visually separates can stick out of their respective halves of the split cell, or even overlap each other.  Also, you might need to explicitly set a minimum height of the first header row, in order to not exacerbate the overlap risk just described.

And then there’s a really big caveat: Safari, as of this writing, doesn’t handle the layout at all well, because it doesn’t apply relative positioning to <thead> (or <tfoot> or <tbody>, but at least it does <tr>s).  I went to file a bug and found there’s already one open, so maybe this will be fixed in the near future.  I figured out a way to get at least close to the intended result while still allowing line-wrapping in the column header cells, but it mangled the layout in Firefox and Chrome.  In the end, to work around the problem, I delved into browser strangeness (at the suggestion of Marius Gundersen) and settled on the following:

/* this is gross and I hate it but it works to fix 
   Safari’s layout of the table’s top headers */
@supports (font: -apple-system-body) {
	thead tr:nth-child(1) th {
		white-space: nowrap;
	}
	thead tr:nth-child(2) th {
		position: static;
		display: block;
		margin-block: -1.5lh 0;
		padding-block: 0;
		text-align: start;
		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 to me, and basic testing by both me and Adrian didn’t reveal any major problems, but I still worry about the positioning dorking things up for the users of screen readers I don’t have access to.  So I throw it to the audience, particularly the accessibility-technology-using part of the audience: does this solution fall down for you, or is it good enough? Please let me know!