Posts in the (X)HTML Category

Accessible (I Think) Split-Cell Table Headers

Published 2 days past

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!


Three Decades of HTML

Published 2 years, 5 months past

A few days ago was the 30th anniversary of the first time I wrote an HTML document.  Back in 1993, I took a Usenet posting of the “Incomplete Mystery Science Theater 3000 Episode Guide” and marked it up.  You can see the archived copy here on meyerweb.  At some point, the markup got updated for reasons I don’t remember, but I can guarantee you the original had uppercase tag names and I didn’t close any paragraphs.  That’s because I was using <P> as a shorthand for <BR><BR>, which was the style at the time.

Its last-updated date of December 3, 1993, is also the date I created it.  I was on lobby duty with the CWRU Film Society, and had lugged a laptop (I think it was an Apple PowerBook of some variety, something like a 180, borrowed from my workplace) and a printout of the HTML specification (or maybe it was “Tags in HTML”?) along with me.

I spent most of that evening in the lobby of Strosacker Auditorium, typing tags and doing find-and-replace operations in Microsoft Word, and then saving as text to a file that ended in .html, which was the style at the time.  By the end of the night, I had more or less what you see in the archived copy.

The only visual change between then and now is that a year or two later, when I put the file up in my home directory, I added the toolbars at the top and bottom of the page  —  toolbars I’d designed and made a layout standard as CWRU’s webmaster.  Which itself only happened because I learned HTML.

A couple of years ago, I was fortunate enough to be able to relate some of this story to Joel Hodgson himself.  The story delighted him, which delighted me, because delighting someone who has been a longtime hero really is one of life’s great joys.  And the fact that I got to have that conversation, to feel that joy, is inextricably rooted in my sitting in that lobby with that laptop and that printout and that Usenet post, adding tags and saving as text and hitting reload in Mosaic to instantly see the web page take shape, thirty years ago this week.


Headings and Labels

Published 8 years, 4 months past

Following on my last two posts about accessibility improvements to meyerweb, I’ve made two more adjustments: better heading levels and added ARIA labels.

For the heading levels, the problem I face is one familiar to many authors: what makes sense as an <h1> in some situations needs to be an <h2> in others.  The most common example is the titles of blog posts like this one.  On its permalink page, the title of the page is the title of the post.  There, it should be an <h1>.  On archive pages, including the home page of meyerweb, there are a number of posts shown one after the other.  In those situations, each post title should be an <h2>.

Part of the redesign’s changes were to write a single PHP routine that generated posts and their markup, which I could then simply call from wherever.  So I added an optional function parameter that allowed me to indicate the context in which a post was being placed.  It goes something like this:

<?php blogpostMarkup("archive"); ?>
function blogpostMarkup($type = "standalone") {
    if ($type == "archive") $titletag = "h2"; else $titletag = "h1";
    // …markup is all generated here…
    echo $output;
}

Or code to that effect.  (I did not go copy-paste from my actual code base.)

So now, heading levels are what they should be, at least on most pages (I may have missed updating some of my old static HTML pages; feel free to point them out in the comments if you find one).  As a part of that effort, I removed the <h1> from the masthead except on the home page, being the one place it makes sense to be an <h1>.

As for ARIA labels, that came about due to a comment from Phil Kragnes on my last post, where he observed that pages often have multiple elements with a role of navigation.  In order to make things more clear to ARIA users, I took Phil’s suggestion to add aria-label attributes with clarifying values.  So for the page-top skiplinks, I have:

<nav role="navigation" aria-label="page" id="skiplinks">

Similarly, for the site-navigation bar, I have:

<nav role="navigation" aria-label="site" id="navigate">

The idea is that screen readers will say “Page navigation region” and “Site navigation region” rather than just repeating “Navigation region” over and over.

Other than cleaning up individual pages’ heading levels and the occasional custom layout fix (e.g., the Color Equivalents Table needed a local widening of the content column’s maximum size), I think the redesign has settled into the “occasional tinkering” phase.  I may do something to spruce up my old Web Review articles (like the very first, written when HTML tags were still uppercase!) and I’m thinking about adding subnavigation in certain sections, but otherwise I think this is about it.  Unless I decide to go really over the top and model my Tools page after Simon St. Laurent’s lovely new Grid design, that is…

Of course, if you see something I overlooked, don’t hesitate to let me know!  I can’t guarantee fast response, but I can always guarantee careful consideration.


Increasing Accessibility

Published 8 years, 4 months past

