Components

Card links

Use card links to help users reach the next stage of their NHS App journey.

When to use

Use card links to take users:

  • to the start of an NHS App service
  • deeper into an area of the app

How to use

Use the variation below that fits best with the context.

Use a concise phrase to explain where the link goes.

Only use this variation if you have found a user need for more detailed links.

Use badges on card links to alert users to new, important information.

Use secondary card links to signpost information that is less important in the context of the page.

Colour variations

You can use colour to highlight a card link. This can help draw attention to important content.

Use colour sparingly and make sure there is enough contrast between text and background.

You can add an image to a card link. We use this on the home screen of the NHS App to help users learn about public health campaigns.

You can add custom content to a card link, such as a tag, appointment time and location.

Keep the content short and easy to scan. Test with users to check the card gives them the right amount of information.

You can use a footer to separate related content inside a card link.

Use when the card content is informational only and requires no user interaction.

Multiple card links placed together must be marked up as lists in the HTML code. This helps screen reader users to navigate the content, for example by letting them know how many items there are in the list.

Use grouped card links to separate distinct groups of content or actions. Each card is visually independent.

<ul class="nhsapp-cards">
  <li class="nhsapp-card">
    <div class="nhsapp-card__container">
      <div class="nhsapp-card__content">
        <a
          href="#"
          class="nhsapp-card__link nhsuk-link--no-visited-state nhsuk-u-font-size-22"
          aria-label="Orthopaedic appointment on Friday 7 June 2024 at 8:30am, at The Willows, Croydon University Hospital"
        >
          Orthopaedic appointment
        </a>

<p aria-hidden="true" class="nhsuk-u-font-weight-bold nhsuk-u-margin-top-1 nhsuk-u-margin-bottom-3" > Friday 7 June 2024 <br /> 8:30am </p> <p aria-hidden="true">The Willows, Croydon University Hospital</p> </div>

<svg class="nhsapp-icon nhsapp-icon--chevron-right" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" height="2rem" width="2rem" viewBox="0 0 24 24" > <path d="M8.82 19.11a.97.97 0 0 1-.72-.31.996.996 0 0 1 .03-1.41l5.61-5.38-5.6-5.25c-.4-.38-.42-1.01-.05-1.41.38-.4 1.01-.42 1.41-.05l6.37 5.97c.2.19.31.45.32.72s-.11.54-.31.73l-6.37 6.11c-.19.19-.44.28-.69.28Z" /> </svg> </div> </li>

<li class="nhsapp-card"> <div class="nhsapp-card__container"> <div class="nhsapp-card__content"> <a href="#" class="nhsapp-card__link nhsuk-link--no-visited-state nhsuk-u-font-size-22" aria-label="Orthopaedic appointment on Monday 3 June 2024 at 9:40am, at The Willows, Croydon University Hospital" > Orthopaedic appointment </a>

<p aria-hidden="true" class="nhsuk-u-font-weight-bold nhsuk-u-margin-top-1 nhsuk-u-margin-bottom-3" > Monday 3 June 2024 <br /> 9:40am </p> <p aria-hidden="true">The Willows, Croydon University Hospital</p> </div>

<svg class="nhsapp-icon nhsapp-icon--chevron-right" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" height="2rem" width="2rem" viewBox="0 0 24 24" > <path d="M8.82 19.11a.97.97 0 0 1-.72-.31.996.996 0 0 1 .03-1.41l5.61-5.38-5.6-5.25c-.4-.38-.42-1.01-.05-1.41.38-.4 1.01-.42 1.41-.05l6.37 5.97c.2.19.31.45.32.72s-.11.54-.31.73l-6.37 6.11c-.19.19-.44.28-.69.28Z" /> </svg> </div> </li> </ul>

Nunjucks macro options

Use options to customise the appearance, content and behaviour of a component when using a macro, for example, changing the text.

Some options are required for the macro to work; these are marked as "Required" in the option description.

If you're using Nunjucks macros in production with "html" options, or ones ending with "html", you must sanitise the HTML to protect against cross-site scripting exploits.

