Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

Avoid skipping heading levels (h1 followed by h2, h2 followed by h3,...):

  • Levels can should only be skipped when closing subsections (i.e. an h4 tag followed by an h2 tag to start a new section)

  • If a heading level is skipped, this could provide a negative experience to users as they may feel compelled to go back and look for the “missing” heading

  • An exception to this rule is headings for fixed content (e.g. sidebars) where the rankings should not change depending on the ranks of the content area. Consistency across pages is more important

...

  • If there is no h1 in a mockup, you can add one with className="sr-only" so only screen readers “see” it.

    • Example: <h1 className="sr-only">Hello world</h1>

    • Will be hidden from the view but AT will still pick up on it

  • This doesn’t have to be the first heading element in the document but it usually is (see this example)

  • The page title attribute (in the <head> element) should generally reflect or be a superset of the h1 content.  Example: <h1>Notes</h1> has <title>Notes | edx.org</title>

    • Change the <title> whenever the H1 changes.

    • If possible, also push a new route onto the Back stack when the h1 changes

...

Defines the hierarchical level of an element within a structure; when combined with role="heading" will tell AT that the element is a heading. The “heading” role requires use of the aria-level attribute to indicate its position in the hierarchy.

  • role="heading" without an aria-level attribute should will default to an H2 semantically h2, but you should include the aria-level attribute for clarity anyway.

  • This can even be done to hN tags if necessary

  • Example:

    • <div role="heading" aria-level="3">Hello World</div> is the same as using an h3

  • This also enables devs to level headings beyond what is provided natively (h1 - h6)

    • We could theoretically create an h7 this way using aria-level

...

  • The main header for dialogs is, by convention, an H2 h2. If there is a request to use a different heading level tag as the top-level in the dialog, then add role="heading" and aria-level=N attributes to all headers as appropriate to start from level 2

...

  1. This can be useful when there is more than one of the same sectioning element on a page (e.g. <nav> , <main> , <header> , <footer> , <article>, full list here)

  2. The id of the hN tag will need match the value of the parent element’s aria-labelledby attribute, and must be unique to the page.

  3. See this example of aria-labelledby being used to differentiate two different <nav> elements

  4. You should generally use aria-labelledby to name all <section> and <nav> elements in this way when appropriate visible DOM elements are present (i.e. headings). If they’re they're not present, then you can either use aria-labelledby with sr-only elements, or use aria-label (which takes a human-readable string, not a DOM ID)

  5. Dialogs (div role="dialog"or <dialog>`) need an accessible name, which generally comes from an aria-label attribute or aria-labelledby (pointing to the main header in the dialog).

...

Paragon provides a CSS class for each hN element (.h1, .h2, .h3,...). These do not provide any information for screen readers or accessibility. They are intended to change font-size and styling.

...

There is also a .heading-label class. Worth noting that this doesn’t effect accessibility (has no relation to aria-label) and is primarily for styling purposes.

See Paragon https://paragon-openedx.netlify.app/foundations/typography for more information on which properties are provided in each class and how they can be implemented.

Resources

https://www.tpgi.com/heading-off-confusion-when-do-headings-fail-wcag/

...