Skip to content

Selecting a radio answer re-renders the step and scrolls the page to the top #4

Description

@TaigaTi

What happens

On the form prototypes, selecting an answer on a radio question scrolls the page back to the top. You lose your place and have to scroll down again to continue the step.

Example — Prototypes/nhc-rental-application.html:

Do you or your spouse own land or property?

  • Yes
  • No

Steps to reproduce

  1. Open Prototypes/nhc-rental-application.html.
  2. Go to the step containing "Do you or your spouse own land or property?" and scroll so the question is below the fold.
  3. Select Yes or No.
  4. The page jumps to the top.

Expected: the scroll position stays put and focus stays on the option you just chose; only the revealed/hidden conditional content changes.

Actual: the whole step is re-rendered, the page scrolls to the top, and focus on the radio is lost.

Cause

It's the shared framework, not the individual prototype.

Radios marked { trigger: true } get a data-trigger-render="1" attribute. In assets/govbb-framework.js the change handler calls a full re-render:

// assets/govbb-framework.js:201
if (el.getAttribute('data-trigger-render')) GovBB.render();

And GovBB.render() rebuilds the step and then unconditionally scrolls to the top:

// assets/govbb-framework.js:47
GovBB.render = function () {
  ...
  el.innerHTML = fn();          // whole step rebuilt — focus is destroyed
  ...
  window.scrollTo(0, 0);        // line 63 — always fires
};

window.scrollTo(0, 0) is the right behaviour when render() is called for step navigation (GovBB.next / GovBB.prev, lines 130–150), but wrong when it's called for a mid-step conditional reveal. Both paths share the same function, so the conditional reveal inherits the scroll reset.

Suggested fix

Give render() a way to distinguish the two callers — e.g. GovBB.render({ scroll: false }), with the data-trigger-render handler passing scroll: false and the navigation callers keeping the current behaviour. Restoring focus to the field that triggered the re-render would also be needed, since innerHTML = fn() throws focus away.

Scope — wider than this one form

data-trigger-render is used across many prototypes, so this affects all of them. Grep shows it on radios, selects and text inputs in at least: nhc-rental-application, nhc-state-land, terms-leave, uniform-grant, textbook-grant, home-schooling, special-ed-bursary, direct-deposit, bssee-choice, bssee-defer, exam-fee-refund, examination-travel, exam-duties-claim, nscp-camper-registration, temporary-teacher, non-nationals-entry.

Worth checking as part of the same fix: for text inputs the bound event is input rather than change (govbb-framework.js:196), so a text field carrying data-trigger-render — e.g. child-school in uniform-grant.html — would re-render, scroll to top and drop focus on every keystroke. I've read this from the code but not run it, so it needs confirming in the browser.

Why it matters

An unexpected change of scroll position and loss of focus on input is what WCAG 2.2 3.2.2 On Input is about. For keyboard and screen reader users the focus loss is the more serious half — they're returned to the top of the document mid-question.

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions