Customizing Your Markup
Published 12 years, 8 months pastSo 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 :
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 anelement
element. That’s not a typo.- To your
element
element, add anextends
attribute whose value is the HTML5 element you plan to extend. We’ll usespan
, but you can extend any element. - Now add a
name
attribute that names your custom “element” name, likex-kern
. - Okay, you’re ready! Now anywhere you want to add a customized element, drop in the elements named by
extends
and then supply thename
via anis
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.