Thanks to the fantastic comments on my previous post, I’ve made some accessibility improvements.  Chief among them: adding WAI-ARIA role values to various parts of the structure.  These include:

  • role="banner" for the site’s masthead
  • role="navigation" added to the navigation links, including subnavigation links like previous/next posts
  • role="main" for the main portion of a page
  • role="complementary" for sidebars in the blog archives
  • role="article" for any blog post, whether there are several on a page or just one

In addition, I restored skip links to the masthead of most pages (the rest will get them soon).  The links are revealed on keyboard focus, which I’m not sure I like.  I feel like these aren’t quite where they need to be.  A big limitation is the lack of :matches() (or similar) support in browsers, since I’d love to have any keyboard focus in the masthead or navigation links bring up the skip links, which requires some sort of parent selection.  I may end up using a tiny bit of enhancing Javascript to make the links’ UX more robust in JS situations, but still obviously available if JS fails.  And I may replicate them in the footer, as a way to quickly jump back up the page, especially to the navigation.

Speaking of the navigation links, they’ve been moved in the source order to match their place in the visual layout.  My instincts with regard to source order and layout placement were confirmed to be woefully out of date: the best advice now is to put the markup where the layout calls for the content to be.  If you’re putting navigation links just under the masthead, then put their markup right after the masthead’s markup.  So I did that.

The one thing I didn’t change is heading levels, which suffer all the usual problems.  Right now, the masthead’s “meyerweb.com” is always an <h1> and the page title (or blog post titles) are all <h2>.  If I demoted the masthead content to, say, a plain old <div>, and promoted the post headings, then on pages like the home page, there’d be a whole bunch of <h1>s.  I’ve been told that’s a no-no.  If I’m wrong about that, let me know!

There’s still more to do, but I was able to put these into place with no more than a few minutes’ work, and going by what commenters told me, these will help quite a bit.  My thanks to everyone who contributed their insights and expertise!


Element Customization

Published 14 years, 1 month past

A couple of weeks back I wrote about customizing your markup, but I got an important bit wrong and while I’ve corrected the post, I wanted to clear up the error in detail.

I said that you wrap portions of your document (or the whole thing) in an element element and use the customized element inside.  This is incorrect, and actually a very bad idea.  In fact, you define your customized elements using an element element and then use the customized elements later in the document.  Something like this:

<element extends="h1" name="x-superh1">
</element>

<h1 is="superh1">UltraMegaPower!!!</h1>
<h1>Regular Old Power</h1>

The line break inside the element element isn’t required — I just threw it in for clarity.

The element element can optionally contain template markup, but I honestly don’t understand that part of it yet.  I get the general idea, but I haven’t crawled through the specifics long enough to have really internalized all the fiddly bits.  And as we all know by know, the fiddly bits are where understanding lives and dies.  (Also where the Devil hangs out, or so I’ve been told.)

I still firmly believe that all this papers over a much bigger problem, which is the arbitrary barrier to devising and using actual custom elements (as opposed to customized existing elements).  HTML5 already allows you to make up your own bits of language: you can make up any attribute you want as long as your preface the name with data-.  Okay, so that’s a little bit clumsy naming-wise, but the capability is there.  You don’t have to register your attributes, or declare them in a list, or any of that other stuff.  You just make up data-timing or data-proglang or data-sttngcharacter on the spot and off you go.

This is not possible for elements.  You can’t even make up a prefixed element name, whether it’s data-kern or x-kern or even xkern (to avoid the limitation that hyphens aren’t allowed in element names).  You just can’t devise your own elements.  The best you can do is use the element element to sprinkle some semantic dust bunnies on top of elements that already exist.

Of course, all this “you can’t” and “not possible” applies to the specification.  Browsers will let you feed them any old element name and style it, script it, whatever.  Some say that’s more than enough.  If the browser lets you do it, why let the specification hold you back?  And of course, that’s how most people will approach the situation.

To someone like me, though, who spent years (literal years) explaining to web folk the world over that just because Internet Explorer for Windows let you write width: 12 px, actually writing it was still a bad idea — well, those habits die hard.  Just doing stuff because the browser let you do it is not always a good idea.  In fact, more often than not it’s a bad idea.

None of that really matters, as I say, because people are going to inject their own elements into their markup.  They’ll do it because it’s easier than thinking about the proper element to use, or they’ll do it because no appropriate element yet exists, or for some other reason.  That’s why the HTML5 specification ought to include the ability to do it, so that we have a paved path and defined best practices.  The capability is useful, as the data- attribute feature demonstrates.  If there’s a good, solid technical reason why extending that customization from attributes to elements is not desirable, I’d really like to know what it is.