Name Type Required Description
heading string conditional Text to use for the heding of the card group. If headingHtml is provided, the heading argument will be ignored.
headingHtml string conditional HTML to use for the heading of the card group. If headingHtml is provided, the heading argument will be ignored.
headingLevel number conditional Heading level (2–6) for the heading. Defaults to 2 when not set. If headingHtml is provided, the headingLevel argument will be ignored.
description string conditional Plain text shown under the group heading. If descriptionHtml is provided, the description argument will be ignored.
descriptionHtml string conditional HTML version of the description. If descriptionHtml is provided, the description argument will be ignored..
stacked boolean no Adds nhsapp-cards--stacked class to card group.
isListItem boolean no If true (default) wrapper is <ul> with each card as <li>. If false uses <div> wrappers.
id string no ID for the card group.
classes string no Classes for the card group.
attributes object no HTML attributes for the card group (data-_ or aria-_).
cards array yes Array of card objects.
cards[]title string yes The card title text. Renders as: link (if href), heading (if headingLevel and no href), else a paragraph.
cards[]href string conditional Makes the title a link when provided.
cards[]linkAriaLabel string no aria-label for the title link. Use only if the visible text is not clear.
cards[]headingLevel number conditional Heading level (2–6) used only when there is no href. If not set (and no href) the title is a paragraph.
cards[]titleClasses string no Classes for the title element.
cards[]containerClasses string no Classes for the inner container.
cards[]description string conditional Plain text description below the title. Ignored if descriptionHtml is given.
cards[]descriptionHtml string conditional HTML description (allows markup). Overrides description.
cards[]descriptionClasses string no Classes for the description.
cards[]aboveContent.html string no HTML shown above the title (for example a tag).
cards[]footer.html string no HTML shown in the footer.
cards[]img{}.src string conditional Image URL. Adds an image section when present.
cards[]img{}.alt string no Image alt text. Leave empty only if purely decorative.
cards[]badgeLarge{}.count number conditional Number for the large badge. Badge appears only when count > 0.
cards[]badgeLarge{}.label string yes Visually hidden text read after the number.
cards[]badgeLarge{}.id string no ID attribute for the badge.
cards[]badgeLarge{}.classes string no Classes for the badge.
cards[]badgeLarge{}.attributes object no HTML attributes for the badge (e.g. data-*, aria-*).
cards[]id string no ID for the card.
cards[]classes string no Classes for the card.
cards[]attributes object no HTML attributes for the card (e.g. data-*, aria-*).


{% from 'nhsapp/components/card/macro.njk' import nhsappCardGroup %}
{% from 'nhsapp/components/card/macro.njk' import nhsappCard %}

{{ nhsappCardGroup({
  cards: [
    {
      title: 'Orthopaedic appointment',
      href: '#',
      titleClasses: 'nhsuk-u-font-size-22',
      linkAriaLabel: 'Orthopaedic appointment on Friday 7 June 2024 at 8:30am, at The Willows, Croydon University Hospital',
      descriptionHtml: '
        <p aria-hidden="true" class="nhsuk-u-font-weight-bold nhsuk-u-margin-top-1 nhsuk-u-margin-bottom-3">Friday 7 June 2024 <br> 8:30am</p>
        <p aria-hidden="true">The Willows, Croydon University Hospital</p>
      '
    },
    {
      title: 'Orthopaedic appointment',
      href: '#',
      titleClasses: 'nhsuk-u-font-size-22',
      linkAriaLabel: 'Orthopaedic appointment on Monday 3 June 2024 at 9:40am, at The Willows, Croydon University Hospital',
      descriptionHtml: '
        <p aria-hidden="true" class="nhsuk-u-font-weight-bold nhsuk-u-margin-top-1 nhsuk-u-margin-bottom-3">Monday 3 June 2024 <br> 9:40am</p>
        <p aria-hidden="true">The Willows, Croydon University Hospital</p>
      '
    }
  ]
}) }}

To use the component in your Vue application, install the NHS App Vue Component Library and import the component.

View component in Vue (opens in a new tab)

Use stacked card links to show multiple items within a single group, such as different sections of the same service or related tasks.

<ul class="nhsapp-cards nhsapp-cards--stacked">
  <li class="nhsapp-card">
    <div class="nhsapp-card__container">
      <div class="nhsapp-card__content">
        <a href="#" class="nhsapp-card__link nhsuk-link--no-visited-state">
          GP health record
        </a>
      </div>

<svg class="nhsapp-icon nhsapp-icon--chevron-right" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" height="2rem" width="2rem" viewBox="0 0 24 24" > <path d="M8.82 19.11a.97.97 0 0 1-.72-.31.996.996 0 0 1 .03-1.41l5.61-5.38-5.6-5.25c-.4-.38-.42-1.01-.05-1.41.38-.4 1.01-.42 1.41-.05l6.37 5.97c.2.19.31.45.32.72s-.11.54-.31.73l-6.37 6.11c-.19.19-.44.28-.69.28Z" /> </svg> </div> </li>

