Html5-h custom element

Custom heading element intended to replace h1 to h6 with a single heading element (yup just like XHTML promised land) and the promise of the HTML5 outline.

github repo read me

discuss here if you like (rather than twitter)


I noted that the current proposal appears to use attributes such that it would be impossible to select what is currently <h2> without using both a tag and attribute selector. This seems pretty out of step with how everything else in HTML is today (or maybe I’ve just never noted it) and I’m curious as to whether that is intentional, or just missed when creating. It matters because the specificity is automatically considerably higher and specificity is important in CSS. To produce, with the current proposal, something that had tag-similar specificity would require as near, as I can tell, adding a new kind of selector to CSS which seems like kind of a high bar. Worth considering if this is resolvable/how?

I do think that it will be hard to have a 100% useful <h>-esque element, outline algorithm and all, without also adding a corresponding new CSS selector. But in the meantime it’s still pretty cool. And maybe some Hitch example code could be added for prolyfilling that CSS selector?

BTW I find it kind of funny that <html5-h> essentially polyfills <h1> :). If only browsers would correctly implement <h1>, haha.

Thanks @briankardell and @domenic for the replies and suggestions. Hitch sounds interesting and I wonder if we can do something along these lines with it. The reason why we haven’t already is that we were simply concentrating on developing the element—and have a goal to minimise external dependencies.

However this seems like a really important feature from the feedback so far, and maybe with Hitch we can make an optional extra JS file that people can include in order to be able to select it (at least almost) as simply as using “h1/h2/…” in their CSS now.

We have the twin goals of making the element as minimally-dependent on other things as possible—so as to encourage adoption—but also as close to being as feature-rich as its native-HTML compatriots as possible—to show as ideally as possible how it might be when adopted.

Help with developing an optional Hitch(-or-otherwise)-based CSS selector for <html5-h> would be welcomed.

Edit: I love the “polyfill” way of seeing <html5-h> ;-).

Actually, I didn’t read far enough to notice that it automatically sets level for you, so it’s usable out of the box in CSS (unlike <h1>, notably, which would require a :heading(n) or similar). I now understand why @briankardell was focused on the specificity issues, since that’s the only real difference. I no longer feel that a Hitch-based prolyfill is necessary for 100% usefulness, since it would just translate between :heading(n) and html5-h[level="n"].

However, that does bring up an interesting point. Why does input:checked exist, when we could just do input[checked]? I feel like I used to know the answer to this, but forgot it… It seems related to the [level] versus :heading distinction.

My personal preference would be the exact reverse <h1> through <h∞>. I mean the number of the H does have some semantic meaning to the document.

My concern was basically that no other element that I can think of requires you to use attribute selectors for basic styling. I suppose there’s <input type="*"> but then, those are notoriously un-stylable anyway. Maybe it’s a non-issue, but it seems a little like trading problems and conveniences in parts of the platform… This might matter for a number of reasons - first, do we want to set a precedent if it’s not already there. It might add confusion… For example: if you took apart an existing site with some regexs to replace all of your properly done h1,h2,h3’s etc with heading and then changed your h1,h2,h3 style selectors you might get some unexpected garbage because you may no longer trump selectors you thought you would be. Still, maybe that’s not a big deal, I’m not sure - I’m just saying it would be great if we had a whole proposal without issue or at least a rationale as to why this is acceptable if not better and if it requires :heading or something spell it out.

Now to @domenic’s points about Hitch and things like :checked or :heading. In terms of specificity, Hitch would add barely anything here as specified in terms of specificity changing (attribute and pseudo-class are worth the same - Hitch actually capitalizes on this to add pretty good parity). :checked is a simplification for developer ergonomics, it normalizes the concept for more than just input type (it also works with <option> for example) and it’s slightly easier to type. If attribute selection is better and all that is necessary then that’s all that’s needed. However, if we think that you might want to say something like “heading levels greater than 1” there is currently no way to do that with attribute selectors and writing it with attribute syntax is way less ergonomic than with tags. :heading could be handy there, but I think actually adding that as a generalized capability for attributes in CSS would be more useful/ergonomic (note this proposal uses a pseudo but ideally that would be via syntax in attribute selectors - both have the same specificity though).

