1. Component Guide
  2. Accordion (experimental)
Component

Accordion (experimental)

The accordion component lets users show and hide sections of related content on a page.

This component is based on the GOV.UK Design System accordion component and is currently experimental because more research is needed to validate it. If using this component, please feed back any research findings to the Design System team.

Search for usage of this component on GitHub.

How it looks (preview) (preview all)

Writing well for the web

This is the content for Writing well for the web.

Writing well for specialists

This is the content for Writing well for specialists.

Know your audience

This is the content for Know your audience.

How people read

This is the content for How people read.

How to call this component

<%= render "govuk_publishing_components/components/accordion", {
  items: [
    {
      heading: {
        text: "Writing well for the web"
      },
      content: {
        html: sanitize("<p class=\"govuk-body\">This is the content for Writing well for the web.</p>")
      },
      data_attributes: null
    },
    {
      heading: {
        text: "Writing well for specialists"
      },
      content: {
        html: sanitize("<p class=\"govuk-body\">This is the content for Writing well for specialists.</p>")
      },
      data_attributes: null
    },
    {
      heading: {
        text: "Know your audience"
      },
      content: {
        html: sanitize("<p class=\"govuk-body\">This is the content for Know your audience.</p>")
      },
      data_attributes: null
    },
    {
      heading: {
        text: "How people read"
      },
      content: {
        html: sanitize("<p class=\"govuk-body\">This is the content for How people read.</p>")
      },
      data_attributes: null
    }
  ]
} %>

GOV.UK Design System

This component incorporates components from the GOV.UK Design System:

Accessibility acceptance criteria

The accordion must:

  • accept focus
  • be usable with a keyboard
  • allow the controls to change in appearance when keyboard focus moves to it
  • allow the controls to indicate when users hover their cursor over it
  • be usable with touch
  • be usable with voice commands
  • have visible text
  • indicate to users that each section can be expanded and collapsed
  • tell the user when a step has been expanded or collapsed
  • be readable when only the text of the page is zoomed in
  • zoom in up to 300% without the text spilling off the screen
  • pass colour contrast
  • be readable should a user change colours
  • associate panel content with the control that opens it using the aria-controls attribute
  • have aria-label / aria-labelledby on section content with a value that refers to the button that controls display of the content

Section headings must use a button element so that users:

  • can toggle sections with the space and enter keys
  • cannot open sections in a new tab or window

When CSS and / or JavaScript is unavailable, the component must:

  • be fully expanded
  • not be marked as expandable

Links in the component must:

  • accept focus
  • be focusable with a keyboard
  • be usable with a keyboard
  • indicate when they have focus
  • change in appearance when touched (in the touch-down state)
  • change in appearance when hovered
  • be usable with touch
  • be usable with voice commands
  • have visible text
  • have meaningful text

Other examples

With supplied identification (preview)

An id for an individual accordion is optional as it’s automatically generated, but it can be supplied if a specific id is required.

The id must be unique across the domain of your service. This is because the open or closed state of individual instances of the accordion uses localStorage to persist across page loads.

Used as an id in the HTML for the accordion as a whole, and also as a prefix for the ids of the section contents and the buttons that open them, so that those ids can be the target of aria-labelledby and aria-control attributes.

Writing well for the web

This is the content for Writing well for the web.

Writing well for specialists

This is the content for Writing well for specialists.

Know your audience

This is the content for Know your audience.

How people read

This is the content for How people read.

<%= render "govuk_publishing_components/components/accordion", {
  id: "with-supplied-id-thats-unique-across-the-domain",
  items: [
    {
      heading: {
        text: "Writing well for the web"
      },
      content: {
        html: sanitize("<p class=\"govuk-body\">This is the content for Writing well for the web.</p>")
      },
      data_attributes: null
    },
    {
      heading: {
        text: "Writing well for specialists"
      },
      content: {
        html: sanitize("<p class=\"govuk-body\">This is the content for Writing well for specialists.</p>")
      },
      data_attributes: null
    },
    {
      heading: {
        text: "Know your audience"
      },
      content: {
        html: sanitize("<p class=\"govuk-body\">This is the content for Know your audience.</p>")
      },
      data_attributes: null
    },
    {
      heading: {
        text: "How people read"
      },
      content: {
        html: sanitize("<p class=\"govuk-body\">This is the content for How people read.</p>")
      },
      data_attributes: null
    }
  ]
} %>

With summary (preview)

Adds a subheading below each section heading.

