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.
Comments (16)
While it’s true that hyphens aren’t allowed in token names, and hence x-prefixed names aren’t valid, you can indeed create arbitrary tag names. According to 8.2.5.1, unknown names will construct elements of type HTMLUnknownElement, and at the very end of 8.2.5.4.7 (the in-body insertion mode), “Any other start tag” will trigger the closing of any open formatting elements, followed by the “insertion of an HTML element” (c.f. 8.2.5.1) for that unknown tag name. HTMLUnknownElements don’t have any special behavior defined by the HTML5 spec, but they do have tag names and can participate in CSS selector matching. If I’m reading this right, isn’t that exactly the behavior you’re after?
It’s hard for me to be sure, Ben—I tend to get lost in any subsection that’s beyond three levels deep—but if that’s possible then I don’t understand why the
element
-based element customization exists. Surely if there was an easier method available, nobody would’ve gone to the effort of writing the more complicated thing?Disruptively delicious thoughts Eric. Scott Jehl’s polyfill for RWD and Rachel Andrew’s contemptuous article, Stop Solving Problems You Don’t Have come to mind. Would you say either of these ideas spurred on your article, or was it purely based on experiments with TypeButter?
Trever: It was mostly based on what I found in poking under TypeButter’s hood, but I’m sure the existence of those tools and commentaries filtered into my subconscious and nudged me in this direction as well.
Perhaps HTML5 could go the route of data-attribute and use a prefix element sort of like <element-mycustnamehere></element-mycustnamehere>
That way, it won’t conflict with future versions of HTML where new elements may be created.
I wonder if the over-complication and potential CSS run-ins was intentional, for the sake of preventing an onslaught of new elements — really goofy ones like crapulent or epeen. (I claim the right to use those first if the playing field opens up.)
I think you mostly misunderstood the point of web components. The idea is not to make up a new element name; the idea is to assign to a given element (which should have some semantically appropriate element name to start with) a set of behavior and presentation.
This misunderstanding leads to your markup being completely wrong (and in fact, if used, would lead to an infinite loop). It also leads to you complaining about the fact that a tool that’s not designed to solve your problem is not solving your problem…
(There’s a side point that the web components draft is basically one guy’s thoughts, and not actually part of HTML5 yet, and may never get there in its current form, but that’s all less relevant.)
Okay, Boris, then perhaps you could point us in the right direction? I appreciate being systematically dressed down as much as the next guy, but I always like a bit of a knowledge chaser to perk the spirits back up. Bonus kudos if you answer the question of whether it’s legal to invent your own HTML5 elements and insert them into the document, but I’ll take what I can get.
Maybe I’m missing something here, but isn’t this what namespaces is meant to solve? So can’t you just use HTML5 in it’s XML form, and then use namespaces to throw in your various custom elements? A quick web search suggests this is a perfectly valid approach. (Though you do have to use XML, which you may not want to for various other reasons.)
OK, but what about in plain HTML? What about having an <element> attribute defined in the <head>, perhaps using the same form as currently >element extends=”span” name=”x-kern”<. The new tag <x-kern>> then takes on the various default attributes of the <span> tag, such as being inline, etc. Or, you could use <template> as well, to give it style or whatever.
Alternatively you could define a custom DTD…
Or, you could, I don’t know, just go with existing elements (span and div probably) with specific class names and make sure that you aren’t having styles that’ll cause problems for those specific cases.
At least some people think it’s bad form to create custom elements. Because, you know, they won’t have any semantics attached.
I certainly wasn’t intending to dress you down… I’m sorry if it came across that way.
HTML5 really doesn’t have a “spec-compliant” way to address you use case. Inventing your own names will make the document not “valid HTML5”, though of course the processing model requires the browser to have the right behavior for them. So your advice to “just go ahead and do it” is spot on. There will still be issues (e.g. if you want your custom element as a child of a table row group or some such), but that’s the best you can do right now without spec changes.
Thinking of new tags, I wanna define a new tag based on <a>. So, using the syntax mentioned previously (which isn’t showing up just now, but was basically move the proposed element tag to the head) create:
<element extends="a" name="bullshit">
<template>
<style>
color { #abcdef;} /* shit brown (not actually shit brown)*/
:after
{
content: "(eww)";
}
</style>
<attributes>
<attribute>rel="nofollow"</attribute>
<attributes>
</template>
</element>
So, our new tag is like an anchor, except that it has a default colour of “shit brown”, and “(eww)” after it. It will also have the default attribute rel=”nowfollow”.
It should be used to link to sites such as Faux News, or The Conservative News Network.
I’m not sure whether browsers should by default:
* go through and change all the bullshit elements to a elements (with the defaults) and then continue (which might make JS unhappy, because they won’t get the new element to play with, but would make generating the DOM easier); or
* keep them in the DOM, and just magically treat them as the type of element they are.
If we could create any element we wanted to, what would stop people from creating super semantic tags and striving towards XML-ification?
No more just use in the HTML itself. I assume that’s what they may be trying to prevent from happening.
Hi Eric,
I agree that the custom elements proposal is clumsy.
I think TypeButter is a good use-case for a shadow DOM (http://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/shadow/index.html) which is being proposed by the same author.
I imagine any shadow DOM solution is 5-10 years away, but in the mean-time wouldn’t be appropriate for this job? I don’t think anyone styles it and it’s semantically close.
Bottom line: We can create any element we want to. The W3C argument against creating custom DTDs has to do with the old school browser wars, where each browser had its own set of unique elements. Obviously that’s bad and we don’t want to go back to those days. However, a developer creating their own unique element for their own unique site is a different matter entirely. Yes, it’s possible that the tag will someday be added to the HTML DTD which could cause unforeseen problems, but if we name our elements carefully we can avoid namespacing issues. Anyone who develops a website thinking they can future-proof it with standards compliant code doesn’t understand the history of the web. I mean, even if you could future-proof a website, it’s going to look like crap in 10 years when we have super retina displays that attach directly to our brain-stems that are controlled by our thoughts and are charged by our farts. We should plan for maintainability more than trying to eliminate the need for maintenance entirely.
I definitely want to avoid some dystopian version of the interwebs where a developer’s ability to innovate is limited, all in the name of “standards”. I’d rather have to do a little extra work to make my site compatible with most browsers while still having the ability to shape my text into bacon just for fun: http://baconforme.com/
Pingback ::
Customizing Your Markup « Raanan Avidor
[…] this article http://meyerweb.com/eric/thoughts/2012/03/28/customizing-your-markup/ by Eric Meyer, published on March 28, 2012 at 04:55PM. Share this:StumbleUponDiggRedditLike […]
Apologies. My last comment was meant to end with:
wouldn’t the “font” element be appropriate for this job? I don’t think anyone styles it and it’s semantically close.