Essentially, I’m just trying to think about what it would mean to me as I try to use this.

My concern was basically that no other element that I can think of requires you to use attribute selectors for basic styling.

Isn’t this the same as the situation with using just h1’s insetad of h1-h6? or am i missing something

h1-h6 use a tag selector, it’s a different way of writing and a different specificity. People already complain about h1-h6 and lets do some comparison…

Given the following code today:

.special { color: red; }
h3 { color: blue; }

the following tag will be red, not blue because the specificity of a tag is 1 but class is 10:

<h3 class="special">Why would I be blue? I'm special!</h3>

However with the proposal, if all we did was swap out how you write the selector, as in:

.special { color: red; }
html5-h[level="3"] { color: blue; }

Then the same instance above will be red, not blue because the specificity is tag (1) + attribute (10) - so 11, while the specificity of class is 10. Again, maybe that matters, maybe it doesn’t. It’s also a lot less ergonomic and more verbose in that particular case (where we need attribute selectors to do really basic styling - esp in the case where we move from tag to attr - based… Has it ever happened?). I really can’t think of another case like that in HTML today, again, with the possible exception of input type but, again, that is less common and very limited.

If I have to select heading levels 1-3 today (at least pre-:matches/:any) I say:

h1,h2,h3 { color: orange; }

If I have to do the same with this it is:

html5-h[level="3"] { color: orange; }