<li class="nhsapp-card"> <div class="nhsapp-card__container"> <div class="nhsapp-card__content"> <a href="#" class="nhsapp-card__link nhsuk-link--no-visited-state"> View and manage prescriptions </a> </div>

<svg class="nhsapp-icon nhsapp-icon--chevron-right" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" height="2rem" width="2rem" viewBox="0 0 24 24" > <path d="M8.82 19.11a.97.97 0 0 1-.72-.31.996.996 0 0 1 .03-1.41l5.61-5.38-5.6-5.25c-.4-.38-.42-1.01-.05-1.41.38-.4 1.01-.42 1.41-.05l6.37 5.97c.2.19.31.45.32.72s-.11.54-.31.73l-6.37 6.11c-.19.19-.44.28-.69.28Z" /> </svg> </div> </li>

<li class="nhsapp-card"> <div class="nhsapp-card__container"> <div class="nhsapp-card__content"> <a href="#" class="nhsapp-card__link nhsuk-link--no-visited-state"> Upcoming and past appointments </a> </div>

<svg class="nhsapp-icon nhsapp-icon--chevron-right" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" height="2rem" width="2rem" viewBox="0 0 24 24" > <path d="M8.82 19.11a.97.97 0 0 1-.72-.31.996.996 0 0 1 .03-1.41l5.61-5.38-5.6-5.25c-.4-.38-.42-1.01-.05-1.41.38-.4 1.01-.42 1.41-.05l6.37 5.97c.2.19.31.45.32.72s-.11.54-.31.73l-6.37 6.11c-.19.19-.44.28-.69.28Z" /> </svg> </div> </li> </ul>

Nunjucks macro options

Use options to customise the appearance, content and behaviour of a component when using a macro, for example, changing the text.

Some options are required for the macro to work; these are marked as "Required" in the option description.

If you're using Nunjucks macros in production with "html" options, or ones ending with "html", you must sanitise the HTML to protect against cross-site scripting exploits.

Name Type Required Description
heading string conditional Text to use for the heding of the card group. If headingHtml is provided, the heading argument will be ignored.
headingHtml string conditional HTML to use for the heading of the card group. If headingHtml is provided, the heading argument will be ignored.
headingLevel number conditional Heading level (2–6) for the heading. Defaults to 2 when not set. If headingHtml is provided, the headingLevel argument will be ignored.
description string conditional Plain text shown under the group heading. If descriptionHtml is provided, the description argument will be ignored.
descriptionHtml string conditional HTML version of the description. If descriptionHtml is provided, the description argument will be ignored..
stacked boolean no Adds nhsapp-cards--stacked class to card group.
isListItem boolean no If true (default) wrapper is <ul> with each card as <li>. If false uses <div> wrappers.
id string no ID for the card group.
classes string no Classes for the card group.
attributes object no HTML attributes for the card group (data-_ or aria-_).
cards array yes Array of card objects.
cards[]title string yes The card title text. Renders as: link (if href), heading (if headingLevel and no href), else a paragraph.
cards[]href string conditional Makes the title a link when provided.
cards[]linkAriaLabel string no aria-label for the title link. Use only if the visible text is not clear.
cards[]headingLevel number conditional Heading level (2–6) used only when there is no href. If not set (and no href) the title is a paragraph.
cards[]titleClasses string no Classes for the title element.
cards[]containerClasses string no Classes for the inner container.
cards[]description string conditional Plain text description below the title. Ignored if descriptionHtml is given.
cards[]descriptionHtml string conditional HTML description (allows markup). Overrides description.
cards[]descriptionClasses string no Classes for the description.
cards[]aboveContent.html string no HTML shown above the title (for example a tag).
cards[]footer.html string no HTML shown in the footer.
cards[]img{}.src string conditional Image URL. Adds an image section when present.
cards[]img{}.alt string no Image alt text. Leave empty only if purely decorative.
cards[]badgeLarge{}.count number conditional Number for the large badge. Badge appears only when count > 0.
cards[]badgeLarge{}.label string yes Visually hidden text read after the number.
cards[]badgeLarge{}.id string no ID attribute for the badge.
cards[]badgeLarge{}.classes string no Classes for the badge.
cards[]badgeLarge{}.attributes object no HTML attributes for the badge (e.g. data-*, aria-*).
cards[]id string no ID for the card.
cards[]classes string no Classes for the card.
cards[]attributes object no HTML attributes for the card (e.g. data-*, aria-*).


{% from 'nhsapp/components/card/macro.njk' import nhsappCardGroup %}
{% from 'nhsapp/components/card/macro.njk' import nhsappCard %}

