Guidance

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

Accordions hide content, so the titles need to be clear.

When to use

Use the Accordions component to make a page easier to scan when it contains information that only some users will need.

When not to use

Accordions hide content from users and not everyone will notice them or understand how they work. For this reason do not use an accordion for content which is essential to all users.

Do not use the Accordions component for large amounts of content or for complex layouts. Consider if it's better to:

  • simplify and reduce the amount of content
  • split the content across multiple pages
  • keep the content on a single page, separated by headings
  • use a list of links to let users navigate quickly to specific sections of content

Developer guidance

Options

Name Type Description
accordions array Required. An array of accordion items.

Options for accordion items

Name Type Description
title string Required. The title of each section. Also used as the JavaScript generated button text.
content string Required. The text content of each section, which is hidden when the section is closed.
heading_tag string Heading level, from h1 to h6. Default is h2.

Ensure the heading_tag used maintains the correct semantic heading structure. If appropriate training is provided, the choice of heading could be set by content authors using a CMS.

{# TODO
Must be an easier way to say if there's one publication within the accordion group show this header before the accordion
#}
{% for accordion in accordions %}
  {% if accordion.publications and loop.index == 1 %}
    <div class="uol-article-section uol-rich-text">
      <h2 class="uol-article-section__title">Publications</h2>
      <div class="uol-article-section__content">
  {% endif %}
{% endfor %}

{% for accordion in accordions %}
    <div class="uol-accordion uol-rich-text">
        <{{ accordion.heading_tag if accordion.heading_tag else 'h2' }} class="uol-accordion__title">
            {{ accordion.title }}
        </{{ accordion.heading_tag if accordion.heading_tag else 'h2' }}>

        <div class="uol-accordion__content">
          <div class="uol-accordion__content-inner">
            {% if accordion.content %}
              <div class="uol-rich-text">
                {{ accordion.content | safe }}
              </div>
            {% endif %}

            {% if accordion.tables %}
              {% render '@uol-index-table', { tables: accordion.tables } %}
            {% endif %}

            {% if accordion.list %}
              <ul>
              {% for item in accordion.list %}
                <li>
                  <a href="{{ item.url }}" {% if item.current == true %} aria-current="page" {% endif %}>{{ item.text }}</a>
                </li>
              {% endfor %}
              </ul>
            {% endif %}

            {% if accordion.publications %}
              {% for publication in accordion.publications %}
                
                {% if loop.index < 6 %}
                  {% render '@uol-publications-list', publication %}
                {% endif %} 

                {% if loop.index == 6 %}
                  <a href="{{ accordion.further_publications.link_url }}" class="uol-publications-list__further-link">{{ accordion.further_publications.link_title }}</a>
                {% endif %}

              {% endfor %}
            {% endif %}


          </div>
        </div>

    </div>
{% endfor %}

{% for accordion in accordions %}
  {% if accordion.publications and loop.index == 1 %}
      </div>
    </div>
  {% endif %}
{% endfor %}
<div class="uol-accordion uol-rich-text">
    <h2 class="uol-accordion__title">
        Accordion title
    </h2>

    <div class="uol-accordion__content">
        <div class="uol-accordion__content-inner">

            <div class="uol-rich-text">
                <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
            </div>

        </div>
    </div>

</div>
  • Content:
    // All accordion styling is js dependent. If no js use default styling
    .js {
    
      .uol-accordion {
        position: relative;
        border-top: 1px solid $color-border--light;
        border-bottom: 1px solid $color-border--light;
        opacity: 0;
        transition: opacity 0.3s ease;
        margin-top: $spacing-6;
        margin-bottom: $spacing-6;
    
        @include media(">=uol-media-m") {
          margin-bottom: $spacing-7;
        }
    
        + .uol-accordion {
          border-top: none;
          margin-top: -#{$spacing-6};
    
          @include media(">=uol-media-m") {
            margin-top: -#{$spacing-7};
          }
        }
      }
    
      .uol-accordion--group-heading {
        
        margin: $spacing-6 0 $spacing-2;
        padding-bottom: $spacing-2;
    
        @include media(">=uol-media-m") {
          margin: $spacing-7 0 $spacing-4;
          padding-bottom: $spacing-4;
        }
      }
    
        .uol-accordion__title {
          @extend %text-size-paragraph;
          @extend %uol-font-sans-serif;
    
          font-weight: $font-weight-bold--sans-serif;
          margin: 0;
        }
    
        .uol-accordion__btn {
          width: 100%;
          text-align: inherit;
          font-weight: inherit;
          background: none;
          border: none;
          padding: $spacing-4 $spacing-6 $spacing-4 0;
          color: inherit;
    
          &::before,
          &::after {
            content: "";
            width: 0.7em;
            height: 2px;
            position: absolute;
            top: 1.4em;
            right: $spacing-2;
            background: $color-black;
            transition: transform 0.3s ease;
    
            @media (forced-colors: active) {
              border: 1px solid transparent;
            }
          
            @media (-ms-high-contrast: active) {
              border: 1px solid WindowText;
            }
          }
    
          &::after {
            transform: rotate(0deg);
          }
    
          &:hover,
          &:focus {
            text-decoration: underline;
          }
    
          &[aria-expanded="false"] {
            &::after {
              transform: rotate(90deg);
            }
          }
    
          &[aria-expanded="true"] {
            &::after {
              transform: rotate(180deg);
            }
          }
        }
    
        .uol-accordion__content {
          position: relative;
          transition: max-height 0.5s ease;
          overflow-y: hidden;
    
          *:last-child {
            margin-bottom: 0;
          }
        }
    
          .uol-accordion__content-inner {
            padding-bottom: $spacing-5;
          }
    
    }
    
  • URL: /components/raw/uol-accordion/_accordion.scss
  • Filesystem Path: src/library/02-components/accordion/_accordion.scss
  • Size: 2.3 KB
  • Content:
    export default () => {
        //
        const accordions = document.querySelectorAll('.uol-accordion')
    
        accordions.forEach( (accordion) => {
          // Get heading
          const accordionHeading = accordion.querySelector('.uol-accordion__title')
          // Get content
          const accordionContent = accordion.querySelector('.uol-accordion__content')
    
          // Wrap heading inner with button
          accordionHeading.innerHTML = `
              <button type="button" class="uol-accordion__btn uol-accordion__btn--expand" aria-expanded="false">
                  ${accordionHeading.textContent}
              </button>
            `
    
          // Get button we've just created
          const toggleBtn = accordionHeading.querySelector('.uol-accordion__btn')
    
          // Hides the content to prevent FOC
          accordionContent.style.opacity = 0
    
          // Get content height
          let accordionContentHeight;
          accordionContentHeight = accordionContent.clientHeight;
          setTimeout(() => {
            accordionContent.style.visibility = 'hidden';
            accordionContent.style.maxHeight = '0px';
          }, 100);
    
          accordion.style.opacity = '1'
    
          // Toggle
          toggleBtn.onclick = () => {
            accordionContent.style.opacity = 1
    
            let expanded = toggleBtn.getAttribute('aria-expanded') === 'true' || false
    
            toggleBtn.setAttribute('aria-expanded', !expanded)
    
            if (!expanded) {
              accordionContent.classList.add('uol-accordion__content--expanded')
    
              accordionContent.style.visibility = 'visible'
    
                console.log('height check ' + accordionContentHeight)
                accordionContent.style.maxHeight = '100%'
    
            } else {
              accordionContent.classList.remove('uol-accordion__content--expanded')
    
              accordionContent.style.maxHeight = '0px'
    
              setTimeout(function() {
                accordionContent.style.visibility = 'hidden';
              }, 100)
            }
          }
    
        })
      }
    
  • URL: /components/raw/uol-accordion/accordion.module.js
  • Filesystem Path: src/library/02-components/accordion/accordion.module.js
  • Size: 1.9 KB
{
  "accordions": [
    {
      "title": "Accordion title",
      "content": "<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>"
    }
  ]
}