GithubHelp home page GithubHelp logo

Comments (120)

sideshowbarker avatar sideshowbarker commented on May 22, 2024 4

I added a use counter to the W3C HTML checker to collect data on some particular cases relevant to recent discussions here. The data so far from a total of 223,507 requests looks like this:

case # found / 223,507 fraction
h1 multiple found 23434 0.104847
h1 multiple with section ancestor found 6291 0.028147
h1 multiple with article ancestor found 4636 0.020742
h1 multiple with aside ancestor found 825 0.003691
h1 multiple with nav ancestor found 917 0.004103

That is, 10.5% of documents checked have multiple h1 elements, 2.8% have at least one h1 among multiple h1 elements nested within a section, 2.1% have at least one nested within an article.

One case that seemed like it might be interesting to examine more is the case where a document has multiple h1 elements not nested within section/article/aside/nav. So I have the checker set up to log the URL for each instance it finds of that case. I dropped a sample of that log output to here:

https://gist.githubusercontent.com/sideshowbarker/8284404/raw/9220fb7b5a1befbabc04dc27943a5255cdfecc3e/h1.log

I have thousands more if anybody wants to look further — but after browsing through that sample, they turn out to mostly not be interesting at all; instead they seem to mostly just be documents that use a lot of nested div (instead of section/article/aside/nav) but that for some reason just use h1 at arbitrary levels of nesting throughout (rather than using h2-h6).

from html.

prlbr avatar prlbr commented on May 22, 2024 4

Does anybody still think that it was a good idea to reuse <h1> instead of a new element <h> for the explicit <section> modell? All of this would be easier and more intuitive, if authors could chose between the traditional heading focused <h1><h6> modell with implicit sections and an explicit <section>/<h> modell. It may not be to late to recognize a mistake and fix it at the root.

from html.

domenic avatar domenic commented on May 22, 2024 3

I kind of feel we should either leave as-is or just remove the outline algorithm altogether...

from html.

annevk avatar annevk commented on May 22, 2024 3

@alastc currently

The first heading within document headings must have a heading level of 1.

forbids that, but it seems reasonable to change that to require at least one heading to have a heading level of 1 and not require a particular position. Thanks for raising that.

from html.

LJWatson avatar LJWatson commented on May 22, 2024 3

@annevk
< my impression is that there's too much content out there that uses h2-h6 without regard for their sectioning content element ancestors so adjusting them
would do too much damage to existing content.<

It would, but a question worth asking, is what impact that damage would actually have. To some extent this idea is based on the assumption that most/many pages have a useful heading hierarchy, and that introducing these changes would therefore break it.

My own experience is that heading hierarchies are almost always broken as it is. So perhaps we should be asking whether the damage this algorithm might cause is better or worse, than the existing status quo?

My (entirely unscientific) hunch is that it would not make things worse. If that assertion can be backed up with evidence, then the question is whether it is worth exchanging one kind of broken for another, as a means of getting everyone to the point where things get easier for authors and better for users?

from html.

JohnnyWalkerDigital avatar JohnnyWalkerDigital commented on May 22, 2024 2

I would love to help campaign UAs to use it. It would make everyone's lives (developers and users) if they did.

from html.

annevk avatar annevk commented on May 22, 2024 2

Here’s a proposal that I’d like to pursue if there’s interest from @whatwg/a11y and implementers. If we cannot get agreement I’ll work on defining the status quo and aligning the HTML Standard with that, bitter sweet as it may be.

Having read through this issue and its links, the recurring theme is that the existing outline algorithm is too complex to implement. More importantly, it doesn’t match with the UI of assistive technology, which exposes landmarks and headings as distinct concepts. Unfortunately, this feedback was not addressed, which I suspect is why it never took off. However, developers do favor it (also indicated by the comments in this issue).

I think what’s worth pursuing is a variation on what @cookiecrook suggested back in 2014:

  • Focus on headings alone and leave landmarks to their own UI.
  • h2-h6 always have heading level 2-6, unless their parent is hgroup, in which case hgroup is the heading and h2-h6 are just content.
  • h1 and hgroup have heading level 1 + the number of ancestor sectioning content / sectioning root elements. (We include sectioning roots as it seems sensible that a h1 inside a blockquote should have a higher level than the one in the section or article the blockquote is in.)
  • hgroup presents itself as a heading (role=heading) and its h1-h6 children as ordinary content (no role, like span).