This doesn’t feel great. The one case it is nice for is “all heading levels” which can now be expressed as one tag instead of 6, but we could also accomplish that via a :heading (that’s been proposed and is supported (as :header) in jQuery for many years - also notable is that virtually every pre-processor or simple text mechanism can easily expand this too.

So, basically - CSS ergonomic and precedent wise, I think that no they are not the same.

Interesting… I’m a fan of the purpose that the document outline from HTML5 set out to achieve. I’ve found it sad that we have been telling people to avoid using it rather than somehow applying the necessary pressure to get the algorithms implemented.

I’m not sure I see how this is any different? I’d be absolutely behind a / element and it’s automatic application of levels by UAs, but surely none of the criticisms about legacy support for the h1-h6 structure go away, and surely therefore none of the lethargy from accessibility groups and UA developers would dissipate on this matter?

Am I missing something here, would love to understand what is different about this approach compared to the algorithm suggested within the w3c spec?

Maybe we misunderstand each other. What I am talking about is the promise of the HTML doc outline is that you don’t have to use h1-h6 as h1 nested in sectioning elements produces the appropriate outline. What I am trying to understand is how does html5-h introduce a new problem for styling that was not already present in the use of only h1?

I am one of the people that has pushed back on using h1 only and the HTML5 doc outline. Simply because accessibility support is not implemented in browsers (IE, chrome, Firefox, Safari). html5-h is an attempt to polyfill support in a way that asks for minimal work from the developer, the semantics are handled automatically via scripting.

There is no difference between this approach and what is in the HTML spec, html5-h implements the document outline algorithm via scripting because browsers have not yet.

Indeed. One way of looking at it: an alternative approach would be to use whole-document mutation observers to monitor the addition, removal, or changes in any <hn>, <article>, <section>, etc. elements, and then go and set the appropriate aria-level attributes on the <hn>s that show up.

This is worse than <html5-h> because:

  • Naively, it seems likely to be slower (although custom elements are heavy machinery, so I might be wrong)
  • It has all of the styling problems, i.e. it’s hard to write a CSS selector for “headings at level 3”. (Although I guess since the polyfill would be setting aria-label, you could use [aria-level="3"]?)

It is better than <html5-h> because:

  • It allows you to just do what the spec says should work, despite implementer failings.
  • <h1> is shorter to type.

I’m aware of your involvement in pushing back on the HTML5 document outline, it’s partly why this discussion surprises me :smile:

The question in my mind is what advantage using this “polyfill” has in a world where legacy UAs are extremely likely to access your content, and where interpretation of the semantic levels of headings (and sections) still reside within the responsibilities of those developing the UAs? Are they (google, mozilla, microsoft… but also the developers of JAWS and other accessibility technology) more likely to implement a <html5-h> element properly in the future than the defined section outline algorithm you linked to?

If all the polyfill does is allow aria-levels to be assigned to header elements, thereby helping to conform to accessibility standards, what are the gains you see that are made over the script simply traversing the structures on the page to fill out the same properties?

Forgive me if I’m sounding crazy(!), I am just not really getting a perspective here on why this alternate approach is preferable over making the polyfill work more precisely to the existing spec.

Constructively speaking, I can see that the use of a <html5-h> element is something that puts less cognitive load on someone looking to only use one element in their markup, since it takes the explicit idea of a level out of the element’s name, but that by contrast it could actually be less logical to work with in situations where multiple levels of heading are needed within one section, especially if the fall back is to then resort to <hn> elements (though I assume you’d expect people to ‘hard-code’ the level property?)

Styling wise I don’t understand how it would face any more or less difficulties than the h1 only approach so I don’t see this as a discussion about anything other than how logical the element would be to use vs <hn>, and it’s impact on accessibility, with a view to it’s likelihood of being a route forward to a meaningful implementation in UAs of this more logical outline model… :smile:

Well, that script would need to run every time you updated the DOM, so there’s that disadvantage. Whereas <html5-h> figures out its level when you insert it. (It doesn’t seem to update itself when it’s moved around though… I’ll go file a bug.)

I’m running fairly fast/loose on this since I’m in the middle of work (but this is a really important subject for HTML’s future, IMO, so quite interested!)…so forgive me if I’m missing something obvious…

When the page is initialised, whether using <hn> or <html5-h>, a script needs to insert properties on the headings to provide the right levels on them.

When something is inserted into the DOM, whether using <hn> or <html5-h>, a script needs to insert properties on the new headings to provide the right level for them, and potentially alter the properties on nearby headings.

When the DOM is seriously manipulated, such as to wrap existing content inside of a newly added section, whether using <hn> or <html5-h>, a script needs to insert properties on the new headings created, and re-compute the properties for the existing headings.

Whenever the DOM is altered, regardless of whether the bit before aria-level="X" level="X" is named html5-h or h1, those calculations will need to happen. Won’t it?

And if that’s the case why are we moving away from what people know (<h1>) in favour of something that people don’t? I’m confused because I also see references in the readme to not simply using aria-level="1" because “people don’t know about ARIA”, and the solution to this problem (people not being educated enough on accessibility standards) is to create a new custom and non-normative property of level (that surely people that are also educated on accessibility standards might be thrown by)?

I am unclear what issue you are raising, AT don’t have to implement anything, nor do browsers its already there in the browsers (ARIA) and exposed by the browsers (acc API role/property) to AT. I would suggest <h1 is=“html5-h”> is just a simple way for devs to get the best of both worlds, ability to use only <h1> if they desire so, while at the same time providing a meaningful document structure to users. devs could just add is=“html5-h” to all H1’s if that’s what they want to use and the rest is done.

This would be most useful, when generating content (i.e. widgets, blocks, sidebar elements) it is often impossible to determine where you are at in your <h*> incrementation. Inferring the level from the context is a great way to go. Also, CSS frameworks all have a different way of dealing with <h*> and it is almost always in your way. Heading should be semantic, not be used as “the bigger, the bolder”.

However, I personally believe <html5-h> is ugly and a bit awkward, the html5 prefix is completely unnecessary, why not simply <h> ? Does it conflict with anything existing ?

Why add is="html5-h" at all? I think that’s the issue I’m getting at. Why not just perform the addition of the aria-level property to header elements that are within the spec of HTML?

The option is surely here to make this do the job that the vendors should be doing in line with the spec, though they could do it with more efficiency than a “polyfill” like this ever could, so that in the future if the vendors change their mind the polyfill can be just turned off/ignored thanks to some modernizr use?

Is complicating the logic with these new tag names and properties really in our best interest?

If you are only using h1 now, there is actually no difference, you are correct… You’re right, I missed that. But, TBH, I know of literally not a single person IRL who actually does this. I’m sure they exist, but I don’t think they are the norm - I look at code every day and I’ve never seen anyone doing that. Perhaps some of the above is why :smile: