Error summary

Shown only after a submit fails (UX guide §6.2): all errors at once, in the order of the form. Each entry links to its field (#fieldId), so a click or Enter jumps there. The same messages also appear at the fields themselves.

After rendering, move focus to the summary (el.focus() — it has tabindex="-1") and scroll it into view below the sticky top bar. It has role="alert", so the count and the list are announced.

The title states the number of problems ("Bitte prüfe 2 Angaben"). Messages say what to do, not what is wrong in technical terms. Server errors (problem+json errors[]) map onto the same entries.

Examples

Two errors (default title)

Data
render({
  "errors": [
    {
      "fieldId": "email",
      "message": "E-Mail ist unvollständig"
    },
    {
      "fieldId": "birthdate",
      "message": "Geburtsdatum fehlt"
    }
  ]
})
Markup
<div class="error-summary" id="error-summary" tabindex="-1" role="alert" aria-labelledby="error-summary-title">
<h2 class="error-summary__title" id="error-summary-title">Bitte prüfe 2 Angaben</h2>
<ul><li><a href="#email">E-Mail ist unvollständig</a></li><li><a href="#birthdate">Geburtsdatum fehlt</a></li></ul>
</div>

Custom title and id

Data
render({
  "id": "guardian-errors",
  "title": "Angaben zur erziehungsberechtigten Person fehlen",
  "errors": [
    {
      "fieldId": "guardian-name",
      "message": "Gib den Namen der erziehungsberechtigten Person ein."
    }
  ]
})
Markup
<div class="error-summary" id="guardian-errors" tabindex="-1" role="alert" aria-labelledby="guardian-errors-title">
<h2 class="error-summary__title" id="guardian-errors-title">Angaben zur erziehungsberechtigten Person fehlen</h2>
<ul><li><a href="#guardian-name">Gib den Namen der erziehungsberechtigten Person ein.</a></li></ul>
</div>

Data contract

What render(data) accepts — validated against this JSON Schema in development and tests. Unknown fields are rejected. The same schema is in components.json.

FieldTypeRequiredDefaultDescription
idstringoptional"error-summary"Id of the box; the title gets {id}-title. Must be unique on the page.
pattern ^[A-Za-z][\w-]*$
titlestringoptional—Heading. Defaults to "Bitte prüfe 1 Angabe" / "Bitte prüfe {n} Angaben".
min 1 chars
errorsarray of objectsrequired—One entry per invalid field, in form order.
min 1 items
errors[].fieldIdstringrequired—Id of the invalid control (link target #fieldId). For a choice group use the id of its first input ({id}-1).
pattern ^[A-Za-z][\w-]*$
errors[].messagestringrequired—What to do, usually the same text as the field's error ("Gib ein Geburtsdatum ein.").
min 1 chars
JSON Schema
{
  "type": "object",
  "additionalProperties": false,
  "required": [
    "errors"
  ],
  "properties": {
    "id": {
      "type": "string",
      "pattern": "^[A-Za-z][\\w-]*$",
      "default": "error-summary",
      "description": "Id of the box; the title gets `{id}-title`. Must be unique on the page."
    },
    "title": {
      "type": "string",
      "minLength": 1,
      "description": "Heading. Defaults to \"Bitte prüfe 1 Angabe\" / \"Bitte prüfe {n} Angaben\"."
    },
    "errors": {
      "type": "array",
      "minItems": 1,
      "description": "One entry per invalid field, in form order.",
      "items": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "fieldId",
          "message"
        ],
        "properties": {
          "fieldId": {
            "type": "string",
            "pattern": "^[A-Za-z][\\w-]*$",
            "description": "Id of the invalid control (link target `#fieldId`). For a choice group use the id of its first input (`{id}-1`)."
          },
          "message": {
            "type": "string",
            "minLength": 1,
            "description": "What to do, usually the same text as the field's error (\"Gib ein Geburtsdatum ein.\")."
          }
        }
      }
    }
  }
}

Markup & states

Root: div.error-summary — usable without render() by writing the markup directly.

Attributes

AttributeValuesDefaultDescription
role="alert"——Announced when inserted.
tabindex="-1"——Can receive focus programmatically after submit.
aria-labelledby"{id}-title"—Named by its heading.

Parts

PartDescription
.error-summary__titleThe h2 title with the number of problems: semibold, --color-danger-text.
ul > li > a[href="#fieldId"]Linked error messages.

Behaviour & events

Module: (page code)

Render on failed submit, then summary.focus() and scroll into view. Remove it when the form is submitted again successfully. Clicking a link moves focus to the field (native fragment navigation focuses focusable targets).

Accessibility

  • Focus moves to the summary after a failed submit; role="alert" announces it.
  • Every error is a link to its field, and the same message appears at the field (WCAG 3.3.1 / 3.3.3).
  • Errors are identified in text — the danger tint and the 4 px danger edge on the start side (design guide §9.2) are not the only signal.

Guidance

DoList errors in form order.
DoKeep the filled-in values — a failed submit never clears fields.
Don'tDon't show the summary while the user is still typing.
Don'tDon't use a toast for field errors.

Related: Form field · Checkbox / radio group · Alert / banner