{{ nhsappCardGroup({
  stacked: true,
  cards: [
    {
      title: 'GP health record',
      href: '#'
    },
    {
      title: 'View and manage prescriptions',
      href: '#'
    },
    {
      title: 'Upcoming and past appointments',
      href: '#'
    }
  ]
}) }}

To use the component in your design, add the NHS App Figma library to your working files, and navigate using the components tab.

View component in Figma (opens in a new tab)

To use the component in your Vue application, install the NHS App Vue Component Library and import the component.

View component in Vue (opens in a new tab)

Use secondary card links below primary card links which signpost more important information.

<ul class="nhsapp-cards nhsapp-cards--stacked">
  <li class="nhsapp-card">
    <div class="nhsapp-card__container">
      <div class="nhsapp-card__content">
        <a href="#" class="nhsapp-card__link nhsuk-link--no-visited-state">
          Login and security
        </a>
      </div>

<svg class="nhsapp-icon nhsapp-icon--chevron-right" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" height="2rem" width="2rem" viewBox="0 0 24 24" > <path d="M8.82 19.11a.97.97 0 0 1-.72-.31.996.996 0 0 1 .03-1.41l5.61-5.38-5.6-5.25c-.4-.38-.42-1.01-.05-1.41.38-.4 1.01-.42 1.41-.05l6.37 5.97c.2.19.31.45.32.72s-.11.54-.31.73l-6.37 6.11c-.19.19-.44.28-.69.28Z" /> </svg> </div> </li>

<li class="nhsapp-card"> <div class="nhsapp-card__container"> <div class="nhsapp-card__content"> <a href="#" class="nhsapp-card__link nhsuk-link--no-visited-state"> Face ID </a> </div>

<svg class="nhsapp-icon nhsapp-icon--chevron-right" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" height="2rem" width="2rem" viewBox="0 0 24 24" > <path d="M8.82 19.11a.97.97 0 0 1-.72-.31.996.996 0 0 1 .03-1.41l5.61-5.38-5.6-5.25c-.4-.38-.42-1.01-.05-1.41.38-.4 1.01-.42 1.41-.05l6.37 5.97c.2.19.31.45.32.72s-.11.54-.31.73l-6.37 6.11c-.19.19-.44.28-.69.28Z" /> </svg> </div> </li> </ul>

<ul class="nhsapp-cards nhsapp-cards--stacked nhsapp-cards--secondary"> <li class="nhsapp-card"> <div class="nhsapp-card__container"> <div class="nhsapp-card__content"> <a href="#" class="nhsapp-card__link nhsuk-link--no-visited-state"> Privacy and legal policies </a> </div>

<svg class="nhsapp-icon nhsapp-icon--chevron-right" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" height="2rem" width="2rem" viewBox="0 0 24 24" > <path d="M8.82 19.11a.97.97 0 0 1-.72-.31.996.996 0 0 1 .03-1.41l5.61-5.38-5.6-5.25c-.4-.38-.42-1.01-.05-1.41.38-.4 1.01-.42 1.41-.05l6.37 5.97c.2.19.31.45.32.72s-.11.54-.31.73l-6.37 6.11c-.19.19-.44.28-.69.28Z" /> </svg> </div> </li>

<li class="nhsapp-card"> <div class="nhsapp-card__container"> <div class="nhsapp-card__content"> <a href="#" class="nhsapp-card__link nhsuk-link--no-visited-state"> Join our user research panel </a> </div>

<svg class="nhsapp-icon nhsapp-icon--chevron-right" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" height="2rem" width="2rem" viewBox="0 0 24 24" > <path d="M8.82 19.11a.97.97 0 0 1-.72-.31.996.996 0 0 1 .03-1.41l5.61-5.38-5.6-5.25c-.4-.38-.42-1.01-.05-1.41.38-.4 1.01-.42 1.41-.05l6.37 5.97c.2.19.31.45.32.72s-.11.54-.31.73l-6.37 6.11c-.19.19-.44.28-.69.28Z" /> </svg> </div> </li> </ul>

Nunjucks macro options

Use options to customise the appearance, content and behaviour of a component when using a macro, for example, changing the text.

Some options are required for the macro to work; these are marked as "Required" in the option description.

If you're using Nunjucks macros in production with "html" options, or ones ending with "html", you must sanitise the HTML to protect against cross-site scripting exploits.

