Headings and text

knitr::opts_chunk$set(
  collapse = TRUE,
  comment = "#>"
)
library(shinyGovstyle)

Overview

This vignette covers all functions in shinyGovstyle that produce styled text content: headings, body text, lists, callout components, links, and typography. For page structure and layout, see the Layout options vignette.


heading_text()

Creates a semantic HTML heading element with a GOV.UK heading CSS class.

heading_text("Summary", size = "l", level = 2)

Arguments

| Argument | Default | Description | |---|---|---| | text_input | — | The heading text to display | | size | "xl" | Visual size: "xl", "l", "m", or "s" | | level | 1 | HTML heading level: integer 1–6 | | id | auto | Element ID — auto-generated from text_input if omitted |

Visual size and semantic level are independent

size controls the CSS class applied (govuk-heading-xl, govuk-heading-l, etc.), which determines how the heading looks. level controls the HTML element used (<h1>, <h2>, etc.), which determines its position in the document outline read by screen readers and assistive technologies.

These are independent because it is occasionally necessary to use a smaller visual heading at a higher semantic level, or vice versa. For example, a page where the first visible heading needs to be modest in size but is still structurally the <h1>:

heading_text("User guide", size = "m", level = 1)

Always set both arguments deliberately. Do not leave level at its default of 1 for every heading on a page.

Recommended size–level pairings

Standard pages (most dashboards and data tools):

| Heading role | size | level | |---|---|---| | Page title | "l" | 1 | | Section heading | "m" | 2 | | Sub-section heading | "s" | 3 |

Long-form content (user guides, methodology, accessibility statements):

| Heading role | size | level | |---|---|---| | Page title | "xl" | 1 | | Section heading | "l" | 2 | | Sub-section heading | "m" | 3 | | Sub-sub-section heading | "s" | 4 |

Accessibility

Do not skip heading levels. Moving from an <h1> straight to an <h3> breaks the document outline and makes it harder for screen reader users to navigate, as they commonly jump between headings to scan a page. This is a requirement under WCAG 2.2 success criterion 1.3.1: Info and Relationships.

Write headings in sentence case. Only capitalise the first word and proper nouns.

# Correct — sentence case
heading_text("Summary of findings", size = "l", level = 1)

# Incorrect — title case
heading_text("Summary Of Findings", size = "l", level = 1)

For more information, read the GOV.UK headings guidance.

Heading IDs

If id is not supplied it is auto-generated by lowercasing text_input and replacing non-alphanumeric characters with underscores. Supply an explicit id when you need a stable anchor to link to, or when two headings would otherwise generate the same ID:

heading_text("Methodology", size = "l", level = 2, id = "methodology")

gov_text()

A wrapper that produces a <p class="govuk-body"> paragraph element. Use it when you want to add body text with correct GOV.UK styling without writing raw tag calls.

gov_box(
  size = "two-thirds",
  gov_text("This is a paragraph of body text.")
)

gov_list()

Creates a GOV.UK-styled list. The style argument controls both the HTML element used and the visual presentation:

| style | HTML element | Appearance | |---|---|---| | "none" (default) | <ul> | Plain, no markers | | "bullet" | <ul> | Bulleted list | | "number" | <ol> | Numbered list |

gov_list(c("First item", "Second item", "Third item"), style = "bullet")

gov_list(c("First step", "Second step", "Third step"), style = "number")

Use style = "number" when order matters — steps in a process, ranked results, or sequential instructions. Use style = "bullet" for unordered items. The plain style ("none") is useful when you want list semantics for screen readers without a visual marker.

For more information, read the GOV.UK lists guidance.


insert_text()

Displays a GOV.UK inset text box — a bordered callout for supplementary information that is related to, but not the main focus of, the surrounding content.

insert_text(
  inputId = "processing-note",
  text = "It can take up to 8 weeks to process your application."
)

Use inset text for information the user needs to know but that is not the primary action or decision on the page — for example, a processing time, an exception to a rule, or a clarification. Do not use it for warnings about consequences; use warning_text() instead.

For more information, read the GOV.UK inset text guidance.