Customizing Your Markup

Published 14 years, 2 months past

So HTML5 allows you (at the moment) to create your own custom elements.  Only, not really.

(Ed. note: this post has been corrected since its publication, and a followup clarification has been posted.)

Suppose you’re creating a super-sweet JavaScript library to improve text presentation — like, say, TypeButter — and you need to insert a bunch of elements that won’t accidentally pick up pre-existing CSS.  That rules span right out the door, and anything else would be either a bad semantic match, likely to pick up CSS by mistake, or both.

Assuming you don’t want to spend the hours and lines of code necessary to push ahead with span and a whole lot of dynamic CSS rewriting, the obvious solution is to invent a new element and drop that into place.  If you’re doing kerning, then a kern element makes a lot of sense, right?  Right.  And you can certainly do that in browsers today, as well as years back.  Stuff in a new element, hit it up with some CSS, and you’re done.

Now, how does this fit with the HTML5 specification?  Not at all well.  HTML5 does not allow you to invent new elements and stuff them into your document willy-nilly.  You can’t even do it with a prefix like x-kern, because hyphens aren’t valid characters for element names (unless I read the rules incorrectly, which is always possible).

No, here’s what you do instead :

  1. Wrap your document, or at least the portion of it where you plan to use your custom markup,Define the element customization you want with an element element.  That’s not a typo.
  2. To your element element, add an extends attribute whose value is the HTML5 element you plan to extend.  We’ll use span, but you can extend any element.
  3. Now add a name attribute that names your custom “element” name, like x-kern.
  4. Okay, you’re ready!  Now anywhere you want to add a customized element, drop in the elements named by extends and then supply the name via an is attribute.

Did you follow all that?  No?  Okay, maybe this will make it a bit less unclear.  (Note: the following code block was corrected 10 Apr 12.)

<element extends="span" name="x-kern"></element>
<h1>
<span is="x-kern" style="…">A</span>
<span is="x-kern" style="…">u</span>
<span is="x-kern" style="…">t</span>
<span is="x-kern" style="…">u</span>
mn
</h1>
<p>...</p>
<p>...</p>
<p>...</p>

(Based on markup taken from the TypeButter demo page.  I simplified the inline style attributes that TypeButter generates for purposes of clarity.)

So that’s how you create “custom elements” in HTML5 as of now.  Which is to say, you don’t.  All you’re doing is attaching a label to an existing element; you’re sort of customizing an existing element, not creating a customized element.  That’s not going to help prevent CSS from being mistakenly applied to those elements.

Personally, I find this a really, really, really clumsy approach — so clumsy that I don’t think I could recommend its use.  Given that browsers will accept, render, and style arbitrary elements, I’d pretty much say to just go ahead and do it.  Do try to name your elements so they won’t run into problems later, such as prefixing them with an “x” or your username or something, but since browsers support it, may as well capitalize on their capabilities.

I’m not in the habit of saying that sort of thing lightly, either.  While I’m not the wild-eyed standards-or-be-damned radical some people think I am, I have always striven to play within the rules when possible.  Yes, there are always situations where you work counter to general best practices or even the rules, but I rarely do so lightly.  As an example, my co-founders and I went to some effort to play nice when we created the principles for Microformats, segregating our semantics into attribute values — but only because Tantek, Matt, and I cared a lot about long-term stability and validation.  We went as far as necessary to play nice, and not one millimeter further, and all the while we wished mightily for the ability to create custom attributes and elements.

Most people aren’t going to exert that much effort: they’re going to see that something works and never stop to question if what they’re doing is valid or has long-term stability.  “If the browser let me do it, it must be okay” is the background assumption that runs through our profession, and why wouldn’t it?  It’s an entirely understandable assumption to make.

We need something better.  My personal preference would be to expand the “foreign elements” definition to encompass any unrecognized element, and let the parser deal with any structural problems like lack of well-formedness.  Perhaps also expand the rules about element names to permit hyphens, so that we could do things like x-kern or emeyer-disambiguate or whatever.  I could even see my way clear to defining an way to let an author list their customized elements.  Say, something like <meta name="custom-elements" content="kern lead follow embiggen shrink"/>.  I just made that up off the top of my head, so feel free to ignore the syntax if it’s too limiting. The general concept is what’s important.

The creation of customized elements isn’t a common use case, but it’s an incredibly valuable ability, and people are going to do it.  They’re already doing it, in fact.  It’s important to figure out how to make the process of doing so simpler and more elegant.


Invented Elements

Published 14 years, 2 months past