Name Type Required Description
heading string conditional Text to use for the heding of the card group. If headingHtml is provided, the heading argument will be ignored.
headingHtml string conditional HTML to use for the heading of the card group. If headingHtml is provided, the heading argument will be ignored.
headingLevel number conditional Heading level (2–6) for the heading. Defaults to 2 when not set. If headingHtml is provided, the headingLevel argument will be ignored.
description string conditional Plain text shown under the group heading. If descriptionHtml is provided, the description argument will be ignored.
descriptionHtml string conditional HTML version of the description. If descriptionHtml is provided, the description argument will be ignored..
stacked boolean no Adds nhsapp-cards--stacked class to card group.
isListItem boolean no If true (default) wrapper is <ul> with each card as <li>. If false uses <div> wrappers.
id string no ID for the card group.
classes string no Classes for the card group.
attributes object no HTML attributes for the card group (data-_ or aria-_).
cards array yes Array of card objects.
cards[]title string yes The card title text. Renders as: link (if href), heading (if headingLevel and no href), else a paragraph.
cards[]href string conditional Makes the title a link when provided.
cards[]linkAriaLabel string no aria-label for the title link. Use only if the visible text is not clear.
cards[]headingLevel number conditional Heading level (2–6) used only when there is no href. If not set (and no href) the title is a paragraph.
cards[]titleClasses string no Classes for the title element.
cards[]containerClasses string no Classes for the inner container.
cards[]description string conditional Plain text description below the title. Ignored if descriptionHtml is given.
cards[]descriptionHtml string conditional HTML description (allows markup). Overrides description.
cards[]descriptionClasses string no Classes for the description.
cards[]aboveContent.html string no HTML shown above the title (for example a tag).
cards[]footer.html string no HTML shown in the footer.
cards[]img{}.src string conditional Image URL. Adds an image section when present.
cards[]img{}.alt string no Image alt text. Leave empty only if purely decorative.
cards[]badgeLarge{}.count number conditional Number for the large badge. Badge appears only when count > 0.
cards[]badgeLarge{}.label string yes Visually hidden text read after the number.
cards[]badgeLarge{}.id string no ID attribute for the badge.
cards[]badgeLarge{}.classes string no Classes for the badge.
cards[]badgeLarge{}.attributes object no HTML attributes for the badge (e.g. data-*, aria-*).
cards[]id string no ID for the card.
cards[]classes string no Classes for the card.
cards[]attributes object no HTML attributes for the card (e.g. data-*, aria-*).


{% from 'nhsapp/components/card/macro.njk' import nhsappCardGroup %}
{% from 'nhsapp/components/card/macro.njk' import nhsappCard %}

{{ nhsappCardGroup({
  stacked: true,
  cards: [
    {
      title: 'Login and security',
      href: '#'
    },
    {
      title: 'Face ID',
      href: '#'
    }
  ]
}) }}

{{ nhsappCardGroup({
  stacked: true,
  classes: 'nhsapp-cards--secondary',
  cards: [
    {
      title: 'Privacy and legal policies',
      href: '#'
    },
    {
      title: 'Join our user research panel',
      href: '#'
    }
  ]
}) }}

To use the component in your design, add the NHS App Figma library to your working files, and navigate using the components tab.

View component in Figma (opens in a new tab)

To use the component in your Vue application, install the NHS App Vue Component Library and import the component.

View component in Vue (opens in a new tab)

Using headings

Break up long lists of card links by using headings. It makes pages easier to scan and helps screen reader users to navigate.

<h2 class="nhsapp-cards__heading">Your GP services</h2>

<ul class="nhsapp-cards nhsapp-cards--stacked"> <li class="nhsapp-card"> <div class="nhsapp-card__container"> <div class="nhsapp-card__content"> <a href="#" class="nhsapp-card__link nhsuk-link--no-visited-state"> Request repeat prescriptions </a> </div>

<svg class="nhsapp-icon nhsapp-icon--chevron-right" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" height="2rem" width="2rem" viewBox="0 0 24 24" > <path d="M8.82 19.11a.97.97 0 0 1-.72-.31.996.996 0 0 1 .03-1.41l5.61-5.38-5.6-5.25c-.4-.38-.42-1.01-.05-1.41.38-.4 1.01-.42 1.41-.05l6.37 5.97c.2.19.31.45.32.72s-.11.54-.31.73l-6.37 6.11c-.19.19-.44.28-.69.28Z" /> </svg> </div> </li>

<li class="nhsapp-card"> <div class="nhsapp-card__container"> <div class="nhsapp-card__content"> <a href="#" class="nhsapp-card__link nhsuk-link--no-visited-state"> Contact your GP surgery for a document or update </a> </div>