<%= render "govuk_publishing_components/components/accordion", {
  items: [
    {
      heading: {
        text: "Understanding agile project management"
      },
      summary: {
        text: "Introductions, methods, core features."
      },
      content: {
        html: sanitize("<ul class=\"govuk-list\"> <li> <a class=\"govuk-link\" href=\"#\">Agile and government services: an introduction</a> </li> <li> <a class=\"govuk-link\" href=\"#\">Agile methods: an introduction</a> </li> <li> <a class=\"govuk-link\" href=\"#\">Core principles of agile</a> </li> </ul>")
      },
      data_attributes: null
    },
    {
      heading: {
        text: "Working with agile methods"
      },
      summary: {
        text: "Workspaces, tools and techniques, user stories, planning."
      },
      content: {
        html: sanitize("<ul class=\"govuk-list\"> <li> <a class=\"govuk-link\" href=\"#\">Creating an agile working environment</a> </li> <li> <a class=\"govuk-link\" href=\"#\">Agile tools and techniques</a> </li> <li> <a class=\"govuk-link\" href=\"#\">Set up a team wall</a> </li> <li> <a class=\"govuk-link\" href=\"#\">Writing user stories</a> </li> <li> <a class=\"govuk-link\" href=\"#\">Planning in agile</a> </li> <li> <a class=\"govuk-link\" href=\"#\">Deciding on priorities</a> </li> <li> <a class=\"govuk-link\" href=\"#\">Developing a roadmap</a> </li> </ul>")
      },
      data_attributes: null
    },
    {
      heading: {
        text: "Governing agile services"
      },
      summary: {
        text: "Principles, measuring progress, spending money."
      },
      content: {
        html: sanitize("<ul class=\"govuk-list\"> <li> <a class=\"govuk-link\" href=\"#\">Governance principles for agile service delivery</a> </li> <li> <a class=\"govuk-link\" href=\"#\">Measuring and reporting progress</a> </li> <li> <a class=\"govuk-link\" href=\"#\">Spend controls: check if you need approval to spend money on a service</a> </li> <li> <a class=\"govuk-link\" href=\"#\">Spend controls: apply for approval to spend money on a service</a> </li> <li> <a class=\"govuk-link\" href=\"#\">Spend controls: the new pipeline process</a> </li> <li> <a class=\"govuk-link\" href=\"#\">Working across organisational boundaries</a> </li> </ul>")
      },
      data_attributes: null
    },
    {
      heading: {
        text: "Phases of an agile project"
      },
      summary: {
        text: "Discovery, alpha, beta, live and retirement."
      },
      content: {
        html: sanitize("<ul class=\"govuk-list\"> <li> <a class=\"govuk-link\" href=\"#\">How the discovery phase works</a> </li> <li> <a class=\"govuk-link\" href=\"#\">How the alpha phase works</a> </li> <li> <a class=\"govuk-link\" href=\"#\">How the beta phase works</a> </li> <li> <a class=\"govuk-link\" href=\"#\">How the live phase works</a> </li> <li> <a class=\"govuk-link\" href=\"#\">Retiring your service</a> </li> </ul>")
      },
      data_attributes: null
    }
  ]
} %>

With data attributes (preview)

Adds custom data attributes to each section of the accordion. Accepts a hash, so multiple attributes can be added.

The data_attributes hash is for the outermost element in the accordion.

Each item can also have a data_attributes hash. These data_attributes are placed on the button that triggers the opening and closing - useful for differentiating between each section of the accordion.

Data attributes can also be added to the ‘Show/hide all’ link using the data_attributes_show_all option, primarily where custom tracking is required. These attributes are read from the accordion markup and then added to the link by JavaScript (which is how the link is created).

Writing well for the web

This is the content for Writing well for the web.

Writing well for specialists

This is the content for Writing well for specialists.

Know your audience

This is the content for Know your audience.

How people read

This is the content for How people read.