This morning I caught a pointer to TypeButter, which is a jQuery library that does “optical kerning” in an attempt to improve the appearance of type.  I’m not going to get into its design utility because I’m not qualified; I only notice kerning either when it’s set insanely wide or when it crosses over into keming.  I suppose I’ve been looking at web type for so many years, it looks normal to me now.  (Well, almost normal, but I’m not going to get into my personal typographic idiosyncrasies now.)

My reason to bring this up is that I’m very interested by how TypeButter accomplishes its kerning: it inserts kern elements with inline style attributes that bear letter-spacing values.  Not span elements, kern elements.  No, you didn’t miss an HTML5 news bite; there is no kern element, nor am I aware of a plan for one.  TypeButter basically invents a specific-purpose element.

I believe I understand the reasoning.  Had they used span, they would’ve likely tripped over existing author styles that apply to span.  Browsers these days don’t really have a problem accepting and styling arbitrary elements, and any that do would simply render type their usual way.  Because the markup is script-generated, markup validation services don’t throw conniption fits.  There might well be browser performance problems, particularly if you optically kern all the things, but used in moderation (say, on headings) I wouldn’t expect too much of a hit.

The one potential drawback I can see, as articulated by Jake Archibald, is the possibility of a future kern element that might have different effects, or at least be styled by future author CSS and thus get picked up by TypeButter’s kerns.  The currently accepted way to avoid that sort of problem is to prefix with x-, as in x-kern.  Personally, I find it deeply unlikely that there will ever be an official kern element; it’s too presentationally focused.  But, of course, one never knows.

If TypeButter shifted to generating x-kern before reaching v1.0 final, I doubt it would degrade the TypeButter experience at all, and it would indeed be more future-proof.  It’s likely worth doing, if only to set a good example for libraries to follow, unless of course there’s downside I haven’t thought of yet.  It’s definitely worth discussing, because as more browser enhancements are written, this sort of issue will come up more and more.  Settling on some community best practices could save us some trouble down the road.

Update 23 Mar 12: it turns out custom elements are not as simple as we might prefer; see the comment below for details.  That throws a fairly large wrench into the gears, and requires further contemplation.


My Own Private HTML5 Survey

Published 15 years, 1 month past

Yesterday, Brandy Fortune asked me on Twitter if there are “any major sites written in HTML 5 now“.  I decided to throw the question to my Twitter gang, and was of course immediately deluged in answers.  Also a small helping of standards politics, which  wasn’t really what I was after but probably should have known was inevitable.  Le sigh.

Anyway, here’s a sampling of the sites most frequently mentioned and how they’re using HTML5, listed in no particular order.

Using new-to-HTML5 markup (and DOCTYPE)

Using HTML5 DOCTYPE but no apparent new-to-HTML5 markup

And then there’s Facebook.  Rumor has it they’re using HTML5 features like the History API while still bearing an XHTML DOCTYPE.  I was also told they use video but all the videos I saw were Flash-based.  It’s possible that more is going on — who knows, maybe Farmville is all HTML5 now — but I was only willing to put up with the user experience for so long.

Some notes:

  • I didn’t run a spider script to verify which HTML5 elements, if any, were being used on a site.  Instead I surfed around using a user stylesheet that highlights HTML5 elements and looked for dashed red outlines.  If they were there, the site got “uses HTML5 markup”.  If I didn’t see any, then “no apparent HTML5 markup”.  This may mean I miscategorized a site or two, in which case sorry.  Even if not, these lists won’t stay current for more than a couple of weeks, so regard this as a single snapshot in time, not the whole movie.
  • In my limited and purely anecdotal peerings, far and away the most commonly-used HTML5 element was sectionnav appeared to run a distant second.
  • Any site that uses font replacement is using HTML5: canvas.  I didn’t list such sites, so bear that in mind.  (Sorry, Beano.)  I just hope such sites change their DOCTYPEs to match.
  • I did not list any site that lacked a DOCTYPE.  I don’t care if the HTML5 DOCTYPE is optional, that doesn’t mean any DOCTYPE-less page is using HTML5.  Or, if it does, my next step is to write a MeyerHTML DTD with an optional DOCTYPE and then charge you all $1 per site for using invalid markup in violation of the terms of the DTD’s license.  And then I’m buying an island.  Oahu seems nice.

Comments are switched off for once partly because I don’t really want another faceful of politics right now, and partly because attempts to post links to other HTML5 sites will end up in the spam trap and frustrate posters.  Feel free to go nuts on your own sites, of course.


Browse the Archive

Earlier Entries