<svg class="nhsapp-icon nhsapp-icon--chevron-right" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" height="2rem" width="2rem" viewBox="0 0 24 24" > <path d="M8.82 19.11a.97.97 0 0 1-.72-.31.996.996 0 0 1 .03-1.41l5.61-5.38-5.6-5.25c-.4-.38-.42-1.01-.05-1.41.38-.4 1.01-.42 1.41-.05l6.37 5.97c.2.19.31.45.32.72s-.11.54-.31.73l-6.37 6.11c-.19.19-.44.28-.69.28Z" /> </svg> </div> </li>

<li class="nhsapp-card"> <div class="nhsapp-card__container"> <div class="nhsapp-card__content"> <a href="#" class="nhsapp-card__link nhsuk-link--no-visited-state"> Check for available GP appointments </a> </div>

<svg class="nhsapp-icon nhsapp-icon--chevron-right" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" height="2rem" width="2rem" viewBox="0 0 24 24" > <path d="M8.82 19.11a.97.97 0 0 1-.72-.31.996.996 0 0 1 .03-1.41l5.61-5.38-5.6-5.25c-.4-.38-.42-1.01-.05-1.41.38-.4 1.01-.42 1.41-.05l6.37 5.97c.2.19.31.45.32.72s-.11.54-.31.73l-6.37 6.11c-.19.19-.44.28-.69.28Z" /> </svg> </div> </li> </ul>

<h2 class="nhsapp-cards__heading">Other NHS services</h2>

<ul class="nhsapp-cards nhsapp-cards--stacked"> <li class="nhsapp-card"> <div class="nhsapp-card__container"> <div class="nhsapp-card__content"> <a href="#" class="nhsapp-card__link nhsuk-link--no-visited-state"> Book </a> </div>

<svg class="nhsapp-icon nhsapp-icon--chevron-right" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" height="2rem" width="2rem" viewBox="0 0 24 24" > <path d="M8.82 19.11a.97.97 0 0 1-.72-.31.996.996 0 0 1 .03-1.41l5.61-5.38-5.6-5.25c-.4-.38-.42-1.01-.05-1.41.38-.4 1.01-.42 1.41-.05l6.37 5.97c.2.19.31.45.32.72s-.11.54-.31.73l-6.37 6.11c-.19.19-.44.28-.69.28Z" /> </svg> </div> </li>

<li class="nhsapp-card"> <div class="nhsapp-card__container"> <div class="nhsapp-card__content"> <a href="#" class="nhsapp-card__link nhsuk-link--no-visited-state"> Request prescriptions </a> </div>

<svg class="nhsapp-icon nhsapp-icon--chevron-right" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" height="2rem" width="2rem" viewBox="0 0 24 24" > <path d="M8.82 19.11a.97.97 0 0 1-.72-.31.996.996 0 0 1 .03-1.41l5.61-5.38-5.6-5.25c-.4-.38-.42-1.01-.05-1.41.38-.4 1.01-.42 1.41-.05l6.37 5.97c.2.19.31.45.32.72s-.11.54-.31.73l-6.37 6.11c-.19.19-.44.28-.69.28Z" /> </svg> </div> </li> </ul>

Nunjucks macro options

Use options to customise the appearance, content and behaviour of a component when using a macro, for example, changing the text.

Some options are required for the macro to work; these are marked as "Required" in the option description.

If you're using Nunjucks macros in production with "html" options, or ones ending with "html", you must sanitise the HTML to protect against cross-site scripting exploits.