<%= render "govuk_publishing_components/components/accordion", {
  data_attributes: {
    gtm: "gtm-accordion",
    ga: "ga-accordion",
    module: "govuk-accordion gem-accordion",
    anchor_navigation: false,
    track_show_all_clicks: false,
    track_sections: false,
    show_all_attributes: {
      "gtm-event-name": "example",
      "gtm-attributes": "{ 'ui': { 'type': 'type value', 'section': 'section value' } }"
    },
    show_text: "Show",
    hide_text: "Hide",
    show_all_text: "Show all sections",
    hide_all_text: "Hide all sections",
    this_section_visually_hidden: " this section"
  },
  data_attributes_show_all: {
    "gtm-event-name": "example",
    "gtm-attributes": "{ 'ui': { 'type': 'type value', 'section': 'section value' } }"
  },
  items: [
    {
      heading: {
        text: "Writing well for the web"
      },
      content: {
        html: sanitize("<p class=\"govuk-body\">This is the content for Writing well for the web.</p>")
      },
      data_attributes: {
        gtm: "gtm-accordion-item-1"
      }
    },
    {
      heading: {
        text: "Writing well for specialists"
      },
      content: {
        html: sanitize("<p class=\"govuk-body\">This is the content for Writing well for specialists.</p>")
      },
      data_attributes: {
        gtm: "gtm-accordion-item-2"
      }
    },
    {
      heading: {
        text: "Know your audience"
      },
      content: {
        html: sanitize("<p class=\"govuk-body\">This is the content for Know your audience.</p>")
      },
      data_attributes: {
        gtm: "gtm-accordion-item-3"
      }
    },
    {
      heading: {
        text: "How people read"
      },
      content: {
        html: sanitize("<p class=\"govuk-body\">This is the content for How people read.</p>")
      },
      data_attributes: {
        gtm: "gtm-accordion-item-4"
      }
    }
  ]
} %>

Different heading level (preview)

This will alter the level of the heading, not the appearance of the heading.

Writing well for the web

This is the content for Writing well for the web.

Writing well for specialists

This is the content for Writing well for specialists.

Know your audience

This is the content for Know your audience.

How people read

This is the content for How people read.

<%= render "govuk_publishing_components/components/accordion", {
  heading_level: 3,
  items: [
    {
      heading: {
        text: "Writing well for the web"
      },
      content: {
        html: sanitize("<p class=\"govuk-body\">This is the content for Writing well for the web.</p>")
      },
      data_attributes: null
    },
    {
      heading: {
        text: "Writing well for specialists"
      },
      content: {
        html: sanitize("<p class=\"govuk-body\">This is the content for Writing well for specialists.</p>")
      },
      data_attributes: null
    },
    {
      heading: {
        text: "Know your audience"
      },
      content: {
        html: sanitize("<p class=\"govuk-body\">This is the content for Know your audience.</p>")
      },
      data_attributes: null
    },
    {
      heading: {
        text: "How people read"
      },
      content: {
        html: sanitize("<p class=\"govuk-body\">This is the content for How people read.</p>")
      },
      data_attributes: null
    }
  ]
} %>

With margin bottom (preview)

The component accepts a number for margin bottom from 0 to 9 (0px to 60px) using the GOV.UK Frontend spacing scale. It defaults to having a margin bottom of 30px.

Writing well for the web

This is the content for Writing well for the web.

Writing well for specialists

This is the content for Writing well for specialists.

<%= render "govuk_publishing_components/components/accordion", {
  margin_bottom: 0,
  items: [
    {
      heading: {
        text: "Writing well for the web"
      },
      content: {
        html: sanitize("<p class=\"govuk-body\">This is the content for Writing well for the web.</p>")
      },
      data_attributes: null
    },
    {
      heading: {
        text: "Writing well for specialists"
      },
      content: {
        html: sanitize("<p class=\"govuk-body\">This is the content for Writing well for specialists.</p>")
      },
      data_attributes: null
    }
  ]
} %>

With section open (preview)

Adding expanded: true to the item will mean the section defaults to being open, rather than closed. Once a user opens or closes a section, the state of each section is remembered.

Writing well for the web

This is the content for Writing well for the web.

Writing well for specialists

This is the content for Writing well for specialists.

Know your audience

This is the content for Know your audience.

How people read

This is the content for How people read.

<%= render "govuk_publishing_components/components/accordion", {
  items: [
    {
      heading: {
        text: "Writing well for the web"
      },
      content: {
        html: sanitize("<p class=\"govuk-body\">This is the content for Writing well for the web.</p>")
      },
      expanded: true,
      data_attributes: null
    },
    {
      heading: {
        text: "Writing well for specialists"
      },
      content: {
        html: sanitize("<p class=\"govuk-body\">This is the content for Writing well for specialists.</p>")
      },
      data_attributes: null
    },
    {
      heading: {
        text: "Know your audience"
      },
      content: {
        html: sanitize("<p class=\"govuk-body\">This is the content for Know your audience.</p>")
      },
      data_attributes: null
    },
    {
      heading: {
        text: "How people read"
      },
      content: {
        html: sanitize("<p class=\"govuk-body\">This is the content for How people read.</p>")
      },
      data_attributes: null
    }
  ]
} %>

