Skip to content

Add label and legend headingLevel option#1670

Open
colinrotherham wants to merge 5 commits intomainfrom
heading-level
Open

Add label and legend headingLevel option#1670
colinrotherham wants to merge 5 commits intomainfrom
heading-level

Conversation

@colinrotherham
Copy link
Contributor

@colinrotherham colinrotherham commented Nov 5, 2025

Description

The Nunjucks option isPageHeading sets whether the label or legend also acts as the heading for the page.

This PR adds a new headingLevel Nunjucks option as a replacement for isPageHeading when a custom heading level is necessary, for example when a label or legend acts as the heading for a landmark:

<aside>
  {{ input({
    label: {
      text: 'Search',
-     isPageHeading: true
+     headingLevel: 2
    }
  }) }}

  <!-- // … -->
</aside>

This aligns with support already in NHS.UK React components

See related PR and issue over on GOV.UK Frontend

Checklist

@edwardhorsford
Copy link
Contributor

I support adding a size option, but am unsure / cautious about headingLevel and wonder if it should be considered separately. I think we'd want to be cautious about the guidance for headingLevel whereas size is probably much more straightforward to document.

We don't expect users to navigate form pages by heading - they typically need to complete the entire form. I'll note GOV.UK does not have such an option, and only added isPageHeading because there's a strict requirement for pages to have an h1, and in 'page per thing', having both a legend and a heading on the page was messy. I don't think we've seen a requirement that other things get marked up as headings. They could do, but it would be good to hear from screen reader users about whether that's valuable vs extra noise and overly semantic.

More generally on the web I don't think forms tend to mark up every legend as a heading, and I worry that if this headingLevel option were introduced, we'd start to see these extra semantics added that may not actually be helpful. If they are, then great - but we should understand first if that's the case.

@selfthinker have you looked at this at all before?

@colinrotherham colinrotherham temporarily deployed to nhsuk-frontend-pr-1670 November 5, 2025 12:01 Inactive
@frankieroberto
Copy link
Contributor

I like the size option! That feels uncontroversial, and a lot easier for people to remember than the right class.

I don't have strong views on headingLevel (needs detailed accessibility research), but if we do add that, then does it make isPageHeading: true redundant?

@colinrotherham
Copy link
Contributor Author

I don't have strong views on headingLevel (needs detailed accessibility research), but if we do add that, then does it make isPageHeading: true redundant?

It does indeed. The same point was made in alphagov/govuk-frontend#5240 (comment)

Makes sense

@colinrotherham
Copy link
Contributor Author

colinrotherham commented Nov 21, 2025

I shared an example with the GOV.UK Design System team:

For extra context, some staff facing services can have multiple <form> elements on a page:

  • Main content (e.g. comment box) <form> with <h1>
  • Aside content (e.g. search box) <form> with <h2>

An update from the GOV.UK team has been passed back in return

They're using custom heading levels in smart answers and (internal) publishing applications

But other than that the heading level options are not widely used

@colinrotherham
Copy link
Contributor Author

colinrotherham commented Nov 21, 2025

HTML examples shared with the GOV.UK Design System team

We've reached an early agreement that custom heading levels should be limited to:

  • Whether the label or legend also acts as the heading for the page
  • Whether the label or legend also acts as the heading for the page or landmark

They'd like to discuss this further at their dev catch up sessions, with emphasis on guiding people to only use headingLevel option when strictly necessary (e.g. avoiding duplicate content and ensuring unique landmarks)

Main content with aside

E.g. Search sidebar alongside main content

<main>
  <h1><label for="question">Question</label></h1>
  <input id="question">

  <!-- // … -->
</main>

<aside>
  <h2><label for="search">Search</label></h2>
  <input id="search">

  <label for="sort-by">Sort by</label></h2>
  <select id="sort-by">

  <!-- // … -->
</aside>

Main content with multiple sections

E.g. Staff facing team profile page with editable sections per team member

<main>
  <h1>Your team</h1>

  <!-- // … -->
</main>

<section>
  <h2><label for="person1-question1">What about Colin?</label></h2>
  <input id="person1-question1">

  <label for="person1-question2">Another question</label>
  <input id="person1-question2">

  <!-- // … -->
</section>

<section>
  <h2><label for="person2-question1">What about Romaric?</label></h2>
  <input id="person2-question1">

  <label for="person2-question2">Another question</label>
  <input id="person2-question2">

  <!-- // … -->
</section>

@colinrotherham colinrotherham changed the base branch from main to example-variants November 26, 2025 18:31
@colinrotherham colinrotherham changed the title Add label and legend size and headingLevel options Add label and legend headingLevel option Nov 26, 2025
@colinrotherham colinrotherham changed the base branch from example-variants to heading-size November 26, 2025 19:43
@colinrotherham colinrotherham temporarily deployed to nhsuk-frontend-pr-1670 November 26, 2025 20:43 Inactive
@colinrotherham colinrotherham marked this pull request as ready for review November 26, 2025 20:46
@colinrotherham colinrotherham temporarily deployed to nhsuk-frontend-pr-1670 November 27, 2025 07:18 Inactive
@colinrotherham colinrotherham temporarily deployed to nhsuk-frontend-pr-1670 November 27, 2025 07:50 Inactive
@colinrotherham colinrotherham temporarily deployed to nhsuk-frontend-pr-1670 November 27, 2025 09:45 Inactive
Base automatically changed from heading-size to main November 27, 2025 16:40
@colinrotherham colinrotherham temporarily deployed to nhsuk-frontend-pr-1670 December 2, 2025 12:48 Inactive
@colinrotherham colinrotherham temporarily deployed to nhsuk-frontend-pr-1670 December 5, 2025 17:06 Inactive
@colinrotherham colinrotherham temporarily deployed to nhsuk-frontend-pr-1670 December 9, 2025 14:04 Inactive
@colinrotherham colinrotherham temporarily deployed to nhsuk-frontend-pr-1670 December 22, 2025 09:33 Inactive
@colinrotherham colinrotherham temporarily deployed to nhsuk-frontend-pr-1670 January 2, 2026 21:17 Inactive
@sonarqubecloud
Copy link

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

Status: Needs review

Development

Successfully merging this pull request may close these issues.

4 participants