Name Type Required Description
heading string conditional Text to use for the heding of the card group. If headingHtml is provided, the heading argument will be ignored.
headingHtml string conditional HTML to use for the heading of the card group. If headingHtml is provided, the heading argument will be ignored.
headingLevel number conditional Heading level (2–6) for the heading. Defaults to 2 when not set. If headingHtml is provided, the headingLevel argument will be ignored.
description string conditional Plain text shown under the group heading. If descriptionHtml is provided, the description argument will be ignored.
descriptionHtml string conditional HTML version of the description. If descriptionHtml is provided, the description argument will be ignored..
stacked boolean no Adds nhsapp-cards--stacked class to card group.
isListItem boolean no If true (default) wrapper is <ul> with each card as <li>. If false uses <div> wrappers.
id string no ID for the card group.
classes string no Classes for the card group.
attributes object no HTML attributes for the card group (data-_ or aria-_).
cards array yes Array of card objects.
cards[]title string yes The card title text. Renders as: link (if href), heading (if headingLevel and no href), else a paragraph.
cards[]href string conditional Makes the title a link when provided.
cards[]linkAriaLabel string no aria-label for the title link. Use only if the visible text is not clear.
cards[]headingLevel number conditional Heading level (2–6) used only when there is no href. If not set (and no href) the title is a paragraph.
cards[]titleClasses string no Classes for the title element.
cards[]containerClasses string no Classes for the inner container.
cards[]description string conditional Plain text description below the title. Ignored if descriptionHtml is given.
cards[]descriptionHtml string conditional HTML description (allows markup). Overrides description.
cards[]descriptionClasses string no Classes for the description.
cards[]aboveContent.html string no HTML shown above the title (for example a tag).
cards[]footer.html string no HTML shown in the footer.
cards[]img{}.src string conditional Image URL. Adds an image section when present.
cards[]img{}.alt string no Image alt text. Leave empty only if purely decorative.
cards[]badgeLarge{}.count number conditional Number for the large badge. Badge appears only when count > 0.
cards[]badgeLarge{}.label string yes Visually hidden text read after the number.
cards[]badgeLarge{}.id string no ID attribute for the badge.
cards[]badgeLarge{}.classes string no Classes for the badge.
cards[]badgeLarge{}.attributes object no HTML attributes for the badge (e.g. data-*, aria-*).
cards[]id string no ID for the card.
cards[]classes string no Classes for the card.
cards[]attributes object no HTML attributes for the card (e.g. data-*, aria-*).


{% from 'nhsapp/components/card/macro.njk' import nhsappCardGroup %}
{% from 'nhsapp/components/card/macro.njk' import nhsappCard %}

{{ nhsappCardGroup({
  stacked: true,
  heading: 'Your GP services',
  cards: [
    {
      title: 'Request repeat prescriptions',
      href: '#'
    },
    {
      title: 'Contact your GP surgery for a document or update',
      href: '#'
    },
    {
      title: 'Check for available GP appointments',
      href: '#'
    }
  ]
}) }}

{{ nhsappCardGroup({
  stacked: true,
  heading: 'Other NHS services',
  cards: [
    {
      title: 'Book',
      href: '#'
    },
    {
      title: 'Request prescriptions',
      href: '#'
    }
  ]
}) }}

You can add custom HTML to the heading using headingHtml.

<div
  class="nhsapp-cards__heading"
  style="justify-content: space-between; align-items: center; display: flex"
>
  <h2 class="nhsuk-heading-s nhsuk-u-margin-bottom-0">Services</h2>
  <a
    class="nhsuk-u-font-size-19 nhsuk-link nhsuk-link--no-visited-state nhsuk-u-nowrap"
    href="#"
    >View all <span class="nhsuk-u-visually-hidden">services</span></a
  >
</div>

<ul class="nhsapp-cards nhsapp-cards--stacked"> <li class="nhsapp-card"> <div class="nhsapp-card__container"> <div class="nhsapp-card__content"> <a href="#" class="nhsapp-card__link nhsuk-link--no-visited-state"> Request repeat prescriptions </a> </div>

<svg class="nhsapp-icon nhsapp-icon--chevron-right" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" height="2rem" width="2rem" viewBox="0 0 24 24" > <path d="M8.82 19.11a.97.97 0 0 1-.72-.31.996.996 0 0 1 .03-1.41l5.61-5.38-5.6-5.25c-.4-.38-.42-1.01-.05-1.41.38-.4 1.01-.42 1.41-.05l6.37 5.97c.2.19.31.45.32.72s-.11.54-.31.73l-6.37 6.11c-.19.19-.44.28-.69.28Z" /> </svg> </div> </li>

<li class="nhsapp-card"> <div class="nhsapp-card__container"> <div class="nhsapp-card__content"> <a href="#" class="nhsapp-card__link nhsuk-link--no-visited-state"> Check if you need urgent medical help using 111 online </a> </div>

<svg class="nhsapp-icon nhsapp-icon--chevron-right" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" height="2rem" width="2rem" viewBox="0 0 24 24" > <path d="M8.82 19.11a.97.97 0 0 1-.72-.31.996.996 0 0 1 .03-1.41l5.61-5.38-5.6-5.25c-.4-.38-.42-1.01-.05-1.41.38-.4 1.01-.42 1.41-.05l6.37 5.97c.2.19.31.45.32.72s-.11.54-.31.73l-6.37 6.11c-.19.19-.44.28-.69.28Z" /> </svg> </div> </li> </ul>

Nunjucks macro options

Use options to customise the appearance, content and behaviour of a component when using a macro, for example, changing the text.

Some options are required for the macro to work; these are marked as "Required" in the option description.

If you're using Nunjucks macros in production with "html" options, or ones ending with "html", you must sanitise the HTML to protect against cross-site scripting exploits.