With the anchor link navigation (preview)

Some apps require custom ids per accordion section heading. Custom ids allow you to link section headings, sometimes across multiple pages.

For example on guidance pages for Content Designers, referred to as “manuals”, each manual includes multiple sets of accordions and will reference between specific sections to easily access content.

Using the same rules, custom ids automatically open accordions when users click within another accordion that links to either

  • the id of an accordion section heading
  • an id within the content of an accordion (this will also automatically navigate to and open accordions on page load)

This feature will only be used if the anchor_navigation flag is passed as true. This mitigates performance risk from event listeners on a large number of links.

Unlike with the accordion-wide custom id attribute, any ids passed to accordion headings as part of this are not stored in localStorage. ids do not need to be unique across your domain, but should still be unique in the context of the page.

Writing well for the web

This is content for accordion 1 of 2

This content contains a link

Writing well for specialists

This is content for accordion 2 of 2

Know your audience

This is the content for Know your audience.

How people read

This is the content for How people read.

<%= render "govuk_publishing_components/components/accordion", {
  anchor_navigation: true,
  items: [
    {
      heading: {
        text: "Writing well for the web",
        id: "writing-well-for-the-web-1"
      },
      content: {
        html: sanitize("<p class=\"govuk-body\">This is content for accordion 1 of 2</p><p class=\"govuk-body\">This content contains a <a href=\"#anchor-nav-test-1\" class=\"govuk-link\">link</a></p>")
      },
      data_attributes: null
    },
    {
      heading: {
        text: "Writing well for specialists"
      },
      content: {
        html: sanitize("<p class=\"govuk-body\" id=\"anchor-nav-test-1\">This is content for accordion 2 of 2</p>")
      },
      data_attributes: null
    },
    {
      heading: {
        text: "Know your audience"
      },
      content: {
        html: sanitize("<p class=\"govuk-body\">This is the content for Know your audience.</p>")
      },
      data_attributes: null
    },
    {
      heading: {
        text: "How people read"
      },
      content: {
        html: sanitize("<p class=\"govuk-body\">This is the content for How people read.</p>")
      },
      data_attributes: null
    }
  ]
} %>

With track show all clicks (preview)

To switch on Google Analytics for the “Show all sections” button on click, pass track_show_all_clicks: true the values passed on open will be Event Action: accordionOpened Event Category: pageElementInteraction Event Label: Show all sections

Writing well for the web

This is content for accordion 1 of 2

Writing well for specialists

This is content for accordion 2 of 2

<%= render "govuk_publishing_components/components/accordion", {
  track_show_all_clicks: true,
  items: [
    {
      heading: {
        text: "Writing well for the web",
        id: "writing-well-for-the-web-2"
      },
      content: {
        html: sanitize("<p class=\"govuk-body\">This is content for accordion 1 of 2</p>")
      },
      data_attributes: null
    },
    {
      heading: {
        text: "Writing well for specialists"
      },
      content: {
        html: sanitize("<p class=\"govuk-body\">This is content for accordion 2 of 2</p>")
      },
      data_attributes: null
    }
  ]
} %>

With track sections (preview)

To switch on Google Analytics for each section, on click, pass track_sections: true the values passed on open will be Event Action: accordionOpened / accordionClosed Event Category: pageElementInteraction and the Event Label being the heading text.

If track_options in an item is set, then it is possible to pass a custom dimension when the section is clicked.

(track_show_all_clicks: true can be added to track the “Show all sections” button as well, if required)

Writing well for the web

This is content for accordion 1 of 2

This content contains a link

Writing well for specialists

This is content for accordion 2 of 2

<%= render "govuk_publishing_components/components/accordion", {
  track_sections: true,
  items: [
    {
      heading: {
        text: "Writing well for the web",
        id: "writing-well-for-the-web-3"
      },
      content: {
        html: sanitize("<p class=\"govuk-body\">This is content for accordion 1 of 2</p><p class=\"govuk-body\">This content contains a <a href=\"#anchor-nav-test\" class=\"govuk-link\">link</a></p>")
      },
      data_attributes: {
        track_options: {
          dimension114: 1
        }
      }
    },
    {
      heading: {
        text: "Writing well for specialists"
      },
      content: {
        html: sanitize("<p class=\"govuk-body\" id=\"anchor-nav-test\">This is content for accordion 2 of 2</p>")
      },
      data_attributes: null
    }
  ]
} %>