I wrote a polyfill for this proposal (demo, demo 2. It gives results that seem pretty good in Safari using VoiceOver and I think those results would translate elsewhere given ARIA support being pretty good. If that’s confirmed, it would give a transition path for developers while implementers update the mappings in browsers.

We’d also define an algorithm that finds all the h1-h6 and hgroup elements in a document so they can be presented as an outline. Léonie Watson mentioned such a view existing and it’s also useful for server-side tooling, such as what we use to publish various standards.

In conclusion, this proposal would avoid the massive complexity that the current outline algorithm imposes on computing a heading level as well as it mixing headings and landmarks. Effectively, we replace having to traverse previous siblings and their descendants, than the parent’s previous siblings and their descendants, etc. with counting ancestor elements of a specific type. And as a bonus, this would make the accessibility mapping match the rendering.

Looking forward to your feedback!

from html.

annevk avatar annevk commented on May 22, 2024 2

On data gathering: I think what would be interesting to look at are pages that use more than a single h1 today as they might be impacted by this algorithm. hgroup usage would indeed be interesting as well.

On hgroup: we might want to further revise hgroup such that only the first child would be seen as part of the outline or when skipping through headings (in the polyfill this could be accomplished with aria-labelledby). It seems that's the conclusion from W3C's efforts on subheadings (I haven't taken the time yet to find the deliberation).

On role=heading and the outline algorithm: I'm a little torn on this one. Obviously browsers will expose and include them in their assistive technology interface, but semantically ARIA is supposed to be neutral, I thought. I suspect that means we'll end up with two algorithms. It does seem that the conformance requirements around ARIA and HTML usage need to take this into account as to make sure that assistive technology is not presented with an outline that skips levels.

On falling back when h2-h6 are found: it seems this would be quite expensive, especially with dynamic changes. And given legacy data migration as you mentioned it might actually be quite acceptable to have them there while other parts of a large document are being refactored.

On having an API of sorts to enable testing: I like the idea of having a :heading(level) pseudo-class as suggested by @othermaciej and also @jakearchibald out-of-band. That would also make things easier for developers wanting to style these headings differently so that might make sense to ship at the same time too. (There's precedent for defining new pseudo-classes in the HTML Standard by the way; :defined is a recent addition.)

from html.

othermaciej avatar othermaciej commented on May 22, 2024 2

I don't know about other AT, but I do know about VoiceOver and how it integrates with WebKit. VoiceOver does not make use of the current outline algorithm or anything remotely similar, nor would it benefit from having such a thing.

As I understand it, the outline is a list of sections with possible nesting (i.e. a "forest" or potentially multi-rooted tree). This is the output of the outline algorithm. A potential described use is to dynamically create an interactive table of contents that lets you jump to a section. It doesn't actually relate to headers at all, except that outline depth of heading content is defined in terms of the output of the outline algorithm, and each section has an associated header.

VoiceOver has commands for "Find next heading", "Find previous heading", "Find the next heading of the same level" and "Find the previous heading of the same level". It tells you the level that is currently on. That's it. All of these commands can be implemented with a way to get the heading level for a heading, and a way to traverse forward or backward in document order until a heading is found. None of them need a forest of sections. Jumping to sections is not exposed. If the heading for a section was somewhere in the middle, there isn't a way to jump to the start of the section instead of the heading.

Given all that, an algorithm that produces a forest of sections is neither necessary nor helpful.

It could be that a different outline algorithm would produce more useful output. Anne suggests that the new outline algorithm would operate on headings, not sections:

We’d also define an algorithm that finds all the h1-h6 and hgroup elements in a document so they can be presented as an outline.

I guess this could be useful, since it is about headings, not sections. If it produces a flat list in document order, then it would match what VoiceOver needs, but it would be kind of trivial and not really an "outline". If it produces a forest of headings, where tree level may not match heading level, then it may or may not be useful. We'd have to decide whether "Find the next heading of the same level" is about the heading level or the outline level. I'm not sure it is helpful to have two different notions of heading level, so I don't think an algorithm like that would be useful.

It's hard to evaluate its usefulness further without more specifics about what it does.

The effective heading level algorithm is much more obviously useful, so I've focused my review on that.

from html.

annevk avatar annevk commented on May 22, 2024 2

@LJWatson the other reason for avoiding adjusting h2-h6 is that we have styling in place for h1 (based on nesting depth) and we cannot add equivalent styling for h2-h6 (and we also cannot change it for h1). It also seems like an easier pitch to say that folks should just use h1 and sectioning content elements.

from html.

gsnedders avatar gsnedders commented on May 22, 2024 1

An outline algorithm probably makes sense to keep around, given outlining is used in some sense in most screenreaders, as far as I'm aware. That said, may well make sense to drop the current one (and the semantics that go along with it...).

from html.

domenic avatar domenic commented on May 22, 2024 1

@Hixie, when you say "tools," do you include user agents and their accessibility bindings?

At some point we cannot claim that user agents are broken. They are instead rejecting our change request. https://www.w3.org/Bugs/Public/show_bug.cgi?id=25003 contains comments from both Firefox and Chrome accessibility developers explicitly rejecting the idea of implementing the outline algorithm in their accessibility bindings. It also outlines the history of JAWS removing their support. Although their reasoning may be wrong, it doesn't seem fruitful at this point to challenge them.

I think it would be better for the semantics in the spec to match the semantics already exposed through accessibility bindings in implementations. People have been using these elements for years, but either (a) they have been using them in a way supported by user agents, which contradicts the spec; or (b) they have been using them in the way specified, which means their content is broken in current user agents (for users which count on those accessibility bindings). Neither of these seem good.

from html.

Hixie avatar Hixie commented on May 22, 2024 1

@domenic Consider the following:

<h1>A</h1>
<section>
 <p>aaa
 <h1>B</h1>
 <p>bbb
</section>
<p>bbb

What are the sections in that document? If the <section> element doesn't align with that answer, then what are the semantics of <section>?

@gsnedders I don't think the battle's been fought. Any time I've seen people say they don't want to do it (e.g. in the bug above) the reasons they've given don't actually fit the facts (e.g. I've heard complaints that it would be prohibitively expensive, but that's only if you recomputed the entire tree, which as far as I can tell is unnecessary). But in any case in my comment above I gave two paths: one that I think is the right path, and another path for the case where we give up on making accessibility tools give good results. We could go down the second path, certainly. It's not just removing text from the spec, though, as I described above.

from html.

stevefaulkner avatar stevefaulkner commented on May 22, 2024 1

@domenic section is mapped to a region role in browsers, section is not exposed in the aural UI unless it has an accessible name.

There are 2 document scope navigation methods implemented across AT:

  • landmark navigation of header/footer/nav/main/form/section(only if accessible name present) elements.
  • heading navigation via h1-h6 elements.

Implementation of accessibility layer semantics for html element landmarks and h1-h6 is complete in chrome, firefox, Safari

Data on the utilisation of each can be found in webaim screen reader surveys

from html.

stevefaulkner avatar stevefaulkner commented on May 22, 2024 1

The reason for the warning is so authors are not mislead into thinking that use of sectioning elements actually does anything for users who consume heading semantics to make sense of and navigate document content.

from html.

stevefaulkner avatar stevefaulkner commented on May 22, 2024 1

@sideshowbarker wrote:

Experimentally implementing a Show Outline feature in the Nu HTML Checker that shows a “Here’s what the outline of your document looks like to AT users in practice” view—in parallel to or even in place of the current Show Outline view the checker provides, which shows what the outline looks like according to the outline algorithm in the HTML spec.

It is now in the validator: example https://validator.w3.org/nu/?showoutline=yes&doc=http%3A%2F%2Fapple.com#headingoutline

from html.

othermaciej avatar othermaciej commented on May 22, 2024 1

I think the talk of how ARIA fits into this is getting a little muddied. I want to clarify a few key points:

  1. The algorithm being proposed is not an outline algorithm. It replaces some of the intended purpose of the outline algorithm, but it does not produce an outline as output. It's better thought of as an "effective heading level" algorithm. It takes an element in the DOM as input, and produces its effective heading level as output. Heading levels are an output, not an input, and no heading is affected by the level of any other heading. So whether it considers ARIA does not make much difference. The ARIA override is applied after this algorithm produces its result.

  2. In the amended proposal, the effective heading level would be exposed directly to CSS via the :heading() pseudo-class. For implementation complexity and layering reasons, ARIA can't play into this CSS selector. So something has to define the effective heading level pre-ARIA-override.

  3. For purposes of what is exposed to assistive technology, accessibility mappings take the output of the effective heading level algorithm as the default. However, if the same element has aria-level on it, then assistive technologies get that level instead.

  4. This is actually the normal way ARIA works for everything else. Many elements in HTML have a default accessibility mapping. However, ARIA markup always takes precedence at the accessibility layer, but does not directly affect the rendering, behavior or non-accessibility semantics. This is due to ARIA's origin as a solution for "div soup" style JavaScript frameworks that do not use semantic markup. So, for example, at the HTML and CSS levels, only <input type=checkbox> is a checkbox, and it always is one. But at the assistive technology mapping level, that is the default, and ARIA takes precedence. For assistive technology mapping purposes, <div role=checkbox> is a checkbox, and <input type=checkbox role=banner> is not.

  5. Why would an author intentionally make the assistive technology mapping of an element conflict with its base semantics? The fact is, most of the time, they should not. It's better to use correct semantic markup in the first place and be consistent at all layers. But the purpose of ARIA is to give authors the override switch for the cases where it gives the best outcome.

In conclusion, I think a layered approach is correct. HTML should define an "effective heading level" algorithm as proposed by @annevk. That would get exposed directly to the proposed :heading() pseudo-class. Then, HTML Accessibility Mappings would take that as the default, and let ARIA be an override at the accessibility mapping layer.

In fact, HTML AAM is already kind of set up this way. HTML AAM links to Core AAM's language on conflicts to say that ARIA role and heading level always overrides this for purposes of accessibility. But in 4.4 Element Role Mappings, it says h1-h6 elements default to a heading level of the element's outline depth, as defined in current HTML.

Unfortunately, this is widely ignored, because the way "outline depth" is defined is not practical to implement. It always gives the wrong answer for elements not in a section; it says that an h3 outside a section has an outline depth of 1, for example.

If HTML provides a new definition of effective heading level", then it will be very easy to fit it into the architecture of existing accessibility specs. HTML AAM simply needs to replace its reference to "outline depth" with one to "effective heading level", and all the layers will hook together correctly.

Trying to consider ARIA when computing the effective heading level in the first place will not be a good fit. It will cause ARIA to get applied twice, at two different layers, and would not match how ARIA works for other elements.

(Sorry for the long-winded explanation. This is a bit complicated and subtle to explain. I hope the explanation was helpful for some people.)

from html.

xi avatar xi commented on May 22, 2024 1

I don't know about other AT, but I do know about VoiceOver and how it integrates with WebKit. VoiceOver does not make use of the current outline algorithm
or anything remotely similar, nor would it benefit from having such a thing.

I do not use a screen reader myself, but a quick image search turned out some images showing a nested list of headings in NVDA:

NVDA heading list

So I think there is benefit of specing how this nested list is generated from a flat list. That should be relatively simple.

I am not sure yet how this algorithm should deal with skipped heading levels: Should it just ignore them (like the current outline algorithm) or should it add empty nodes for them (like the current heading outline in the validator)?

I believe the correct solution to this problem is for the Markdown --> HTML converter to lower the heading level by one.

I feel this should go into ATAG, not sure where exactly. Also note that there is a post about this on the commonmark forum.

from html.

annevk avatar annevk commented on May 22, 2024 1

The first is just that as steve said earlier it'd be effectively building in a pattern that would create something we historically advise authors to explicitly not to write manually.

This is not true. The proposed change actually makes it a conformance error to skip a heading level. (Currently this is not flagged by the validator.) That alone should have a positive effect on the kind of documents that get written.

My rationale for this change overall is as follows:

  • h1 being special is already enshrined in styling.
  • h1 being special is already advocated in the HTML Standard and elsewhere.
  • h1 being special is not much of a compatibility risk, and there are upsides for users confronted with pages of developers who have not been considering AT, but have started using h1 with sectioning content elements.
  • It's an easy model for web developers to understand. (Especially compared to the outline algorithm, but also just in general.)
  • It's an easy model for browsers to be able to adopt quickly without regressing on performance.
  • It's a feature (as demonstrated by this thread early on) that most folks still want to have, even if it's delivered many years late.

My rationale for :heading/:heading(level) is:

  • It gives developers an easier way to style their headings than having to deal with various descendant selectors.
  • It makes this feature easy to test.

There is some compatibility risk, and some potential for confusion, but overall I think the advantages far outweigh the drawbacks of only having h1-h6 and rather useless sectioning content elements.

from html.

bkardell avatar bkardell commented on May 22, 2024 1

@jakearchibald mentioned:

I'd rather we bumped the level of all headings according to the number of ancestor sectioning elements than introduce something extra like heading-policy.

Sorry to add more noise on this,but for clarity: Is this on the table or off the table? My reading is probably incorrect, but I understood that there were reasons to not want to do that? The reason I am asking is that @jakearchibald's basic use case is pretty much the reality of most CMSes I know of - different authored content is going to keep on using 'flat' h1...h6 and I think that ideally we'd like them to "make sense" like this?

from html.

rehierl avatar rehierl commented on May 22, 2024 1

@annevk
Allow me to recap the main points of your proposal:

  1. The heading level of h1 elements depends on its placement: 1 + the number of ancestor sectioning content elements.
  2. The heading level of an h2-h6 element is constant (fixed to the number value).
  3. The lower a heading's heading level is, the more important the heading is.
  4. "Each heading following another heading lead in document headings must have a heading level that is less, equal, or 1 greater than lead's heading level."

I am having difficulties to understand (4): Could you please rephrase (4) so that it is more clear what it means.

<body>
  <h1> A </h1>            toc-1
  <section>               =====
    <h1> B </h1>          1. A
    <section>             1.1. B
      <h1> C </h1>        1.1.1. C
      <h2> D </h2>        1.2. D
    </section>
  </section>
</body>

If I understand your approach correctly, then the heading level of heading C is 3. And because the heading level of the h2 element is constant, its heading level is still 2. So, is "toc-1" an accurate representation of the intended table-of-contents listing (because the h2 element, is now more important than the h1 element), or is it supposed to be something else (e.g. undefined because non-conformant)?

from html.

annevk avatar annevk commented on May 22, 2024 1

@bkardell my impression is that there's too much content out there that uses h2-h6 without regard for their sectioning content element ancestors so adjusting them would do too much damage to existing content.

@rehierl 4 means that you cannot skip heading levels when the heading level increases relative to a previous heading. And toc-1 is indeed accurate (and conforming).

from html.

annevk avatar annevk commented on May 22, 2024 1

Yes (or use the polyfill if requiring script is acceptable for your site).

from html.

Hixie avatar Hixie commented on May 22, 2024

The algorithm just describes the semantics of the elements. If the tools aren't supporting the semantics, they're buggy and should be fixed. Changing the semantics would be a pretty drastic change to the spec, especially as people have been using these elements for years.

We can't just remove the outline algorithm, either. We need something to define the semantics of these elements. Even if we were to say that tools should ignore the semantics and just use the h1-h6 elements in the naive flat way (ignoring tree structure, as if we were back in the 90s), you'd still need the algorithm to be able to define the authoring conformance criteria (so that conforming documents only used h1-h6 in a manner consistent with the semantics). That's pretty silly though. The right solution is just to fix the tools.

from html.

domenic avatar domenic commented on May 22, 2024

My last message wasn't entirely clear. I agree with @gsnedders and phrasing this as "removing the outline algorithm" was incorrect. Rather, we should update the outline algorithm to reflect implementations. In some ways this is a "revert" of the "change request" that proposed a sectioning-based outline algorithm; it differs only in degree from a4313d3, which was a revert of the change request 78f1994 to simplify selector case-sensitivity matching rules.

from html.

Hixie avatar Hixie commented on May 22, 2024

If we want to require that authors use h1-h6 instead of being able to do the XHTML-style <h1>-everywhere, then we need two outline algorithms: one that describes how user agents are to act, and one that describes the restrictions that authors have to follow in order for their h1-h6 headers to not contradict the sectioning semantics. (And maybe a third one, that describes how an authoring tool could convert from the saner one-heading-element style to the legacy h1-h6 style for UAs.)

But IMHO that's a poor place to be in. I don't really see why accessibility tools couldn't expose the real semantics here. It doesn't require a complex algorithm (you only need "previous", "next", and "up" to be able to navigate the tree, and walking around the tree that way is pretty straight-forward as far as I can tell). Accessibility tools are notoriously slow about catching up to implementing new features, this algorithm is not that old by their time scales. (I mean, they still haven't implemented stuff from the 90s correctly, even though there's obvious usability gains to be had by doing so.)

from html.

domenic avatar domenic commented on May 22, 2024

Can you explain why you need two outline algorithms? Authors would use the sectioning elements the same way they are exposed in accessibility technologies: just like divs.

from html.

gsnedders avatar gsnedders commented on May 22, 2024

That ignores that fact that both Firefox and Chrome have explicitly refused to support it, and that algorithm is hella old by their standards (it's what, seven years old now?). I think the battle's lost at this point, sadly. I don't have strong opinions on what we should do, but the spec as it stands now is fiction and will remain fiction. Your argument that they should implement it because they're buggy per spec is trying to oblige behaviour by spec, and we know that's a fallacy when everyone is refusing to implement it.

from html.

domenic avatar domenic commented on May 22, 2024

My understanding is that as implemented section has no semantics, just like div. I am not sure that implementations have a concept of "sections of a document" as much as they have an accessibility tree plus an outline tree which consists of links into nodes in the accessibility tree. But I am not sure on that; presumably @stevefaulkner has done the research there.

from html.

Hixie avatar Hixie commented on May 22, 2024

I'm not sure what it would mean for <section> to have "implemented" semantics. Semantics by their very nature are about the meaning of the elements, which is something for humans. It's how you get maintainable documents that different people who have never met can approach and understand.

from html.

annevk avatar annevk commented on May 22, 2024

Yeah, I guess either you keep the current outline algorithm, or you obsolete <section>/<h1> & <hgroup>?

from html.

domenic avatar domenic commented on May 22, 2024

Is the idea to keep the current outline algorithm but the output of the algorithm is only something that exists in authors' minds? If so I'd be fine moving it to some section with a preface like "If you want to assemble a mental outline, that does not match that displayed by screen readers, follow the following algorithm: ... NOTE: authors are advised not to author documents that produce outlines catering to this algorithm, but instead author documents catering to accessibility tools, which follow the algorithm in $cross-link-here, according to the priority of constituencies (users over authors)"

But that seems kind of pointless.

from html.

annevk avatar annevk commented on May 22, 2024

It all depends on whether user agents will implement these elements. If they don't, we should scrap them and the outline algorithm can be simplified to what is supported. If they do, or we expect them to within the next five years or so, it might be worth waiting a little longer.

from html.

domenic avatar domenic commented on May 22, 2024

Hmm, to be clear, what does "implement these elements" mean? They implement them as HTMLElement instead of HTMLUnknownElement, but they do not implement the accessibility mapping implied by the current outline algorithm, and as discussed up-thread at least a couple have publicly stated they are not planning to do so. (Are those the only two relevant requirements on implementations, or am I missing some?)

from html.

annevk avatar annevk commented on May 22, 2024

There are some styling and parser requirements too. And there are some speculative CSS features that would build upon the outline algorithm. We would have to check. But styling and outline would be the most important aspects.

from html.

domenic avatar domenic commented on May 22, 2024

Ah right, thanks for pointing those out.

Also, when you say "obsolete <section> etc.", we could give them "the <main> treatment" instead of "the <dir> treatment". I'm not sure there's any practical difference besides what section they go in, but it's worth pointing out.

from html.

annevk avatar annevk commented on May 22, 2024

Perhaps it would end up like main since it still has some default ARIA semantics that might be useful. Not sure. I haven't studied this in detail, but I do agree with @Hixie that the fix isn't as simple as adding a note to the outline algorithm or dropping it altogether.

from html.

JohnnyWalkerDigital avatar JohnnyWalkerDigital commented on May 22, 2024

Adding a similar warning makes most sense, IMO, at least until the Outline Algorithm starts being more adopted. Many authors most likely think that (correctly) placing a <h1> element both inside and outside an <article> will be understood by those using assistive technology.

from html.

alastc avatar alastc commented on May 22, 2024

I do quite a bit of accessibility training and regularly come across developers who think they should just use H1s (they don't always know about sectioning either).
I agree that it would be more elegant to use sectioning, but unless someone is going to campaign for UAs to implement it, then the spec should align with the reality.

from html.

nhoizey avatar nhoizey commented on May 22, 2024

Has a web developer, I also would be really happy if the outline worked as intended with sectioning elements, at last.

Working with only h1 is much easier when you want to include (server-side or with Ajax) the same HTML fragment in several places of your pages, with appropriate hierarchy.

from html.

domenic avatar domenic commented on May 22, 2024

Some Twitter discussion reminded me about this neglected issue. I wanted to summarize the action items here:

  • We are not interested in simply adding a warning like the W3C fork does. "Warning: ignore the following. Here is a bunch of normative text about outlines..." We have higher standards for our specs than that kind of self-contradictory patchwork. Instead, we should actually update the spec to reflect reality.
  • The outline algorithm should be rewritten or replaced to reflect @stevefaulkner's description of implemented AT mechanisms in #83 (comment). Namely, it should primarily inform about landmark navigation and heading navigation. (Or maybe only the latter of these?)
    • Maybe these are already specced somewhere we should be referring to?
    • It should reflected implemented heading level semantics as announced by screen-readers, not the ones derived from nesting level.
    • We should do some serious hands-on testing with a11y tools (or we could continue to lean on a11y experts to do so for us, but that is not very good) to figure out how to best phrase these things. For example it's not entirely clear to me whether headings are presented as a nested list, or as a flat list with heading level numbers. We should encourage authors to have a mental model that matches what's implemented.
  • With these in mind, we should carefully change the authoring guidance and semantics for related elements (article, section, nav, aside, h1-h6, hgroup, header, footer). In general I think we can keep the "spirit" of existing semantics, e.g. nothing needs to change about what a section "is". But the advice about how to use it relative to headings, or how to use markup patterns that give it an accessible name, and how that impacts the document outline, will need to be carefully reviewed.
    • One exception may be hgroup. But maybe we should leave it as-is for the first pass.

Potential future work:

  • Consider the fate of hgroup further. Does it impact a11y processing anywhere? Should it be repurposed, or obsoleted, or...? Does it have semantics independent of its a11y processing, like non-accessible-name'd sections could be said to?
  • Propose a <h> element that actually gets treated like people want <h1> to be treated. (If we can get the a11y teams of various browsers to implement, then we can merge it into the spec. But let's not add something until we have experimental implementations and commitments.)

All that said, this isn't that high on my priority list, or my employer's. If someone does have the time to devote to this, I'd be happy to help review patches.

from html.

stevefaulkner avatar stevefaulkner commented on May 22, 2024

"Warning: ignore the following. Here is a bunch of normative text about
outlines..."

While there is normative requirement for UAs to implement the outline
algorithm, many web developers have been lead to believe it is implemented,
the whatwg spec continues to perpetrate the myth. However you choose to
modify the spec to bring it closer to reality will be an improvement.

from html.

sideshowbarker avatar sideshowbarker commented on May 22, 2024

I agree with much of the comments fro @Hixie and @annevk in this thread, especially the comment from @Hixie that “We can't just remove the outline algorithm” without needing to make other changes as a consequence, and the question “Yeah, I guess either you keep the current outline algorithm, or you obsolete <section>/<h1> & <hgroup>?”.

But all that said, I have over the years learned a huge amount of things from @stevefaulkner around the problems that some things in the spec cause for AT users, and I think others should read his comments here very carefully. We’re here to solve existing real problems for real users—not to hypothetically solve problems for some of them if we could somehow just get browser implementors to see things our way and implement what we’ve specced, or get AT vendors to fix their horribly broken/buggy tools.

In that spirit I agree very strongly with the implicit goals in the latest comment that @domenic posted and with his concrete suggestions there about how to get progress here. See the related IRC discussion.

Some ways I could help with this might be:

  • Experimentally implementing a Show Outline feature in the Nu HTML Checker that shows a “Here’s what the outline of your document looks like to AT users in practice” view—in parallel to or even in place of the current Show Outline view the checker provides, which shows what the outline looks like according to the outline algorithm in the HTML spec.
  • Adding further experimental warnings to help authors avoid using H1-H6 headings in any way bad for AT users; basically that amounts to uses of H1-H6 in ways different from how we told authors they should use them before we added section and article and allowed nested H1s to be used within them, and allowed uses of H2-H6 that break the existing simple hierarchical use of them.

As far as the second item above, I have already implemented experimental support in the checker for reporting (mis)use of H1 as anything other than a top-level head, and that’s been deployed in the checker for quite a long time now, and I think it’s been helping. But I’d like to help more if I can. I want to make the HTML checker be a tool that helps developers avoid making uninformed authoring choices that are going to cause problems in practice for real users.

from html.

stevefaulkner avatar stevefaulkner commented on May 22, 2024

We should do some serious hands-on testing with a11y tools
(or we could continue to lean on a11y experts to do so for us,
but that is not very good)

Unclear what you mean here, who is the 'we'? Are people such as myself who
have some knowledge about accessibility implementations in browsers and
assistive tech and who contribute to HTML not part of the group considered
to be 'we'?

It strikes me as counter productive "not very good" not to embrace the
knowledge and input of the wider web standards community.

from html.

domenic avatar domenic commented on May 22, 2024

I meant the spec editors should actually do the testing themselves, instead of always leaning on people like you to do it for us :). It seems irresponsible of us to always be speculating about a11y tool behavior until you or someone else comes into the thread to set us straight. Not that it isn't appreciated! It just shouldn't be necessary.

from html.

stevefaulkner avatar stevefaulkner commented on May 22, 2024

Hi Domenic, thanks for clarifying, it's difficult to know sometimes when
'we' is used, who it is referring to.

While I encourage the editors to become more familiar with AT, I warn
against drawing conclusions based on a single AT and limited
understanding. I also suggest not to make decisions about AT interaction
behaviour, and what is 'good' for users, without consulting users and
understanding the constraints of AT. It is relatively easy to test the
technical accessibility implementation aspects in browsers, it is more
complicated with AT. Recent tests I carried out on one small aspect of
HTML links , may be helpful reading
http://thepaciellogroup.github.io/AT-browser-tests/acc-name-test/a-href.html

Related articles by James Teh (a Screen Reader implementer and user)

http://blog.jantrid.net/2015/12/woe-aria-surprisingly-but-ridiculously.html?m=1

http://blog.jantrid.net/2015/12/woe-aria-aria-describedby-to-report-or.html?m=1

from html.

fititnt avatar fititnt commented on May 22, 2024

Much of my work involves working with sites like CMSs that part of the content is supplied by the user or third-party extensions. The document outline, and the sectioning logic was perfect.

The HTML 5.0 brought many features. So many people were more concerned with how the tag video worked than semantics. Just don't give up. Headings navigation is very important to assistive technologies. And can be even for standard users.

It's not hard to do creative uses, how to use devices without screen, or even a phone via voice commands to know what's on a website. I can find people to do something like that in 2017 to allow ordinary developers or even customers to test they site "on the phone", with a friendly voice.

If the developers can't test with AT, this at some point can be just a marketing thing that someone will sell with buzzwords like IoT and people using Raspberry PIs programmed with JavaScript with just voice can access e-commerce and a buy a product. And at some, after these proof of concept, we can have like cars with voice commands, 3rd apps or even by default apps on cellphones that at the end are just one AT with a soft voice that can buy a a product in sites using default Magento template.

Someone at some point can just create a icon with buzzwords like "Site IoT Ready" or "Compatible with voice commands" and make ARIA great again by calling a different name.

from html.

fititnt avatar fititnt commented on May 22, 2024

I feel that most of you are disappointed because you have not been heard by everyone. These changes were a little large, and depended on different people accept at the same time.

It's like everyone expects other people to accept first. And you don't have time to insist, because you're too busy. But I can find people who have the patience to go after it.

What I and some friends we can help here

  • It the problem is browsers to implement, change the browsers, not the documentation
  • If browser vendors do not do it, it's simple, I and some friends created extensions for all of them, and we started a campaign to say that they don't know how to do it right
  • About Assistive Technologies needs change, ok too. For all that are Open Source, at least for Python, I find someone help us here. JAWS will need a few emails, explanation and help with testing, but we can do it
  • I can help to force the changes on CMS. I'm a Joomla guy for almost 10 years, and I can find people from Wordpress and Drupal. We are talking here about 60% of entire internet

What we need in return

  • You here to decide the best path, explain it, and be consistent (think that for CMSs there's no guarantee h1-h6, that HTML 5.0 document outline was good)
  • If need, ensure that the official Validators do not accuse validation error for those who follow this rule immediately (i.e. do not wait years for HTML 5.X)
  • At least for open source software CMSs, LMSs etc, ensure that if they accept help to change default templates, and my friends submit improvements, you here will test and give feedback before it was released for the public.

You here can decide the best path, assuming that ATs, web developers and browsers (with extensions) will follow after just 6 months. If the best way is to implement the outline as already described, say that. If it involves creating new element, say that too. But lets decide what is best, theoretically speaking.

No problem if this decision just break something, just can't break more than it already is broken.

A very good date to have a plan would be before Google Summer of Code 2017. I was mentor twice. If there is sufficient awareness here, I believe I can convince even more people than just the folks from Joomla, Wordpress and Drupal. Each organization can have at least a almost full time student just for implement this feature, who will also make documentation on how to use it for extension developers of these CMSs.

I spoke of CMSs, but maybe I can try to contact all organizations today keeps open source screen reader and try to help them be a part of the GSoC program with the condition that they accept what you set here.

from html.

othermaciej avatar othermaciej commented on May 22, 2024

I like this proposal. I believe it is implementable and would work well. Does the computed heading level in this proposal fully match the rules for choosing heading font size here? https://html.spec.whatwg.org/multipage/rendering.html#sections-and-headings

from html.

LJWatson avatar LJWatson commented on May 22, 2024

This feels like a good solution. Quick back/packet testing suggests that the polyfill is well supported across current Windows browser/screen reader combinations.

from html.

annevk avatar annevk commented on May 22, 2024

@othermaciej the main difference is https://html.spec.whatwg.org/multipage/sections.html#sectioning-root which this proposal includes, but the rendering section does not (and the rendering section only goes up to level 6). Given it's likely uncommon to have a heading there the difference seems acceptable (in that you can add the necessary styling in such uncommon situations), but might be worth thinking about a bit more.

from html.

othermaciej avatar othermaciej commented on May 22, 2024

It sounds like there are two differences between the AT-exposed heading level in this proposal and the existing hN rendering rules:

  1. This proposal counts total of both sectioning root ancestors and sectioning content ancestors, while rendering only counts sectioning content.
  2. This proposal can represent heading levels higher than 6, while the rendering section has no extra styling beyond 6 levels.

On (1), if headers in those spots are rare anyway, it seems better to be consistent between rendering and AT-exposed level.

On (2), that seems like an ok difference. We can model it as the default rendering being the same for levels 6 and up.

I wonder if it's useful to expose the computed heading level to CSS selectors in some way? (Probably out of scope for this change).

from html.

stevefaulkner avatar stevefaulkner commented on May 22, 2024

@annevk this looks interesting, a few suggestions:
Gather data about nesting of sectioning content that do not have interleaved headings (hint to @sideshowbarker) , for example:

<body>
<h1>An h1</h1>
<section>
<section>
<h1>An h1</h1>
</section>
</section>
</body>

Results in the h1 in the nested sections having a level=3. I surmise that in many cases nesting of this type is not what a developer would have intended, but is the effect of sectioning content on the outline being opaque and therefore not understanding how sectioning elements effect the outline.

Gather data about how hgroup is used. As you may know it was obsoleted in w3c land as it was considered not fit for purpose, that is not to suggest the same necessarily occurs here, but to investigate how it is used in order to better understand if how it is specified reflects usage and how it is best exposed in the accessibility layer, if it is exposed. I see some issues in relation to rolling up all content into one big heading in cases where there is largish amounts of structured content in hgroup.

Look at how role=heading and aria-level are to be factored into the algorithm as they represent an outline to users.

from html.

cookiecrook avatar cookiecrook commented on May 22, 2024

A couple suggestions to consider:

  1. Backwards compatibility may be safer to only compute levels if no h2-h6 headings occur on the page. In other words, the presences of one of those elements counts as an explicit opt-out. I acknowledge that there are potential downsides to this edit. For example, if this edit were made, the inclusion of a legacy block of markup (with an h2) may inadvertently cause validly nested heading levels to not be computed. I'm fine with either.

  2. A computed (probably readonly) Element.headingLevel property may be useful for authors and for spec testability. This suggestion may be out-of-scope.

I support the proposal as-is regardless if these suggestions are included.

from html.

cookiecrook avatar cookiecrook commented on May 22, 2024

@stevefaulkner wrote:

Look at how role=heading and aria-level are to be factored into the algorithm…

Presence of role=heading (no aria-level specified) or role=heading aria-level=1 could be considered identical to h1 for the algorithm. If h2-h6 ends up opting the page out of automatic level computation, the same should be true for ARIA levels not equal to 1.

from html.

cookiecrook avatar cookiecrook commented on May 22, 2024

Heading levels are exposed in the Mac AX API as any positive integer, so <h1 aria-level="42">foo</h1> for example will cause VoiceOver to speak "heading level 42, foo." VoiceOver braille output will display something like hd lvl 42, foo

It may be worthwhile to check other platform accessibility APIs (particularly MSAA and UIA) to see if restrictions apply. For example, can you represent a heading level larger than 6 in NVDA? I don't know the answer.

from html.

othermaciej avatar othermaciej commented on May 22, 2024

I'm not sure role=heading or aria-level needs to play into this algorithm at all. The algorithm provides the presumed default header level for H1s that can then be used by accessibility mapping specs when an explicit aria level is not provided. It makes using all h1 headers with nested section elements do the right thing for AX without adding ARIA markup.

ARIA is not supposed to affect semantics for cases other than accessibility, so I think it would be a layering violation for it to apply at this level (even though it will affect the final result exposed to AT).

Also, there is no giant per-page mode switch. Using a single h2 element will not stop h1s from getting a computed level based on count of section ancestors.

from html.

stevefaulkner avatar stevefaulkner commented on May 22, 2024

@othermaciej

I'm not sure role=heading or aria-level needs to play into this algorithm at all.

That may well be the correct view. What we do know is that role=heading and aria-level=x will represent the document in the acc layer regardless of the <Hx> levels. So user agents such as JAWS will expose, potentially a different document outline to users than the one expected/experienced by developers. I suggest that it is worth considering a normative requirement that software such as conformance checkers should provide a representation that includes the document outline as computed with ARIA taken into account, which would reflect AT exposure, as the UI for aural user agent users is a core constituency for consumption of headings semantics.

from html.

alastc avatar alastc commented on May 22, 2024

Possibly an aside, but:

Obviously browsers will expose and include them in their assistive technology interface, but semantically ARIA is supposed to be neutral, I thought. I suspect that means we'll end up with two algorithms.

I think the more common understanding is that ARIA is an over-ride for semantics. That's built in to how it works, applying a role to an element overrides the default element semantics for AT (but not styling, unless you get clever with attribute selectors).

With my developer hat on (rather than accessibility consultant), you'd only use role=heading + level if you couldn't use standard Hx elements, so you'd be over-riding the markup to generate the desired heading levels.

Therefore, it appears there should be one algorithm which takes into account ARIA levels.

from html.

annevk avatar annevk commented on May 22, 2024

@alastc what I mean by neutral is that I don't think, e.g., :heading(level) should end up matching role=heading, just like :link doesn't match role=link. I think that leads to two systems, which from the AT view end up being one.

from html.

alastc avatar alastc commented on May 22, 2024

@annevk I'd rather they did match (so the override works universally), but I assume it's too late for that.

The outline algorythm is more important for this though, where I'd hope we'd have one for simplicity & sanity.

from html.

cookiecrook avatar cookiecrook commented on May 22, 2024

@alastc wrote:

I'd rather [the CSS :heading(level) selector] did match [ARIA headings] (so the override works universally), but I assume it's too late for that.

We looked into doing something similar a few years ago with a :role() selector. Example: *:role(heading) would have been equivalent to h1, h2, h3, h4, h5, h6, *[role^="heading"]

Unfortunately the implementation of :role() was so complicated that it would have required major rewrites of every rendering engine. In WebKit and Blink for example, CSS selection would have become dependent on the accessibility runtime, which is dependent on the render tree, which is dependent upon CSS. Similar circular dependencies existed in other implementations, too. Maybe not impossible, but definitely not worth it.

We could probably shortcut the :heading() selector to work in most cases with ARIA headings, but in order for the heading selector to perfectly include ARIA heading levels, you need to spin up the accessibility runtime to verify the role. E.g. Is role="anotherRole heading" really a heading, or is that just the fallback for anotherRole the runtime knows about? Once you need to verify the role for the :heading() selector to include ARIA headings, you've reached the same implementation complexity as the abandoned role selector.

Given the previous experimentation, I think it's okay for :heading(level) to forego including ARIA headings. If a web author needs that functionality, recommending a dual selector is reasonable: :heading(2), [role="heading"][aria-level="2"] { }

from html.

alastc avatar alastc commented on May 22, 2024

Thanks @cookiecrook, good to know. I missed your messages that came in overnight (for me), scanning back I was essentially agreeing with:

Presence of role=heading (no aria-level specified) or role=heading aria-level=1 could be considered identical to h1 for the algorithm.

To keep it simple for developers, if you need to adjust headings with ARIA it would make sense for the outline to assume they are an over-ride therefore dealt with the same way in the algorithm.

I'd also emphasis @stevefaulkner's point:

I surmise that in many cases nesting of this type is not what a developer would have intended, but is the effect of sectioning content on the outline being opaque and therefore not understanding how sectioning elements effect the outline.

When running training, it is fairly common to come across someone assuming that you can use all H1s, but they don't really understand how the nesting works. It isn't unusual to have over-nested headings (e.g. in an article, which is in a section, which is in another section because sections are better than divs, right?).

Therefore I certainly support the h2-6 aspect of @annevk's proposal above.

from html.

stevefaulkner avatar stevefaulkner commented on May 22, 2024

Thanks @othermaciej

But in 4.4 Element Role Mappings, it says h1-h6 elements default to a heading level of the element's outline depth, as defined in current HTML.

That's a bug in the spec given its lack of implementation have filed an issue to correct this.

Thinking on this more:

  • The specification of the role/level mappings for headings will occur, as it is now, in the HTML AAM.. Likewise any agreed mapping for hgroup will be specified there.
  • The appropriate place to specify advice/requirements for conformance checkers in for providing a view of a documents heading levels (including ARIA semantics), as conveyed in the aural UI, is in ARIA in HTML.

The factors that I consider need further investigation to reach an agreement on how the above are mapped:

  • Should parent sectioning elements that do not include a h1 effect the resulting level calculation for a child h1
  • Should hgroup have an effect upon the accessibility level calculation of child headings? And if so how?

As previously suggested, looking at data for usage of sectioning elements and hgroup should inform these considerations.

from html.

annevk avatar annevk commented on May 22, 2024

Note that if you want to skip a sectioning content element whose h1 element descendants' nearest ancestor sectioning content element is not that sectioning content element you are again looking at an algorithm that is complex as you cannot just go through the parent chain anymore.

I agree we should look at data, but I don't think that's going to be a solution we can use.

from html.

asurkov avatar asurkov commented on May 22, 2024

I like the proposal. It feels strange though that h1 is treated a special way. It would be more consistent if all h1/h2/h3/etc would earn +1 for each nesting section, or neither of them. The latter one looks cleaner and easier with me.

The old way:
<h1>heading#1</h1>
<h2>heading#2</h2>

and the new way:

<hgroup>heading#1<hgroup>
<section>
<hgroup>heading#2</hgroup>
</section>

both look good.

Is the point of adjustable h1 is to use it instead of hgroup? If so this moves me back wondering whether HTML:h element should be revisited.

from html.

othermaciej avatar othermaciej commented on May 22, 2024

@asurkov The rendering rules in the HTML standard act the same way - h2-h6 are fixed, while h1 is sized differently depending on nesting level. I think the accessibility mapping should match the rendering unless there is some hugely compelling reason otherwise.

from html.

othermaciej avatar othermaciej commented on May 22, 2024

I agree with @annevk . It's really important for this algorithm to remain a walk up the ancestor chain instead of a full document traversal.

from html.

domenic avatar domenic commented on May 22, 2024

The algorithm being proposed is not an outline algorithm. It replaces some of the intended purpose of the outline algorithm, but it does not produce an outline as output.

I'm not sure it was clear, but I think the intent of #83 (comment) (specifically the paragraph starting "We’d also define an algorithm that finds...") is to keep having an outline algorithm in the spec. Personally I think that is important at the semantic level. That would be in addition to the heading-level determination algorithm.

The question of whether that outline should contain role="heading" elements is an interesting one. I am not sure, but I lean toward yes. Ideally I think the "semantic outline" specified in HTML and the "AT outline" are the same; that seems like it is most likely to steer authors down the correct path. The alternative is to say that HTML has an outline algorithm that only takes actual headings into account, whereas HTML-AAM has a different outline algorithm that reflects what ATs will implement. But that seems confusing to me.

from html.

othermaciej avatar othermaciej commented on May 22, 2024

Oh, sure. If we're talking about the remaining outline algorithm and not the effective heading level algorithm, then it doesn't necessarily have the same constraints. However, it seems like the two algorithms should produce consistent results. I am not sure if it would be inconsistent for role="heading" to be considered by one or not the other. Maybe not, as long as the presence of a heading never affects the heading levels of other headings.

I am not sure anyone will implement the outline algorithm at all though, at least in a mainstream browser or AT. My assumption is that the proposed effective heading level algorithm is pretty likely to be widely implemented, but the new outline algorithm probably won't be implemented any more than the current one.

from html.

domenic avatar domenic commented on May 22, 2024

My understanding is that the proposed outline algorithm is already listed in many ATs, in the form of the ability to list all of a document's headings and navigate between them. I have not tested myself, and so welcome corrections.

The current outline algorithm is also implemented by a variety of tools. At least some authors I know use the output of those tools to guide their development. This is currently a bad thing, because creating an outline that looks good according to those tools can lead to create an outline with a bad experience for AT users. But if we aligned the outline algorithm with what AT users experience, then it could become a good thing.

from html.

LJWatson avatar LJWatson commented on May 22, 2024

@othermaciej wrote:
<I don't know about other AT, but I do know about VoiceOver and how it integrates with WebKit. VoiceOver does not make use of the current outline algorithm
or anything remotely similar, nor would it benefit from having such a thing.<

This is the case for all screen readers that I'm aware of. @domenic is right that screen readers have the ability to navigate between headings, but this is based on the headings themselves, not the outline algorithm.

from html.

jakearchibald avatar jakearchibald commented on May 22, 2024

@othermaciej

I think the accessibility mapping should match the rendering unless there is some hugely compelling reason otherwise.

The best use case I can think of is a template like:

<article>
  <h1>Reasons Event Horizon is actually quite good</h1>
  <section>
    {{{articleContent}}}
  </section>
</article>

…where articleContent is HTML generated from Markdown.

Now, if I use Markdown's ## Headings syntax, it produces the correct heading structure.

I'm undecided whether this is worth it. But, "number of ancestor sectioning elements + default heading level - 1" is simpler than I thought it'd be.

from html.

domenic avatar domenic commented on May 22, 2024

Right, it's not based on the current outline algorithm, because the current outline algorithm is not usable for that purpose. I'm trying to say we should create an outline algorithm that is usable for that purpose, by virtue of it correctly listing all the headings. This is effectively what we see today in several implementations of today's (flawed) outline algorithm; see e.g. https://checker.html5.org/?showoutline=yes&doc=https%3A%2F%2Fstreams.spec.whatwg.org and notice how the heading-based outline (similar to @annevk's proposal) and the "structural" outline (based on the current HTML Standard) are basically the same. (The differences would be larger if the document used <section> elements, but it does not.)

People saying that the outline algorithm is not necessary or helpful seem mostly to be focusing on the fact that it points to sections + their headings, instead of directly to their headings. But I think this is not a very important difference; we can change it to point to headings and the result will be almost exactly the same, except in some cases of un-heading-ified sections (which I am happy to omit). That is, sections and headings are usually 1:1 in well-structured documents.

I think it's still useful to call the resulting list of headings (which can indeed be displayed in a nested fashion, as shown by the above link) an outline, and call the algorithm that collects them an outline algorithm, and use it in the same semantic fashion as the current outline algorithm.

from html.

othermaciej avatar othermaciej commented on May 22, 2024

Getting a flat list of headings (each with an associated level) is potentially useful. It is kind of simple (basically document order traversal + "is this a heading" test) but at least it won't conflict with other info in a confusing way, and it is obvious how to do previous/next operations without implementing it literally. I have no objection to it being called "outline". That name is a bit tainted in some circles, but it can be redeemed.

A forest of headings with their own hierarchy that does not necessarily match heading level would be less useful. But if that's not what is intended, there is no point complaining about it.

from html.

othermaciej avatar othermaciej commented on May 22, 2024

@jakearchibald

Interesting example. I believe a rule of "number of ancestor sectioning elements + default heading level - 1" for the heading level exposed to accessibility would make it mismatch the rendering in your example. A ## heading (level 2) would render at level 2 style, but be exposed to accessibility as a level 3 heading. I think making the accessibility view diverge from the rendering is a bigger issue than the structure of this document being logically correct in only one of these views.

In theory we could change rendering for h2 nested in a section too, but I fear that ship has sailed.

I believe the correct solution to this problem is for the Markdown --> HTML converter to lower the heading level by one. In fact, that's exactly what I did in the converter that's used to produce the HTML versions of the WHATWG's policy documents, and it's super simple to do at conversion time:

 def lower_headers(policy_markdown):
     return re.sub(r'^#', '##', policy_markdown, flags=re.MULTILINE)

from html.

jakearchibald avatar jakearchibald commented on May 22, 2024

@othermaciej I made my example confusing, sorry. I'd write my markdown so I'd use # for top level headings, then ## for next level etc etc, without having to consider the context of the content on the page.

This means I can use some of the same HTML as a "preview" on the article homepage, without having to shift all the heading levels.

I really don't have strong feelings about it, but it's a practical benefit.

The alternative is finding a markdown html generator that uses sections.

from html.

annevk avatar annevk commented on May 22, 2024

@LJWatson I thought I read somewhere that some AT does present the user with a list of headings, rather than just ways to navigate between them (as is the case in VoiceOver). If that's not the case, than the main use case for such an algorithm would be server-side scripts, to generate a "table of contents" or some such. I'm not entirely sure to what extent we should consider them as we also don't define many of the other features such scripts use. The main use of defining the algorithm then would be as a conformance requirement, to ensure that no heading levels from low to high are skipped.

As for considering h2-h6:

  • As @othermaciej already indicated these are not styled according to their nesting level. Keeping that synchronized seems good.
  • These will be frequently used throughout documents today and likely with section/article/etc. ancestor elements. The resulting heading level of a new algorithm taking them into account would very likely make the experience worse for users. This is much less of a risk with h1. With h1 it's likely that we'll make the experience better (to be clear, we'll look through data to confirm).

from html.

stevefaulkner avatar stevefaulkner commented on May 22, 2024

The following popular browsers expose the semantics of h1 to h6 elements to assistive technology (e.g. screen readers), by reference to the numeric in their TagNames (h1 = heading level 1 and so on):

  • Firefox
  • Internet Explorer
  • Chrome
  • Opera
  • Safari

JAWS for example provides the following ways to interact with headings:

  • List Headings INSERT+F6
  • Next Heading H
  • Prior Heading SHIFT+H
  • First Heading ALT+INSERT+HOME
  • Last Heading ALT+INSERT+END
  • Next Heading at Level - number keys 1 through 6
  • Prior Heading at Level SHIFT+1 through 6
  • First Heading at Level ALT+CTRL+INSERT+1 through 6
  • Last Heading at Level ALT+CTRL+INSERT+ SHIFT+1 through 6

from html.

stevefaulkner avatar stevefaulkner commented on May 22, 2024

Advice we provide to developers is "do not skip heading levels"
<h1> → <h3> is bad
<h1> → <h2> → <h3> is good
If the algorithm produces skipped levels because headingless sectioning elements are taken into account in the calculation of a headings level it codifies a practice we tell developers to avoid.

from html.

LJWatson avatar LJWatson commented on May 22, 2024

@annevk wrote:
< I thought I read somewhere that some AT does present the user with a list of headings, rather than just ways to navigate between them (as is the case
in VoiceOver).<

They do, including VO. As @stevefaulkner notes, the screen readers take the heading information exposed by the browser, and present it in different ways.

In VO for example, hit the VO modifier u, use left/right to locate the list of headings, use up/down to navigate the list of headings, and enter to select (navigate to) one.

from html.

annevk avatar annevk commented on May 22, 2024

Given that it seems this doesn't have much compatibility impact and there's some agreement on what I proposed, I went ahead and detailed it in #3499. I still need to go through all existing examples and element definitions to make sure they all make sense in this heading-focused world, but the proposal itself should now be clear.

from html.

bkardell avatar bkardell commented on May 22, 2024

I think that for the most part I like this proposal. I have three 'concerns'.. The first two are mostly about impact and messaging.

The first is just that as steve said earlier it'd be effectively building in a pattern that would create something we historically advise authors to explicitly not to write manually. That could use a solid explanation of why everyone is ok flipping on that (and confirmation that they are) or I think that could go badly.

Second is that as it stands, for those people who spent a lot of time and effort using sectioning and made good headings that didn't rely on the phantom 'document outline' that never shipped, the beautiful AT heading relationships, the conceptual 'outline' that they built will get less beautiful. For example, given something like:

  <article>
    <h1>Apple varieties</h1>
    <p>The apple is the pomaceous fruit of the apple tree...</p>

    <section>
      <h2>Red Delicious</h2>
      <p>These bright red apples are the most common found in many supermarkets...</p>
    </section>

    <section>
      <h2>Granny Smith</h2>
      <p>These juicy, green apples make a great filling for apple pies...</p>
      <div role="heading" class="note" aria-level="3">The origin of the name</div>
      <p>...blah...</p>
    </section>
  </article>

Today, this has a pretty decent AT tree and comminicates sensible heading relationships. While there is no 'outline', it's totally all 'there' for someone to make sense of with the navigational tools available in the AT... If you used them (but I'll come back to that). Some even use this their to their advantage to autogenerate TOCs and things so that everyone benefits from this, and the relationships look like this:

  • Apple Varieties
    • Red Delicious
    • Granny Smith
      • The origin of the name

But, the result of this approach to their AT trees is that it gets less sensible by the measures we have previously laid out. In other words, it's been stressed over the years "it's quite important you get this right" and "here's the critieria for what it means to be 'right'". Some people, maybe not that many, but some, for whatever reason and sometimes at great cost (sometimes by force of law) went back and tried really hard to meet those criteria, and now by those same measures it seems like we are undoing some of that. That's really the thing that worries me just a bit, because it feels like it could kind of be... disheartening.

I want to stress that I don't actually know how important this is, I'm just pointint it out as a thing to consider. It definitely should have some strong messaging about why I think if that's the route. I've said before that I think that numbers are less important than relationships and that that is confusing right now because the only relationships anyone has to make sense of the world is via numbers that implied structure and not the other way round. My experience is limited, but from the folks I've talked to, depite what we encourage, I don't think people 'use' the tools in readers to think about structures that much precisely because they have always been so broken 99% of the time and they were based on really 'flat' models. Maybe the best thing to do is to just admit that and provide a good plan going forward, and this might be it.

My third thing is that none of the proposed solutions (even mine so far) that seem 'doable' have dealt well IMO with the reality that Jake mentions and I think that's potential fatal to real success. Very often a site (or sections of a site) can be very structured, but what is frequently just referred to as content is authored in a way a lot more like it is read - either with a decent rich text editor or as simple markdown or something. Speaking "by volume" this is a huge huge huge amount of the web for the simple reason that tools like this dramatically increase the potential number of authors by specifically being not intensely structured, more like the traditional 'flat' documents. It's entirely possible to author "good" content with good/sensible headings that isn't really 'compatible' with inclusion in your pretty structured page.

So, I have what I think is a rather small tweak to suggest: What if we added to this proposal a non-reflected, non-dynamic policy attribute or something (forgive my potential butchering/overloading of terms here as I try to explain) so that authors could simply identify upfront that this particular container will hold 'flat' content so that we could maybe choose a slightly different strategy there. In these, we'd simply use Anne's logic to calculate the effective level of the container and then add that to the specified tag heading level. Thus you could have something like

  <section>
    <h1>One</h1>
    <section>
      <h1>Two</h1>
      <article heading-policy="flat">
        <!-- this is simply included 'flat' content -->
        <h1>Apple varieties</h1>
        <p>The apple is the pomaceous fruit of the apple tree...</p>

          <h2>Red Delicious</h2>
          <p>These bright red apples are the most common found in many supermarkets...</p>

          <h2>Granny Smith</h2>
          <p>These juicy, green apples make a great filling for apple pies...</p>
      </article>
      </section>
    </section>
  </section>

and the result would be like

<section>
    <h1 aria-level="2">One</h1>
    <section>
      <h1 aria-level="3">Two</h1>
      <article heading-policy="flat">
        <h1 role="heading" aria-level="4">Apple varieties</h1>
        <p>The apple is the pomaceous fruit of the apple tree...</p>

          <h2 role="heading" aria-level="5">Red Delicious</h2>
          <p>These bright red apples are the most common found in many supermarkets...</p>

          <h2 role="heading" aria-level="5">Granny Smith</h2>
          <p>These juicy, green apples make a great filling for apple pies...</p>
      </article>
    </section>
  </section>

I have hacked a mod of Anne's polyfill which does this, it seems like a fairly minor tweak? Again, I'm suggesting this would only be at parse time and not live, that is, adding or removing the attribute (or however it might be done) wouldn't affect things. That makes me think this would make more sense as a tag (since that would better explain that relationship)? Maybe it would make sense to separately float a custom element and see if people used it/correctly? I'm unsure, I guess I just think this very very common use case deserves some discussion/thought.

from html.

jakearchibald avatar jakearchibald commented on May 22, 2024

it'd be effectively building in a pattern that would create something we historically advise authors to explicitly not to write manually. That could use a solid explanation of why everyone is ok flipping on that

"The bug was fixed" seems good enough. I mean, we've done that a lot in the past.

<article>
  <h1>Apple varieties</h1>

In this case the article is redundant. From the spec:

When the main content of the page (i.e. excluding footers, headers, navigation blocks, and sidebars) is all one single self-contained composition, that content may be marked with an article, but it is technically redundant in that case (since it's self-evident that the page is a single composition, as it is a single document).

I'd rather we bumped the level of all headings according to the number of ancestor sectioning elements than introduce something extra like heading-policy.

from html.

bkardell avatar bkardell commented on May 22, 2024

"The bug was fixed" seems good enough. I mean, we've done that a lot in the past.

I'm not sure which bug this really refers to. Effectively, as I understand it: A whole bunch of documents that would have been previously evaluated as "this contains some bad practices that create a poor experience and here's why" still would be experienced the same way, but the bar just moved... Again, I think it's entirely plausible that there's a perfectly acceptable explanation for this reversal of position. I'd just like to see it articulated by a11y folks because a lot of investment has gone into explaining why this is undesirable and training people to identify by noticing that experience and then opening bugs to remediate this. I feel like for sure this is going to have a not-insignificant impact for me personally at work which will require explanation/retraining. Again, not an argument against it - just asking for someone to articulate well.

In this case the article is redundant.

This was just intended as a fragment demonstrating both use of section/h1 and 'flat' content, not an entire document (thus no body, etc), so it's not.

I'd rather we bumped the level of all headings according to the number of ancestor sectioning elements than introduce something extra like heading-policy.

That seems... simple and fine? I thought this was decided against earlier in the thread because of some issue and was offering a compromise based on the distinction between 'flat' stuff and 'structured' stuff, but... I like the simplicity of that actually.

from html.

jakearchibald avatar jakearchibald commented on May 22, 2024

I'm not sure which bug this really refers to. Effectively, as I understand it: A whole bunch of documents that would have been previously evaluated as "this contains some bad practices that create a poor experience and here's why" still would be experienced the same way, but the bar just moved

The bug was "browsers do not consider sectioning elements when exposing the outline to AT via heading levels", and that's what we're aiming to fix here.

Many years ago, we used to say "Don't concatenate strings using +, instead create an array of strings then .join('') them. It's faster in IE". Anyway, new versions of IE fixed the issue, and market share shifted to browsers without the bug. In these modern browsers, + is faster than the array method. Advice to developers was "The bug has been fixed. Just use +".

This was just intended as a fragment demonstrating both use of section/h1 and 'flat' content, not an entire document (thus no body, etc), so it's not.

Does that mean you'd have multiple <h1>s in the page then? Isn't that bad practice?

from html.

bkardell avatar bkardell commented on May 22, 2024

The bug was "browsers do not consider sectioning elements when exposing the outline to AT via heading levels", and that's what we're aiming to fix here.

Right now, if i have no sectioning elements and make explicit markup that skips levels. We would say, "that is bad because it creates an experience where users cannot understand - a 3 should be preceded by a 2 because this is how you understand structure using numbers (a mental outline)". No 'bug' is being fixed with relation to that markup. Nothing about experience changes there, simply a thing that my QA/a11y depts might identify as 'bad' yesterday, suddenly isn't. From my understanding, at least. I'd like to have an explanation to hand them, that's it.

Does that mean you'd have multiple <h1>s in the page then? Isn't that bad practice?

Sure, but isn't the whole current proposal actually based on sectioning plus h1s? I'm showing what I thought is your actual use case. You do this right? Then you want to include some flat content and have the relationships continue to make sense. That's it.

from html.

bkardell avatar bkardell commented on May 22, 2024

This is not true. The proposed change actually makes it a conformance error to skip a heading level.

The "why" of not skipping heading levels that I have always heard and explained has to do with the AT, not the markup. There, even if you don't in markup - this creates skipped heading levels in AT, right? Again, I want to be super clear that I am not against this change. I pondered hard how to reply because I know the 'concerns' sound kind of negative, but they're mostly just about asking for a lucid explanation from a11y folk who support this on this seeming dissonance and messaging this well.

from html.

jakearchibald avatar jakearchibald commented on May 22, 2024

simply a thing that my QA/a11y depts might identify as 'bad' yesterday, suddenly isn't. From my understanding, at least. I'd like to have an explanation to hand them, that's it.

Did you see my stringArray.join('') example? Doesn't this answer your question?

Sure, but isn't the whole current proposal actually based on sectioning plus h1s? I'm showing what I thought is your actual use case.

I was taking from your "as it stands" example. You were giving an example of something that's good practice today, but it doesn't seem to be good practice today.

I don't think I'm helping here, so I'll step back.

from html.

bkardell avatar bkardell commented on May 22, 2024

@annevk has just explained to me a misunderstanding I was operating under with regard to @stevefaulkner's comment

Advice we provide to developers is "do not skip heading levels"
<h1> → <h3> is bad
<h1> → <h2> → <h3> is good
If the algorithm produces skipped levels because headingless sectioning elements are taken into account in the calculation of a headings level it codifies a practice we tell developers to avoid.

While the algorithm can, in theory, create skipped levels they wouldn't be any more 'acceptable' than they were before and the ways that would create them would now be flaggable as conformance errors. Sorry for any noise/confusion on that item, that's enough for me.

from html.

stevefaulkner avatar stevefaulkner commented on May 22, 2024

Note: the w3c nu markup checker has warnings (and has had for some time) for sections missing headings and use of multiple h1's etc.
for example:
https://validator.w3.org/nu/?showsource=yes&showoutline=yes&doc=https%3A%2F%2Fs.codepen.io%2Fstevef%2Fdebug%2FNyJKJz

from html.

annevk avatar annevk commented on May 22, 2024

Given the requirement in the proposed change that you cannot skip heading levels:

Each heading following another heading lead in document headings must have a heading level that is less, equal, or 1 greater than lead's heading level.

I don't think we need to require that sectioning content has a heading, unless there's a concern with that on its own, but then that's probably best discussed in a new issue.

Not using multiple headings with heading level 1 is something we could consider adding, though currently the specification says this is fine and even includes an example that does that. I think that therefore that's also best discussed separately.

from html.

alastc avatar alastc commented on May 22, 2024

Not sure I'm following entirely, but there is an exception I'd like to check.

A fairly common pattern is to have one or more headings above/before the H1.

E.g.

  • H2: Site menu
  • H1: Main heading
  • H2: Section 1

etc. Such as http://www.bbc.co.uk/news/live/uk-43202018
image

This is a desirable pattern from an accessibility point of view, is that still valid with this new approach?

from html.

alastc avatar alastc commented on May 22, 2024

It's worth examining, from the summary I'd expect these sites to be fine:

  • H1s only with good section nesting for levels.
  • An H1 at the top (not in nested sections) and then H2-H6 properly.

Sites that would not provide a good experience would be:

  • Any site using a mix of (mutiple) H1s and H2-H6s will be broken as per @rehierl's example above.
  • Any site using H1s with poor section structure.

I'm trying to think of any inbetween structures, for example:

<body>
  <banner>
     <h2>Nav heading</h2>
  </banner>
  <main>  
     <h1>Page heading</h1>
    <article>
      <h2> C </h2> 
      <h3> D </h3>
    </article>
  </main>
</body>

I think that would be fine, but if the structure was main > section > h1, that would be an H2? That seems like an easy mistake to make.

It feels like you really have to go one way or the other, mixing multiple H1s with H2-6s is where it would go wrong. I'm guessing someone already came up with the idea of detecting H2-6 and switching to classic heading-levels?

from html.

annevk avatar annevk commented on May 22, 2024

@alastc switching is too expensive (and could also lead to very weird experiences on slow loading pages).

from html.

bkardell avatar bkardell commented on May 22, 2024

I'm guessing someone already came up with the idea of detecting H2-6 and switching to classic heading-levels?

Yes, but because this is difficult and expensive and simultaneously also a very real thing that will happen with pretty much any existing tool or CMS (because visual editors, markdown, etc think of text in a more traditional 'flat' way - that's where our original ideas about them come from in fact) I offered that a kind of indicator that let you know 'this element contains that kind of stuff' would be a way to potentially bridge the gap in a way that seems achievable both from an implementation standpoint and an 'authors could actually accomplish this' standpoint. Effectively, the current proposal says that h1's level becomes the section depth - this would allow that all the levels inside an element with such an indicator become section depth + (tag level -1). It seems pretty easy to make as a custom element or polyfill (in fact, I'm playing with a version of it in a project right now) so I'm not trying to push that it has to be a part of this, but it does seem like without it it will still be very hard for most authors to use common tools to create good headings.

from html.

alastc avatar alastc commented on May 22, 2024

Fair enough.

In general then safe authoring advice for this proposal would be:

  • Use an H1 for the main page heading, make sure it is not in a nested section element.
  • Use H2-6 as you do now. Sorry: as you should now.

Then, when there is reasonable UA support you could switch to H1s only and use sectioning for levels.

Have I understood that correctly?

from html.

rehierl avatar rehierl commented on May 22, 2024

Even though I am only a member of the general public, I need to ask you to do the following:
If only for a moment, try to take a look at the bigger picture.

tldr - The proposed heading-level algorithm may reflect "reality", but it won't solve the core problem: Figure out a way to teach computers how to read the content an author associates with a heading (aka. sections). The core concept of the current algorithm (i.e. sections) isn't what made it fail. The attempt to make it reflect reality is what broke the algorithm we have! So use the proposed design to complement (i.e. not replace) it. And, in the long run, fix the existing design, because that is what will drag us out of the mess we are in. - /tldr

With regards to ...

(2015-12-27, @domenic) - Quotes some twitter discussion: ... We have higher standards ... (W3C's) kind of self-contradictory patchwork ... update the spec to reflect reality.

(2016-10-23, @fititnt) - A requests to: decide the best path, explain it, and be consistent.

(2018-03-01, @bkardell) - A reminder that: it's been stressed over the years "it's quite important you get this right" and "here's the criteria for what it means to be 'right'".

(2018-01-26, @othermaciej) - The outline (as currently defined) is a list of (nested) sections (i.e. a "forest") ... an algorithm that produces a forest of sections is neither necessary nor helpful ... the new outline algorithm (should) operate on headings, not sections.

The reason for "a list of sections"

Take a closer look at WHATWG's outline algorithm in order to figure out what the reason for the "a list of sections" definition really is. (Note that I fully agree here: That part (i.e. forest) does not make sense and should be changed). However, if you'd scroll down to "When entering a heading content element", then you might notice this:

  1. The only case in which the "current section" can end up with having no heading is, if that section was declared by an element of sectioning content or sectioning root.

  2. If the "current section" has no heading, and if the first element of heading content is entered inside of such a section, then that heading element is reused as the section's heading.

  3. The first "Otherwise" block is what I'd call a "performance shortcut" which causes the loop beneath it to always create a subsection (see "append it to candidate section"). So the first "Otherwise" block is what is relevant with regards to the above definition, not the loop beneath it.

fragment 4-1      toc 4-1   fragment 4-2       toc 4-2
============      =======   ============       =======
<body>            1. A      <body>             1. Untitled
  <h1> A </h1>    2. B        <section>        1.1. A
  <h1> B </h1>                  <h1> A </h1>   2. B
</body>                       </section>
                              <h1> B </h1>
                            </body>

4-1) If the current heading being entered has a rank that is greater or equal to the rank of the current section's heading, then a sibling section is created (i.e. a forest).

4-2) If the current section has an implied heading, then a sibling section is created (i.e. a forest). Note that this case will only be triggered under certain circumstances. However, if you look close enough at toc 4-2, you could spot an inconsistency error with regards to the "the first element of heading content" definition. Other than that, I'll ignore fragment 4-2 because of it being "bad-practice".

Now, please focus on 4-1: (1) The reason why the current algorithm ends up with "a list of sections" is
due to a heading/rank-based perspective. But, instead of actually taking a look at what went wrong, you (2) suggest to let the "new" outline algorithm operate on headings.

I don't know about you, but I find that rather ironical because a heading-based perspective is largely responsible for our situation. And that is why I have to disagree: "It" is about sections, not headings!

With regards to fixing what we already have ...

I can only cite what @fititnt and @bkardell wrote (see above): Get it right!

Use Graph Theory (i.e. not statistics) to prove on a formal level that, whatever you come up with next, is consistent. One way or another, I am convinced that Graph Theory will win. After all, ... Earth isn't the center of the universe, it never was! ... (Note the critical switch in perspective!)

from html.

rehierl avatar rehierl commented on May 22, 2024

@bkardell - I am in the process of spending some time with some "it" ("some time", what an understatement that is). Here is what I think:

You are right, the outline is a higher level version of a document's node tree. And if you understand "sectioning nodes" as a class of nodes which, more or less, tell an algorithm where exactly a section begins and where it ends (i.e. heading elements, sectioning content elements, sectioning root elements), then that tree of sections (aka. outline) is defined by those sectioning nodes.

However, you could even take it one step further: Some of those sectioning nodes (i.e. the sectioning root elements) can even be understood to not just define sections within a document's node tree, but also to define sections within the document's outline. After all, a tree of sections is in its core just another node tree. So what you actually have is this: a document, an outline, and an outline of an outline.

from html.

rehierl avatar rehierl commented on May 22, 2024

The <h> element ... I have seen the discussions, but I didn't have enough time to really think about it in detail. So here is my current and limited take on that element in order to avoid drifting off in a "war of beliefs":

The reason for "a forest of sections" is the reuse of heading elements. But instead of limiting the "reuse" to what it was supposed to do (i.e. only define a heading), people thought that a heading element should still have a rank under these kind of circumstances. What proof is there that the section of a <section> element even needs an inner or an outer rank?

The problem with the <h> element is that it "looks" too similar to the <hX> elements. My guess is, that people will confuse it with an element that declares a section (i.e. a sectioning node) and thus would try to use it just like all the other <hX> elements. Yes, introduce it to teach the core concept of a rank-less sectioning node. No, don't introduce it as an element that is not a sectioning node.

If used as a sectioning node, then what rank should it have? Should it act as a <h0> element? Or should it act more like a <h7> element instead?

The <h> element is just an option, not the solution itself.

And here is the bummer: In the long run, I'd much prefer the reuse of another element, the title element: If every element of sectioning content or sectioning root has only one top-level section and, as such, represents a "flat thing", then what is the heading of the <body> element? The document's title ... The current definition of the <title> element (IMHO) seems to better fit the intended purpose than the <h> element.

from html.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.