Name Type Required Description
heading string conditional Text to use for the heding of the card group. If headingHtml is provided, the heading argument will be ignored.
headingHtml string conditional HTML to use for the heading of the card group. If headingHtml is provided, the heading argument will be ignored.
headingLevel number conditional Heading level (2–6) for the heading. Defaults to 2 when not set. If headingHtml is provided, the headingLevel argument will be ignored.
description string conditional Plain text shown under the group heading. If descriptionHtml is provided, the description argument will be ignored.
descriptionHtml string conditional HTML version of the description. If descriptionHtml is provided, the description argument will be ignored..
stacked boolean no Adds nhsapp-cards--stacked class to card group.
isListItem boolean no If true (default) wrapper is <ul> with each card as <li>. If false uses <div> wrappers.
id string no ID for the card group.
classes string no Classes for the card group.
attributes object no HTML attributes for the card group (data-_ or aria-_).
cards array yes Array of card objects.
cards[]title string yes The card title text. Renders as: link (if href), heading (if headingLevel and no href), else a paragraph.
cards[]href string conditional Makes the title a link when provided.
cards[]linkAriaLabel string no aria-label for the title link. Use only if the visible text is not clear.
cards[]headingLevel number conditional Heading level (2–6) used only when there is no href. If not set (and no href) the title is a paragraph.
cards[]titleClasses string no Classes for the title element.
cards[]containerClasses string no Classes for the inner container.
cards[]description string conditional Plain text description below the title. Ignored if descriptionHtml is given.
cards[]descriptionHtml string conditional HTML description (allows markup). Overrides description.
cards[]descriptionClasses string no Classes for the description.
cards[]aboveContent.html string no HTML shown above the title (for example a tag).
cards[]footer.html string no HTML shown in the footer.
cards[]img{}.src string conditional Image URL. Adds an image section when present.
cards[]img{}.alt string no Image alt text. Leave empty only if purely decorative.
cards[]badgeLarge{}.count number conditional Number for the large badge. Badge appears only when count > 0.
cards[]badgeLarge{}.label string yes Visually hidden text read after the number.
cards[]badgeLarge{}.id string no ID attribute for the badge.
cards[]badgeLarge{}.classes string no Classes for the badge.
cards[]badgeLarge{}.attributes object no HTML attributes for the badge (e.g. data-*, aria-*).
cards[]id string no ID for the card.
cards[]classes string no Classes for the card.
cards[]attributes object no HTML attributes for the card (e.g. data-*, aria-*).


{% from 'nhsapp/components/card/macro.njk' import nhsappCardGroup %}
{% from 'nhsapp/components/card/macro.njk' import nhsappCard %}

{{ nhsappCardGroup({
  stacked: true,
  headingHtml: '<div class="nhsapp-cards__heading" style="justify-content: space-between; align-items: center; display: flex;">
                  <h2 class="nhsuk-heading-s nhsuk-u-margin-bottom-0">Services</h2>
                  <a class="nhsuk-u-font-size-19 nhsuk-link nhsuk-link--no-visited-state nhsuk-u-nowrap" href="#">View all <span class="nhsuk-u-visually-hidden">services</span></a> 
                </div>',
  cards: [
    {
      title: 'Request repeat prescriptions',
      href: '#'
    },
    {
      title: 'Check if you need urgent medical help using 111 online',
      href: '#'
    }
  ]
}) }}

Accesibility

Screen reader users often navigate by pulling up a list of all the links on a page. When they do this, they only hear the link text, not the content around it.

This means your linkAriaLabel must include all the important information from the card. It needs to make sense on its own, out of context.

In this example, a sighted user sees the date, location and 'Action needed' tag laid out visually. A screen reader user hears all of this in the linkAriaLabel: "Action needed: Orthopaedic appointment on Monday 3 June 2024 at 9:40am, at The Willows, Croydon University Hospital".

You can mark the visual content as aria-hidden="true" because it's already in the link label. This stops screen reader users hearing the same information twice.

Before you hide content with aria-hidden="true", check it appears in the linkAriaLabel. If it does not, do not hide it. Screen reader users will miss it when they navigate through links.

Research

In our research, people successfully navigated the NHS App and completed a range of tasks using short card links. They understood the meaning of the links despite the short amount of text.

Some people overlooked description text when it was included in card links.

Help improve this component

The NHS App design system team would like to hear:

  • how you have used this component in your service
  • any feedback you have about its usage, for example accessibility or ideas for improvement

Add these comments to the 'Card links' discussion on GitHub.