warning_text()

Displays a GOV.UK warning text component: a bold statement with a prominent "!" icon, used to warn users about something with serious consequences.

warning_text(
  inputId = "fine-warning",
  text = "You can be fined up to £5,000 if you do not register."
)

The "!" icon carries aria-hidden = "true" and the word "Warning" is prepended as visually hidden text, so screen readers announce "Warning: [your text]" without reading out the icon character. Given this, you should avoid starting the text with 'Warning', else you'll submit users to 'Warning Warning'.

Use warning_text() when the consequence of missing the information is serious. For less critical supplementary information, use insert_text() instead.

For more information, read the GOV.UK warning text guidance.


noti_banner()

Displays a GOV.UK notification banner for information that is not directly related to the current page content — such as a service-wide problem, an upcoming deadline, or the outcome of a previous action.

Two types

Standard (default, blue): for neutral information such as service problems or upcoming events.

noti_banner(
  inputId = "service-notice",
  title_txt = "Important",
  body_txt = paste0(
    "This service will be unavailable on Saturday ",
    "14 June from 8am to 6pm."
  )
)

Success (green): to confirm that a previous action completed successfully. Uses role="alert" so screen readers announce it automatically on page load.

noti_banner(
  inputId = "submission-confirm",
  title_txt = "Success",
  body_txt = "Your report has been submitted.",
  type = "success"
)

When to use each component

| Situation | Component | |---|---| | Information not related to the current page task | noti_banner() | | Supplementary information related to the page | insert_text() | | Serious consequences if the user misses information | warning_text() | | Form validation errors | error_summary() / error messages |

Use notification banners sparingly — users often overlook them when they appear frequently. Show only one at a time, and never alongside an error summary.

For more information, read the GOV.UK notification banner guidance.


external_link()

A wrapper for HTML anchor elements that produces safe, accessible external links with consistent behaviour.

external_link("https://www.example.gov.uk/guidance", "Guidance for applicants")

What the function does automatically

Descriptive link text

The function validates link_text and will error if you supply a raw URL as the link text, vague text such as "click here" or "here", or text ending with a full stop. It will also warn if the text is fewer than 7 characters.

This enforces WCAG 2.2 success criterion 2.4.4: Link Purpose (In Context), which requires link text to describe the destination without needing the surrounding context to make sense of it.

# Correct — descriptive
external_link("https://www.example.gov.uk/apply", "Apply for a licence")

# Will error — vague text
external_link("https://www.example.gov.uk/apply", "click here")

# Will error — raw URL as text
external_link(
  "https://www.example.gov.uk/apply",
  "https://www.example.gov.uk/apply"
)

Grouped links

When displaying several external links together, repeating "(opens in new tab)" on each is visually repetitive. Set add_warning = FALSE and add a single explanatory sentence above the group instead:

gov_text("The following links open in a new tab.")
shiny::tags$ul(
  shiny::tags$li(
    external_link(
      "https://www.example.gov.uk/a",
      "Guidance document A",
      add_warning = FALSE
    )
  ),
  shiny::tags$li(
    external_link(
      "https://www.example.gov.uk/b",
      "Guidance document B",
      add_warning = FALSE
    )
  )
)

For more information, read the GOV.UK links guidance.


font()

GDS Transport is a restricted typeface and must only be used on GOV.UK domains. If your app is not hosted on a GOV.UK domain, do not call font(). You do not need to do anything and your app will default to Arial instead, which is the correct behaviour.

If you are on a GOV.UK domain and therefore want to use the font() function, putting it within your UI will load the GDS Transport typeface for use in your app. By default the GOV.UK Frontend CSS specifies font-family: GDS Transport, arial, sans-serif — if the font files are not loaded the browser falls back to Arial automatically.

# Only include this if your app is on a GOV.UK domain
font()

For more information on when GDS Transport is permitted, read the GOV.UK typeface guidance.



Try the shinyGovstyle package in your browser

Any scripts or data that you put into this service are public.

shinyGovstyle documentation built on April 13, 2026, 5:06 p.m.